From 18bf6ebf65809c7d7d4982f4e7a9904edf7eeb77 Mon Sep 17 00:00:00 2001 From: Dominick Baier Date: Tue, 20 Mar 2012 23:40:21 +0100 Subject: [PATCH] first commit --- .gitignore | 17 + Azure/.nuget/NuGet.Config | 6 + Azure/.nuget/NuGet.exe | Bin 0 -> 558080 bytes Azure/.nuget/NuGet.targets | 52 + Azure/Azure Scripts/Add-Claims.ps1 | 65 + Azure/Azure Scripts/Add-User.ps1 | 69 + Azure/Azure Scripts/Delete-User.ps1 | 42 + Azure/Azure Scripts/Enable-DotNet4Access.ps1 | 86 + Azure/Azure Scripts/List-Claims.ps1 | 48 + Azure/Azure Scripts/List-Users.ps1 | 55 + ...inktecture.IdentityServer.WindowsAzure.sln | 98 + .../ServiceConfiguration.GitHub.cscfg | 43 + .../ServiceDefinition.csdef | 67 + .../WebSite (WindowsAzure).Azure.ccproj | 62 + Azure/WebSite_WindowsAzure/Azure readme.txt | 67 + .../Configuration/connectionStrings.config | 6 + .../Configuration/profile.config | 32 + .../Configuration/repositories.config | 10 + .../Configuration/tracing.config | 54 + .../Configuration/wif.config | 41 + Azure/WebSite_WindowsAzure/Content/Site.css | 175 + .../Content/images/logo.jpg | Bin 0 -> 4766 bytes .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin 0 -> 180 bytes .../images/ui-bg_flat_75_ffffff_40x100.png | Bin 0 -> 178 bytes .../images/ui-bg_glass_55_fbf9ee_1x400.png | Bin 0 -> 120 bytes .../images/ui-bg_glass_65_ffffff_1x400.png | Bin 0 -> 105 bytes .../images/ui-bg_glass_75_dadada_1x400.png | Bin 0 -> 111 bytes .../images/ui-bg_glass_75_e6e6e6_1x400.png | Bin 0 -> 110 bytes .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin 0 -> 119 bytes .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin 0 -> 101 bytes .../base/images/ui-icons_222222_256x240.png | Bin 0 -> 4369 bytes .../base/images/ui-icons_2e83ff_256x240.png | Bin 0 -> 4369 bytes .../base/images/ui-icons_454545_256x240.png | Bin 0 -> 4369 bytes .../base/images/ui-icons_888888_256x240.png | Bin 0 -> 4369 bytes .../base/images/ui-icons_cd0a0a_256x240.png | Bin 0 -> 4369 bytes .../Content/themes/base/jquery-ui.css | 635 + Azure/WebSite_WindowsAzure/Global.asax | 1 + Azure/WebSite_WindowsAzure/Global.asax.cs | 154 + .../Properties/AssemblyInfo.cs | 34 + .../Scripts/MicrosoftAjax.debug.js | 7117 ++++++++++ .../Scripts/MicrosoftAjax.js | 6 + .../Scripts/MicrosoftMvcAjax.debug.js | 408 + .../Scripts/MicrosoftMvcAjax.js | 25 + .../Scripts/MicrosoftMvcValidation.debug.js | 883 ++ .../Scripts/MicrosoftMvcValidation.js | 55 + .../Scripts/jquery-1.6.4-vsdoc.js | 7024 ++++++++++ .../Scripts/jquery-1.6.4.js | 9046 ++++++++++++ .../Scripts/jquery-1.6.4.min.js | 4 + .../WebSite_WindowsAzure/Scripts/jquery-ui.js | 11630 ++++++++++++++++ .../Scripts/jquery-ui.min.js | 409 + .../Scripts/jquery.unobtrusive-ajax.js | 165 + .../Scripts/jquery.unobtrusive-ajax.min.js | 5 + .../Scripts/jquery.validate-vsdoc.js | 1286 ++ .../Scripts/jquery.validate.js | 1150 ++ .../Scripts/jquery.validate.min.js | 20 + .../Scripts/jquery.validate.unobtrusive.js | 319 + .../jquery.validate.unobtrusive.min.js | 5 + .../Startup/disableTimeout.cmd | 1 + .../Startup/unlockSSL.cmd | 1 + .../Views/Account/SignIn.cshtml | 65 + .../Views/Admin/Certificates.cshtml | 85 + .../Views/Admin/Configuration.cshtml | 37 + .../Views/Admin/Endpoints.cshtml | 37 + .../Views/Admin/Index.cshtml | 41 + .../Views/Admin/MyClaims.cshtml | 16 + .../Views/ClientCertificatesAdmin/Add.cshtml | 60 + .../ClientCertificatesAdmin/Delete.cshtml | 16 + .../Views/ClientCertificatesAdmin/Edit.cshtml | 32 + .../ClientCertificatesAdmin/Index.cshtml | 28 + .../Views/DelegationAdmin/Add.cshtml | 56 + .../Views/DelegationAdmin/Delete.cshtml | 16 + .../Views/DelegationAdmin/Edit.cshtml | 32 + .../Views/DelegationAdmin/Index.cshtml | 28 + .../Views/Home/AppIntegration.cshtml | 16 + .../Views/Home/Index.cshtml | 13 + .../Views/InitialConfiguration/Index.cshtml | 49 + .../Views/RelyingPartiesAdmin/Add.cshtml | 116 + .../Views/RelyingPartiesAdmin/Delete.cshtml | 19 + .../Views/RelyingPartiesAdmin/Edit.cshtml | 123 + .../Views/RelyingPartiesAdmin/Index.cshtml | 22 + .../Views/Shared/Confirm.cshtml | 16 + .../Views/Shared/Error.cshtml | 15 + .../Views/Shared/SignedOut.cshtml | 15 + .../Views/Shared/_Layout.cshtml | 48 + .../Views/WSFederation/SignOut.cshtml | 24 + Azure/WebSite_WindowsAzure/Views/Web.config | 60 + .../Views/_ViewStart.cshtml | 3 + Azure/WebSite_WindowsAzure/Web.Debug.config | 30 + Azure/WebSite_WindowsAzure/Web.Release.config | 31 + Azure/WebSite_WindowsAzure/Web.config | 164 + .../WebSite (WindowsAzure).csproj | 406 + .../WebSite.csproj.vspscc | 10 + Azure/WebSite_WindowsAzure/license.txt | 24 + Azure/WebSite_WindowsAzure/packages.config | 14 + .../App.config | 14 + .../ClientCertificatesRepository.cs | 110 + .../ConfigurationRepository.cs | 253 + .../DelegationRepository.cs | 108 + .../EntityModel/Certificates.cs | 21 + .../EntityModel/ClientCertificates.cs | 28 + .../EntityModel/Delegation.cs | 24 + .../EntityModel/Endpoints.cs | 50 + .../EntityModel/Global.cs | 74 + .../EntityModel/RelyingParties.cs | 37 + .../Extensions.cs | 137 + .../IdentityServerConfigurationContext.cs | 62 + .../MemoryCacheRepository.cs | 39 + .../NullCacheRepository.cs | 25 + .../Properties/AssemblyInfo.cs | 35 + .../ProviderUserRepository.cs | 125 + .../RelyingPartyRepository.cs | 114 + ...re.IdentityServer.Core.Repositories.csproj | 99 + .../packages.config | 5 + .../RepositoryConfigurationSection.cs | 195 + .../Constants.cs | 55 + .../DateTimeEpochExtensions.cs | 61 + .../Endpoints.cs | 139 + .../Helper/Cache.cs | 30 + .../Helper/X509Certificates.cs | 100 + .../Models/CertificateConfiguration.cs | 19 + .../Models/ClientCertificate.cs | 18 + .../Models/DelegationSetting.cs | 20 + .../Models/EndpointConfiguration.cs | 26 + .../Models/GlobalConfiguration.cs | 37 + .../Models/RelyingParty.cs | 27 + .../Properties/AssemblyInfo.cs | 35 + .../Repositories/Container.cs | 18 + .../Repositories/ICacheRepository.cs | 18 + .../IClientCertificatesRepository.cs | 28 + .../Repositories/IConfigurationRepository.cs | 26 + .../Repositories/IDelegationRepository.cs | 27 + .../Repositories/IRelyingPartyRepository.cs | 27 + .../Repositories/IUserRepository.cs | 32 + .../Repositories/RepositoryExportProvider.cs | 61 + .../SWT/SimpleWebToken.cs | 114 + .../SWT/SwtConstants.cs | 12 + .../SWT/SwtSecurityKeyClause.cs | 22 + .../SWT/SwtSecurityTokenHandler.cs | 217 + .../SWT/SymmetricSigningCredentials.cs | 18 + .../Thinktecture.IdentityServer.Core.csproj | 149 + .../Thinktecture.IdentityServer.csproj.vspscc | 10 + .../ClientCertificateIssuerNameRegistry.cs | 37 + .../GenericUserNameSecurityTokenHandler.cs | 142 + .../RepositoryUserNameSecurityTokenHandler.cs | 26 + .../RepositoryX509SecurityTokenHandler.cs | 65 + .../TokenService/Request.cs | 450 + .../TokenService/RequestDetails.cs | 38 + .../TokenService/RequestDetailsScope.cs | 42 + .../TokenService/SignInSessionsManager.cs | 89 + .../TokenService/TokenService.cs | 228 + .../TokenService/TokenServiceConfiguration.cs | 78 + .../TokenService/TokenServiceHostFactory.cs | 133 + .../WSFederationMetadataGenerator.cs | 139 + ...9CertificateSessionSecurityTokenHandler.cs | 36 + .../Tracing/Tracing.cs | 72 + .../packages.config | 4 + .../ActionResults/AccessTokenResponse.cs | 29 + .../ActionResults/JSNotifyResult.cs | 47 + .../ActionResults/OAuth2AccessTokenResult.cs | 39 + .../ActionResults/SimpleHttpResult.cs | 45 + .../ActionResults/UnauthorizedResult.cs | 57 + .../ActionResults/WSFederationResult.cs | 22 + .../ActionResults/WrapResult.cs | 55 + .../GlobalFilter/GlobalViewModelFilter.cs | 33 + .../InitialConfigurationFilter.cs | 43 + .../GlobalFilter/SslRedirectFilter.cs | 45 + .../Properties/AssemblyInfo.cs | 36 + .../Resources/jsnotify.htm | 17 + .../Security/AuthenticationHelper | 47 + .../Security/AuthenticationHelper.cs | 317 + .../Security/AuthorizationManager.cs | 104 + .../Security/ClaimsAuthorizeAttribute.cs | 97 + .../Security/ClaimsTransformer.cs | 40 + .../OAuth2/ResourceOwnerCredentialRequest.cs | 17 + .../Security/TokenResponse.cs | 10 + ...ktecture.IdentityServer.Web.Library.csproj | 95 + .../packages.config | 4 + .../EntryPoint.cs | 101 + .../Properties/AssemblyInfo.cs | 35 + .../Configuration/ClientCertificateEntity.cs | 34 + .../ClientCertificatesRepository.cs | 109 + .../Configuration/ConfigurationRepository.cs | 192 + .../Configuration/DelegationEntity.cs | 23 + .../Configuration/DelegationRepository.cs | 108 + .../Configuration/RelyingPartyEntity.cs | 29 + .../Configuration/RelyingPartyRepository.cs | 148 + .../Repositories/Extensions.cs | 189 + .../Repositories/TableStorageContext.cs | 323 + .../Repositories/Users/PasswordCrypto.cs | 32 + .../Users/TableStorageUserRepository.cs | 128 + .../Repositories/Users/UserAccountEntity.cs | 14 + .../Repositories/Users/UserClaimEntity.cs | 13 + ...tecture.IdentityServer.WindowsAzure.csproj | 91 + .../packages.config | 4 + OnPremise/.nuget/NuGet.Config | 6 + OnPremise/.nuget/NuGet.exe | Bin 0 -> 558080 bytes OnPremise/.nuget/NuGet.targets | 52 + OnPremise/Local.testsettings | 10 + OnPremise/Thinktecture.IdentityServer.sln | 98 + OnPremise/Thinktecture.IdentityServer.vsmdi | 6 + OnPremise/TraceAndTestImpact.testsettings | 21 + .../App_Data/IdentityServerConfiguration.sdf | Bin 0 -> 172032 bytes OnPremise/WebSite/App_Data/script.sql | 132 + .../EntityFramework.SqlServerCompact.cs | 30 + .../Configuration/connectionStrings.config | 8 + .../WebSite/Configuration/profile.config | 32 + .../WebSite/Configuration/repositories.config | 6 + .../Configuration/tracing.azure.config | 86 + .../WebSite/Configuration/tracing.config | 70 + OnPremise/WebSite/Configuration/wif.config | 41 + OnPremise/WebSite/Content/Site.css | 175 + OnPremise/WebSite/Content/images/logo.jpg | Bin 0 -> 4766 bytes .../WebSite/Content/resources/jsnotify.htm | 17 + .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin 0 -> 180 bytes .../images/ui-bg_flat_75_ffffff_40x100.png | Bin 0 -> 178 bytes .../images/ui-bg_glass_55_fbf9ee_1x400.png | Bin 0 -> 120 bytes .../images/ui-bg_glass_65_ffffff_1x400.png | Bin 0 -> 105 bytes .../images/ui-bg_glass_75_dadada_1x400.png | Bin 0 -> 111 bytes .../images/ui-bg_glass_75_e6e6e6_1x400.png | Bin 0 -> 110 bytes .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin 0 -> 119 bytes .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin 0 -> 101 bytes .../base/images/ui-icons_222222_256x240.png | Bin 0 -> 4369 bytes .../base/images/ui-icons_2e83ff_256x240.png | Bin 0 -> 4369 bytes .../base/images/ui-icons_454545_256x240.png | Bin 0 -> 4369 bytes .../base/images/ui-icons_888888_256x240.png | Bin 0 -> 4369 bytes .../base/images/ui-icons_cd0a0a_256x240.png | Bin 0 -> 4369 bytes .../WebSite/Content/themes/base/jquery-ui.css | 635 + .../WebSite/Controllers/AccountController.cs | 116 + .../Controllers/Admin/AdminController.cs | 217 + .../ClientCertificatesAdminController.cs | 158 + .../Admin/DelegationAdminController.cs | 140 + .../Admin/RelyingPartiesAdminController.cs | 149 + .../FederationMetadataController.cs | 63 + .../WebSite/Controllers/HomeController.cs | 65 + .../InitialConfigurationController.cs | 94 + .../Controllers/Issue/JSNotifyController.cs | 78 + .../Controllers/Issue/OAuth2Controller.cs | 122 + .../Controllers/Issue/SimpleHttpController.cs | 89 + .../Issue/WSFederationController.cs | 102 + .../Controllers/Issue/WrapController.cs | 92 + OnPremise/WebSite/Global.asax | 1 + OnPremise/WebSite/Global.asax.cs | 154 + OnPremise/WebSite/Properties/AssemblyInfo.cs | 34 + .../WebSite/Scripts/MicrosoftAjax.debug.js | 7117 ++++++++++ OnPremise/WebSite/Scripts/MicrosoftAjax.js | 6 + .../WebSite/Scripts/MicrosoftMvcAjax.debug.js | 408 + OnPremise/WebSite/Scripts/MicrosoftMvcAjax.js | 25 + .../Scripts/MicrosoftMvcValidation.debug.js | 883 ++ .../WebSite/Scripts/MicrosoftMvcValidation.js | 55 + .../WebSite/Scripts/jquery-1.7.1-vsdoc.js | 7153 ++++++++++ OnPremise/WebSite/Scripts/jquery-1.7.1.js | 9266 ++++++++++++ OnPremise/WebSite/Scripts/jquery-1.7.1.min.js | 4 + OnPremise/WebSite/Scripts/jquery-ui.js | 11630 ++++++++++++++++ OnPremise/WebSite/Scripts/jquery-ui.min.js | 409 + .../Scripts/jquery.unobtrusive-ajax.js | 165 + .../Scripts/jquery.unobtrusive-ajax.min.js | 5 + .../WebSite/Scripts/jquery.validate-vsdoc.js | 1286 ++ OnPremise/WebSite/Scripts/jquery.validate.js | 1150 ++ .../WebSite/Scripts/jquery.validate.min.js | 20 + .../Scripts/jquery.validate.unobtrusive.js | 319 + .../jquery.validate.unobtrusive.min.js | 5 + .../AddClientCertificateModel.cs | 27 + .../Administration/AddDelegationModel.cs | 26 + .../Administration/EditCertificatesModel.cs | 56 + .../EditClientCertificatesModel.cs | 20 + .../Administration/EditDelegationModel.cs | 20 + .../EndpointConfigurationModel.cs | 58 + .../ViewModels/Administration/Extensions.cs | 136 + .../GlobalConfigurationModel.cs | 90 + .../ViewModels/Administration/MyModel.cs | 20 + .../Administration/RelyingPartiesModel.cs | 18 + .../Administration/RelyingPartyModel.cs | 51 + .../ViewModels/InitialConfigurationModel.cs | 54 + OnPremise/WebSite/ViewModels/SignInModel.cs | 29 + OnPremise/WebSite/Views/Account/SignIn.cshtml | 65 + .../WebSite/Views/Admin/Certificates.cshtml | 85 + .../WebSite/Views/Admin/Configuration.cshtml | 37 + .../WebSite/Views/Admin/Endpoints.cshtml | 37 + OnPremise/WebSite/Views/Admin/Index.cshtml | 41 + OnPremise/WebSite/Views/Admin/MyClaims.cshtml | 16 + .../Views/ClientCertificatesAdmin/Add.cshtml | 60 + .../ClientCertificatesAdmin/Delete.cshtml | 16 + .../Views/ClientCertificatesAdmin/Edit.cshtml | 32 + .../ClientCertificatesAdmin/Index.cshtml | 28 + .../WebSite/Views/DelegationAdmin/Add.cshtml | 56 + .../Views/DelegationAdmin/Delete.cshtml | 16 + .../WebSite/Views/DelegationAdmin/Edit.cshtml | 32 + .../Views/DelegationAdmin/Index.cshtml | 28 + .../WebSite/Views/Home/AppIntegration.cshtml | 16 + OnPremise/WebSite/Views/Home/Index.cshtml | 13 + .../Views/InitialConfiguration/Index.cshtml | 49 + .../Views/RelyingPartiesAdmin/Add.cshtml | 116 + .../Views/RelyingPartiesAdmin/Delete.cshtml | 19 + .../Views/RelyingPartiesAdmin/Edit.cshtml | 123 + .../Views/RelyingPartiesAdmin/Index.cshtml | 22 + OnPremise/WebSite/Views/Shared/Confirm.cshtml | 16 + OnPremise/WebSite/Views/Shared/Error.cshtml | 15 + .../WebSite/Views/Shared/SignedOut.cshtml | 15 + OnPremise/WebSite/Views/Shared/_Layout.cshtml | 48 + .../WebSite/Views/WSFederation/SignOut.cshtml | 24 + OnPremise/WebSite/Views/Web.config | 60 + OnPremise/WebSite/Views/_ViewStart.cshtml | 3 + OnPremise/WebSite/Web.Debug.config | 30 + OnPremise/WebSite/Web.Release.config | 31 + OnPremise/WebSite/Web.config | 136 + OnPremise/WebSite/WebSite.Publish.xml | 101 + OnPremise/WebSite/WebSite.csproj | 338 + OnPremise/WebSite/WebSite.csproj.vspscc | 10 + OnPremise/WebSite/license.txt | 24 + OnPremise/WebSite/packages.config | 14 + OnPremise/WebSite/readme.txt | 41 + Tests/Extensions.cs | 48 + Tests/Factories/ConfigurationFactory.cs | 78 + Tests/Factories/Constants.cs | 83 + Tests/Factories/HttpClientFactory.cs | 33 + Tests/Factories/PrincipalFactory.cs | 47 + Tests/Factories/RstFactory.cs | 27 + Tests/Factories/WSTrustClientFactory.cs | 49 + Tests/Integration Tests/OAuth2Tests.cs | 144 + Tests/Integration Tests/SimpleHttpTests.cs | 196 + Tests/Integration Tests/WSTrustTests.cs | 235 + Tests/Integration Tests/WrapTests.cs | 127 + Tests/Properties/AssemblyInfo.cs | 34 + .../TestRelyingPartyRepository.cs | 101 + Tests/Tests.csproj | 120 + Tests/Tests.csproj.vspscc | 10 + Tests/Tools/AccessTokenResponse.cs | 19 + Tests/Tools/OAuth2Client.cs | 106 + Tests/Tools/OAuth2Constants.cs | 21 + Tests/Tools/WrapClient.cs | 147 + Tests/Unit Tests/PolicyEnforcementTest.cs | 226 + Tests/Unit Tests/ReplyToHandlingTest.cs | 77 + Tests/packages.config | 6 + readme | 1 + 334 files changed, 97855 insertions(+) create mode 100644 .gitignore create mode 100644 Azure/.nuget/NuGet.Config create mode 100644 Azure/.nuget/NuGet.exe create mode 100644 Azure/.nuget/NuGet.targets create mode 100644 Azure/Azure Scripts/Add-Claims.ps1 create mode 100644 Azure/Azure Scripts/Add-User.ps1 create mode 100644 Azure/Azure Scripts/Delete-User.ps1 create mode 100644 Azure/Azure Scripts/Enable-DotNet4Access.ps1 create mode 100644 Azure/Azure Scripts/List-Claims.ps1 create mode 100644 Azure/Azure Scripts/List-Users.ps1 create mode 100644 Azure/Thinktecture.IdentityServer.WindowsAzure.sln create mode 100644 Azure/WebSite (WindowsAzure).Azure/ServiceConfiguration.GitHub.cscfg create mode 100644 Azure/WebSite (WindowsAzure).Azure/ServiceDefinition.csdef create mode 100644 Azure/WebSite (WindowsAzure).Azure/WebSite (WindowsAzure).Azure.ccproj create mode 100644 Azure/WebSite_WindowsAzure/Azure readme.txt create mode 100644 Azure/WebSite_WindowsAzure/Configuration/connectionStrings.config create mode 100644 Azure/WebSite_WindowsAzure/Configuration/profile.config create mode 100644 Azure/WebSite_WindowsAzure/Configuration/repositories.config create mode 100644 Azure/WebSite_WindowsAzure/Configuration/tracing.config create mode 100644 Azure/WebSite_WindowsAzure/Configuration/wif.config create mode 100644 Azure/WebSite_WindowsAzure/Content/Site.css create mode 100644 Azure/WebSite_WindowsAzure/Content/images/logo.jpg create mode 100644 Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png create mode 100644 Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-bg_flat_75_ffffff_40x100.png create mode 100644 Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png create mode 100644 Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-bg_glass_65_ffffff_1x400.png create mode 100644 Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-bg_glass_75_dadada_1x400.png create mode 100644 Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png create mode 100644 Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-bg_glass_95_fef1ec_1x400.png create mode 100644 Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png create mode 100644 Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-icons_222222_256x240.png create mode 100644 Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-icons_2e83ff_256x240.png create mode 100644 Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-icons_454545_256x240.png create mode 100644 Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-icons_888888_256x240.png create mode 100644 Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-icons_cd0a0a_256x240.png create mode 100644 Azure/WebSite_WindowsAzure/Content/themes/base/jquery-ui.css create mode 100644 Azure/WebSite_WindowsAzure/Global.asax create mode 100644 Azure/WebSite_WindowsAzure/Global.asax.cs create mode 100644 Azure/WebSite_WindowsAzure/Properties/AssemblyInfo.cs create mode 100644 Azure/WebSite_WindowsAzure/Scripts/MicrosoftAjax.debug.js create mode 100644 Azure/WebSite_WindowsAzure/Scripts/MicrosoftAjax.js create mode 100644 Azure/WebSite_WindowsAzure/Scripts/MicrosoftMvcAjax.debug.js create mode 100644 Azure/WebSite_WindowsAzure/Scripts/MicrosoftMvcAjax.js create mode 100644 Azure/WebSite_WindowsAzure/Scripts/MicrosoftMvcValidation.debug.js create mode 100644 Azure/WebSite_WindowsAzure/Scripts/MicrosoftMvcValidation.js create mode 100644 Azure/WebSite_WindowsAzure/Scripts/jquery-1.6.4-vsdoc.js create mode 100644 Azure/WebSite_WindowsAzure/Scripts/jquery-1.6.4.js create mode 100644 Azure/WebSite_WindowsAzure/Scripts/jquery-1.6.4.min.js create mode 100644 Azure/WebSite_WindowsAzure/Scripts/jquery-ui.js create mode 100644 Azure/WebSite_WindowsAzure/Scripts/jquery-ui.min.js create mode 100644 Azure/WebSite_WindowsAzure/Scripts/jquery.unobtrusive-ajax.js create mode 100644 Azure/WebSite_WindowsAzure/Scripts/jquery.unobtrusive-ajax.min.js create mode 100644 Azure/WebSite_WindowsAzure/Scripts/jquery.validate-vsdoc.js create mode 100644 Azure/WebSite_WindowsAzure/Scripts/jquery.validate.js create mode 100644 Azure/WebSite_WindowsAzure/Scripts/jquery.validate.min.js create mode 100644 Azure/WebSite_WindowsAzure/Scripts/jquery.validate.unobtrusive.js create mode 100644 Azure/WebSite_WindowsAzure/Scripts/jquery.validate.unobtrusive.min.js create mode 100644 Azure/WebSite_WindowsAzure/Startup/disableTimeout.cmd create mode 100644 Azure/WebSite_WindowsAzure/Startup/unlockSSL.cmd create mode 100644 Azure/WebSite_WindowsAzure/Views/Account/SignIn.cshtml create mode 100644 Azure/WebSite_WindowsAzure/Views/Admin/Certificates.cshtml create mode 100644 Azure/WebSite_WindowsAzure/Views/Admin/Configuration.cshtml create mode 100644 Azure/WebSite_WindowsAzure/Views/Admin/Endpoints.cshtml create mode 100644 Azure/WebSite_WindowsAzure/Views/Admin/Index.cshtml create mode 100644 Azure/WebSite_WindowsAzure/Views/Admin/MyClaims.cshtml create mode 100644 Azure/WebSite_WindowsAzure/Views/ClientCertificatesAdmin/Add.cshtml create mode 100644 Azure/WebSite_WindowsAzure/Views/ClientCertificatesAdmin/Delete.cshtml create mode 100644 Azure/WebSite_WindowsAzure/Views/ClientCertificatesAdmin/Edit.cshtml create mode 100644 Azure/WebSite_WindowsAzure/Views/ClientCertificatesAdmin/Index.cshtml create mode 100644 Azure/WebSite_WindowsAzure/Views/DelegationAdmin/Add.cshtml create mode 100644 Azure/WebSite_WindowsAzure/Views/DelegationAdmin/Delete.cshtml create mode 100644 Azure/WebSite_WindowsAzure/Views/DelegationAdmin/Edit.cshtml create mode 100644 Azure/WebSite_WindowsAzure/Views/DelegationAdmin/Index.cshtml create mode 100644 Azure/WebSite_WindowsAzure/Views/Home/AppIntegration.cshtml create mode 100644 Azure/WebSite_WindowsAzure/Views/Home/Index.cshtml create mode 100644 Azure/WebSite_WindowsAzure/Views/InitialConfiguration/Index.cshtml create mode 100644 Azure/WebSite_WindowsAzure/Views/RelyingPartiesAdmin/Add.cshtml create mode 100644 Azure/WebSite_WindowsAzure/Views/RelyingPartiesAdmin/Delete.cshtml create mode 100644 Azure/WebSite_WindowsAzure/Views/RelyingPartiesAdmin/Edit.cshtml create mode 100644 Azure/WebSite_WindowsAzure/Views/RelyingPartiesAdmin/Index.cshtml create mode 100644 Azure/WebSite_WindowsAzure/Views/Shared/Confirm.cshtml create mode 100644 Azure/WebSite_WindowsAzure/Views/Shared/Error.cshtml create mode 100644 Azure/WebSite_WindowsAzure/Views/Shared/SignedOut.cshtml create mode 100644 Azure/WebSite_WindowsAzure/Views/Shared/_Layout.cshtml create mode 100644 Azure/WebSite_WindowsAzure/Views/WSFederation/SignOut.cshtml create mode 100644 Azure/WebSite_WindowsAzure/Views/Web.config create mode 100644 Azure/WebSite_WindowsAzure/Views/_ViewStart.cshtml create mode 100644 Azure/WebSite_WindowsAzure/Web.Debug.config create mode 100644 Azure/WebSite_WindowsAzure/Web.Release.config create mode 100644 Azure/WebSite_WindowsAzure/Web.config create mode 100644 Azure/WebSite_WindowsAzure/WebSite (WindowsAzure).csproj create mode 100644 Azure/WebSite_WindowsAzure/WebSite.csproj.vspscc create mode 100644 Azure/WebSite_WindowsAzure/license.txt create mode 100644 Azure/WebSite_WindowsAzure/packages.config create mode 100644 Libraries/Thinktecture.IdentityServer.Core.Repositories/App.config create mode 100644 Libraries/Thinktecture.IdentityServer.Core.Repositories/ClientCertificatesRepository.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core.Repositories/ConfigurationRepository.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core.Repositories/DelegationRepository.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core.Repositories/EntityModel/Certificates.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core.Repositories/EntityModel/ClientCertificates.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core.Repositories/EntityModel/Delegation.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core.Repositories/EntityModel/Endpoints.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core.Repositories/EntityModel/Global.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core.Repositories/EntityModel/RelyingParties.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core.Repositories/Extensions.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core.Repositories/IdentityServerConfigurationContext.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core.Repositories/MemoryCacheRepository.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core.Repositories/NullCacheRepository.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core.Repositories/Properties/AssemblyInfo.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core.Repositories/ProviderUserRepository.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core.Repositories/RelyingPartyRepository.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core.Repositories/Thinktecture.IdentityServer.Core.Repositories.csproj create mode 100644 Libraries/Thinktecture.IdentityServer.Core.Repositories/packages.config create mode 100644 Libraries/Thinktecture.IdentityServer.Core/Configuration/RepositoryConfigurationSection.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/Constants.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/DateTimeEpochExtensions.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/Endpoints.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/Helper/Cache.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/Helper/X509Certificates.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/Models/CertificateConfiguration.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/Models/ClientCertificate.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/Models/DelegationSetting.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/Models/EndpointConfiguration.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/Models/GlobalConfiguration.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/Models/RelyingParty.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/Properties/AssemblyInfo.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/Repositories/Container.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/Repositories/ICacheRepository.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/Repositories/IClientCertificatesRepository.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/Repositories/IConfigurationRepository.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/Repositories/IDelegationRepository.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/Repositories/IRelyingPartyRepository.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/Repositories/IUserRepository.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/Repositories/RepositoryExportProvider.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/SWT/SimpleWebToken.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/SWT/SwtConstants.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/SWT/SwtSecurityKeyClause.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/SWT/SwtSecurityTokenHandler.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/SWT/SymmetricSigningCredentials.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/Thinktecture.IdentityServer.Core.csproj create mode 100644 Libraries/Thinktecture.IdentityServer.Core/Thinktecture.IdentityServer.csproj.vspscc create mode 100644 Libraries/Thinktecture.IdentityServer.Core/TokenService/ClientCertificateIssuerNameRegistry.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/TokenService/GenericUserNameSecurityTokenHandler.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/TokenService/RepositoryUserNameSecurityTokenHandler.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/TokenService/RepositoryX509SecurityTokenHandler.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/TokenService/Request.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/TokenService/RequestDetails.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/TokenService/RequestDetailsScope.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/TokenService/SignInSessionsManager.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/TokenService/TokenService.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/TokenService/TokenServiceConfiguration.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/TokenService/TokenServiceHostFactory.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/TokenService/WSFederationMetadataGenerator.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/TokenService/X509CertificateSessionSecurityTokenHandler.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/Tracing/Tracing.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Core/packages.config create mode 100644 Libraries/Thinktecture.IdentityServer.Web.Library/ActionResults/AccessTokenResponse.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Web.Library/ActionResults/JSNotifyResult.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Web.Library/ActionResults/OAuth2AccessTokenResult.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Web.Library/ActionResults/SimpleHttpResult.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Web.Library/ActionResults/UnauthorizedResult.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Web.Library/ActionResults/WSFederationResult.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Web.Library/ActionResults/WrapResult.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Web.Library/GlobalFilter/GlobalViewModelFilter.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Web.Library/GlobalFilter/InitialConfigurationFilter.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Web.Library/GlobalFilter/SslRedirectFilter.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Web.Library/Properties/AssemblyInfo.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Web.Library/Resources/jsnotify.htm create mode 100644 Libraries/Thinktecture.IdentityServer.Web.Library/Security/AuthenticationHelper create mode 100644 Libraries/Thinktecture.IdentityServer.Web.Library/Security/AuthenticationHelper.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Web.Library/Security/AuthorizationManager.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Web.Library/Security/ClaimsAuthorizeAttribute.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Web.Library/Security/ClaimsTransformer.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Web.Library/Security/OAuth2/ResourceOwnerCredentialRequest.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Web.Library/Security/TokenResponse.cs create mode 100644 Libraries/Thinktecture.IdentityServer.Web.Library/Thinktecture.IdentityServer.Web.Library.csproj create mode 100644 Libraries/Thinktecture.IdentityServer.Web.Library/packages.config create mode 100644 Libraries/Thinktecture.IdentityServer.WindowsAzure/EntryPoint.cs create mode 100644 Libraries/Thinktecture.IdentityServer.WindowsAzure/Properties/AssemblyInfo.cs create mode 100644 Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Configuration/ClientCertificateEntity.cs create mode 100644 Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Configuration/ClientCertificatesRepository.cs create mode 100644 Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Configuration/ConfigurationRepository.cs create mode 100644 Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Configuration/DelegationEntity.cs create mode 100644 Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Configuration/DelegationRepository.cs create mode 100644 Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Configuration/RelyingPartyEntity.cs create mode 100644 Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Configuration/RelyingPartyRepository.cs create mode 100644 Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Extensions.cs create mode 100644 Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/TableStorageContext.cs create mode 100644 Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Users/PasswordCrypto.cs create mode 100644 Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Users/TableStorageUserRepository.cs create mode 100644 Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Users/UserAccountEntity.cs create mode 100644 Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Users/UserClaimEntity.cs create mode 100644 Libraries/Thinktecture.IdentityServer.WindowsAzure/Thinktecture.IdentityServer.WindowsAzure.csproj create mode 100644 Libraries/Thinktecture.IdentityServer.WindowsAzure/packages.config create mode 100644 OnPremise/.nuget/NuGet.Config create mode 100644 OnPremise/.nuget/NuGet.exe create mode 100644 OnPremise/.nuget/NuGet.targets create mode 100644 OnPremise/Local.testsettings create mode 100644 OnPremise/Thinktecture.IdentityServer.sln create mode 100644 OnPremise/Thinktecture.IdentityServer.vsmdi create mode 100644 OnPremise/TraceAndTestImpact.testsettings create mode 100644 OnPremise/WebSite/App_Data/IdentityServerConfiguration.sdf create mode 100644 OnPremise/WebSite/App_Data/script.sql create mode 100644 OnPremise/WebSite/App_Start/EntityFramework.SqlServerCompact.cs create mode 100644 OnPremise/WebSite/Configuration/connectionStrings.config create mode 100644 OnPremise/WebSite/Configuration/profile.config create mode 100644 OnPremise/WebSite/Configuration/repositories.config create mode 100644 OnPremise/WebSite/Configuration/tracing.azure.config create mode 100644 OnPremise/WebSite/Configuration/tracing.config create mode 100644 OnPremise/WebSite/Configuration/wif.config create mode 100644 OnPremise/WebSite/Content/Site.css create mode 100644 OnPremise/WebSite/Content/images/logo.jpg create mode 100644 OnPremise/WebSite/Content/resources/jsnotify.htm create mode 100644 OnPremise/WebSite/Content/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png create mode 100644 OnPremise/WebSite/Content/themes/base/images/ui-bg_flat_75_ffffff_40x100.png create mode 100644 OnPremise/WebSite/Content/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png create mode 100644 OnPremise/WebSite/Content/themes/base/images/ui-bg_glass_65_ffffff_1x400.png create mode 100644 OnPremise/WebSite/Content/themes/base/images/ui-bg_glass_75_dadada_1x400.png create mode 100644 OnPremise/WebSite/Content/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png create mode 100644 OnPremise/WebSite/Content/themes/base/images/ui-bg_glass_95_fef1ec_1x400.png create mode 100644 OnPremise/WebSite/Content/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png create mode 100644 OnPremise/WebSite/Content/themes/base/images/ui-icons_222222_256x240.png create mode 100644 OnPremise/WebSite/Content/themes/base/images/ui-icons_2e83ff_256x240.png create mode 100644 OnPremise/WebSite/Content/themes/base/images/ui-icons_454545_256x240.png create mode 100644 OnPremise/WebSite/Content/themes/base/images/ui-icons_888888_256x240.png create mode 100644 OnPremise/WebSite/Content/themes/base/images/ui-icons_cd0a0a_256x240.png create mode 100644 OnPremise/WebSite/Content/themes/base/jquery-ui.css create mode 100644 OnPremise/WebSite/Controllers/AccountController.cs create mode 100644 OnPremise/WebSite/Controllers/Admin/AdminController.cs create mode 100644 OnPremise/WebSite/Controllers/Admin/ClientCertificatesAdminController.cs create mode 100644 OnPremise/WebSite/Controllers/Admin/DelegationAdminController.cs create mode 100644 OnPremise/WebSite/Controllers/Admin/RelyingPartiesAdminController.cs create mode 100644 OnPremise/WebSite/Controllers/FederationMetadataController.cs create mode 100644 OnPremise/WebSite/Controllers/HomeController.cs create mode 100644 OnPremise/WebSite/Controllers/InitialConfigurationController.cs create mode 100644 OnPremise/WebSite/Controllers/Issue/JSNotifyController.cs create mode 100644 OnPremise/WebSite/Controllers/Issue/OAuth2Controller.cs create mode 100644 OnPremise/WebSite/Controllers/Issue/SimpleHttpController.cs create mode 100644 OnPremise/WebSite/Controllers/Issue/WSFederationController.cs create mode 100644 OnPremise/WebSite/Controllers/Issue/WrapController.cs create mode 100644 OnPremise/WebSite/Global.asax create mode 100644 OnPremise/WebSite/Global.asax.cs create mode 100644 OnPremise/WebSite/Properties/AssemblyInfo.cs create mode 100644 OnPremise/WebSite/Scripts/MicrosoftAjax.debug.js create mode 100644 OnPremise/WebSite/Scripts/MicrosoftAjax.js create mode 100644 OnPremise/WebSite/Scripts/MicrosoftMvcAjax.debug.js create mode 100644 OnPremise/WebSite/Scripts/MicrosoftMvcAjax.js create mode 100644 OnPremise/WebSite/Scripts/MicrosoftMvcValidation.debug.js create mode 100644 OnPremise/WebSite/Scripts/MicrosoftMvcValidation.js create mode 100644 OnPremise/WebSite/Scripts/jquery-1.7.1-vsdoc.js create mode 100644 OnPremise/WebSite/Scripts/jquery-1.7.1.js create mode 100644 OnPremise/WebSite/Scripts/jquery-1.7.1.min.js create mode 100644 OnPremise/WebSite/Scripts/jquery-ui.js create mode 100644 OnPremise/WebSite/Scripts/jquery-ui.min.js create mode 100644 OnPremise/WebSite/Scripts/jquery.unobtrusive-ajax.js create mode 100644 OnPremise/WebSite/Scripts/jquery.unobtrusive-ajax.min.js create mode 100644 OnPremise/WebSite/Scripts/jquery.validate-vsdoc.js create mode 100644 OnPremise/WebSite/Scripts/jquery.validate.js create mode 100644 OnPremise/WebSite/Scripts/jquery.validate.min.js create mode 100644 OnPremise/WebSite/Scripts/jquery.validate.unobtrusive.js create mode 100644 OnPremise/WebSite/Scripts/jquery.validate.unobtrusive.min.js create mode 100644 OnPremise/WebSite/ViewModels/Administration/AddClientCertificateModel.cs create mode 100644 OnPremise/WebSite/ViewModels/Administration/AddDelegationModel.cs create mode 100644 OnPremise/WebSite/ViewModels/Administration/EditCertificatesModel.cs create mode 100644 OnPremise/WebSite/ViewModels/Administration/EditClientCertificatesModel.cs create mode 100644 OnPremise/WebSite/ViewModels/Administration/EditDelegationModel.cs create mode 100644 OnPremise/WebSite/ViewModels/Administration/EndpointConfigurationModel.cs create mode 100644 OnPremise/WebSite/ViewModels/Administration/Extensions.cs create mode 100644 OnPremise/WebSite/ViewModels/Administration/GlobalConfigurationModel.cs create mode 100644 OnPremise/WebSite/ViewModels/Administration/MyModel.cs create mode 100644 OnPremise/WebSite/ViewModels/Administration/RelyingPartiesModel.cs create mode 100644 OnPremise/WebSite/ViewModels/Administration/RelyingPartyModel.cs create mode 100644 OnPremise/WebSite/ViewModels/InitialConfigurationModel.cs create mode 100644 OnPremise/WebSite/ViewModels/SignInModel.cs create mode 100644 OnPremise/WebSite/Views/Account/SignIn.cshtml create mode 100644 OnPremise/WebSite/Views/Admin/Certificates.cshtml create mode 100644 OnPremise/WebSite/Views/Admin/Configuration.cshtml create mode 100644 OnPremise/WebSite/Views/Admin/Endpoints.cshtml create mode 100644 OnPremise/WebSite/Views/Admin/Index.cshtml create mode 100644 OnPremise/WebSite/Views/Admin/MyClaims.cshtml create mode 100644 OnPremise/WebSite/Views/ClientCertificatesAdmin/Add.cshtml create mode 100644 OnPremise/WebSite/Views/ClientCertificatesAdmin/Delete.cshtml create mode 100644 OnPremise/WebSite/Views/ClientCertificatesAdmin/Edit.cshtml create mode 100644 OnPremise/WebSite/Views/ClientCertificatesAdmin/Index.cshtml create mode 100644 OnPremise/WebSite/Views/DelegationAdmin/Add.cshtml create mode 100644 OnPremise/WebSite/Views/DelegationAdmin/Delete.cshtml create mode 100644 OnPremise/WebSite/Views/DelegationAdmin/Edit.cshtml create mode 100644 OnPremise/WebSite/Views/DelegationAdmin/Index.cshtml create mode 100644 OnPremise/WebSite/Views/Home/AppIntegration.cshtml create mode 100644 OnPremise/WebSite/Views/Home/Index.cshtml create mode 100644 OnPremise/WebSite/Views/InitialConfiguration/Index.cshtml create mode 100644 OnPremise/WebSite/Views/RelyingPartiesAdmin/Add.cshtml create mode 100644 OnPremise/WebSite/Views/RelyingPartiesAdmin/Delete.cshtml create mode 100644 OnPremise/WebSite/Views/RelyingPartiesAdmin/Edit.cshtml create mode 100644 OnPremise/WebSite/Views/RelyingPartiesAdmin/Index.cshtml create mode 100644 OnPremise/WebSite/Views/Shared/Confirm.cshtml create mode 100644 OnPremise/WebSite/Views/Shared/Error.cshtml create mode 100644 OnPremise/WebSite/Views/Shared/SignedOut.cshtml create mode 100644 OnPremise/WebSite/Views/Shared/_Layout.cshtml create mode 100644 OnPremise/WebSite/Views/WSFederation/SignOut.cshtml create mode 100644 OnPremise/WebSite/Views/Web.config create mode 100644 OnPremise/WebSite/Views/_ViewStart.cshtml create mode 100644 OnPremise/WebSite/Web.Debug.config create mode 100644 OnPremise/WebSite/Web.Release.config create mode 100644 OnPremise/WebSite/Web.config create mode 100644 OnPremise/WebSite/WebSite.Publish.xml create mode 100644 OnPremise/WebSite/WebSite.csproj create mode 100644 OnPremise/WebSite/WebSite.csproj.vspscc create mode 100644 OnPremise/WebSite/license.txt create mode 100644 OnPremise/WebSite/packages.config create mode 100644 OnPremise/WebSite/readme.txt create mode 100644 Tests/Extensions.cs create mode 100644 Tests/Factories/ConfigurationFactory.cs create mode 100644 Tests/Factories/Constants.cs create mode 100644 Tests/Factories/HttpClientFactory.cs create mode 100644 Tests/Factories/PrincipalFactory.cs create mode 100644 Tests/Factories/RstFactory.cs create mode 100644 Tests/Factories/WSTrustClientFactory.cs create mode 100644 Tests/Integration Tests/OAuth2Tests.cs create mode 100644 Tests/Integration Tests/SimpleHttpTests.cs create mode 100644 Tests/Integration Tests/WSTrustTests.cs create mode 100644 Tests/Integration Tests/WrapTests.cs create mode 100644 Tests/Properties/AssemblyInfo.cs create mode 100644 Tests/Repositories/TestRelyingPartyRepository.cs create mode 100644 Tests/Tests.csproj create mode 100644 Tests/Tests.csproj.vspscc create mode 100644 Tests/Tools/AccessTokenResponse.cs create mode 100644 Tests/Tools/OAuth2Client.cs create mode 100644 Tests/Tools/OAuth2Constants.cs create mode 100644 Tests/Tools/WrapClient.cs create mode 100644 Tests/Unit Tests/PolicyEnforcementTest.cs create mode 100644 Tests/Unit Tests/ReplyToHandlingTest.cs create mode 100644 Tests/packages.config create mode 100644 readme diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a9a3575 --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ +bin/ +obj/ +packages/ +TestResults/ +build/ +DefaultConfiguration/ +Documentation/ +csx/ +Profiles/ + +ServiceConfiguration.Cloud.cscfg +ServiceConfiguration.Local.cscfg +ServiceDefinition.build.csdef +testimpactdata.sdf +Packages.dgml +*.suo +*.user \ No newline at end of file diff --git a/Azure/.nuget/NuGet.Config b/Azure/.nuget/NuGet.Config new file mode 100644 index 0000000..67f8ea0 --- /dev/null +++ b/Azure/.nuget/NuGet.Config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Azure/.nuget/NuGet.exe b/Azure/.nuget/NuGet.exe new file mode 100644 index 0000000000000000000000000000000000000000..34ad49b494dd855dabf1b1cee5d3a8d51525d3b9 GIT binary patch literal 558080 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%0A|w=%&@u7j7;}<-)k0>bYB`T-B(A&wRHbW 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

Ekj^+5jehgt4{Op!7wB|J;~=-=l2?c3i{CT#0( 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 z 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 G=zjnx2wiCa literal 0 HcmV?d00001 diff --git a/Azure/.nuget/NuGet.targets b/Azure/.nuget/NuGet.targets new file mode 100644 index 0000000..25380fe --- /dev/null +++ b/Azure/.nuget/NuGet.targets @@ -0,0 +1,52 @@ + + + + $(MSBuildProjectDirectory)\..\ + $([System.IO.Path]::Combine($(SolutionDir), ".nuget")) + $(NuGetToolsPath)\nuget.exe + $([System.IO.Path]::Combine($(ProjectDir), "packages.config")) + $([System.IO.Path]::Combine($(SolutionDir), "packages")) + $(TargetDir.Trim('\\')) + + + "" + + + false + + + false + + + "$(NuGetExePath)" install "$(PackagesConfig)" -source $(PackageSources) -o "$(PackagesDir)" + "$(NuGetExePath)" pack "$(ProjectPath)" -p Configuration=$(Configuration) -o "$(PackageOutputDir)" -symbols + + + + RestorePackages; + $(BuildDependsOn); + + + + + $(BuildDependsOn); + BuildPackage; + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Azure/Azure Scripts/Add-Claims.ps1 b/Azure/Azure Scripts/Add-Claims.ps1 new file mode 100644 index 0000000..973aa5a --- /dev/null +++ b/Azure/Azure Scripts/Add-Claims.ps1 @@ -0,0 +1,65 @@ +<# +.SYNOPSIS + Adds claims to an IdentityServer table storage user +.DESCRIPTION + Adds claims to an IdentityServer table storage user +.PARAMETER claims + One or multiple claim type/value pairs separated by % (see examples) +.PARAMETER username + Logon name of the user +.PARAMETER connectionString + Connection string to table storage +.EXAMPLE + Add-Claims -username alice -connectionString 'connectionstring to storage' -claims claimtype1%value1, claimtype2%value2 +#> + +[CmdletBinding()] +param( + [Parameter( + Mandatory=$True, + ValueFromPipeline=$False, + ValueFromPipelineByPropertyName=$True + )] + [string]$username, + + [Parameter( + Mandatory=$True, + ValueFromPipeline=$False, + ValueFromPipelineByPropertyName=$True + )] + [string[]]$claims, + + [Parameter( + Mandatory=$True, + ValueFromPipeline=$False, + ValueFromPipelineByPropertyName=$True + )] + [string]$connectionString +) + +begin { + $wif = $env:ProgramFiles + "\Reference Assemblies\Microsoft\Windows Identity Foundation\v3.5\Microsoft.IdentityModel.dll" + + Add-Type -Path "Thinktecture.IdentityServer.WindowsAzure.dll" + Add-Type -Path $wif +} + +process { + + $claimsList = New-Object System.Collections.Generic.List[Microsoft.IdentityModel.Claims.Claim] + + foreach ($claim in $claims) { + $items = $claim.split("%") + $wifClaim = New-Object Microsoft.IdentityModel.Claims.Claim -ArgumentList $items[0], $items[1] + + $claimsList.Add($wifClaim) + } + + try { + $context = New-Object Thinktecture.IdentityServer.Repositories.WindowsAzure.TableStorageContext -arg $connectionString + $context.AddUserClaims($username, $claimsList) + } + catch { + Write-Error $_.Exception.ToString() + } +} \ No newline at end of file diff --git a/Azure/Azure Scripts/Add-User.ps1 b/Azure/Azure Scripts/Add-User.ps1 new file mode 100644 index 0000000..8310942 --- /dev/null +++ b/Azure/Azure Scripts/Add-User.ps1 @@ -0,0 +1,69 @@ +<# +.SYNOPSIS + Adds a user to the IdentityServer table storage +.DESCRIPTION + Adds a user to the IdentityServer table storage +.PARAMETER username + Logon name of the user +.PARAMETER password + password of the user +.PARAMETER isAdmin + Specifies whether the user should be able to administrate IdentityServer +.PARAMETER connectionString + Connection string to table storage +#> + +[CmdletBinding()] +param( + [Parameter( + Mandatory=$True, + ValueFromPipeline=$False, + ValueFromPipelineByPropertyName=$True + )] + [string]$username, + + [Parameter( + Mandatory=$True, + ValueFromPipeline=$False, + ValueFromPipelineByPropertyName=$True + )] + [ValidateLength(7,255)] + [string]$password, + + [Parameter( + Mandatory=$False, + ValueFromPipeline=$False, + ValueFromPipelineByPropertyName=$True + )] + [switch]$isAdmin = $false, + + [Parameter( + Mandatory=$True, + ValueFromPipeline=$False, + ValueFromPipelineByPropertyName=$True + )] + [string]$connectionString +) + +begin { + Add-Type -Path "Thinktecture.IdentityServer.WindowsAzure.dll" + + try { + [Thinktecture.IdentityServer.Repositories.WindowsAzure.TableStorageContext]::SetupTables($connectionString) + } + catch { + Write-Error $_.Exception.ToString() + exit + } +} + +process { + try { + $context = New-Object Thinktecture.IdentityServer.Repositories.WindowsAzure.TableStorageContext -arg $connectionString + $context.AddUserAccount($username, $password, $isAdmin) + } + catch { + Write-Error $_.Exception.ToString() + } +} + diff --git a/Azure/Azure Scripts/Delete-User.ps1 b/Azure/Azure Scripts/Delete-User.ps1 new file mode 100644 index 0000000..15cda92 --- /dev/null +++ b/Azure/Azure Scripts/Delete-User.ps1 @@ -0,0 +1,42 @@ +<# +.SYNOPSIS + Deletes a user from the IdentityServer table storage +.DESCRIPTION + Deletes a user from the IdentityServer table storage +.PARAMETER username + Logon name of the user +.PARAMETER connectionString + Connection string to table storage +#> + +[CmdletBinding()] +param( + [Parameter( + Mandatory=$True, + ValueFromPipeline=$False, + ValueFromPipelineByPropertyName=$True + )] + [string]$username, + + [Parameter( + Mandatory=$True, + ValueFromPipeline=$False, + ValueFromPipelineByPropertyName=$True + )] + [string]$connectionString +) + +begin { + Add-Type -Path "Thinktecture.IdentityServer.WindowsAzure.dll" +} + +process { + try { + $context = New-Object Thinktecture.IdentityServer.Repositories.WindowsAzure.TableStorageContext -arg $connectionString + + $context.DeleteUserAccount($username) + } + catch { + Write-Error $_.Exception.ToString() + } +} \ No newline at end of file diff --git a/Azure/Azure Scripts/Enable-DotNet4Access.ps1 b/Azure/Azure Scripts/Enable-DotNet4Access.ps1 new file mode 100644 index 0000000..92062eb --- /dev/null +++ b/Azure/Azure Scripts/Enable-DotNet4Access.ps1 @@ -0,0 +1,86 @@ + <# + .SYNOPSIS + Enables PowerShell access to the .NET 4.0 framework by creating a configuration file. + + .DESCRIPTION + Enables PowerShell access to the .NET 4.0 framework by creating a configuration file. You will need to + restart PowerShell in order for this to take effect. In a default installation of PowerShell V2, these + files do not exist. + + .PARAMETER Computername + Name of computer to enable .NET 4 for PowerShell against. + + .PARAMETER Console + Apply configuration change for console only + + .PARAMETER ISE + Apply configuration change to ISE only + + .NOTES + Name: Enable-DotNet4Access + Author: Boe Prox + DateCreated: 10JAN2012 + + .LINK + https://learn-powershell.net + + .EXAMPLE + Enable-DotNet4Access -Console -ISE + + Description + ----------- + Enables .NET 4.0 access for PowerShell on console and ISE + #> + + [cmdletbinding( + SupportsShouldProcess = $True + )] + Param ( + [parameter(Position='0',ValueFromPipeLine = $True,ValueFromPipelineByPropertyName=$True)] + [Alias('__Server','Computer','Server','CN')] + [string[]]$Computername, + [parameter(Position='1')] + [switch]$Console, + [parameter(Position='2')] + [switch]$ISE + ) + Begin { + Write-Verbose ("Creating file data") +$file = @' + + + + + + + +'@ + } + Process { + If (-Not $PSBoundParameters['Computername']) { + Write-Warning ("No computername given! Using {0} as computername." -f $Env:Computername) + $Computername = $Env:Computername + } + ForEach ($Computer in $computername) { + If ($PSBoundParameters['Console']) { + If ($pscmdlet.ShouldProcess("Console","Enable .NET 4.0 Access")) { + Try { + $file | Out-file "\\$computer\C$\Windows\System32\WindowsPowerShell\v1.0\PowerShell.Exe.Config" -Force + Write-Host ("{0}: Console must be restarted before changes will take effect!" -f $Computer) -fore Green -Back Black + } Catch { + Write-Warning ("{0}: {1}" -f $computer,$_.Exception.Message) + } + } + } + If ($PSBoundParameters['ISE']) { + If ($pscmdlet.ShouldProcess("ISE","Enable .NET 4.0 Access")) { + Try { + $file | Out-file "\\$computer\C$\Windows\System32\WindowsPowerShell\v1.0\PowerShell_ISE.Exe.Config" -Force + Write-Host ("{0}: ISE must be restarted before changes will take effect!" -f $Computer) -fore Green -Back Black + } Catch { + Write-Warning ("{0}: {1}" -f $computer,$_.Exception.Message) + } + } + } + } + } diff --git a/Azure/Azure Scripts/List-Claims.ps1 b/Azure/Azure Scripts/List-Claims.ps1 new file mode 100644 index 0000000..deae622 --- /dev/null +++ b/Azure/Azure Scripts/List-Claims.ps1 @@ -0,0 +1,48 @@ +<# +.SYNOPSIS + Lists alls claims for a user from the IdentityServer table storage +.DESCRIPTION + Lists alls claims for a user from the IdentityServer table storage +.PARAMETER username + Logon name of the user +.PARAMETER connectionString + Connection string to table storage +#> + +[CmdletBinding()] +param( + [Parameter( + Mandatory=$True, + ValueFromPipeline=$False, + ValueFromPipelineByPropertyName=$True + )] + [string]$username, + + [Parameter( + Mandatory=$True, + ValueFromPipeline=$False, + ValueFromPipelineByPropertyName=$True + )] + [string]$connectionString +) + +begin { + Add-Type -Path "Thinktecture.IdentityServer.WindowsAzure.dll" +} + +process { + try { + $context = New-Object Thinktecture.IdentityServer.Repositories.WindowsAzure.TableStorageContext -arg $connectionString + + $claims = $context.GetUserClaims($username) + Write-Host + + foreach ($claim in $claims) { + Write-Host $claim.ClaimType + Write-Host " " $claim.Value `n + } + } + catch { + Write-Error $_.Exception.ToString() + } +} \ No newline at end of file diff --git a/Azure/Azure Scripts/List-Users.ps1 b/Azure/Azure Scripts/List-Users.ps1 new file mode 100644 index 0000000..3c6b7e8 --- /dev/null +++ b/Azure/Azure Scripts/List-Users.ps1 @@ -0,0 +1,55 @@ +<# +.SYNOPSIS + Lists all users from the IdentityServer table storage +.DESCRIPTION + Lists all users from the IdentityServer table storage +.PARAMETER connectionString + Connection string to table storage +.PARAMETER includeClaims + Also show the claims for the corresponding users +#> + +[CmdletBinding()] +param( + [Parameter( + Mandatory=$True, + ValueFromPipeline=$False, + ValueFromPipelineByPropertyName=$True + )] + [string]$connectionString, + + [Parameter( + Mandatory=$False, + ValueFromPipeline=$False, + ValueFromPipelineByPropertyName=$True + )] + [switch]$includeClaims = $false +) + +begin { + Add-Type -Path "Thinktecture.IdentityServer.WindowsAzure.dll" +} + +process { + try { + $context = New-Object Thinktecture.IdentityServer.Repositories.WindowsAzure.TableStorageContext -arg $connectionString + $users = $context.GetUsers() + + foreach ($user in $users) { + Write-Host $user + + if ($includeClaims) { + $claims = $context.GetUserClaims($user) + Write-Host + + foreach ($claim in $claims) { + Write-Host $claim.ClaimType + Write-Host " " $claim.Value `n + } + } + } + } + catch { + Write-Error $_.Exception.ToString() + } +} \ No newline at end of file diff --git a/Azure/Thinktecture.IdentityServer.WindowsAzure.sln b/Azure/Thinktecture.IdentityServer.WindowsAzure.sln new file mode 100644 index 0000000..9e63358 --- /dev/null +++ b/Azure/Thinktecture.IdentityServer.WindowsAzure.sln @@ -0,0 +1,98 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Thinktecture.IdentityServer.WindowsAzure", "..\Libraries\Thinktecture.IdentityServer.WindowsAzure\Thinktecture.IdentityServer.WindowsAzure.csproj", "{36D5F61F-F4BA-41F8-AA13-1F32DDB970A4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Thinktecture.IdentityServer.Core", "..\Libraries\Thinktecture.IdentityServer.Core\Thinktecture.IdentityServer.Core.csproj", "{38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebSite (WindowsAzure)", "WebSite_WindowsAzure\WebSite (WindowsAzure).csproj", "{B9C90A36-86C0-4974-B0B4-3524F508D847}" +EndProject +Project("{CC5FD16D-436D-48AD-A40C-5A424C6E3E79}") = "WebSite (WindowsAzure).Azure", "WebSite (WindowsAzure).Azure\WebSite (WindowsAzure).Azure.ccproj", "{FC6F1D5A-DB06-421F-95CD-EFE7490D9663}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Thinktecture.IdentityServer.Core.Repositories", "..\Libraries\Thinktecture.IdentityServer.Core.Repositories\Thinktecture.IdentityServer.Core.Repositories.csproj", "{9658F86F-3059-4731-9EB0-5F67A4FF1A8A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Thinktecture.IdentityServer.Web.Library", "..\Libraries\Thinktecture.IdentityServer.Web.Library\Thinktecture.IdentityServer.Web.Library.csproj", "{FC2D7E2A-65A2-480F-AAE8-855FD026AF85}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libraries", "Libraries", "{7EA5E092-4277-4CC8-A7BA-4AD3DD85CFE0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|Mixed Platforms = Release|Mixed Platforms + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {36D5F61F-F4BA-41F8-AA13-1F32DDB970A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {36D5F61F-F4BA-41F8-AA13-1F32DDB970A4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {36D5F61F-F4BA-41F8-AA13-1F32DDB970A4}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {36D5F61F-F4BA-41F8-AA13-1F32DDB970A4}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {36D5F61F-F4BA-41F8-AA13-1F32DDB970A4}.Debug|x86.ActiveCfg = Debug|Any CPU + {36D5F61F-F4BA-41F8-AA13-1F32DDB970A4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {36D5F61F-F4BA-41F8-AA13-1F32DDB970A4}.Release|Any CPU.Build.0 = Release|Any CPU + {36D5F61F-F4BA-41F8-AA13-1F32DDB970A4}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {36D5F61F-F4BA-41F8-AA13-1F32DDB970A4}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {36D5F61F-F4BA-41F8-AA13-1F32DDB970A4}.Release|x86.ActiveCfg = Release|Any CPU + {38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A}.Debug|x86.ActiveCfg = Debug|Any CPU + {38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A}.Release|Any CPU.Build.0 = Release|Any CPU + {38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A}.Release|x86.ActiveCfg = Release|Any CPU + {B9C90A36-86C0-4974-B0B4-3524F508D847}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B9C90A36-86C0-4974-B0B4-3524F508D847}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B9C90A36-86C0-4974-B0B4-3524F508D847}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {B9C90A36-86C0-4974-B0B4-3524F508D847}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {B9C90A36-86C0-4974-B0B4-3524F508D847}.Debug|x86.ActiveCfg = Debug|Any CPU + {B9C90A36-86C0-4974-B0B4-3524F508D847}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B9C90A36-86C0-4974-B0B4-3524F508D847}.Release|Any CPU.Build.0 = Release|Any CPU + {B9C90A36-86C0-4974-B0B4-3524F508D847}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {B9C90A36-86C0-4974-B0B4-3524F508D847}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {B9C90A36-86C0-4974-B0B4-3524F508D847}.Release|x86.ActiveCfg = Release|Any CPU + {FC6F1D5A-DB06-421F-95CD-EFE7490D9663}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FC6F1D5A-DB06-421F-95CD-EFE7490D9663}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FC6F1D5A-DB06-421F-95CD-EFE7490D9663}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {FC6F1D5A-DB06-421F-95CD-EFE7490D9663}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {FC6F1D5A-DB06-421F-95CD-EFE7490D9663}.Debug|x86.ActiveCfg = Debug|Any CPU + {FC6F1D5A-DB06-421F-95CD-EFE7490D9663}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FC6F1D5A-DB06-421F-95CD-EFE7490D9663}.Release|Any CPU.Build.0 = Release|Any CPU + {FC6F1D5A-DB06-421F-95CD-EFE7490D9663}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {FC6F1D5A-DB06-421F-95CD-EFE7490D9663}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {FC6F1D5A-DB06-421F-95CD-EFE7490D9663}.Release|x86.ActiveCfg = Release|Any CPU + {9658F86F-3059-4731-9EB0-5F67A4FF1A8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9658F86F-3059-4731-9EB0-5F67A4FF1A8A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9658F86F-3059-4731-9EB0-5F67A4FF1A8A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {9658F86F-3059-4731-9EB0-5F67A4FF1A8A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {9658F86F-3059-4731-9EB0-5F67A4FF1A8A}.Debug|x86.ActiveCfg = Debug|Any CPU + {9658F86F-3059-4731-9EB0-5F67A4FF1A8A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9658F86F-3059-4731-9EB0-5F67A4FF1A8A}.Release|Any CPU.Build.0 = Release|Any CPU + {9658F86F-3059-4731-9EB0-5F67A4FF1A8A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {9658F86F-3059-4731-9EB0-5F67A4FF1A8A}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {9658F86F-3059-4731-9EB0-5F67A4FF1A8A}.Release|x86.ActiveCfg = Release|Any CPU + {FC2D7E2A-65A2-480F-AAE8-855FD026AF85}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FC2D7E2A-65A2-480F-AAE8-855FD026AF85}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FC2D7E2A-65A2-480F-AAE8-855FD026AF85}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {FC2D7E2A-65A2-480F-AAE8-855FD026AF85}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {FC2D7E2A-65A2-480F-AAE8-855FD026AF85}.Debug|x86.ActiveCfg = Debug|Any CPU + {FC2D7E2A-65A2-480F-AAE8-855FD026AF85}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FC2D7E2A-65A2-480F-AAE8-855FD026AF85}.Release|Any CPU.Build.0 = Release|Any CPU + {FC2D7E2A-65A2-480F-AAE8-855FD026AF85}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {FC2D7E2A-65A2-480F-AAE8-855FD026AF85}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {FC2D7E2A-65A2-480F-AAE8-855FD026AF85}.Release|x86.ActiveCfg = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A} = {7EA5E092-4277-4CC8-A7BA-4AD3DD85CFE0} + {9658F86F-3059-4731-9EB0-5F67A4FF1A8A} = {7EA5E092-4277-4CC8-A7BA-4AD3DD85CFE0} + {FC2D7E2A-65A2-480F-AAE8-855FD026AF85} = {7EA5E092-4277-4CC8-A7BA-4AD3DD85CFE0} + {36D5F61F-F4BA-41F8-AA13-1F32DDB970A4} = {7EA5E092-4277-4CC8-A7BA-4AD3DD85CFE0} + EndGlobalSection +EndGlobal diff --git a/Azure/WebSite (WindowsAzure).Azure/ServiceConfiguration.GitHub.cscfg b/Azure/WebSite (WindowsAzure).Azure/ServiceConfiguration.GitHub.cscfg new file mode 100644 index 0000000..cb3a15c --- /dev/null +++ b/Azure/WebSite (WindowsAzure).Azure/ServiceConfiguration.GitHub.cscfg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Azure/WebSite (WindowsAzure).Azure/ServiceDefinition.csdef b/Azure/WebSite (WindowsAzure).Azure/ServiceDefinition.csdef new file mode 100644 index 0000000..0bb2efb --- /dev/null +++ b/Azure/WebSite (WindowsAzure).Azure/ServiceDefinition.csdef @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Azure/WebSite (WindowsAzure).Azure/WebSite (WindowsAzure).Azure.ccproj b/Azure/WebSite (WindowsAzure).Azure/WebSite (WindowsAzure).Azure.ccproj new file mode 100644 index 0000000..c0bc269 --- /dev/null +++ b/Azure/WebSite (WindowsAzure).Azure/WebSite (WindowsAzure).Azure.ccproj @@ -0,0 +1,62 @@ + + + + + Debug + AnyCPU + 1.6 + {fc6f1d5a-db06-421f-95cd-efe7490d9663} + Library + Properties + WebSite__WindowsAzure_.Azure + WebSite__WindowsAzure_.Azure + True + WebSite (WindowsAzure).Azure + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + WebSite (WindowsAzure) + {b9c90a36-86c0-4974-b0b4-3524f508d847} + True + Web + WebSite (WindowsAzure) + True + + + + + + + + + + + 10.0 + $(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Windows Azure Tools\1.6\ + + + \ No newline at end of file diff --git a/Azure/WebSite_WindowsAzure/Azure readme.txt b/Azure/WebSite_WindowsAzure/Azure readme.txt new file mode 100644 index 0000000..566752a --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Azure readme.txt @@ -0,0 +1,67 @@ +Thinktecture IdentityServer Azure Edition + +Please use the below steps to setup IdSrv. + + +Setup Instructions +__________________________________________ + +Prerequisites: + +- Create a new Hosted Service in the Azure Portal +- Upload your SSL cert (and optionally a separate signing cert) using the portal + - make note of the thumbprint + + +Configuration: + +- Open ServiceConfiguration.cloud.cscfg + - set "StorageConnectionString" to your storage account + - set "Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" to your storage account + - set "SigningCertificateDistinguishedName" to the distinguished name of the signing certificate you uploaded earlier (you can also use the SSL certificate) + - set the SSL certificate thumbprint + + - set the instance count to the number of instances you want to deploy + +- Upload package + - either via the portal ("New Production deployment") or the command line (using the SDK tools) + +- Make sure deployment was successful + + +Create admin user + +If you are using SQL Azure as your user store, you need to configure the connection string in configuration\connectionStrings.config, and the right repository +in configuration\repositories.config (see the comments in those files). Use any provider user frontend to create your users and roles. + +If you are using table storage, you can use the below powershell commands to set up users. +Prereqs for running the scripts: + - Azure SDK + - WIF + + +- make sure you can execute scripts (you may need to use Set-ExecutionPolicy to adjust your local settings) +- go to the "Azure Scripts" directory using Powershell +- run ".\Enable-DotNet4Access -console" (as admin) + +- use the Add-User script to add an initial administrator, e.g.: + + .\Add-User -username administrator -password somePassword -isAdmin -connectionString 'connection string to storage account' + + +- login with this account to make sure it works and that you have access to the administration area + +- create other users (without the -isAdmin switch). You can also use Add-Claims script to add claims to those newly created users, e.g.: + + .\Add-User -username alice -password somePassword -connectionString 'connection string to storage account' + + .\Add-Claims -username alice -connectionString 'connection string to storageaccount' + -claims http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress%alice@thinktecture.com, + http://schemas.microsoft.com/ws/2008/06/identity/claims/role%foo + + +Now IdSrv should be ready to use... + +feedback to: dominick.baier@thinktecture.com + + diff --git a/Azure/WebSite_WindowsAzure/Configuration/connectionStrings.config b/Azure/WebSite_WindowsAzure/Configuration/connectionStrings.config new file mode 100644 index 0000000..b78af10 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Configuration/connectionStrings.config @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/Azure/WebSite_WindowsAzure/Configuration/profile.config b/Azure/WebSite_WindowsAzure/Configuration/profile.config new file mode 100644 index 0000000..8dab4a5 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Configuration/profile.config @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Azure/WebSite_WindowsAzure/Configuration/repositories.config b/Azure/WebSite_WindowsAzure/Configuration/repositories.config new file mode 100644 index 0000000..2b2f347 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Configuration/repositories.config @@ -0,0 +1,10 @@ + + + + + diff --git a/Azure/WebSite_WindowsAzure/Configuration/tracing.config b/Azure/WebSite_WindowsAzure/Configuration/tracing.config new file mode 100644 index 0000000..0728db3 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Configuration/tracing.config @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Azure/WebSite_WindowsAzure/Configuration/wif.config b/Azure/WebSite_WindowsAzure/Configuration/wif.config new file mode 100644 index 0000000..f2d65cd --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Configuration/wif.config @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Azure/WebSite_WindowsAzure/Content/Site.css b/Azure/WebSite_WindowsAzure/Content/Site.css new file mode 100644 index 0000000..ce5197f --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Content/Site.css @@ -0,0 +1,175 @@ +body +{ + font-family: Calibri, Verdana, Tahoma, Arial, "Helvetica Neue", Helvetica, Sans-Serif; + color: #232323; + background-color: #fff; +} + +/* Styles for basic forms +-----------------------------------------------------------*/ + +fieldset +{ + border:1px solid #ddd; + padding:0 1.4em 1.4em 1.4em; + margin:0 0 1.5em 0; +} + +legend +{ + font-size:1.2em; + font-weight: bold; +} + +textarea +{ + min-height: 75px; +} + +.editor-label +{ + margin: 1em 0 0 0; +} + +.editor-field +{ + margin:0.5em 0 0 0; +} + +.editor-field-slim +{ + margin:0.5em 0 0 0; +} + +.editor-field input[type=text] +{ + width:400px +} + +.editor-field input[type=file] +{ + width:400px +} + +/* 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 the web frontent +-----------------------------------------------------------*/ + + +a:link +{ + color: Black; + text-decoration: none; +} + +a:visited +{ + color: Black; + text-decoration: none; +} +a:hover +{ + color: Black; + text-decoration: overline underline; +} +a:active +{ + color: Black; + text-decoration: none; +} + +.masterHeader +{ + background-color: #606060; + padding-top: 5px; + padding-bottom: 5px; +} + +.masterHeaderText +{ + padding-left: 15px; + font-weight: bold; + color: White; +} + +.menu +{ + background-color: #7285a3; + padding-top: 5px; + padding-bottom: 5px; + color: #000000; + padding-left: 15px; +} + +.menu a:link +{ + color: #FFFFFF; + text-decoration: none; +} + +.menu a:visited +{ + color: #FFFFFF; + text-decoration: none; +} +.menu a:hover +{ + color: #FFFFFF; + text-decoration: overline underline; +} +.menu a:active +{ + color: #FFFFFF; + text-decoration: none; +} + +a.bodyLink:link +{ + color: #7285a3; + text-decoration: none; +} +a.bodyLink:visited +{ + color: #7285a3; + text-decoration: none; +} + +a.bodyLink:hover +{ + color: #7285a3; + text-decoration: overline underline; +} +a.bodyLink:active +{ + color: #7285a3; + text-decoration: none; +} + diff --git a/Azure/WebSite_WindowsAzure/Content/images/logo.jpg b/Azure/WebSite_WindowsAzure/Content/images/logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7ea7b8b5db728e0488513f1b00d79428c72e15e4 GIT binary patch literal 4766 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 bKWmfUD(bFmXg1D%J*s>ni@Uo&M4$c-Sr;Ki literal 0 HcmV?d00001 diff --git a/Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png b/Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..5b5dab2ab7b1c50dea9cfe73dc5a269a92d2d4b4 GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FscKIb$B>N1x91EQ4=4yQ7#`R^ z$vje}bP0l+XkK DSH>_4 literal 0 HcmV?d00001 diff --git a/Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-bg_flat_75_ffffff_40x100.png b/Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-bg_flat_75_ffffff_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..ac8b229af950c29356abf64a6c4aa894575445f0 GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FsY*{5$B>N1x91EQ4=4yQYz+E8 zPo9&<{J;c_6SHRil>2s{Zw^OT)6@jj2u|u!(plXsM>LJD`vD!n;OXk;vd$@?2>^GI BH@yG= literal 0 HcmV?d00001 diff --git a/Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png b/Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..ad3d6346e00f246102f72f2e026ed0491988b394 GIT binary patch literal 120 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnour0hLi978O6-<~(*I$*%ybaDOn z{W;e!B}_MSUQoPXhYd^Y6RUoS1yepnPx`2Kz)7OXQG!!=-jY=F+d2OOy?#DnJ32>z UEim$g7SJdLPgg&ebxsLQ09~*s;{X5v literal 0 HcmV?d00001 diff --git a/Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-bg_glass_65_ffffff_1x400.png b/Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-bg_glass_65_ffffff_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..42ccba269b6e91bef12ad0fa18be651b5ef0ee68 GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouqzpV=978O6-=0?FV^9z|eBtf= z|7WztIJ;WT>{+tN>ySr~=F{k$>;_x^_y?afmf9pRKH0)6?eSP?3s5hEr>mdKI;Vst E0O;M1& literal 0 HcmV?d00001 diff --git a/Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-bg_glass_75_dadada_1x400.png b/Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-bg_glass_75_dadada_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..5a46b47cb16631068aee9e0bd61269fc4e95e5cd GIT binary patch literal 111 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouq|7{B978O6lPf+wIa#m9#>Unb zm^4K~wN3Zq+uP{vDV26o)#~38k_!`W=^oo1w6ixmPC4R1b Tyd6G3lNdZ*{an^LB{Ts5`idse literal 0 HcmV?d00001 diff --git a/Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png new file mode 100644 index 0000000000000000000000000000000000000000..7c9fa6c6edcfcdd3e5b77e6f547b719e6fc66e30 GIT binary patch literal 101 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 literal 0 HcmV?d00001 diff --git a/Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-icons_2e83ff_256x240.png b/Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-icons_2e83ff_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..45e8928e5284adacea3f9ec07b9b50667d2ac65f GIT binary patch literal 4369 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 literal 0 HcmV?d00001 diff --git a/Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-icons_454545_256x240.png b/Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-icons_454545_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..7ec70d11bfb2f77374dfd00ef61ba0c3647b5a0c GIT binary patch literal 4369 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 k*Kv;w;*%(i9W@fAqs5i2wiq literal 0 HcmV?d00001 diff --git a/Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-icons_888888_256x240.png b/Azure/WebSite_WindowsAzure/Content/themes/base/images/ui-icons_888888_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..5ba708c39172a69e069136bd1309c4322c61f571 GIT binary patch literal 4369 zcmd^?`8yPD_s3^phOrG}UnfiUEn8(9QW1?MNkxXVDEpFin2{xWrLx5kBC;k~GmI3`<(O3xvulR&VAkQJHZBho(m=l0{{SA7UpJl008iB z3RqU$@Wfh}nb?QCTyjovo2=)B^qQB=#XMCF_n=?1Jbh>5sptJM?}}{I zHzR=-V_TFXKM0P+&lrh3TPr)c<8EmLl3g~EY}W@od*0X6Ljv>L(67bjz58EDypsu&ddu2a@@x)`5aA^S^DxkW8rs_vKtu8N8(o0 z#Nf}*Ch4&iw866BiW!_r4*HRsHn%80xlBW<`IOcXDu%LQam7$Ge$q#1415XvN>cnS zk_qU%P}4fO0v>J{Zw9o*)JF-CPA!KcpFR1Pn(l@*bKh=1_!ZRWb?FoG5a22cVG<$5 z0|%Qj7p@n}=Hrkk`BkD99I57h7_+lQ-AZ-?fETz5E~q(= z!!d%~_yivn82d_pX#M+Y`|`-F^s6-{6}S!?_mFzr<=n>M{{PUq7g-N`hqOcY-y_m= zc#xZEqMPgqc5cu{ag@Tdli5@JlV{xH8J%TA}P<$=Qej`5Hq>_Gzk+NDFM{b*SA6Yydp9VOs1VgIYAcj@1BIt< zXz@=NF2DLCC>`r|^h-z5@eIEh>Vnjh+|-6M@nuC!oc*856_8#_6jL|rKLYu=)Ew4+ z*XiJVgHrKl?=0wjQ)aeNu2^jkUW>@Hei_S;nuA%RRe49V`VM;8SxUBxpZPe>l9ZA{YS(NU; zhnP(vSd1kYiV^KQ02>XpH6u}Xk)wrk`+SxNxC73cSAefm+V!<`c^b#A9NaTn45bEq zkRYp$U%h-|^9P*syb!eKG!QC-$;IS9MdE^@-`WRSzTp+8M9zqJCUsoPC-3Tr+qbkO z$o;ra-wGjC64H8m{(*FVitg+LQKH+96D4!FREFb|Scex)lw()`rHV$WMdUJNe3E}`->+?@(FDYcZt1#>wXwgHzQ6{p% zTY#PF?iBGE7<=u*`SFt0Lw0HX!oh85UlzQH{;k~&JH?kPJzdQX=gAmX40n@#()wBu zSllJ`lX^ZF9!&n2{1443>o2BzK(6sGDQ?n~RYk_ih&{?TJNBH*Eq`73g$F~WrJz{` zce}LL0;S^ZMb&nKyWR#(_t{VguBs~LOSLX&q*$M&haRh5HO5G%C&MvDmi{a@PM;Zq z)h;XzD;Cshu#GG)RsptBTJvnQHC(-#7@G7B`iqJMl=F%g zD7I#-8sWBC_kJC!{tU)rGSX-nt`B$M86ARc$^oIWRNOCMU!X+%PKM$X`mI~kxxaKB znBMvsb8nZ)0}JBmidn3FUeG@ZcdpwZy_4oi*b{&c?T^HaVC|`tnlo?1SjRKLNPk{gDWT+_1fio|Ic{5kU=X{rvm3 zZIZ6BO4vMQdqO`~Ef~j4Z?cQ(+Ff$wxGAlyMBqd}_S__(_xM@v-fTM;$Q^HhR@PU= zE|8KP1IM4s;)*-+Z@m25>p^N(PgHJsq+a!8`ezsTQ3Np0+k4Mtdkgu z^}tg`-YMQKuuO>dsJQkgyjabt1)2OM)|R(}hto4zSIj5V;^@PYtIwI&4#+%;&Kf)o z7)jrDgZ%f?x$UCa=&~<9SHq{ZhxKx!b+ft~!I?(H$&BMOox4KuOo95gl<%5AIg+is zd=%?6ZOr(k=S0U?!*k{1h5q3O_ZrYo5Hq#Sl|1?L+WU%}6JI(orD)*qq-300E63z? z#iM){^ff?RwehBsE3Uh)}m z74!C`a^?2x1@?-i<#cI?a=RcP4Xx$88l&B!g`Nm)Fo$Fcf!VX@0y$z7EVz~OXbALP zyfX0m-nf+4I&E=bsAjk~l_2g3i}1e%qO!KkQ@Ij*%HbGO)w=i^^5FvkHIIee`4l@J zN(eR%MpMiipJjP0Cxd|&4n@b?>6{Ue05+A0q?xd^oCpYNXpePmO#{q`vISfX)oT82 zc+d5gPn5-?9wBmlt3pk*z*hj`X#ycn4?KJY!|++>4l2@t>FhVEjPeFAhW%k5Vkm2~ zbcy`#HFb1XOYOKAcKGGN*GG%skMBnYSL@4d#@wS$CLny@9vSEwSCUSW;OHk%_<>T$ z7HwfvT&)@WQFkIm_dH-5Csjc|H+OBX6;F-rR3wuTudV;|_Oc(#-}UUgloD_-!aH>L z-NF)hJ|F-%gI?Y8Jvo7qXRG7UV5l2_yAHF93IhsP-b`cH*wlEz^Qi99$$*D?10PGQ zCkYPA5Hltd=c+>(bWIfjJP@1Obe?Gx$=qVDe)rPM+5sw)!8F3K7T{OMLFj_+>SX>F zTT-48YC1?q1IV|?OSG8?IGXAN;&q~nz?z0#i+qM9P~U@BNG1FyO9#kvk>T>G=#)_^ zj!fMlH{X;+ONmr!LsJx(j*b2&WMpJ+s&cN;7Tyu8gf>RT2kOR+DBzZr7=m-v-UheM zgj$|(0HN;F)qrlz6$FyVsy6e02`M!$<1L&Bz z+b!=_(#ur8?I=h&thJP2c+^S%)lEi*8fSaPs>Or&i1kF^p9QX&8C;)E+S__7fCh{W zSpW930L|8eV$Pa=LO*oao@VWHUr>MSl`x%iydJaFA!rB6u0`Jo5337p0UZNmSb{=o z*%W(>6W|^!F&8DUAC~&Vo2D?gE{V0S3{B;atoXLUNo9J? z0AWHot1HHimnr%xGf~-qSOO6>z*MtHe(EIN3<7@k-U&gFD+Xq}Ua*o~(!1kApC zO+-7O=jP#uq4B~*JwPs<`_;tw%;J3m{g-9xU(RBU&q^x&eSc@Ik<8NR$i0+>JBKgT zPqjfRC3Q3V=4q|BVK-yVuyUMByvXqR1a4^k&=*MqJ_v2b7I+El z1&0}s^tJ?^uXsz@oZ9j4x^n+$X$>D_nE$4#I-;EJG6wc;Jy@i$hSA&JVNoE;;UpDo l!Q;r<<-MKrq~`aIaqoP9xRgPV&EKy+z~U_0tkM({{ePlYU?u&Z`mr_kcwz5Nh&g=McJ3E!;CE1E0ryV5Ro;>nvty8 zA{omJnn+{p4952Let*87zvA;auXFF~{<`_uPA4&sV%P>LMpp1PTBEIL*yWZ2%{t3Pe;FXZ3XmxI8(D_g57_$Zil~sY6d4T}-hu9_Wqp4C0AMO{-e2$W~1A}=8 z?24)=?B)4HUDo_oXckN%okP)HFJjaB4*3_SNpKaf;yPT}KqfS{2x7`d{0xbPErH%h zh`mQJ03DaATP9aP!}a4$fY#``NI~M6&RljED)8z}hhWxrNbxIBlTxG^j z!X>$3AQQ&I%_5mRECOjaGwR-GHmde})^)t-3_~aFM1G_L#mpCNdcLqr(RKjv3R}(z zG2^yBftMYh;H3a#-slaj|5$BX9+{PTv&NtR*P-L?l21FGTG`$H9~##p%VE!uR>=NG zc&auxVl!1_lP%uX71AJvlz(wLYl?63oLd~dqjZRrU#UEWw8J6Yn-7L~T$$tjeAQiW z9$XG5Hu>rxFBnzgd6ho#^gE5pY>U$dTCRN85Y1tQQ0=Pn{?7OJ10x9Xk!>P2f(f^f zILd}5--N;Po4*25F|J3ywIv+R@rfcYNj}R-sXrH2TFAiK{jFGG(ru1p=w$wR;IXQwAX*S~oiEK{g;kZPW;YE|!QY|g^2`dMS{&1Fr zkf?!sj~m)xO3v`hh4KQRJ&&Q!=X1HNq8T_Sg2P^B&rZX{VQUNc9O(K+B_Z4hiTH7M zW7K5Y!Ec5xD~B9zFlKUWG_Rd)xTK7U#hRGhp51T++e6oS{gT^?3s~>V4?6{zchhc_ z3UBb_W2U+~guMsG-g=@#aWPSFypk)5jIUTxFiM zycGZzbxQuCTnvH*kv=E=LsRnltLbhgm$=ttS1IzU0)1t~4(XE>bHVwJpAPKOqoI-# zrdc{yo0R7Qx%~ZQl{UPa?gmxo#ZWM|vNHNxl@8NLksfn5Ek>C${w=x~pekl%gfwaLwWspL{af)?f zTOBmhTyU&3;}QeF&VLwhJ>Dezu>~P zc+$aFxKDWKj-CmD(v`}uH|ts*SefX@lyrc<%~WE6tHU#dv;y+LlA@cTgl8J!u@@u6 z@@fvJdC)1TvBa$QT@ck`rUxF**7w4Yh0!vZUsGu%Lm(cl(l#QPpmoOH3JC>FMe07G zq0kl#K+GLndyoOx8{t9g8JiLs#`pH8JWqR_ZM%J!Yr>cp>95<^#=FWQfzPm%q;5B+ z0>}ul8+l+gRaHV$$tsq5|MU;?AJ~m-XNxjW3U6JH2k`tOXAqi)yGI@^uA&dQ% zZCJIe7{qK>+p_F)Sqy-GC!x-5MgogsP6lwiUH`N^a7*LKPdO{!4L^_^;goe*e}3s( z0i~~@V#)#L*W~2F?}&N*IQ)0a4Z1$uTU)p7^Mq&IM6K6d*$vpX2+L*+$9vY0=7?$b zxdD4R`8~74HMWsx#*goNSp#(_;z`UT-GuGxoUl-){JNk1rf)aSKE!W`#m`t#v6V!u zgn>fufpkVprL(KqSkhl*Z+yRQosF)bEiV<#K8hOr>yQ1@7Xg>g3EjKwLB7)(9$3%X z$G30OD&Z2Nh{;v5!}oF4fUu0TM%&2F-6aS1+fqu3cn;K4k4-#kkB|BO?bZtcTygp+ zB|R0)0x`)UVEm;Fwx~Vt*6ZV3k5Xcj6_=(X2y*8M&NGz^?Jr>Jutu8idcHpesED^^ znM9MV2AcX%oppm45TS9yYBtteX?1liAe($}l8Mrk|YY*cFUp@Yl5_|Ih%+ z5^dz*^BpQ&l8;Le-Z+E?J1_|}dtK>`0HCSg@u z*e9pUpX4zkcJ~*%3c8N=D_*8f&2puu6>riMeA#MG3E+*kYt|0Dnl;U^u0x`IJLnY* zjELAyFaL6=ihd=uwgnc)F;a_ZKEBsA_UuVc$NS1$GwozcE)2-hGS_c!*V9@%u`#?lhbMR;p$MXpbUS7*AsAt5?3(xQtcatZ zK;B-KhX__vb(?F4Q0GloBJ>|QvdJoM?lDbgsR3iM@a;Z3?cA&4wtslYkr80ETZHkc z9*>q7Q7<0~XHK7PK#yo@cBi@smopq(-%`e-KH4Qx-~rbHu}dW58QqJ{;3Inef@=x4 zI)BgQYXff|j7xg1Qx_M8s)u`0@M0d&aKAfD6qe?B3THxh84PWrQX5xII()>h>b|f$ zpKR+*4#vbnsS3H{v&>IrrO}Xrp{O`p?Q{I%z{XPHRAc7mQ~rVVZ80t_sel;~R{!fE znoWNU9=P1`jx=A?#Ye1fm8**6`|yK3jKQSofyZy4XkM$FK?NExjqO&YVea7N(7$X$ zbR{k3PT@a2CJt_@Dead-55GO?f3gVr{BdM(wXV#1%q{YCJlyB~k-m;m1@SZyhI$5p z9ViBGQ5QzVRGUDbbtaN^E&{f(lI64ub2s){aFm!11riDV*6MFh58H{nU5}0{$^Hi; zJVW(-UYp)>>|Lx|%+y^DwKhz`tPS-85#6Rh0)ckL)U$^na{7 z@VVG(5^ui@Hf1odF537(mlR>ZBhjf%rT+ zPUdZ~CgvIZM_wUkJAw%w}x9jc8!TL)0!EfOi*AMUgP00QdmWDhdxHH4HGc<~J zIVYb|Vj$~E#d*)1>gzKQFOMaAy}BVVo}IK&7ZMB zx!9l*+ek@g>FsKVCTu!A+bt50<5zR%LvhtB47 zphLoLmz-;H4@2#)g8=!k#zLI#UMqFnH)&}~tj#&gW_Q99mQw+L7dU5Tu)W%;@9Qi9 z>QGi--TSZnR2z4)8B5wJy^vu$s+IRc0ll#|LNt!?I`me%fGty24eDN4Xl+O{(+NPj z1ygVh>zf*$Pk&fEX-3AP^1w$s1y_e7lBxzgSu6?iXt=l939t1dNMV&Hw?hI}<+!vx zKuXRw@aAWBEW)iT2xma>qG11B|GnfLf43m`S%SD z3d3^-2o=m;T`_XFO4d`JiOd4T*vl!w_t?SMNPGOr712xew$!m3PP4`3g2iVGiU!9* z&w=GY2O}!evGB%RQa5rA7s5%`YA&A$+(`a%B< z)4%^Wyf-xKA)KjJ=y>(k$Cki3nVk)wxAEYIGA3p>sG^i;f$cIw3$H&^I7dNHU=sw$d)j7 zh|(sSuhT>1EWU{wVQLz{XV1iYPIvxnNv=>Vu3kdkB_SVNJ(KJiSF;#9T-Gc6A9!kU z?a4i1-1H;R$hx=;;1@G7Jsm?|a=U>2b+qZz`aN9sgsIyFSp6r%%!9oq%tbmjY#K7P z-Gux{jUMaKw>DF`W{3tTZ|SIDqX6v)w4@1rITXmow6pv9GTr+NsJ`V>Zv++iD5MFK z@5#Rx6sk|u-Qs__;w5Q)X2-Ad+QXxzHC&)U-n+`G@G_e77|5&TV3EucN^AXqK{AmK pCn+FvZU>f5ukGw-)qi%3dglGbB=rNWkH7i=^YbXv3KMkH{{f&jC-?vW literal 0 HcmV?d00001 diff --git a/Azure/WebSite_WindowsAzure/Content/themes/base/jquery-ui.css b/Azure/WebSite_WindowsAzure/Content/themes/base/jquery-ui.css new file mode 100644 index 0000000..30f0ed1 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Content/themes/base/jquery-ui.css @@ -0,0 +1,635 @@ +/* + * 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 UI CSS Framework 1.8.7 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * + * http://docs.jquery.com/UI/Theming/API + */ + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { display: none; } +.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); } +.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } +.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } +.ui-helper-clearfix { display: inline-block; } +/* required comment for clearfix to work in Opera \*/ +* html .ui-helper-clearfix { height:1%; } +.ui-helper-clearfix { display:block; } +/* end clearfix */ +.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { cursor: default !important; } + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } + + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } +/* + * 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 UI Accordion 1.8.7 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * + * http://docs.jquery.com/UI/Accordion#theming + */ +/* IE/Win - Fix animation bug - #4615 */ +.ui-accordion { width: 100%; } +.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; } +.ui-accordion .ui-accordion-li-fix { display: inline; } +.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; } +.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; } +.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; } +.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } +.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; } +.ui-accordion .ui-accordion-content-active { display: block; }/* + * 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 UI Autocomplete 1.8.7 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * + * http://docs.jquery.com/UI/Autocomplete#theming + */ +.ui-autocomplete { position: absolute; cursor: default; } + +/* workarounds */ +* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */ + +/* + * 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 UI Menu 1.8.7 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * + * http://docs.jquery.com/UI/Menu#theming + */ +.ui-menu { + list-style:none; + padding: 2px; + margin: 0; + display:block; + float: left; +} +.ui-menu .ui-menu { + margin-top: -3px; +} +.ui-menu .ui-menu-item { + margin:0; + padding: 0; + zoom: 1; + float: left; + clear: left; + width: 100%; +} +.ui-menu .ui-menu-item a { + text-decoration:none; + display:block; + padding:.2em .4em; + line-height:1.5; + zoom:1; +} +.ui-menu .ui-menu-item a.ui-state-hover, +.ui-menu .ui-menu-item a.ui-state-active { + font-weight: normal; + margin: -1px; +} +/* + * 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 UI Button 1.8.7 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * + * http://docs.jquery.com/UI/Button#theming + */ +.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */ +.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */ +button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */ +.ui-button-icons-only { width: 3.4em; } +button.ui-button-icons-only { width: 3.7em; } + +/*button text element */ +.ui-button .ui-button-text { display: block; line-height: 1.4; } +.ui-button-text-only .ui-button-text { padding: .4em 1em; } +.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; } +.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; } +.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; } +.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; } +/* no icon support for input elements, provide padding by default */ +input.ui-button { padding: .4em 1em; } + +/*button icon element(s) */ +.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; } +.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; } +.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; } +.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } +.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } + +/*button sets*/ +.ui-buttonset { margin-right: 7px; } +.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; } + +/* workarounds */ +button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */ +/* + * 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 UI Datepicker 1.8.7 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * + * http://docs.jquery.com/UI/Datepicker#theming + */ +.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; } +.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } +.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } +.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } +.ui-datepicker .ui-datepicker-prev { left:2px; } +.ui-datepicker .ui-datepicker-next { right:2px; } +.ui-datepicker .ui-datepicker-prev-hover { left:1px; } +.ui-datepicker .ui-datepicker-next-hover { right:1px; } +.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } +.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } +.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; } +.ui-datepicker select.ui-datepicker-month-year {width: 100%;} +.ui-datepicker select.ui-datepicker-month, +.ui-datepicker select.ui-datepicker-year { width: 49%;} +.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } +.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } +.ui-datepicker td { border: 0; padding: 1px; } +.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } +.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } +.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } + +/* with multiple calendars */ +.ui-datepicker.ui-datepicker-multi { width:auto; } +.ui-datepicker-multi .ui-datepicker-group { float:left; } +.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } +.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } +.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } +.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } +.ui-datepicker-row-break { clear:both; width:100%; } + +/* RTL support */ +.ui-datepicker-rtl { direction: rtl; } +.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } +.ui-datepicker-rtl .ui-datepicker-group { float:right; } +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } + +/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ +.ui-datepicker-cover { + display: none; /*sorry for IE5*/ + display/**/: block; /*sorry for IE5*/ + position: absolute; /*must have*/ + z-index: -1; /*must have*/ + filter: mask(); /*must have*/ + top: -4px; /*must have*/ + left: -4px; /*must have*/ + width: 200px; /*must have*/ + height: 200px; /*must have*/ +}/* + * 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 UI Dialog 1.8.7 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * + * http://docs.jquery.com/UI/Dialog#theming + */ +.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; } +.ui-dialog .ui-dialog-titlebar { padding: .5em 1em .3em; position: relative; } +.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .2em 0; } +.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } +.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } +.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } +.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } +.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } +.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; } +.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; } +.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } +.ui-draggable .ui-dialog-titlebar { cursor: move; } +/* + * 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 UI Progressbar 1.8.7 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * + * http://docs.jquery.com/UI/Progressbar#theming + */ +.ui-progressbar { height:2em; text-align: left; } +.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }/* + * 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 UI Resizable 1.8.7 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * + * http://docs.jquery.com/UI/Resizable#theming + */ +.ui-resizable { position: relative;} +.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;} +.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } +.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; } +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; } +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; } +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; } +.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } +.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } +.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } +.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* + * 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 UI Selectable 1.8.7 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * + * http://docs.jquery.com/UI/Selectable#theming + */ +.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; } +/* + * 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 UI Slider 1.8.7 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * + * http://docs.jquery.com/UI/Slider#theming + */ +.ui-slider { position: relative; text-align: left; } +.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } +.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; } + +.ui-slider-horizontal { height: .8em; } +.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } +.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } +.ui-slider-horizontal .ui-slider-range-min { left: 0; } +.ui-slider-horizontal .ui-slider-range-max { right: 0; } + +.ui-slider-vertical { width: .8em; height: 100px; } +.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } +.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } +.ui-slider-vertical .ui-slider-range-min { bottom: 0; } +.ui-slider-vertical .ui-slider-range-max { top: 0; }/* + * 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 UI Tabs 1.8.7 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * + * http://docs.jquery.com/UI/Tabs#theming + */ +.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ +.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; } +.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; } +.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; } +.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ +.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; } +.ui-tabs .ui-tabs-hide { display: none !important; } +/* + * 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 UI CSS Framework 1.8.7 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * + * http://docs.jquery.com/UI/Theming/API + * + * To view and modify this theme, visit http://jqueryui.com/themeroller/ + */ + + +/* Component containers +----------------------------------*/ +.ui-widget { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1.1em/*{fsDefault}*/; } +.ui-widget .ui-widget { font-size: 1em; } +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1em; } +.ui-widget-content { border: 1px solid #aaaaaa/*{borderColorContent}*/; background: #ffffff/*{bgColorContent}*/ url(images/ui-bg_flat_75_ffffff_40x100.png)/*{bgImgUrlContent}*/ 50%/*{bgContentXPos}*/ 50%/*{bgContentYPos}*/ repeat-x/*{bgContentRepeat}*/; color: #222222/*{fcContent}*/; } +.ui-widget-content a { color: #222222/*{fcContent}*/; } +.ui-widget-header { border: 1px solid #aaaaaa/*{borderColorHeader}*/; background: #cccccc/*{bgColorHeader}*/ url(images/ui-bg_highlight-soft_75_cccccc_1x100.png)/*{bgImgUrlHeader}*/ 50%/*{bgHeaderXPos}*/ 50%/*{bgHeaderYPos}*/ repeat-x/*{bgHeaderRepeat}*/; color: #222222/*{fcHeader}*/; font-weight: bold; } +.ui-widget-header a { color: #222222/*{fcHeader}*/; } + +/* Interaction states +----------------------------------*/ +.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3/*{borderColorDefault}*/; background: #e6e6e6/*{bgColorDefault}*/ url(images/ui-bg_glass_75_e6e6e6_1x400.png)/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #555555/*{fcDefault}*/; } +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555/*{fcDefault}*/; text-decoration: none; } +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999/*{borderColorHover}*/; background: #dadada/*{bgColorHover}*/ url(images/ui-bg_glass_75_dadada_1x400.png)/*{bgImgUrlHover}*/ 50%/*{bgHoverXPos}*/ 50%/*{bgHoverYPos}*/ repeat-x/*{bgHoverRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcHover}*/; } +.ui-state-hover a, .ui-state-hover a:hover { color: #212121/*{fcHover}*/; text-decoration: none; } +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa/*{borderColorActive}*/; background: #ffffff/*{bgColorActive}*/ url(images/ui-bg_glass_65_ffffff_1x400.png)/*{bgImgUrlActive}*/ 50%/*{bgActiveXPos}*/ 50%/*{bgActiveYPos}*/ repeat-x/*{bgActiveRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcActive}*/; } +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121/*{fcActive}*/; text-decoration: none; } +.ui-widget :active { outline: none; } + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1/*{borderColorHighlight}*/; background: #fbf9ee/*{bgColorHighlight}*/ url(images/ui-bg_glass_55_fbf9ee_1x400.png)/*{bgImgUrlHighlight}*/ 50%/*{bgHighlightXPos}*/ 50%/*{bgHighlightYPos}*/ repeat-x/*{bgHighlightRepeat}*/; color: #363636/*{fcHighlight}*/; } +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636/*{fcHighlight}*/; } +.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a/*{borderColorError}*/; background: #fef1ec/*{bgColorError}*/ url(images/ui-bg_glass_95_fef1ec_1x400.png)/*{bgImgUrlError}*/ 50%/*{bgErrorXPos}*/ 50%/*{bgErrorYPos}*/ repeat-x/*{bgErrorRepeat}*/; color: #cd0a0a/*{fcError}*/; } +.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a/*{fcError}*/; } +.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a/*{fcError}*/; } +.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } +.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; } +.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; } +.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsHeader}*/; } +.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png)/*{iconsDefault}*/; } +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsHover}*/; } +.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsActive}*/; } +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png)/*{iconsHighlight}*/; } +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png)/*{iconsError}*/; } + +/* positioning */ +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-off { background-position: -96px -144px; } +.ui-icon-radio-on { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-start { background-position: -80px -160px; } +/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + + +/* Misc visuals +----------------------------------*/ + +/* Corner radius */ +.ui-corner-tl { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; } +.ui-corner-tr { -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; } +.ui-corner-bl { -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; } +.ui-corner-br { -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; } +.ui-corner-top { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; } +.ui-corner-bottom { -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; } +.ui-corner-right { -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; } +.ui-corner-left { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; } +.ui-corner-all { -moz-border-radius: 4px/*{cornerRadius}*/; -webkit-border-radius: 4px/*{cornerRadius}*/; border-radius: 4px/*{cornerRadius}*/; } + +/* Overlays */ +.ui-widget-overlay { background: #aaaaaa/*{bgColorOverlay}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlOverlay}*/ 50%/*{bgOverlayXPos}*/ 50%/*{bgOverlayYPos}*/ repeat-x/*{bgOverlayRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityOverlay}*/; } +.ui-widget-shadow { margin: -8px/*{offsetTopShadow}*/ 0 0 -8px/*{offsetLeftShadow}*/; padding: 8px/*{thicknessShadow}*/; background: #aaaaaa/*{bgColorShadow}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlShadow}*/ 50%/*{bgShadowXPos}*/ 50%/*{bgShadowYPos}*/ repeat-x/*{bgShadowRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityShadow}*/; -moz-border-radius: 8px/*{cornerRadiusShadow}*/; -webkit-border-radius: 8px/*{cornerRadiusShadow}*/; border-radius: 8px/*{cornerRadiusShadow}*/; } \ No newline at end of file diff --git a/Azure/WebSite_WindowsAzure/Global.asax b/Azure/WebSite_WindowsAzure/Global.asax new file mode 100644 index 0000000..9098e78 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Global.asax @@ -0,0 +1 @@ +<%@ Application Codebehind="Global.asax.cs" Inherits="Thinktecture.IdentityServer.Web.MvcApplication" Language="C#" %> diff --git a/Azure/WebSite_WindowsAzure/Global.asax.cs b/Azure/WebSite_WindowsAzure/Global.asax.cs new file mode 100644 index 0000000..0110321 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Global.asax.cs @@ -0,0 +1,154 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.ComponentModel.Composition.Hosting; +using System.ServiceModel.Activation; +using System.Web; +using System.Web.Mvc; +using System.Web.Routing; +using Microsoft.IdentityModel.Web; +using Thinktecture.IdentityServer.Repositories; +using Thinktecture.IdentityServer.TokenService; +using Thinktecture.IdentityServer.Web.GlobalFilter; + +namespace Thinktecture.IdentityServer.Web +{ + public class MvcApplication : HttpApplication + { + private const string ConfigurationName = "WebSite"; + + [Import] + public IConfigurationRepository ConfigurationRepository { get; set; } + + protected void Application_Start() + { + SetupCompositionContainer(); + Container.Current.SatisfyImportsOnce(this); + + FederatedAuthentication.ServiceConfigurationCreated += (s, e) => + { + if (!string.IsNullOrWhiteSpace(ConfigurationRepository.SigningCertificate.SubjectDistinguishedName)) + { + e.ServiceConfiguration.SecurityTokenHandlers.AddOrReplace( + new X509CertificateSessionSecurityTokenHandler(ConfigurationRepository.SigningCertificate.Certificate)); + } + }; + + AreaRegistration.RegisterAllAreas(); + RegisterGlobalFilters(GlobalFilters.Filters); + RegisterRoutes(RouteTable.Routes); + } + + private void SetupCompositionContainer() + { + Container.Current = new CompositionContainer(new RepositoryExportProvider()); + } + + public static void RegisterGlobalFilters(GlobalFilterCollection filters) + { + filters.Add(new HandleErrorAttribute()); + filters.Add(new GlobalViewModelFilter()); + filters.Add(new SslRedirectFilter()); + //filters.Add(new InitialConfigurationFilter()); + } + + public static void RegisterRoutes(RouteCollection routes) + { + routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); + + routes.MapRoute( + "FederationMetadata", + "FederationMetadata/2007-06/FederationMetadata.xml", + new { controller = "FederationMetadata", action = "Generate" } + ); + + routes.MapRoute( + "RelyingPartiesAdmin", + "admin/relyingparties/{action}/{id}", + new { controller = "RelyingPartiesAdmin", action = "Index", id = UrlParameter.Optional } + ); + + routes.MapRoute( + "ClientCertificatesAdmin", + "admin/clientcertificates/{action}/{userName}", + new { controller = "ClientCertificatesAdmin", action = "Index", userName = UrlParameter.Optional } + ); + + routes.MapRoute( + "DelegationAdmin", + "admin/delegation/{action}/{userName}", + new { controller = "DelegationAdmin", action = "Index", userName = UrlParameter.Optional } + ); + + routes.MapRoute( + "Default", + "{controller}/{action}/{id}", + new { controller = "Home", action = "Index", id = UrlParameter.Optional }, + new { controller = "^(?!issue).*" } + ); + + // ws-federation (mvc) + routes.MapRoute( + "wsfederation", + "issue/wsfed", + new { controller = "WSFederation", action = "issue" } + ); + + // jsnotify (mvc) + routes.MapRoute( + "jsnotify", + "issue/jsnotify", + new { controller = "JSNotify", action = "issue" } + ); + + // simple http (mvc) + routes.MapRoute( + "simplehttp", + "issue/simple", + new { controller = "SimpleHttp", action = "issue" } + ); + + // oauth wrap (mvc) + routes.MapRoute( + "wrap", + "issue/wrap", + new { controller = "Wrap", action = "issue" } + ); + + // oauth2 (mvc) + routes.MapRoute( + "oauth2", + "issue/oauth2/{action}", + new { controller = "OAuth2", action = "token" } + ); + + // ws-trust (wcf) + routes.Add(new ServiceRoute( + "issue/wstrust", + new TokenServiceHostFactory(), + typeof(TokenServiceConfiguration))); + } + + protected void Application_EndRequest(object sender, EventArgs e) + { + var context = (sender as HttpApplication).Context; + + if (context.Response.StatusCode == 401) + { + var noRedirect = context.Items["NoRedirect"]; + + if (noRedirect == null) + { + var route = new RouteValueDictionary(new Dictionary + { + { "Controller", "Account" }, + { "Action", "SignIn" }, + { "ReturnUrl", HttpUtility.UrlEncode(context.Request.RawUrl, context.Request.ContentEncoding) } + }); + + Response.RedirectToRoute(route); + } + } + } + } +} \ No newline at end of file diff --git a/Azure/WebSite_WindowsAzure/Properties/AssemblyInfo.cs b/Azure/WebSite_WindowsAzure/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..fa81676 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Properties/AssemblyInfo.cs @@ -0,0 +1,34 @@ +using System.Reflection; +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("IdentityServer2")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("IdentityServer2")] +[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("23de8f48-5bfb-481d-9bf4-8b9222efa4bd")] + +// 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")] diff --git a/Azure/WebSite_WindowsAzure/Scripts/MicrosoftAjax.debug.js b/Azure/WebSite_WindowsAzure/Scripts/MicrosoftAjax.debug.js new file mode 100644 index 0000000..a5f7942 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Scripts/MicrosoftAjax.debug.js @@ -0,0 +1,7117 @@ +// Name: MicrosoftAjax.debug.js +// Assembly: System.Web.Extensions +// Version: 4.0.0.0 +// FileVersion: 4.0.20526.0 +//----------------------------------------------------------------------- +// Copyright (C) Microsoft Corporation. All rights reserved. +//----------------------------------------------------------------------- +// MicrosoftAjax.js +// Microsoft AJAX Framework. + +Function.__typeName = 'Function'; +Function.__class = true; +Function.createCallback = function Function$createCallback(method, context) { + ///

+ /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "method", type: Function}, + {name: "context", mayBeNull: true} + ]); + if (e) throw e; + return function() { + var l = arguments.length; + if (l > 0) { + var args = []; + for (var i = 0; i < l; i++) { + args[i] = arguments[i]; + } + args[l] = context; + return method.apply(this, args); + } + return method.call(this, context); + } +} +Function.createDelegate = function Function$createDelegate(instance, method) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "instance", mayBeNull: true}, + {name: "method", type: Function} + ]); + if (e) throw e; + return function() { + return method.apply(instance, arguments); + } +} +Function.emptyFunction = Function.emptyMethod = function Function$emptyMethod() { + /// +} +Function.validateParameters = function Function$validateParameters(parameters, expectedParameters, validateParameterCount) { + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "parameters"}, + {name: "expectedParameters"}, + {name: "validateParameterCount", type: Boolean, optional: true} + ]); + if (e) throw e; + return Function._validateParams(parameters, expectedParameters, validateParameterCount); +} +Function._validateParams = function Function$_validateParams(params, expectedParams, validateParameterCount) { + var e, expectedLength = expectedParams.length; + validateParameterCount = validateParameterCount || (typeof(validateParameterCount) === "undefined"); + e = Function._validateParameterCount(params, expectedParams, validateParameterCount); + if (e) { + e.popStackFrame(); + return e; + } + for (var i = 0, l = params.length; i < l; i++) { + var expectedParam = expectedParams[Math.min(i, expectedLength - 1)], + paramName = expectedParam.name; + if (expectedParam.parameterArray) { + paramName += "[" + (i - expectedLength + 1) + "]"; + } + else if (!validateParameterCount && (i >= expectedLength)) { + break; + } + e = Function._validateParameter(params[i], expectedParam, paramName); + if (e) { + e.popStackFrame(); + return e; + } + } + return null; +} +Function._validateParameterCount = function Function$_validateParameterCount(params, expectedParams, validateParameterCount) { + var i, error, + expectedLen = expectedParams.length, + actualLen = params.length; + if (actualLen < expectedLen) { + var minParams = expectedLen; + for (i = 0; i < expectedLen; i++) { + var param = expectedParams[i]; + if (param.optional || param.parameterArray) { + minParams--; + } + } + if (actualLen < minParams) { + error = true; + } + } + else if (validateParameterCount && (actualLen > expectedLen)) { + error = true; + for (i = 0; i < expectedLen; i++) { + if (expectedParams[i].parameterArray) { + error = false; + break; + } + } + } + if (error) { + var e = Error.parameterCount(); + e.popStackFrame(); + return e; + } + return null; +} +Function._validateParameter = function Function$_validateParameter(param, expectedParam, paramName) { + var e, + expectedType = expectedParam.type, + expectedInteger = !!expectedParam.integer, + expectedDomElement = !!expectedParam.domElement, + mayBeNull = !!expectedParam.mayBeNull; + e = Function._validateParameterType(param, expectedType, expectedInteger, expectedDomElement, mayBeNull, paramName); + if (e) { + e.popStackFrame(); + return e; + } + var expectedElementType = expectedParam.elementType, + elementMayBeNull = !!expectedParam.elementMayBeNull; + if (expectedType === Array && typeof(param) !== "undefined" && param !== null && + (expectedElementType || !elementMayBeNull)) { + var expectedElementInteger = !!expectedParam.elementInteger, + expectedElementDomElement = !!expectedParam.elementDomElement; + for (var i=0; i < param.length; i++) { + var elem = param[i]; + e = Function._validateParameterType(elem, expectedElementType, + expectedElementInteger, expectedElementDomElement, elementMayBeNull, + paramName + "[" + i + "]"); + if (e) { + e.popStackFrame(); + return e; + } + } + } + return null; +} +Function._validateParameterType = function Function$_validateParameterType(param, expectedType, expectedInteger, expectedDomElement, mayBeNull, paramName) { + var e, i; + if (typeof(param) === "undefined") { + if (mayBeNull) { + return null; + } + else { + e = Error.argumentUndefined(paramName); + e.popStackFrame(); + return e; + } + } + if (param === null) { + if (mayBeNull) { + return null; + } + else { + e = Error.argumentNull(paramName); + e.popStackFrame(); + return e; + } + } + if (expectedType && expectedType.__enum) { + if (typeof(param) !== 'number') { + e = Error.argumentType(paramName, Object.getType(param), expectedType); + e.popStackFrame(); + return e; + } + if ((param % 1) === 0) { + var values = expectedType.prototype; + if (!expectedType.__flags || (param === 0)) { + for (i in values) { + if (values[i] === param) return null; + } + } + else { + var v = param; + for (i in values) { + var vali = values[i]; + if (vali === 0) continue; + if ((vali & param) === vali) { + v -= vali; + } + if (v === 0) return null; + } + } + } + e = Error.argumentOutOfRange(paramName, param, String.format(Sys.Res.enumInvalidValue, param, expectedType.getName())); + e.popStackFrame(); + return e; + } + if (expectedDomElement && (!Sys._isDomElement(param) || (param.nodeType === 3))) { + e = Error.argument(paramName, Sys.Res.argumentDomElement); + e.popStackFrame(); + return e; + } + if (expectedType && !Sys._isInstanceOfType(expectedType, param)) { + e = Error.argumentType(paramName, Object.getType(param), expectedType); + e.popStackFrame(); + return e; + } + if (expectedType === Number && expectedInteger) { + if ((param % 1) !== 0) { + e = Error.argumentOutOfRange(paramName, param, Sys.Res.argumentInteger); + e.popStackFrame(); + return e; + } + } + return null; +} + +Error.__typeName = 'Error'; +Error.__class = true; +Error.create = function Error$create(message, errorInfo) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "message", type: String, mayBeNull: true, optional: true}, + {name: "errorInfo", mayBeNull: true, optional: true} + ]); + if (e) throw e; + var err = new Error(message); + err.message = message; + if (errorInfo) { + for (var v in errorInfo) { + err[v] = errorInfo[v]; + } + } + err.popStackFrame(); + return err; +} +Error.argument = function Error$argument(paramName, message) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "paramName", type: String, mayBeNull: true, optional: true}, + {name: "message", type: String, mayBeNull: true, optional: true} + ]); + if (e) throw e; + var displayMessage = "Sys.ArgumentException: " + (message ? message : Sys.Res.argument); + if (paramName) { + displayMessage += "\n" + String.format(Sys.Res.paramName, paramName); + } + var err = Error.create(displayMessage, { name: "Sys.ArgumentException", paramName: paramName }); + err.popStackFrame(); + return err; +} +Error.argumentNull = function Error$argumentNull(paramName, message) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "paramName", type: String, mayBeNull: true, optional: true}, + {name: "message", type: String, mayBeNull: true, optional: true} + ]); + if (e) throw e; + var displayMessage = "Sys.ArgumentNullException: " + (message ? message : Sys.Res.argumentNull); + if (paramName) { + displayMessage += "\n" + String.format(Sys.Res.paramName, paramName); + } + var err = Error.create(displayMessage, { name: "Sys.ArgumentNullException", paramName: paramName }); + err.popStackFrame(); + return err; +} +Error.argumentOutOfRange = function Error$argumentOutOfRange(paramName, actualValue, message) { + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "paramName", type: String, mayBeNull: true, optional: true}, + {name: "actualValue", mayBeNull: true, optional: true}, + {name: "message", type: String, mayBeNull: true, optional: true} + ]); + if (e) throw e; + var displayMessage = "Sys.ArgumentOutOfRangeException: " + (message ? message : Sys.Res.argumentOutOfRange); + if (paramName) { + displayMessage += "\n" + String.format(Sys.Res.paramName, paramName); + } + if (typeof(actualValue) !== "undefined" && actualValue !== null) { + displayMessage += "\n" + String.format(Sys.Res.actualValue, actualValue); + } + var err = Error.create(displayMessage, { + name: "Sys.ArgumentOutOfRangeException", + paramName: paramName, + actualValue: actualValue + }); + err.popStackFrame(); + return err; +} +Error.argumentType = function Error$argumentType(paramName, actualType, expectedType, message) { + /// + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "paramName", type: String, mayBeNull: true, optional: true}, + {name: "actualType", type: Type, mayBeNull: true, optional: true}, + {name: "expectedType", type: Type, mayBeNull: true, optional: true}, + {name: "message", type: String, mayBeNull: true, optional: true} + ]); + if (e) throw e; + var displayMessage = "Sys.ArgumentTypeException: "; + if (message) { + displayMessage += message; + } + else if (actualType && expectedType) { + displayMessage += + String.format(Sys.Res.argumentTypeWithTypes, actualType.getName(), expectedType.getName()); + } + else { + displayMessage += Sys.Res.argumentType; + } + if (paramName) { + displayMessage += "\n" + String.format(Sys.Res.paramName, paramName); + } + var err = Error.create(displayMessage, { + name: "Sys.ArgumentTypeException", + paramName: paramName, + actualType: actualType, + expectedType: expectedType + }); + err.popStackFrame(); + return err; +} +Error.argumentUndefined = function Error$argumentUndefined(paramName, message) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "paramName", type: String, mayBeNull: true, optional: true}, + {name: "message", type: String, mayBeNull: true, optional: true} + ]); + if (e) throw e; + var displayMessage = "Sys.ArgumentUndefinedException: " + (message ? message : Sys.Res.argumentUndefined); + if (paramName) { + displayMessage += "\n" + String.format(Sys.Res.paramName, paramName); + } + var err = Error.create(displayMessage, { name: "Sys.ArgumentUndefinedException", paramName: paramName }); + err.popStackFrame(); + return err; +} +Error.format = function Error$format(message) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "message", type: String, mayBeNull: true, optional: true} + ]); + if (e) throw e; + var displayMessage = "Sys.FormatException: " + (message ? message : Sys.Res.format); + var err = Error.create(displayMessage, {name: 'Sys.FormatException'}); + err.popStackFrame(); + return err; +} +Error.invalidOperation = function Error$invalidOperation(message) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "message", type: String, mayBeNull: true, optional: true} + ]); + if (e) throw e; + var displayMessage = "Sys.InvalidOperationException: " + (message ? message : Sys.Res.invalidOperation); + var err = Error.create(displayMessage, {name: 'Sys.InvalidOperationException'}); + err.popStackFrame(); + return err; +} +Error.notImplemented = function Error$notImplemented(message) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "message", type: String, mayBeNull: true, optional: true} + ]); + if (e) throw e; + var displayMessage = "Sys.NotImplementedException: " + (message ? message : Sys.Res.notImplemented); + var err = Error.create(displayMessage, {name: 'Sys.NotImplementedException'}); + err.popStackFrame(); + return err; +} +Error.parameterCount = function Error$parameterCount(message) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "message", type: String, mayBeNull: true, optional: true} + ]); + if (e) throw e; + var displayMessage = "Sys.ParameterCountException: " + (message ? message : Sys.Res.parameterCount); + var err = Error.create(displayMessage, {name: 'Sys.ParameterCountException'}); + err.popStackFrame(); + return err; +} +Error.prototype.popStackFrame = function Error$popStackFrame() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (typeof(this.stack) === "undefined" || this.stack === null || + typeof(this.fileName) === "undefined" || this.fileName === null || + typeof(this.lineNumber) === "undefined" || this.lineNumber === null) { + return; + } + var stackFrames = this.stack.split("\n"); + var currentFrame = stackFrames[0]; + var pattern = this.fileName + ":" + this.lineNumber; + while(typeof(currentFrame) !== "undefined" && + currentFrame !== null && + currentFrame.indexOf(pattern) === -1) { + stackFrames.shift(); + currentFrame = stackFrames[0]; + } + var nextFrame = stackFrames[1]; + if (typeof(nextFrame) === "undefined" || nextFrame === null) { + return; + } + var nextFrameParts = nextFrame.match(/@(.*):(\d+)$/); + if (typeof(nextFrameParts) === "undefined" || nextFrameParts === null) { + return; + } + this.fileName = nextFrameParts[1]; + this.lineNumber = parseInt(nextFrameParts[2]); + stackFrames.shift(); + this.stack = stackFrames.join("\n"); +} + +Object.__typeName = 'Object'; +Object.__class = true; +Object.getType = function Object$getType(instance) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "instance"} + ]); + if (e) throw e; + var ctor = instance.constructor; + if (!ctor || (typeof(ctor) !== "function") || !ctor.__typeName || (ctor.__typeName === 'Object')) { + return Object; + } + return ctor; +} +Object.getTypeName = function Object$getTypeName(instance) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "instance"} + ]); + if (e) throw e; + return Object.getType(instance).getName(); +} + +String.__typeName = 'String'; +String.__class = true; +String.prototype.endsWith = function String$endsWith(suffix) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "suffix", type: String} + ]); + if (e) throw e; + return (this.substr(this.length - suffix.length) === suffix); +} +String.prototype.startsWith = function String$startsWith(prefix) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "prefix", type: String} + ]); + if (e) throw e; + return (this.substr(0, prefix.length) === prefix); +} +String.prototype.trim = function String$trim() { + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this.replace(/^\s+|\s+$/g, ''); +} +String.prototype.trimEnd = function String$trimEnd() { + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this.replace(/\s+$/, ''); +} +String.prototype.trimStart = function String$trimStart() { + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this.replace(/^\s+/, ''); +} +String.format = function String$format(format, args) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "format", type: String}, + {name: "args", mayBeNull: true, parameterArray: true} + ]); + if (e) throw e; + return String._toFormattedString(false, arguments); +} +String._toFormattedString = function String$_toFormattedString(useLocale, args) { + var result = ''; + var format = args[0]; + for (var i=0;;) { + var open = format.indexOf('{', i); + var close = format.indexOf('}', i); + if ((open < 0) && (close < 0)) { + result += format.slice(i); + break; + } + if ((close > 0) && ((close < open) || (open < 0))) { + if (format.charAt(close + 1) !== '}') { + throw Error.argument('format', Sys.Res.stringFormatBraceMismatch); + } + result += format.slice(i, close + 1); + i = close + 2; + continue; + } + result += format.slice(i, open); + i = open + 1; + if (format.charAt(i) === '{') { + result += '{'; + i++; + continue; + } + if (close < 0) throw Error.argument('format', Sys.Res.stringFormatBraceMismatch); + var brace = format.substring(i, close); + var colonIndex = brace.indexOf(':'); + var argNumber = parseInt((colonIndex < 0)? brace : brace.substring(0, colonIndex), 10) + 1; + if (isNaN(argNumber)) throw Error.argument('format', Sys.Res.stringFormatInvalid); + var argFormat = (colonIndex < 0)? '' : brace.substring(colonIndex + 1); + var arg = args[argNumber]; + if (typeof(arg) === "undefined" || arg === null) { + arg = ''; + } + if (arg.toFormattedString) { + result += arg.toFormattedString(argFormat); + } + else if (useLocale && arg.localeFormat) { + result += arg.localeFormat(argFormat); + } + else if (arg.format) { + result += arg.format(argFormat); + } + else + result += arg.toString(); + i = close + 1; + } + return result; +} + +Boolean.__typeName = 'Boolean'; +Boolean.__class = true; +Boolean.parse = function Boolean$parse(value) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "value", type: String} + ], false); + if (e) throw e; + var v = value.trim().toLowerCase(); + if (v === 'false') return false; + if (v === 'true') return true; + throw Error.argumentOutOfRange('value', value, Sys.Res.boolTrueOrFalse); +} + +Date.__typeName = 'Date'; +Date.__class = true; + +Number.__typeName = 'Number'; +Number.__class = true; + +RegExp.__typeName = 'RegExp'; +RegExp.__class = true; + +if (!window) this.window = this; +window.Type = Function; +Type.__fullyQualifiedIdentifierRegExp = new RegExp("^[^.0-9 \\s|,;:&*=+\\-()\\[\\]{}^%#@!~\\n\\r\\t\\f\\\\]([^ \\s|,;:&*=+\\-()\\[\\]{}^%#@!~\\n\\r\\t\\f\\\\]*[^. \\s|,;:&*=+\\-()\\[\\]{}^%#@!~\\n\\r\\t\\f\\\\])?$", "i"); +Type.__identifierRegExp = new RegExp("^[^.0-9 \\s|,;:&*=+\\-()\\[\\]{}^%#@!~\\n\\r\\t\\f\\\\][^. \\s|,;:&*=+\\-()\\[\\]{}^%#@!~\\n\\r\\t\\f\\\\]*$", "i"); +Type.prototype.callBaseMethod = function Type$callBaseMethod(instance, name, baseArguments) { + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "instance"}, + {name: "name", type: String}, + {name: "baseArguments", type: Array, mayBeNull: true, optional: true, elementMayBeNull: true} + ]); + if (e) throw e; + var baseMethod = Sys._getBaseMethod(this, instance, name); + if (!baseMethod) throw Error.invalidOperation(String.format(Sys.Res.methodNotFound, name)); + if (!baseArguments) { + return baseMethod.apply(instance); + } + else { + return baseMethod.apply(instance, baseArguments); + } +} +Type.prototype.getBaseMethod = function Type$getBaseMethod(instance, name) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "instance"}, + {name: "name", type: String} + ]); + if (e) throw e; + return Sys._getBaseMethod(this, instance, name); +} +Type.prototype.getBaseType = function Type$getBaseType() { + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return (typeof(this.__baseType) === "undefined") ? null : this.__baseType; +} +Type.prototype.getInterfaces = function Type$getInterfaces() { + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + var result = []; + var type = this; + while(type) { + var interfaces = type.__interfaces; + if (interfaces) { + for (var i = 0, l = interfaces.length; i < l; i++) { + var interfaceType = interfaces[i]; + if (!Array.contains(result, interfaceType)) { + result[result.length] = interfaceType; + } + } + } + type = type.__baseType; + } + return result; +} +Type.prototype.getName = function Type$getName() { + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return (typeof(this.__typeName) === "undefined") ? "" : this.__typeName; +} +Type.prototype.implementsInterface = function Type$implementsInterface(interfaceType) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "interfaceType", type: Type} + ]); + if (e) throw e; + this.resolveInheritance(); + var interfaceName = interfaceType.getName(); + var cache = this.__interfaceCache; + if (cache) { + var cacheEntry = cache[interfaceName]; + if (typeof(cacheEntry) !== 'undefined') return cacheEntry; + } + else { + cache = this.__interfaceCache = {}; + } + var baseType = this; + while (baseType) { + var interfaces = baseType.__interfaces; + if (interfaces) { + if (Array.indexOf(interfaces, interfaceType) !== -1) { + return cache[interfaceName] = true; + } + } + baseType = baseType.__baseType; + } + return cache[interfaceName] = false; +} +Type.prototype.inheritsFrom = function Type$inheritsFrom(parentType) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "parentType", type: Type} + ]); + if (e) throw e; + this.resolveInheritance(); + var baseType = this.__baseType; + while (baseType) { + if (baseType === parentType) { + return true; + } + baseType = baseType.__baseType; + } + return false; +} +Type.prototype.initializeBase = function Type$initializeBase(instance, baseArguments) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "instance"}, + {name: "baseArguments", type: Array, mayBeNull: true, optional: true, elementMayBeNull: true} + ]); + if (e) throw e; + if (!Sys._isInstanceOfType(this, instance)) throw Error.argumentType('instance', Object.getType(instance), this); + this.resolveInheritance(); + if (this.__baseType) { + if (!baseArguments) { + this.__baseType.apply(instance); + } + else { + this.__baseType.apply(instance, baseArguments); + } + } + return instance; +} +Type.prototype.isImplementedBy = function Type$isImplementedBy(instance) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "instance", mayBeNull: true} + ]); + if (e) throw e; + if (typeof(instance) === "undefined" || instance === null) return false; + var instanceType = Object.getType(instance); + return !!(instanceType.implementsInterface && instanceType.implementsInterface(this)); +} +Type.prototype.isInstanceOfType = function Type$isInstanceOfType(instance) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "instance", mayBeNull: true} + ]); + if (e) throw e; + return Sys._isInstanceOfType(this, instance); +} +Type.prototype.registerClass = function Type$registerClass(typeName, baseType, interfaceTypes) { + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "typeName", type: String}, + {name: "baseType", type: Type, mayBeNull: true, optional: true}, + {name: "interfaceTypes", type: Type, parameterArray: true} + ]); + if (e) throw e; + if (!Type.__fullyQualifiedIdentifierRegExp.test(typeName)) throw Error.argument('typeName', Sys.Res.notATypeName); + var parsedName; + try { + parsedName = eval(typeName); + } + catch(e) { + throw Error.argument('typeName', Sys.Res.argumentTypeName); + } + if (parsedName !== this) throw Error.argument('typeName', Sys.Res.badTypeName); + if (Sys.__registeredTypes[typeName]) throw Error.invalidOperation(String.format(Sys.Res.typeRegisteredTwice, typeName)); + if ((arguments.length > 1) && (typeof(baseType) === 'undefined')) throw Error.argumentUndefined('baseType'); + if (baseType && !baseType.__class) throw Error.argument('baseType', Sys.Res.baseNotAClass); + this.prototype.constructor = this; + this.__typeName = typeName; + this.__class = true; + if (baseType) { + this.__baseType = baseType; + this.__basePrototypePending = true; + } + Sys.__upperCaseTypes[typeName.toUpperCase()] = this; + if (interfaceTypes) { + this.__interfaces = []; + this.resolveInheritance(); + for (var i = 2, l = arguments.length; i < l; i++) { + var interfaceType = arguments[i]; + if (!interfaceType.__interface) throw Error.argument('interfaceTypes[' + (i - 2) + ']', Sys.Res.notAnInterface); + for (var methodName in interfaceType.prototype) { + var method = interfaceType.prototype[methodName]; + if (!this.prototype[methodName]) { + this.prototype[methodName] = method; + } + } + this.__interfaces.push(interfaceType); + } + } + Sys.__registeredTypes[typeName] = true; + return this; +} +Type.prototype.registerInterface = function Type$registerInterface(typeName) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "typeName", type: String} + ]); + if (e) throw e; + if (!Type.__fullyQualifiedIdentifierRegExp.test(typeName)) throw Error.argument('typeName', Sys.Res.notATypeName); + var parsedName; + try { + parsedName = eval(typeName); + } + catch(e) { + throw Error.argument('typeName', Sys.Res.argumentTypeName); + } + if (parsedName !== this) throw Error.argument('typeName', Sys.Res.badTypeName); + if (Sys.__registeredTypes[typeName]) throw Error.invalidOperation(String.format(Sys.Res.typeRegisteredTwice, typeName)); + Sys.__upperCaseTypes[typeName.toUpperCase()] = this; + this.prototype.constructor = this; + this.__typeName = typeName; + this.__interface = true; + Sys.__registeredTypes[typeName] = true; + return this; +} +Type.prototype.resolveInheritance = function Type$resolveInheritance() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (this.__basePrototypePending) { + var baseType = this.__baseType; + baseType.resolveInheritance(); + for (var memberName in baseType.prototype) { + var memberValue = baseType.prototype[memberName]; + if (!this.prototype[memberName]) { + this.prototype[memberName] = memberValue; + } + } + delete this.__basePrototypePending; + } +} +Type.getRootNamespaces = function Type$getRootNamespaces() { + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return Array.clone(Sys.__rootNamespaces); +} +Type.isClass = function Type$isClass(type) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "type", mayBeNull: true} + ]); + if (e) throw e; + if ((typeof(type) === 'undefined') || (type === null)) return false; + return !!type.__class; +} +Type.isInterface = function Type$isInterface(type) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "type", mayBeNull: true} + ]); + if (e) throw e; + if ((typeof(type) === 'undefined') || (type === null)) return false; + return !!type.__interface; +} +Type.isNamespace = function Type$isNamespace(object) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "object", mayBeNull: true} + ]); + if (e) throw e; + if ((typeof(object) === 'undefined') || (object === null)) return false; + return !!object.__namespace; +} +Type.parse = function Type$parse(typeName, ns) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "typeName", type: String, mayBeNull: true}, + {name: "ns", mayBeNull: true, optional: true} + ]); + if (e) throw e; + var fn; + if (ns) { + fn = Sys.__upperCaseTypes[ns.getName().toUpperCase() + '.' + typeName.toUpperCase()]; + return fn || null; + } + if (!typeName) return null; + if (!Type.__htClasses) { + Type.__htClasses = {}; + } + fn = Type.__htClasses[typeName]; + if (!fn) { + fn = eval(typeName); + if (typeof(fn) !== 'function') throw Error.argument('typeName', Sys.Res.notATypeName); + Type.__htClasses[typeName] = fn; + } + return fn; +} +Type.registerNamespace = function Type$registerNamespace(namespacePath) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "namespacePath", type: String} + ]); + if (e) throw e; + Type._registerNamespace(namespacePath); +} +Type._registerNamespace = function Type$_registerNamespace(namespacePath) { + if (!Type.__fullyQualifiedIdentifierRegExp.test(namespacePath)) throw Error.argument('namespacePath', Sys.Res.invalidNameSpace); + var rootObject = window; + var namespaceParts = namespacePath.split('.'); + for (var i = 0; i < namespaceParts.length; i++) { + var currentPart = namespaceParts[i]; + var ns = rootObject[currentPart]; + var nsType = typeof(ns); + if ((nsType !== "undefined") && (ns !== null)) { + if (nsType === "function") { + throw Error.invalidOperation(String.format(Sys.Res.namespaceContainsClass, namespaceParts.splice(0, i + 1).join('.'))); + } + if ((typeof(ns) !== "object") || (ns instanceof Array)) { + throw Error.invalidOperation(String.format(Sys.Res.namespaceContainsNonObject, namespaceParts.splice(0, i + 1).join('.'))); + } + } + if (!ns) { + ns = rootObject[currentPart] = {}; + } + if (!ns.__namespace) { + if ((i === 0) && (namespacePath !== "Sys")) { + Sys.__rootNamespaces[Sys.__rootNamespaces.length] = ns; + } + ns.__namespace = true; + ns.__typeName = namespaceParts.slice(0, i + 1).join('.'); + var parsedName; + try { + parsedName = eval(ns.__typeName); + } + catch(e) { + parsedName = null; + } + if (parsedName !== ns) { + delete rootObject[currentPart]; + throw Error.argument('namespacePath', Sys.Res.invalidNameSpace); + } + ns.getName = function ns$getName() {return this.__typeName;} + } + rootObject = ns; + } +} +Type._checkDependency = function Type$_checkDependency(dependency, featureName) { + var scripts = Type._registerScript._scripts, isDependent = (scripts ? (!!scripts[dependency]) : false); + if ((typeof(featureName) !== 'undefined') && !isDependent) { + throw Error.invalidOperation(String.format(Sys.Res.requiredScriptReferenceNotIncluded, + featureName, dependency)); + } + return isDependent; +} +Type._registerScript = function Type$_registerScript(scriptName, dependencies) { + var scripts = Type._registerScript._scripts; + if (!scripts) { + Type._registerScript._scripts = scripts = {}; + } + if (scripts[scriptName]) { + throw Error.invalidOperation(String.format(Sys.Res.scriptAlreadyLoaded, scriptName)); + } + scripts[scriptName] = true; + if (dependencies) { + for (var i = 0, l = dependencies.length; i < l; i++) { + var dependency = dependencies[i]; + if (!Type._checkDependency(dependency)) { + throw Error.invalidOperation(String.format(Sys.Res.scriptDependencyNotFound, scriptName, dependency)); + } + } + } +} +Type._registerNamespace("Sys"); +Sys.__upperCaseTypes = {}; +Sys.__rootNamespaces = [Sys]; +Sys.__registeredTypes = {}; +Sys._isInstanceOfType = function Sys$_isInstanceOfType(type, instance) { + if (typeof(instance) === "undefined" || instance === null) return false; + if (instance instanceof type) return true; + var instanceType = Object.getType(instance); + return !!(instanceType === type) || + (instanceType.inheritsFrom && instanceType.inheritsFrom(type)) || + (instanceType.implementsInterface && instanceType.implementsInterface(type)); +} +Sys._getBaseMethod = function Sys$_getBaseMethod(type, instance, name) { + if (!Sys._isInstanceOfType(type, instance)) throw Error.argumentType('instance', Object.getType(instance), type); + var baseType = type.getBaseType(); + if (baseType) { + var baseMethod = baseType.prototype[name]; + return (baseMethod instanceof Function) ? baseMethod : null; + } + return null; +} +Sys._isDomElement = function Sys$_isDomElement(obj) { + var val = false; + if (typeof (obj.nodeType) !== 'number') { + var doc = obj.ownerDocument || obj.document || obj; + if (doc != obj) { + var w = doc.defaultView || doc.parentWindow; + val = (w != obj); + } + else { + val = (typeof (doc.body) === 'undefined'); + } + } + return !val; +} + +Array.__typeName = 'Array'; +Array.__class = true; +Array.add = Array.enqueue = function Array$enqueue(array, item) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "array", type: Array, elementMayBeNull: true}, + {name: "item", mayBeNull: true} + ]); + if (e) throw e; + array[array.length] = item; +} +Array.addRange = function Array$addRange(array, items) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "array", type: Array, elementMayBeNull: true}, + {name: "items", type: Array, elementMayBeNull: true} + ]); + if (e) throw e; + array.push.apply(array, items); +} +Array.clear = function Array$clear(array) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "array", type: Array, elementMayBeNull: true} + ]); + if (e) throw e; + array.length = 0; +} +Array.clone = function Array$clone(array) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "array", type: Array, elementMayBeNull: true} + ]); + if (e) throw e; + if (array.length === 1) { + return [array[0]]; + } + else { + return Array.apply(null, array); + } +} +Array.contains = function Array$contains(array, item) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "array", type: Array, elementMayBeNull: true}, + {name: "item", mayBeNull: true} + ]); + if (e) throw e; + return (Sys._indexOf(array, item) >= 0); +} +Array.dequeue = function Array$dequeue(array) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "array", type: Array, elementMayBeNull: true} + ]); + if (e) throw e; + return array.shift(); +} +Array.forEach = function Array$forEach(array, method, instance) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "array", type: Array, elementMayBeNull: true}, + {name: "method", type: Function}, + {name: "instance", mayBeNull: true, optional: true} + ]); + if (e) throw e; + for (var i = 0, l = array.length; i < l; i++) { + var elt = array[i]; + if (typeof(elt) !== 'undefined') method.call(instance, elt, i, array); + } +} +Array.indexOf = function Array$indexOf(array, item, start) { + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "array", type: Array, elementMayBeNull: true}, + {name: "item", mayBeNull: true, optional: true}, + {name: "start", mayBeNull: true, optional: true} + ]); + if (e) throw e; + return Sys._indexOf(array, item, start); +} +Array.insert = function Array$insert(array, index, item) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "array", type: Array, elementMayBeNull: true}, + {name: "index", mayBeNull: true}, + {name: "item", mayBeNull: true} + ]); + if (e) throw e; + array.splice(index, 0, item); +} +Array.parse = function Array$parse(value) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "value", type: String, mayBeNull: true} + ]); + if (e) throw e; + if (!value) return []; + var v = eval(value); + if (!Array.isInstanceOfType(v)) throw Error.argument('value', Sys.Res.arrayParseBadFormat); + return v; +} +Array.remove = function Array$remove(array, item) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "array", type: Array, elementMayBeNull: true}, + {name: "item", mayBeNull: true} + ]); + if (e) throw e; + var index = Sys._indexOf(array, item); + if (index >= 0) { + array.splice(index, 1); + } + return (index >= 0); +} +Array.removeAt = function Array$removeAt(array, index) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "array", type: Array, elementMayBeNull: true}, + {name: "index", mayBeNull: true} + ]); + if (e) throw e; + array.splice(index, 1); +} +Sys._indexOf = function Sys$_indexOf(array, item, start) { + if (typeof(item) === "undefined") return -1; + var length = array.length; + if (length !== 0) { + start = start - 0; + if (isNaN(start)) { + start = 0; + } + else { + if (isFinite(start)) { + start = start - (start % 1); + } + if (start < 0) { + start = Math.max(0, length + start); + } + } + for (var i = start; i < length; i++) { + if ((typeof(array[i]) !== "undefined") && (array[i] === item)) { + return i; + } + } + } + return -1; +} +Type._registerScript._scripts = { + "MicrosoftAjaxCore.js": true, + "MicrosoftAjaxGlobalization.js": true, + "MicrosoftAjaxSerialization.js": true, + "MicrosoftAjaxComponentModel.js": true, + "MicrosoftAjaxHistory.js": true, + "MicrosoftAjaxNetwork.js" : true, + "MicrosoftAjaxWebServices.js": true }; + +Sys.IDisposable = function Sys$IDisposable() { + throw Error.notImplemented(); +} + function Sys$IDisposable$dispose() { + throw Error.notImplemented(); + } +Sys.IDisposable.prototype = { + dispose: Sys$IDisposable$dispose +} +Sys.IDisposable.registerInterface('Sys.IDisposable'); + +Sys.StringBuilder = function Sys$StringBuilder(initialText) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "initialText", mayBeNull: true, optional: true} + ]); + if (e) throw e; + this._parts = (typeof(initialText) !== 'undefined' && initialText !== null && initialText !== '') ? + [initialText.toString()] : []; + this._value = {}; + this._len = 0; +} + function Sys$StringBuilder$append(text) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "text", mayBeNull: true} + ]); + if (e) throw e; + this._parts[this._parts.length] = text; + } + function Sys$StringBuilder$appendLine(text) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "text", mayBeNull: true, optional: true} + ]); + if (e) throw e; + this._parts[this._parts.length] = + ((typeof(text) === 'undefined') || (text === null) || (text === '')) ? + '\r\n' : text + '\r\n'; + } + function Sys$StringBuilder$clear() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + this._parts = []; + this._value = {}; + this._len = 0; + } + function Sys$StringBuilder$isEmpty() { + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (this._parts.length === 0) return true; + return this.toString() === ''; + } + function Sys$StringBuilder$toString(separator) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "separator", type: String, mayBeNull: true, optional: true} + ]); + if (e) throw e; + separator = separator || ''; + var parts = this._parts; + if (this._len !== parts.length) { + this._value = {}; + this._len = parts.length; + } + var val = this._value; + if (typeof(val[separator]) === 'undefined') { + if (separator !== '') { + for (var i = 0; i < parts.length;) { + if ((typeof(parts[i]) === 'undefined') || (parts[i] === '') || (parts[i] === null)) { + parts.splice(i, 1); + } + else { + i++; + } + } + } + val[separator] = this._parts.join(separator); + } + return val[separator]; + } +Sys.StringBuilder.prototype = { + append: Sys$StringBuilder$append, + appendLine: Sys$StringBuilder$appendLine, + clear: Sys$StringBuilder$clear, + isEmpty: Sys$StringBuilder$isEmpty, + toString: Sys$StringBuilder$toString +} +Sys.StringBuilder.registerClass('Sys.StringBuilder'); + +Sys.Browser = {}; +Sys.Browser.InternetExplorer = {}; +Sys.Browser.Firefox = {}; +Sys.Browser.Safari = {}; +Sys.Browser.Opera = {}; +Sys.Browser.agent = null; +Sys.Browser.hasDebuggerStatement = false; +Sys.Browser.name = navigator.appName; +Sys.Browser.version = parseFloat(navigator.appVersion); +Sys.Browser.documentMode = 0; +if (navigator.userAgent.indexOf(' MSIE ') > -1) { + Sys.Browser.agent = Sys.Browser.InternetExplorer; + Sys.Browser.version = parseFloat(navigator.userAgent.match(/MSIE (\d+\.\d+)/)[1]); + if (Sys.Browser.version >= 8) { + if (document.documentMode >= 7) { + Sys.Browser.documentMode = document.documentMode; + } + } + Sys.Browser.hasDebuggerStatement = true; +} +else if (navigator.userAgent.indexOf(' Firefox/') > -1) { + Sys.Browser.agent = Sys.Browser.Firefox; + Sys.Browser.version = parseFloat(navigator.userAgent.match(/ Firefox\/(\d+\.\d+)/)[1]); + Sys.Browser.name = 'Firefox'; + Sys.Browser.hasDebuggerStatement = true; +} +else if (navigator.userAgent.indexOf(' AppleWebKit/') > -1) { + Sys.Browser.agent = Sys.Browser.Safari; + Sys.Browser.version = parseFloat(navigator.userAgent.match(/ AppleWebKit\/(\d+(\.\d+)?)/)[1]); + Sys.Browser.name = 'Safari'; +} +else if (navigator.userAgent.indexOf('Opera/') > -1) { + Sys.Browser.agent = Sys.Browser.Opera; +} + +Sys.EventArgs = function Sys$EventArgs() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); +} +Sys.EventArgs.registerClass('Sys.EventArgs'); +Sys.EventArgs.Empty = new Sys.EventArgs(); + +Sys.CancelEventArgs = function Sys$CancelEventArgs() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + Sys.CancelEventArgs.initializeBase(this); + this._cancel = false; +} + function Sys$CancelEventArgs$get_cancel() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._cancel; + } + function Sys$CancelEventArgs$set_cancel(value) { + var e = Function._validateParams(arguments, [{name: "value", type: Boolean}]); + if (e) throw e; + this._cancel = value; + } +Sys.CancelEventArgs.prototype = { + get_cancel: Sys$CancelEventArgs$get_cancel, + set_cancel: Sys$CancelEventArgs$set_cancel +} +Sys.CancelEventArgs.registerClass('Sys.CancelEventArgs', Sys.EventArgs); +Type.registerNamespace('Sys.UI'); + +Sys._Debug = function Sys$_Debug() { + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); +} + function Sys$_Debug$_appendConsole(text) { + if ((typeof(Debug) !== 'undefined') && Debug.writeln) { + Debug.writeln(text); + } + if (window.console && window.console.log) { + window.console.log(text); + } + if (window.opera) { + window.opera.postError(text); + } + if (window.debugService) { + window.debugService.trace(text); + } + } + function Sys$_Debug$_appendTrace(text) { + var traceElement = document.getElementById('TraceConsole'); + if (traceElement && (traceElement.tagName.toUpperCase() === 'TEXTAREA')) { + traceElement.value += text + '\n'; + } + } + function Sys$_Debug$assert(condition, message, displayCaller) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "condition", type: Boolean}, + {name: "message", type: String, mayBeNull: true, optional: true}, + {name: "displayCaller", type: Boolean, optional: true} + ]); + if (e) throw e; + if (!condition) { + message = (displayCaller && this.assert.caller) ? + String.format(Sys.Res.assertFailedCaller, message, this.assert.caller) : + String.format(Sys.Res.assertFailed, message); + if (confirm(String.format(Sys.Res.breakIntoDebugger, message))) { + this.fail(message); + } + } + } + function Sys$_Debug$clearTrace() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + var traceElement = document.getElementById('TraceConsole'); + if (traceElement && (traceElement.tagName.toUpperCase() === 'TEXTAREA')) { + traceElement.value = ''; + } + } + function Sys$_Debug$fail(message) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "message", type: String, mayBeNull: true} + ]); + if (e) throw e; + this._appendConsole(message); + if (Sys.Browser.hasDebuggerStatement) { + eval('debugger'); + } + } + function Sys$_Debug$trace(text) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "text"} + ]); + if (e) throw e; + this._appendConsole(text); + this._appendTrace(text); + } + function Sys$_Debug$traceDump(object, name) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "object", mayBeNull: true}, + {name: "name", type: String, mayBeNull: true, optional: true} + ]); + if (e) throw e; + var text = this._traceDump(object, name, true); + } + function Sys$_Debug$_traceDump(object, name, recursive, indentationPadding, loopArray) { + name = name? name : 'traceDump'; + indentationPadding = indentationPadding? indentationPadding : ''; + if (object === null) { + this.trace(indentationPadding + name + ': null'); + return; + } + switch(typeof(object)) { + case 'undefined': + this.trace(indentationPadding + name + ': Undefined'); + break; + case 'number': case 'string': case 'boolean': + this.trace(indentationPadding + name + ': ' + object); + break; + default: + if (Date.isInstanceOfType(object) || RegExp.isInstanceOfType(object)) { + this.trace(indentationPadding + name + ': ' + object.toString()); + break; + } + if (!loopArray) { + loopArray = []; + } + else if (Array.contains(loopArray, object)) { + this.trace(indentationPadding + name + ': ...'); + return; + } + Array.add(loopArray, object); + if ((object == window) || (object === document) || + (window.HTMLElement && (object instanceof HTMLElement)) || + (typeof(object.nodeName) === 'string')) { + var tag = object.tagName? object.tagName : 'DomElement'; + if (object.id) { + tag += ' - ' + object.id; + } + this.trace(indentationPadding + name + ' {' + tag + '}'); + } + else { + var typeName = Object.getTypeName(object); + this.trace(indentationPadding + name + (typeof(typeName) === 'string' ? ' {' + typeName + '}' : '')); + if ((indentationPadding === '') || recursive) { + indentationPadding += " "; + var i, length, properties, p, v; + if (Array.isInstanceOfType(object)) { + length = object.length; + for (i = 0; i < length; i++) { + this._traceDump(object[i], '[' + i + ']', recursive, indentationPadding, loopArray); + } + } + else { + for (p in object) { + v = object[p]; + if (!Function.isInstanceOfType(v)) { + this._traceDump(v, p, recursive, indentationPadding, loopArray); + } + } + } + } + } + Array.remove(loopArray, object); + } + } +Sys._Debug.prototype = { + _appendConsole: Sys$_Debug$_appendConsole, + _appendTrace: Sys$_Debug$_appendTrace, + assert: Sys$_Debug$assert, + clearTrace: Sys$_Debug$clearTrace, + fail: Sys$_Debug$fail, + trace: Sys$_Debug$trace, + traceDump: Sys$_Debug$traceDump, + _traceDump: Sys$_Debug$_traceDump +} +Sys._Debug.registerClass('Sys._Debug'); +Sys.Debug = new Sys._Debug(); + Sys.Debug.isDebug = true; + +function Sys$Enum$parse(value, ignoreCase) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "value", type: String}, + {name: "ignoreCase", type: Boolean, optional: true} + ]); + if (e) throw e; + var values, parsed, val; + if (ignoreCase) { + values = this.__lowerCaseValues; + if (!values) { + this.__lowerCaseValues = values = {}; + var prototype = this.prototype; + for (var name in prototype) { + values[name.toLowerCase()] = prototype[name]; + } + } + } + else { + values = this.prototype; + } + if (!this.__flags) { + val = (ignoreCase ? value.toLowerCase() : value); + parsed = values[val.trim()]; + if (typeof(parsed) !== 'number') throw Error.argument('value', String.format(Sys.Res.enumInvalidValue, value, this.__typeName)); + return parsed; + } + else { + var parts = (ignoreCase ? value.toLowerCase() : value).split(','); + var v = 0; + for (var i = parts.length - 1; i >= 0; i--) { + var part = parts[i].trim(); + parsed = values[part]; + if (typeof(parsed) !== 'number') throw Error.argument('value', String.format(Sys.Res.enumInvalidValue, value.split(',')[i].trim(), this.__typeName)); + v |= parsed; + } + return v; + } +} +function Sys$Enum$toString(value) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "value", mayBeNull: true, optional: true} + ]); + if (e) throw e; + if ((typeof(value) === 'undefined') || (value === null)) return this.__string; + if ((typeof(value) != 'number') || ((value % 1) !== 0)) throw Error.argumentType('value', Object.getType(value), this); + var values = this.prototype; + var i; + if (!this.__flags || (value === 0)) { + for (i in values) { + if (values[i] === value) { + return i; + } + } + } + else { + var sorted = this.__sortedValues; + if (!sorted) { + sorted = []; + for (i in values) { + sorted[sorted.length] = {key: i, value: values[i]}; + } + sorted.sort(function(a, b) { + return a.value - b.value; + }); + this.__sortedValues = sorted; + } + var parts = []; + var v = value; + for (i = sorted.length - 1; i >= 0; i--) { + var kvp = sorted[i]; + var vali = kvp.value; + if (vali === 0) continue; + if ((vali & value) === vali) { + parts[parts.length] = kvp.key; + v -= vali; + if (v === 0) break; + } + } + if (parts.length && v === 0) return parts.reverse().join(', '); + } + throw Error.argumentOutOfRange('value', value, String.format(Sys.Res.enumInvalidValue, value, this.__typeName)); +} +Type.prototype.registerEnum = function Type$registerEnum(name, flags) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "name", type: String}, + {name: "flags", type: Boolean, optional: true} + ]); + if (e) throw e; + if (!Type.__fullyQualifiedIdentifierRegExp.test(name)) throw Error.argument('name', Sys.Res.notATypeName); + var parsedName; + try { + parsedName = eval(name); + } + catch(e) { + throw Error.argument('name', Sys.Res.argumentTypeName); + } + if (parsedName !== this) throw Error.argument('name', Sys.Res.badTypeName); + if (Sys.__registeredTypes[name]) throw Error.invalidOperation(String.format(Sys.Res.typeRegisteredTwice, name)); + for (var j in this.prototype) { + var val = this.prototype[j]; + if (!Type.__identifierRegExp.test(j)) throw Error.invalidOperation(String.format(Sys.Res.enumInvalidValueName, j)); + if (typeof(val) !== 'number' || (val % 1) !== 0) throw Error.invalidOperation(Sys.Res.enumValueNotInteger); + if (typeof(this[j]) !== 'undefined') throw Error.invalidOperation(String.format(Sys.Res.enumReservedName, j)); + } + Sys.__upperCaseTypes[name.toUpperCase()] = this; + for (var i in this.prototype) { + this[i] = this.prototype[i]; + } + this.__typeName = name; + this.parse = Sys$Enum$parse; + this.__string = this.toString(); + this.toString = Sys$Enum$toString; + this.__flags = flags; + this.__enum = true; + Sys.__registeredTypes[name] = true; +} +Type.isEnum = function Type$isEnum(type) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "type", mayBeNull: true} + ]); + if (e) throw e; + if ((typeof(type) === 'undefined') || (type === null)) return false; + return !!type.__enum; +} +Type.isFlags = function Type$isFlags(type) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "type", mayBeNull: true} + ]); + if (e) throw e; + if ((typeof(type) === 'undefined') || (type === null)) return false; + return !!type.__flags; +} +Sys.CollectionChange = function Sys$CollectionChange(action, newItems, newStartingIndex, oldItems, oldStartingIndex) { + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "action", type: Sys.NotifyCollectionChangedAction}, + {name: "newItems", mayBeNull: true, optional: true}, + {name: "newStartingIndex", type: Number, mayBeNull: true, integer: true, optional: true}, + {name: "oldItems", mayBeNull: true, optional: true}, + {name: "oldStartingIndex", type: Number, mayBeNull: true, integer: true, optional: true} + ]); + if (e) throw e; + this.action = action; + if (newItems) { + if (!(newItems instanceof Array)) { + newItems = [newItems]; + } + } + this.newItems = newItems || null; + if (typeof newStartingIndex !== "number") { + newStartingIndex = -1; + } + this.newStartingIndex = newStartingIndex; + if (oldItems) { + if (!(oldItems instanceof Array)) { + oldItems = [oldItems]; + } + } + this.oldItems = oldItems || null; + if (typeof oldStartingIndex !== "number") { + oldStartingIndex = -1; + } + this.oldStartingIndex = oldStartingIndex; +} +Sys.CollectionChange.registerClass("Sys.CollectionChange"); +Sys.NotifyCollectionChangedAction = function Sys$NotifyCollectionChangedAction() { + /// + /// + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); +} +Sys.NotifyCollectionChangedAction.prototype = { + add: 0, + remove: 1, + reset: 2 +} +Sys.NotifyCollectionChangedAction.registerEnum('Sys.NotifyCollectionChangedAction'); +Sys.NotifyCollectionChangedEventArgs = function Sys$NotifyCollectionChangedEventArgs(changes) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "changes", type: Array, elementType: Sys.CollectionChange} + ]); + if (e) throw e; + this._changes = changes; + Sys.NotifyCollectionChangedEventArgs.initializeBase(this); +} + function Sys$NotifyCollectionChangedEventArgs$get_changes() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._changes || []; + } +Sys.NotifyCollectionChangedEventArgs.prototype = { + get_changes: Sys$NotifyCollectionChangedEventArgs$get_changes +} +Sys.NotifyCollectionChangedEventArgs.registerClass("Sys.NotifyCollectionChangedEventArgs", Sys.EventArgs); +Sys.Observer = function Sys$Observer() { + throw Error.invalidOperation(); +} +Sys.Observer.registerClass("Sys.Observer"); +Sys.Observer.makeObservable = function Sys$Observer$makeObservable(target) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target"} + ]); + if (e) throw e; + var isArray = target instanceof Array, + o = Sys.Observer; + Sys.Observer._ensureObservable(target); + if (target.setValue === o._observeMethods.setValue) return target; + o._addMethods(target, o._observeMethods); + if (isArray) { + o._addMethods(target, o._arrayMethods); + } + return target; +} +Sys.Observer._ensureObservable = function Sys$Observer$_ensureObservable(target) { + var type = typeof target; + if ((type === "string") || (type === "number") || (type === "boolean") || (type === "date")) { + throw Error.invalidOperation(String.format(Sys.Res.notObservable, type)); + } +} +Sys.Observer._addMethods = function Sys$Observer$_addMethods(target, methods) { + for (var m in methods) { + if (target[m] && (target[m] !== methods[m])) { + throw Error.invalidOperation(String.format(Sys.Res.observableConflict, m)); + } + target[m] = methods[m]; + } +} +Sys.Observer._addEventHandler = function Sys$Observer$_addEventHandler(target, eventName, handler) { + Sys.Observer._getContext(target, true).events._addHandler(eventName, handler); +} +Sys.Observer.addEventHandler = function Sys$Observer$addEventHandler(target, eventName, handler) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target"}, + {name: "eventName", type: String}, + {name: "handler", type: Function} + ]); + if (e) throw e; + Sys.Observer._ensureObservable(target); + Sys.Observer._addEventHandler(target, eventName, handler); +} +Sys.Observer._removeEventHandler = function Sys$Observer$_removeEventHandler(target, eventName, handler) { + Sys.Observer._getContext(target, true).events._removeHandler(eventName, handler); +} +Sys.Observer.removeEventHandler = function Sys$Observer$removeEventHandler(target, eventName, handler) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target"}, + {name: "eventName", type: String}, + {name: "handler", type: Function} + ]); + if (e) throw e; + Sys.Observer._ensureObservable(target); + Sys.Observer._removeEventHandler(target, eventName, handler); +} +Sys.Observer.raiseEvent = function Sys$Observer$raiseEvent(target, eventName, eventArgs) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target"}, + {name: "eventName", type: String}, + {name: "eventArgs", type: Sys.EventArgs} + ]); + if (e) throw e; + Sys.Observer._ensureObservable(target); + var ctx = Sys.Observer._getContext(target); + if (!ctx) return; + var handler = ctx.events.getHandler(eventName); + if (handler) { + handler(target, eventArgs); + } +} +Sys.Observer.addPropertyChanged = function Sys$Observer$addPropertyChanged(target, handler) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target"}, + {name: "handler", type: Function} + ]); + if (e) throw e; + Sys.Observer._ensureObservable(target); + Sys.Observer._addEventHandler(target, "propertyChanged", handler); +} +Sys.Observer.removePropertyChanged = function Sys$Observer$removePropertyChanged(target, handler) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target"}, + {name: "handler", type: Function} + ]); + if (e) throw e; + Sys.Observer._ensureObservable(target); + Sys.Observer._removeEventHandler(target, "propertyChanged", handler); +} +Sys.Observer.beginUpdate = function Sys$Observer$beginUpdate(target) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target"} + ]); + if (e) throw e; + Sys.Observer._ensureObservable(target); + Sys.Observer._getContext(target, true).updating = true; +} +Sys.Observer.endUpdate = function Sys$Observer$endUpdate(target) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target"} + ]); + if (e) throw e; + Sys.Observer._ensureObservable(target); + var ctx = Sys.Observer._getContext(target); + if (!ctx || !ctx.updating) return; + ctx.updating = false; + var dirty = ctx.dirty; + ctx.dirty = false; + if (dirty) { + if (target instanceof Array) { + var changes = ctx.changes; + ctx.changes = null; + Sys.Observer.raiseCollectionChanged(target, changes); + } + Sys.Observer.raisePropertyChanged(target, ""); + } +} +Sys.Observer.isUpdating = function Sys$Observer$isUpdating(target) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target"} + ]); + if (e) throw e; + Sys.Observer._ensureObservable(target); + var ctx = Sys.Observer._getContext(target); + return ctx ? ctx.updating : false; +} +Sys.Observer._setValue = function Sys$Observer$_setValue(target, propertyName, value) { + var getter, setter, mainTarget = target, path = propertyName.split('.'); + for (var i = 0, l = (path.length - 1); i < l ; i++) { + var name = path[i]; + getter = target["get_" + name]; + if (typeof (getter) === "function") { + target = getter.call(target); + } + else { + target = target[name]; + } + var type = typeof (target); + if ((target === null) || (type === "undefined")) { + throw Error.invalidOperation(String.format(Sys.Res.nullReferenceInPath, propertyName)); + } + } + var currentValue, lastPath = path[l]; + getter = target["get_" + lastPath]; + setter = target["set_" + lastPath]; + if (typeof(getter) === 'function') { + currentValue = getter.call(target); + } + else { + currentValue = target[lastPath]; + } + if (typeof(setter) === 'function') { + setter.call(target, value); + } + else { + target[lastPath] = value; + } + if (currentValue !== value) { + var ctx = Sys.Observer._getContext(mainTarget); + if (ctx && ctx.updating) { + ctx.dirty = true; + return; + }; + Sys.Observer.raisePropertyChanged(mainTarget, path[0]); + } +} +Sys.Observer.setValue = function Sys$Observer$setValue(target, propertyName, value) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target"}, + {name: "propertyName", type: String}, + {name: "value", mayBeNull: true} + ]); + if (e) throw e; + Sys.Observer._ensureObservable(target); + Sys.Observer._setValue(target, propertyName, value); +} +Sys.Observer.raisePropertyChanged = function Sys$Observer$raisePropertyChanged(target, propertyName) { + /// + /// + /// + Sys.Observer.raiseEvent(target, "propertyChanged", new Sys.PropertyChangedEventArgs(propertyName)); +} +Sys.Observer.addCollectionChanged = function Sys$Observer$addCollectionChanged(target, handler) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target", type: Array, elementMayBeNull: true}, + {name: "handler", type: Function} + ]); + if (e) throw e; + Sys.Observer._addEventHandler(target, "collectionChanged", handler); +} +Sys.Observer.removeCollectionChanged = function Sys$Observer$removeCollectionChanged(target, handler) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target", type: Array, elementMayBeNull: true}, + {name: "handler", type: Function} + ]); + if (e) throw e; + Sys.Observer._removeEventHandler(target, "collectionChanged", handler); +} +Sys.Observer._collectionChange = function Sys$Observer$_collectionChange(target, change) { + var ctx = Sys.Observer._getContext(target); + if (ctx && ctx.updating) { + ctx.dirty = true; + var changes = ctx.changes; + if (!changes) { + ctx.changes = changes = [change]; + } + else { + changes.push(change); + } + } + else { + Sys.Observer.raiseCollectionChanged(target, [change]); + Sys.Observer.raisePropertyChanged(target, 'length'); + } +} +Sys.Observer.add = function Sys$Observer$add(target, item) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target", type: Array, elementMayBeNull: true}, + {name: "item", mayBeNull: true} + ]); + if (e) throw e; + var change = new Sys.CollectionChange(Sys.NotifyCollectionChangedAction.add, [item], target.length); + Array.add(target, item); + Sys.Observer._collectionChange(target, change); +} +Sys.Observer.addRange = function Sys$Observer$addRange(target, items) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target", type: Array, elementMayBeNull: true}, + {name: "items", type: Array, elementMayBeNull: true} + ]); + if (e) throw e; + var change = new Sys.CollectionChange(Sys.NotifyCollectionChangedAction.add, items, target.length); + Array.addRange(target, items); + Sys.Observer._collectionChange(target, change); +} +Sys.Observer.clear = function Sys$Observer$clear(target) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target", type: Array, elementMayBeNull: true} + ]); + if (e) throw e; + var oldItems = Array.clone(target); + Array.clear(target); + Sys.Observer._collectionChange(target, new Sys.CollectionChange(Sys.NotifyCollectionChangedAction.reset, null, -1, oldItems, 0)); +} +Sys.Observer.insert = function Sys$Observer$insert(target, index, item) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target", type: Array, elementMayBeNull: true}, + {name: "index", type: Number, integer: true}, + {name: "item", mayBeNull: true} + ]); + if (e) throw e; + Array.insert(target, index, item); + Sys.Observer._collectionChange(target, new Sys.CollectionChange(Sys.NotifyCollectionChangedAction.add, [item], index)); +} +Sys.Observer.remove = function Sys$Observer$remove(target, item) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target", type: Array, elementMayBeNull: true}, + {name: "item", mayBeNull: true} + ]); + if (e) throw e; + var index = Array.indexOf(target, item); + if (index !== -1) { + Array.remove(target, item); + Sys.Observer._collectionChange(target, new Sys.CollectionChange(Sys.NotifyCollectionChangedAction.remove, null, -1, [item], index)); + return true; + } + return false; +} +Sys.Observer.removeAt = function Sys$Observer$removeAt(target, index) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target", type: Array, elementMayBeNull: true}, + {name: "index", type: Number, integer: true} + ]); + if (e) throw e; + if ((index > -1) && (index < target.length)) { + var item = target[index]; + Array.removeAt(target, index); + Sys.Observer._collectionChange(target, new Sys.CollectionChange(Sys.NotifyCollectionChangedAction.remove, null, -1, [item], index)); + } +} +Sys.Observer.raiseCollectionChanged = function Sys$Observer$raiseCollectionChanged(target, changes) { + /// + /// + /// + Sys.Observer.raiseEvent(target, "collectionChanged", new Sys.NotifyCollectionChangedEventArgs(changes)); +} +Sys.Observer._observeMethods = { + add_propertyChanged: function(handler) { + Sys.Observer._addEventHandler(this, "propertyChanged", handler); + }, + remove_propertyChanged: function(handler) { + Sys.Observer._removeEventHandler(this, "propertyChanged", handler); + }, + addEventHandler: function(eventName, handler) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "eventName", type: String}, + {name: "handler", type: Function} + ]); + if (e) throw e; + Sys.Observer._addEventHandler(this, eventName, handler); + }, + removeEventHandler: function(eventName, handler) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "eventName", type: String}, + {name: "handler", type: Function} + ]); + if (e) throw e; + Sys.Observer._removeEventHandler(this, eventName, handler); + }, + get_isUpdating: function() { + /// + /// + return Sys.Observer.isUpdating(this); + }, + beginUpdate: function() { + /// + Sys.Observer.beginUpdate(this); + }, + endUpdate: function() { + /// + Sys.Observer.endUpdate(this); + }, + setValue: function(name, value) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "name", type: String}, + {name: "value", mayBeNull: true} + ]); + if (e) throw e; + Sys.Observer._setValue(this, name, value); + }, + raiseEvent: function(eventName, eventArgs) { + /// + /// + /// + Sys.Observer.raiseEvent(this, eventName, eventArgs); + }, + raisePropertyChanged: function(name) { + /// + /// + Sys.Observer.raiseEvent(this, "propertyChanged", new Sys.PropertyChangedEventArgs(name)); + } +} +Sys.Observer._arrayMethods = { + add_collectionChanged: function(handler) { + Sys.Observer._addEventHandler(this, "collectionChanged", handler); + }, + remove_collectionChanged: function(handler) { + Sys.Observer._removeEventHandler(this, "collectionChanged", handler); + }, + add: function(item) { + /// + /// + Sys.Observer.add(this, item); + }, + addRange: function(items) { + /// + /// + Sys.Observer.addRange(this, items); + }, + clear: function() { + /// + Sys.Observer.clear(this); + }, + insert: function(index, item) { + /// + /// + /// + Sys.Observer.insert(this, index, item); + }, + remove: function(item) { + /// + /// + /// + return Sys.Observer.remove(this, item); + }, + removeAt: function(index) { + /// + /// + Sys.Observer.removeAt(this, index); + }, + raiseCollectionChanged: function(changes) { + /// + /// + Sys.Observer.raiseEvent(this, "collectionChanged", new Sys.NotifyCollectionChangedEventArgs(changes)); + } +} +Sys.Observer._getContext = function Sys$Observer$_getContext(obj, create) { + var ctx = obj._observerContext; + if (ctx) return ctx(); + if (create) { + return (obj._observerContext = Sys.Observer._createContext())(); + } + return null; +} +Sys.Observer._createContext = function Sys$Observer$_createContext() { + var ctx = { + events: new Sys.EventHandlerList() + }; + return function() { + return ctx; + } +} +Date._appendPreOrPostMatch = function Date$_appendPreOrPostMatch(preMatch, strBuilder) { + var quoteCount = 0; + var escaped = false; + for (var i = 0, il = preMatch.length; i < il; i++) { + var c = preMatch.charAt(i); + switch (c) { + case '\'': + if (escaped) strBuilder.append("'"); + else quoteCount++; + escaped = false; + break; + case '\\': + if (escaped) strBuilder.append("\\"); + escaped = !escaped; + break; + default: + strBuilder.append(c); + escaped = false; + break; + } + } + return quoteCount; +} +Date._expandFormat = function Date$_expandFormat(dtf, format) { + if (!format) { + format = "F"; + } + var len = format.length; + if (len === 1) { + switch (format) { + case "d": + return dtf.ShortDatePattern; + case "D": + return dtf.LongDatePattern; + case "t": + return dtf.ShortTimePattern; + case "T": + return dtf.LongTimePattern; + case "f": + return dtf.LongDatePattern + " " + dtf.ShortTimePattern; + case "F": + return dtf.FullDateTimePattern; + case "M": case "m": + return dtf.MonthDayPattern; + case "s": + return dtf.SortableDateTimePattern; + case "Y": case "y": + return dtf.YearMonthPattern; + default: + throw Error.format(Sys.Res.formatInvalidString); + } + } + else if ((len === 2) && (format.charAt(0) === "%")) { + format = format.charAt(1); + } + return format; +} +Date._expandYear = function Date$_expandYear(dtf, year) { + var now = new Date(), + era = Date._getEra(now); + if (year < 100) { + var curr = Date._getEraYear(now, dtf, era); + year += curr - (curr % 100); + if (year > dtf.Calendar.TwoDigitYearMax) { + year -= 100; + } + } + return year; +} +Date._getEra = function Date$_getEra(date, eras) { + if (!eras) return 0; + var start, ticks = date.getTime(); + for (var i = 0, l = eras.length; i < l; i += 4) { + start = eras[i+2]; + if ((start === null) || (ticks >= start)) { + return i; + } + } + return 0; +} +Date._getEraYear = function Date$_getEraYear(date, dtf, era, sortable) { + var year = date.getFullYear(); + if (!sortable && dtf.eras) { + year -= dtf.eras[era + 3]; + } + return year; +} +Date._getParseRegExp = function Date$_getParseRegExp(dtf, format) { + if (!dtf._parseRegExp) { + dtf._parseRegExp = {}; + } + else if (dtf._parseRegExp[format]) { + return dtf._parseRegExp[format]; + } + var expFormat = Date._expandFormat(dtf, format); + expFormat = expFormat.replace(/([\^\$\.\*\+\?\|\[\]\(\)\{\}])/g, "\\\\$1"); + var regexp = new Sys.StringBuilder("^"); + var groups = []; + var index = 0; + var quoteCount = 0; + var tokenRegExp = Date._getTokenRegExp(); + var match; + while ((match = tokenRegExp.exec(expFormat)) !== null) { + var preMatch = expFormat.slice(index, match.index); + index = tokenRegExp.lastIndex; + quoteCount += Date._appendPreOrPostMatch(preMatch, regexp); + if ((quoteCount%2) === 1) { + regexp.append(match[0]); + continue; + } + switch (match[0]) { + case 'dddd': case 'ddd': + case 'MMMM': case 'MMM': + case 'gg': case 'g': + regexp.append("(\\D+)"); + break; + case 'tt': case 't': + regexp.append("(\\D*)"); + break; + case 'yyyy': + regexp.append("(\\d{4})"); + break; + case 'fff': + regexp.append("(\\d{3})"); + break; + case 'ff': + regexp.append("(\\d{2})"); + break; + case 'f': + regexp.append("(\\d)"); + break; + case 'dd': case 'd': + case 'MM': case 'M': + case 'yy': case 'y': + case 'HH': case 'H': + case 'hh': case 'h': + case 'mm': case 'm': + case 'ss': case 's': + regexp.append("(\\d\\d?)"); + break; + case 'zzz': + regexp.append("([+-]?\\d\\d?:\\d{2})"); + break; + case 'zz': case 'z': + regexp.append("([+-]?\\d\\d?)"); + break; + case '/': + regexp.append("(\\" + dtf.DateSeparator + ")"); + break; + default: + Sys.Debug.fail("Invalid date format pattern"); + } + Array.add(groups, match[0]); + } + Date._appendPreOrPostMatch(expFormat.slice(index), regexp); + regexp.append("$"); + var regexpStr = regexp.toString().replace(/\s+/g, "\\s+"); + var parseRegExp = {'regExp': regexpStr, 'groups': groups}; + dtf._parseRegExp[format] = parseRegExp; + return parseRegExp; +} +Date._getTokenRegExp = function Date$_getTokenRegExp() { + return /\/|dddd|ddd|dd|d|MMMM|MMM|MM|M|yyyy|yy|y|hh|h|HH|H|mm|m|ss|s|tt|t|fff|ff|f|zzz|zz|z|gg|g/g; +} +Date.parseLocale = function Date$parseLocale(value, formats) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "value", type: String}, + {name: "formats", mayBeNull: true, optional: true, parameterArray: true} + ]); + if (e) throw e; + return Date._parse(value, Sys.CultureInfo.CurrentCulture, arguments); +} +Date.parseInvariant = function Date$parseInvariant(value, formats) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "value", type: String}, + {name: "formats", mayBeNull: true, optional: true, parameterArray: true} + ]); + if (e) throw e; + return Date._parse(value, Sys.CultureInfo.InvariantCulture, arguments); +} +Date._parse = function Date$_parse(value, cultureInfo, args) { + var i, l, date, format, formats, custom = false; + for (i = 1, l = args.length; i < l; i++) { + format = args[i]; + if (format) { + custom = true; + date = Date._parseExact(value, format, cultureInfo); + if (date) return date; + } + } + if (! custom) { + formats = cultureInfo._getDateTimeFormats(); + for (i = 0, l = formats.length; i < l; i++) { + date = Date._parseExact(value, formats[i], cultureInfo); + if (date) return date; + } + } + return null; +} +Date._parseExact = function Date$_parseExact(value, format, cultureInfo) { + value = value.trim(); + var dtf = cultureInfo.dateTimeFormat, + parseInfo = Date._getParseRegExp(dtf, format), + match = new RegExp(parseInfo.regExp).exec(value); + if (match === null) return null; + + var groups = parseInfo.groups, + era = null, year = null, month = null, date = null, weekDay = null, + hour = 0, hourOffset, min = 0, sec = 0, msec = 0, tzMinOffset = null, + pmHour = false; + for (var j = 0, jl = groups.length; j < jl; j++) { + var matchGroup = match[j+1]; + if (matchGroup) { + switch (groups[j]) { + case 'dd': case 'd': + date = parseInt(matchGroup, 10); + if ((date < 1) || (date > 31)) return null; + break; + case 'MMMM': + month = cultureInfo._getMonthIndex(matchGroup); + if ((month < 0) || (month > 11)) return null; + break; + case 'MMM': + month = cultureInfo._getAbbrMonthIndex(matchGroup); + if ((month < 0) || (month > 11)) return null; + break; + case 'M': case 'MM': + month = parseInt(matchGroup, 10) - 1; + if ((month < 0) || (month > 11)) return null; + break; + case 'y': case 'yy': + year = Date._expandYear(dtf,parseInt(matchGroup, 10)); + if ((year < 0) || (year > 9999)) return null; + break; + case 'yyyy': + year = parseInt(matchGroup, 10); + if ((year < 0) || (year > 9999)) return null; + break; + case 'h': case 'hh': + hour = parseInt(matchGroup, 10); + if (hour === 12) hour = 0; + if ((hour < 0) || (hour > 11)) return null; + break; + case 'H': case 'HH': + hour = parseInt(matchGroup, 10); + if ((hour < 0) || (hour > 23)) return null; + break; + case 'm': case 'mm': + min = parseInt(matchGroup, 10); + if ((min < 0) || (min > 59)) return null; + break; + case 's': case 'ss': + sec = parseInt(matchGroup, 10); + if ((sec < 0) || (sec > 59)) return null; + break; + case 'tt': case 't': + var upperToken = matchGroup.toUpperCase(); + pmHour = (upperToken === dtf.PMDesignator.toUpperCase()); + if (!pmHour && (upperToken !== dtf.AMDesignator.toUpperCase())) return null; + break; + case 'f': + msec = parseInt(matchGroup, 10) * 100; + if ((msec < 0) || (msec > 999)) return null; + break; + case 'ff': + msec = parseInt(matchGroup, 10) * 10; + if ((msec < 0) || (msec > 999)) return null; + break; + case 'fff': + msec = parseInt(matchGroup, 10); + if ((msec < 0) || (msec > 999)) return null; + break; + case 'dddd': + weekDay = cultureInfo._getDayIndex(matchGroup); + if ((weekDay < 0) || (weekDay > 6)) return null; + break; + case 'ddd': + weekDay = cultureInfo._getAbbrDayIndex(matchGroup); + if ((weekDay < 0) || (weekDay > 6)) return null; + break; + case 'zzz': + var offsets = matchGroup.split(/:/); + if (offsets.length !== 2) return null; + hourOffset = parseInt(offsets[0], 10); + if ((hourOffset < -12) || (hourOffset > 13)) return null; + var minOffset = parseInt(offsets[1], 10); + if ((minOffset < 0) || (minOffset > 59)) return null; + tzMinOffset = (hourOffset * 60) + (matchGroup.startsWith('-')? -minOffset : minOffset); + break; + case 'z': case 'zz': + hourOffset = parseInt(matchGroup, 10); + if ((hourOffset < -12) || (hourOffset > 13)) return null; + tzMinOffset = hourOffset * 60; + break; + case 'g': case 'gg': + var eraName = matchGroup; + if (!eraName || !dtf.eras) return null; + eraName = eraName.toLowerCase().trim(); + for (var i = 0, l = dtf.eras.length; i < l; i += 4) { + if (eraName === dtf.eras[i + 1].toLowerCase()) { + era = i; + break; + } + } + if (era === null) return null; + break; + } + } + } + var result = new Date(), defaults, convert = dtf.Calendar.convert; + if (convert) { + defaults = convert.fromGregorian(result); + } + if (!convert) { + defaults = [result.getFullYear(), result.getMonth(), result.getDate()]; + } + if (year === null) { + year = defaults[0]; + } + else if (dtf.eras) { + year += dtf.eras[(era || 0) + 3]; + } + if (month === null) { + month = defaults[1]; + } + if (date === null) { + date = defaults[2]; + } + if (convert) { + result = convert.toGregorian(year, month, date); + if (result === null) return null; + } + else { + result.setFullYear(year, month, date); + if (result.getDate() !== date) return null; + if ((weekDay !== null) && (result.getDay() !== weekDay)) { + return null; + } + } + if (pmHour && (hour < 12)) { + hour += 12; + } + result.setHours(hour, min, sec, msec); + if (tzMinOffset !== null) { + var adjustedMin = result.getMinutes() - (tzMinOffset + result.getTimezoneOffset()); + result.setHours(result.getHours() + parseInt(adjustedMin/60, 10), adjustedMin%60); + } + return result; +} +Date.prototype.format = function Date$format(format) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "format", type: String} + ]); + if (e) throw e; + return this._toFormattedString(format, Sys.CultureInfo.InvariantCulture); +} +Date.prototype.localeFormat = function Date$localeFormat(format) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "format", type: String} + ]); + if (e) throw e; + return this._toFormattedString(format, Sys.CultureInfo.CurrentCulture); +} +Date.prototype._toFormattedString = function Date$_toFormattedString(format, cultureInfo) { + var dtf = cultureInfo.dateTimeFormat, + convert = dtf.Calendar.convert; + if (!format || !format.length || (format === 'i')) { + if (cultureInfo && cultureInfo.name.length) { + if (convert) { + return this._toFormattedString(dtf.FullDateTimePattern, cultureInfo); + } + else { + var eraDate = new Date(this.getTime()); + var era = Date._getEra(this, dtf.eras); + eraDate.setFullYear(Date._getEraYear(this, dtf, era)); + return eraDate.toLocaleString(); + } + } + else { + return this.toString(); + } + } + var eras = dtf.eras, + sortable = (format === "s"); + format = Date._expandFormat(dtf, format); + var ret = new Sys.StringBuilder(); + var hour; + function addLeadingZero(num) { + if (num < 10) { + return '0' + num; + } + return num.toString(); + } + function addLeadingZeros(num) { + if (num < 10) { + return '00' + num; + } + if (num < 100) { + return '0' + num; + } + return num.toString(); + } + function padYear(year) { + if (year < 10) { + return '000' + year; + } + else if (year < 100) { + return '00' + year; + } + else if (year < 1000) { + return '0' + year; + } + return year.toString(); + } + + var foundDay, checkedDay, dayPartRegExp = /([^d]|^)(d|dd)([^d]|$)/g; + function hasDay() { + if (foundDay || checkedDay) { + return foundDay; + } + foundDay = dayPartRegExp.test(format); + checkedDay = true; + return foundDay; + } + + var quoteCount = 0, + tokenRegExp = Date._getTokenRegExp(), + converted; + if (!sortable && convert) { + converted = convert.fromGregorian(this); + } + for (;;) { + var index = tokenRegExp.lastIndex; + var ar = tokenRegExp.exec(format); + var preMatch = format.slice(index, ar ? ar.index : format.length); + quoteCount += Date._appendPreOrPostMatch(preMatch, ret); + if (!ar) break; + if ((quoteCount%2) === 1) { + ret.append(ar[0]); + continue; + } + + function getPart(date, part) { + if (converted) { + return converted[part]; + } + switch (part) { + case 0: return date.getFullYear(); + case 1: return date.getMonth(); + case 2: return date.getDate(); + } + } + switch (ar[0]) { + case "dddd": + ret.append(dtf.DayNames[this.getDay()]); + break; + case "ddd": + ret.append(dtf.AbbreviatedDayNames[this.getDay()]); + break; + case "dd": + foundDay = true; + ret.append(addLeadingZero(getPart(this, 2))); + break; + case "d": + foundDay = true; + ret.append(getPart(this, 2)); + break; + case "MMMM": + ret.append((dtf.MonthGenitiveNames && hasDay()) + ? dtf.MonthGenitiveNames[getPart(this, 1)] + : dtf.MonthNames[getPart(this, 1)]); + break; + case "MMM": + ret.append((dtf.AbbreviatedMonthGenitiveNames && hasDay()) + ? dtf.AbbreviatedMonthGenitiveNames[getPart(this, 1)] + : dtf.AbbreviatedMonthNames[getPart(this, 1)]); + break; + case "MM": + ret.append(addLeadingZero(getPart(this, 1) + 1)); + break; + case "M": + ret.append(getPart(this, 1) + 1); + break; + case "yyyy": + ret.append(padYear(converted ? converted[0] : Date._getEraYear(this, dtf, Date._getEra(this, eras), sortable))); + break; + case "yy": + ret.append(addLeadingZero((converted ? converted[0] : Date._getEraYear(this, dtf, Date._getEra(this, eras), sortable)) % 100)); + break; + case "y": + ret.append((converted ? converted[0] : Date._getEraYear(this, dtf, Date._getEra(this, eras), sortable)) % 100); + break; + case "hh": + hour = this.getHours() % 12; + if (hour === 0) hour = 12; + ret.append(addLeadingZero(hour)); + break; + case "h": + hour = this.getHours() % 12; + if (hour === 0) hour = 12; + ret.append(hour); + break; + case "HH": + ret.append(addLeadingZero(this.getHours())); + break; + case "H": + ret.append(this.getHours()); + break; + case "mm": + ret.append(addLeadingZero(this.getMinutes())); + break; + case "m": + ret.append(this.getMinutes()); + break; + case "ss": + ret.append(addLeadingZero(this.getSeconds())); + break; + case "s": + ret.append(this.getSeconds()); + break; + case "tt": + ret.append((this.getHours() < 12) ? dtf.AMDesignator : dtf.PMDesignator); + break; + case "t": + ret.append(((this.getHours() < 12) ? dtf.AMDesignator : dtf.PMDesignator).charAt(0)); + break; + case "f": + ret.append(addLeadingZeros(this.getMilliseconds()).charAt(0)); + break; + case "ff": + ret.append(addLeadingZeros(this.getMilliseconds()).substr(0, 2)); + break; + case "fff": + ret.append(addLeadingZeros(this.getMilliseconds())); + break; + case "z": + hour = this.getTimezoneOffset() / 60; + ret.append(((hour <= 0) ? '+' : '-') + Math.floor(Math.abs(hour))); + break; + case "zz": + hour = this.getTimezoneOffset() / 60; + ret.append(((hour <= 0) ? '+' : '-') + addLeadingZero(Math.floor(Math.abs(hour)))); + break; + case "zzz": + hour = this.getTimezoneOffset() / 60; + ret.append(((hour <= 0) ? '+' : '-') + addLeadingZero(Math.floor(Math.abs(hour))) + + ":" + addLeadingZero(Math.abs(this.getTimezoneOffset() % 60))); + break; + case "g": + case "gg": + if (dtf.eras) { + ret.append(dtf.eras[Date._getEra(this, eras) + 1]); + } + break; + case "/": + ret.append(dtf.DateSeparator); + break; + default: + Sys.Debug.fail("Invalid date format pattern"); + } + } + return ret.toString(); +} +String.localeFormat = function String$localeFormat(format, args) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "format", type: String}, + {name: "args", mayBeNull: true, parameterArray: true} + ]); + if (e) throw e; + return String._toFormattedString(true, arguments); +} +Number.parseLocale = function Number$parseLocale(value) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "value", type: String} + ], false); + if (e) throw e; + return Number._parse(value, Sys.CultureInfo.CurrentCulture); +} +Number.parseInvariant = function Number$parseInvariant(value) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "value", type: String} + ], false); + if (e) throw e; + return Number._parse(value, Sys.CultureInfo.InvariantCulture); +} +Number._parse = function Number$_parse(value, cultureInfo) { + value = value.trim(); + + if (value.match(/^[+-]?infinity$/i)) { + return parseFloat(value); + } + if (value.match(/^0x[a-f0-9]+$/i)) { + return parseInt(value); + } + var numFormat = cultureInfo.numberFormat; + var signInfo = Number._parseNumberNegativePattern(value, numFormat, numFormat.NumberNegativePattern); + var sign = signInfo[0]; + var num = signInfo[1]; + + if ((sign === '') && (numFormat.NumberNegativePattern !== 1)) { + signInfo = Number._parseNumberNegativePattern(value, numFormat, 1); + sign = signInfo[0]; + num = signInfo[1]; + } + if (sign === '') sign = '+'; + + var exponent; + var intAndFraction; + var exponentPos = num.indexOf('e'); + if (exponentPos < 0) exponentPos = num.indexOf('E'); + if (exponentPos < 0) { + intAndFraction = num; + exponent = null; + } + else { + intAndFraction = num.substr(0, exponentPos); + exponent = num.substr(exponentPos + 1); + } + + var integer; + var fraction; + var decimalPos = intAndFraction.indexOf(numFormat.NumberDecimalSeparator); + if (decimalPos < 0) { + integer = intAndFraction; + fraction = null; + } + else { + integer = intAndFraction.substr(0, decimalPos); + fraction = intAndFraction.substr(decimalPos + numFormat.NumberDecimalSeparator.length); + } + + integer = integer.split(numFormat.NumberGroupSeparator).join(''); + var altNumGroupSeparator = numFormat.NumberGroupSeparator.replace(/\u00A0/g, " "); + if (numFormat.NumberGroupSeparator !== altNumGroupSeparator) { + integer = integer.split(altNumGroupSeparator).join(''); + } + + var p = sign + integer; + if (fraction !== null) { + p += '.' + fraction; + } + if (exponent !== null) { + var expSignInfo = Number._parseNumberNegativePattern(exponent, numFormat, 1); + if (expSignInfo[0] === '') { + expSignInfo[0] = '+'; + } + p += 'e' + expSignInfo[0] + expSignInfo[1]; + } + if (p.match(/^[+-]?\d*\.?\d*(e[+-]?\d+)?$/)) { + return parseFloat(p); + } + return Number.NaN; +} +Number._parseNumberNegativePattern = function Number$_parseNumberNegativePattern(value, numFormat, numberNegativePattern) { + var neg = numFormat.NegativeSign; + var pos = numFormat.PositiveSign; + switch (numberNegativePattern) { + case 4: + neg = ' ' + neg; + pos = ' ' + pos; + case 3: + if (value.endsWith(neg)) { + return ['-', value.substr(0, value.length - neg.length)]; + } + else if (value.endsWith(pos)) { + return ['+', value.substr(0, value.length - pos.length)]; + } + break; + case 2: + neg += ' '; + pos += ' '; + case 1: + if (value.startsWith(neg)) { + return ['-', value.substr(neg.length)]; + } + else if (value.startsWith(pos)) { + return ['+', value.substr(pos.length)]; + } + break; + case 0: + if (value.startsWith('(') && value.endsWith(')')) { + return ['-', value.substr(1, value.length - 2)]; + } + break; + default: + Sys.Debug.fail(""); + } + return ['', value]; +} +Number.prototype.format = function Number$format(format) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "format", type: String} + ]); + if (e) throw e; + return this._toFormattedString(format, Sys.CultureInfo.InvariantCulture); +} +Number.prototype.localeFormat = function Number$localeFormat(format) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "format", type: String} + ]); + if (e) throw e; + return this._toFormattedString(format, Sys.CultureInfo.CurrentCulture); +} +Number.prototype._toFormattedString = function Number$_toFormattedString(format, cultureInfo) { + if (!format || (format.length === 0) || (format === 'i')) { + if (cultureInfo && (cultureInfo.name.length > 0)) { + return this.toLocaleString(); + } + else { + return this.toString(); + } + } + + var _percentPositivePattern = ["n %", "n%", "%n" ]; + var _percentNegativePattern = ["-n %", "-n%", "-%n"]; + var _numberNegativePattern = ["(n)","-n","- n","n-","n -"]; + var _currencyPositivePattern = ["$n","n$","$ n","n $"]; + var _currencyNegativePattern = ["($n)","-$n","$-n","$n-","(n$)","-n$","n-$","n$-","-n $","-$ n","n $-","$ n-","$ -n","n- $","($ n)","(n $)"]; + function zeroPad(str, count, left) { + for (var l=str.length; l < count; l++) { + str = (left ? ('0' + str) : (str + '0')); + } + return str; + } + + function expandNumber(number, precision, groupSizes, sep, decimalChar) { + Sys.Debug.assert(groupSizes.length > 0, "groupSizes must be an array of at least 1"); + var curSize = groupSizes[0]; + var curGroupIndex = 1; + var factor = Math.pow(10, precision); + var rounded = (Math.round(number * factor) / factor); + if (!isFinite(rounded)) { + rounded = number; + } + number = rounded; + + var numberString = number.toString(); + var right = ""; + var exponent; + + + var split = numberString.split(/e/i); + numberString = split[0]; + exponent = (split.length > 1 ? parseInt(split[1]) : 0); + split = numberString.split('.'); + numberString = split[0]; + right = split.length > 1 ? split[1] : ""; + + var l; + if (exponent > 0) { + right = zeroPad(right, exponent, false); + numberString += right.slice(0, exponent); + right = right.substr(exponent); + } + else if (exponent < 0) { + exponent = -exponent; + numberString = zeroPad(numberString, exponent+1, true); + right = numberString.slice(-exponent, numberString.length) + right; + numberString = numberString.slice(0, -exponent); + } + if (precision > 0) { + if (right.length > precision) { + right = right.slice(0, precision); + } + else { + right = zeroPad(right, precision, false); + } + right = decimalChar + right; + } + else { + right = ""; + } + var stringIndex = numberString.length-1; + var ret = ""; + while (stringIndex >= 0) { + if (curSize === 0 || curSize > stringIndex) { + if (ret.length > 0) + return numberString.slice(0, stringIndex + 1) + sep + ret + right; + else + return numberString.slice(0, stringIndex + 1) + right; + } + if (ret.length > 0) + ret = numberString.slice(stringIndex - curSize + 1, stringIndex+1) + sep + ret; + else + ret = numberString.slice(stringIndex - curSize + 1, stringIndex+1); + stringIndex -= curSize; + if (curGroupIndex < groupSizes.length) { + curSize = groupSizes[curGroupIndex]; + curGroupIndex++; + } + } + return numberString.slice(0, stringIndex + 1) + sep + ret + right; + } + var nf = cultureInfo.numberFormat; + var number = Math.abs(this); + if (!format) + format = "D"; + var precision = -1; + if (format.length > 1) precision = parseInt(format.slice(1), 10); + var pattern; + switch (format.charAt(0)) { + case "d": + case "D": + pattern = 'n'; + if (precision !== -1) { + number = zeroPad(""+number, precision, true); + } + if (this < 0) number = -number; + break; + case "c": + case "C": + if (this < 0) pattern = _currencyNegativePattern[nf.CurrencyNegativePattern]; + else pattern = _currencyPositivePattern[nf.CurrencyPositivePattern]; + if (precision === -1) precision = nf.CurrencyDecimalDigits; + number = expandNumber(Math.abs(this), precision, nf.CurrencyGroupSizes, nf.CurrencyGroupSeparator, nf.CurrencyDecimalSeparator); + break; + case "n": + case "N": + if (this < 0) pattern = _numberNegativePattern[nf.NumberNegativePattern]; + else pattern = 'n'; + if (precision === -1) precision = nf.NumberDecimalDigits; + number = expandNumber(Math.abs(this), precision, nf.NumberGroupSizes, nf.NumberGroupSeparator, nf.NumberDecimalSeparator); + break; + case "p": + case "P": + if (this < 0) pattern = _percentNegativePattern[nf.PercentNegativePattern]; + else pattern = _percentPositivePattern[nf.PercentPositivePattern]; + if (precision === -1) precision = nf.PercentDecimalDigits; + number = expandNumber(Math.abs(this) * 100, precision, nf.PercentGroupSizes, nf.PercentGroupSeparator, nf.PercentDecimalSeparator); + break; + default: + throw Error.format(Sys.Res.formatBadFormatSpecifier); + } + var regex = /n|\$|-|%/g; + var ret = ""; + for (;;) { + var index = regex.lastIndex; + var ar = regex.exec(pattern); + ret += pattern.slice(index, ar ? ar.index : pattern.length); + if (!ar) + break; + switch (ar[0]) { + case "n": + ret += number; + break; + case "$": + ret += nf.CurrencySymbol; + break; + case "-": + if (/[1-9]/.test(number)) { + ret += nf.NegativeSign; + } + break; + case "%": + ret += nf.PercentSymbol; + break; + default: + Sys.Debug.fail("Invalid number format pattern"); + } + } + return ret; +} + +Sys.CultureInfo = function Sys$CultureInfo(name, numberFormat, dateTimeFormat) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "name", type: String}, + {name: "numberFormat", type: Object}, + {name: "dateTimeFormat", type: Object} + ]); + if (e) throw e; + this.name = name; + this.numberFormat = numberFormat; + this.dateTimeFormat = dateTimeFormat; +} + function Sys$CultureInfo$_getDateTimeFormats() { + if (! this._dateTimeFormats) { + var dtf = this.dateTimeFormat; + this._dateTimeFormats = + [ dtf.MonthDayPattern, + dtf.YearMonthPattern, + dtf.ShortDatePattern, + dtf.ShortTimePattern, + dtf.LongDatePattern, + dtf.LongTimePattern, + dtf.FullDateTimePattern, + dtf.RFC1123Pattern, + dtf.SortableDateTimePattern, + dtf.UniversalSortableDateTimePattern ]; + } + return this._dateTimeFormats; + } + function Sys$CultureInfo$_getIndex(value, a1, a2) { + var upper = this._toUpper(value), + i = Array.indexOf(a1, upper); + if (i === -1) { + i = Array.indexOf(a2, upper); + } + return i; + } + function Sys$CultureInfo$_getMonthIndex(value) { + if (!this._upperMonths) { + this._upperMonths = this._toUpperArray(this.dateTimeFormat.MonthNames); + this._upperMonthsGenitive = this._toUpperArray(this.dateTimeFormat.MonthGenitiveNames); + } + return this._getIndex(value, this._upperMonths, this._upperMonthsGenitive); + } + function Sys$CultureInfo$_getAbbrMonthIndex(value) { + if (!this._upperAbbrMonths) { + this._upperAbbrMonths = this._toUpperArray(this.dateTimeFormat.AbbreviatedMonthNames); + this._upperAbbrMonthsGenitive = this._toUpperArray(this.dateTimeFormat.AbbreviatedMonthGenitiveNames); + } + return this._getIndex(value, this._upperAbbrMonths, this._upperAbbrMonthsGenitive); + } + function Sys$CultureInfo$_getDayIndex(value) { + if (!this._upperDays) { + this._upperDays = this._toUpperArray(this.dateTimeFormat.DayNames); + } + return Array.indexOf(this._upperDays, this._toUpper(value)); + } + function Sys$CultureInfo$_getAbbrDayIndex(value) { + if (!this._upperAbbrDays) { + this._upperAbbrDays = this._toUpperArray(this.dateTimeFormat.AbbreviatedDayNames); + } + return Array.indexOf(this._upperAbbrDays, this._toUpper(value)); + } + function Sys$CultureInfo$_toUpperArray(arr) { + var result = []; + for (var i = 0, il = arr.length; i < il; i++) { + result[i] = this._toUpper(arr[i]); + } + return result; + } + function Sys$CultureInfo$_toUpper(value) { + return value.split("\u00A0").join(' ').toUpperCase(); + } +Sys.CultureInfo.prototype = { + _getDateTimeFormats: Sys$CultureInfo$_getDateTimeFormats, + _getIndex: Sys$CultureInfo$_getIndex, + _getMonthIndex: Sys$CultureInfo$_getMonthIndex, + _getAbbrMonthIndex: Sys$CultureInfo$_getAbbrMonthIndex, + _getDayIndex: Sys$CultureInfo$_getDayIndex, + _getAbbrDayIndex: Sys$CultureInfo$_getAbbrDayIndex, + _toUpperArray: Sys$CultureInfo$_toUpperArray, + _toUpper: Sys$CultureInfo$_toUpper +} +Sys.CultureInfo.registerClass('Sys.CultureInfo'); +Sys.CultureInfo._parse = function Sys$CultureInfo$_parse(value) { + var dtf = value.dateTimeFormat; + if (dtf && !dtf.eras) { + dtf.eras = value.eras; + } + return new Sys.CultureInfo(value.name, value.numberFormat, dtf); +} +Sys.CultureInfo.InvariantCulture = Sys.CultureInfo._parse({"name":"","numberFormat":{"CurrencyDecimalDigits":2,"CurrencyDecimalSeparator":".","IsReadOnly":true,"CurrencyGroupSizes":[3],"NumberGroupSizes":[3],"PercentGroupSizes":[3],"CurrencyGroupSeparator":",","CurrencySymbol":"\u00A4","NaNSymbol":"NaN","CurrencyNegativePattern":0,"NumberNegativePattern":1,"PercentPositivePattern":0,"PercentNegativePattern":0,"NegativeInfinitySymbol":"-Infinity","NegativeSign":"-","NumberDecimalDigits":2,"NumberDecimalSeparator":".","NumberGroupSeparator":",","CurrencyPositivePattern":0,"PositiveInfinitySymbol":"Infinity","PositiveSign":"+","PercentDecimalDigits":2,"PercentDecimalSeparator":".","PercentGroupSeparator":",","PercentSymbol":"%","PerMilleSymbol":"\u2030","NativeDigits":["0","1","2","3","4","5","6","7","8","9"],"DigitSubstitution":1},"dateTimeFormat":{"AMDesignator":"AM","Calendar":{"MinSupportedDateTime":"@-62135568000000@","MaxSupportedDateTime":"@253402300799999@","AlgorithmType":1,"CalendarType":1,"Eras":[1],"TwoDigitYearMax":2029,"IsReadOnly":true},"DateSeparator":"/","FirstDayOfWeek":0,"CalendarWeekRule":0,"FullDateTimePattern":"dddd, dd MMMM yyyy HH:mm:ss","LongDatePattern":"dddd, dd MMMM yyyy","LongTimePattern":"HH:mm:ss","MonthDayPattern":"MMMM dd","PMDesignator":"PM","RFC1123Pattern":"ddd, dd MMM yyyy HH\':\'mm\':\'ss \'GMT\'","ShortDatePattern":"MM/dd/yyyy","ShortTimePattern":"HH:mm","SortableDateTimePattern":"yyyy\'-\'MM\'-\'dd\'T\'HH\':\'mm\':\'ss","TimeSeparator":":","UniversalSortableDateTimePattern":"yyyy\'-\'MM\'-\'dd HH\':\'mm\':\'ss\'Z\'","YearMonthPattern":"yyyy MMMM","AbbreviatedDayNames":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"ShortestDayNames":["Su","Mo","Tu","We","Th","Fr","Sa"],"DayNames":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"AbbreviatedMonthNames":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec",""],"MonthNames":["January","February","March","April","May","June","July","August","September","October","November","December",""],"IsReadOnly":true,"NativeCalendarName":"Gregorian Calendar","AbbreviatedMonthGenitiveNames":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec",""],"MonthGenitiveNames":["January","February","March","April","May","June","July","August","September","October","November","December",""]},"eras":[1,"A.D.",null,0]}); +if (typeof(__cultureInfo) === "object") { + Sys.CultureInfo.CurrentCulture = Sys.CultureInfo._parse(__cultureInfo); + delete __cultureInfo; +} +else { + Sys.CultureInfo.CurrentCulture = Sys.CultureInfo._parse({"name":"en-US","numberFormat":{"CurrencyDecimalDigits":2,"CurrencyDecimalSeparator":".","IsReadOnly":false,"CurrencyGroupSizes":[3],"NumberGroupSizes":[3],"PercentGroupSizes":[3],"CurrencyGroupSeparator":",","CurrencySymbol":"$","NaNSymbol":"NaN","CurrencyNegativePattern":0,"NumberNegativePattern":1,"PercentPositivePattern":0,"PercentNegativePattern":0,"NegativeInfinitySymbol":"-Infinity","NegativeSign":"-","NumberDecimalDigits":2,"NumberDecimalSeparator":".","NumberGroupSeparator":",","CurrencyPositivePattern":0,"PositiveInfinitySymbol":"Infinity","PositiveSign":"+","PercentDecimalDigits":2,"PercentDecimalSeparator":".","PercentGroupSeparator":",","PercentSymbol":"%","PerMilleSymbol":"\u2030","NativeDigits":["0","1","2","3","4","5","6","7","8","9"],"DigitSubstitution":1},"dateTimeFormat":{"AMDesignator":"AM","Calendar":{"MinSupportedDateTime":"@-62135568000000@","MaxSupportedDateTime":"@253402300799999@","AlgorithmType":1,"CalendarType":1,"Eras":[1],"TwoDigitYearMax":2029,"IsReadOnly":false},"DateSeparator":"/","FirstDayOfWeek":0,"CalendarWeekRule":0,"FullDateTimePattern":"dddd, MMMM dd, yyyy h:mm:ss tt","LongDatePattern":"dddd, MMMM dd, yyyy","LongTimePattern":"h:mm:ss tt","MonthDayPattern":"MMMM dd","PMDesignator":"PM","RFC1123Pattern":"ddd, dd MMM yyyy HH\':\'mm\':\'ss \'GMT\'","ShortDatePattern":"M/d/yyyy","ShortTimePattern":"h:mm tt","SortableDateTimePattern":"yyyy\'-\'MM\'-\'dd\'T\'HH\':\'mm\':\'ss","TimeSeparator":":","UniversalSortableDateTimePattern":"yyyy\'-\'MM\'-\'dd HH\':\'mm\':\'ss\'Z\'","YearMonthPattern":"MMMM, yyyy","AbbreviatedDayNames":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"ShortestDayNames":["Su","Mo","Tu","We","Th","Fr","Sa"],"DayNames":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"AbbreviatedMonthNames":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec",""],"MonthNames":["January","February","March","April","May","June","July","August","September","October","November","December",""],"IsReadOnly":false,"NativeCalendarName":"Gregorian Calendar","AbbreviatedMonthGenitiveNames":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec",""],"MonthGenitiveNames":["January","February","March","April","May","June","July","August","September","October","November","December",""]},"eras":[1,"A.D.",null,0]}); +} +Type.registerNamespace('Sys.Serialization'); +Sys.Serialization.JavaScriptSerializer = function Sys$Serialization$JavaScriptSerializer() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); +} +Sys.Serialization.JavaScriptSerializer.registerClass('Sys.Serialization.JavaScriptSerializer'); +Sys.Serialization.JavaScriptSerializer._charsToEscapeRegExs = []; +Sys.Serialization.JavaScriptSerializer._charsToEscape = []; +Sys.Serialization.JavaScriptSerializer._dateRegEx = new RegExp('(^|[^\\\\])\\"\\\\/Date\\((-?[0-9]+)(?:[a-zA-Z]|(?:\\+|-)[0-9]{4})?\\)\\\\/\\"', 'g'); +Sys.Serialization.JavaScriptSerializer._escapeChars = {}; +Sys.Serialization.JavaScriptSerializer._escapeRegEx = new RegExp('["\\\\\\x00-\\x1F]', 'i'); +Sys.Serialization.JavaScriptSerializer._escapeRegExGlobal = new RegExp('["\\\\\\x00-\\x1F]', 'g'); +Sys.Serialization.JavaScriptSerializer._jsonRegEx = new RegExp('[^,:{}\\[\\]0-9.\\-+Eaeflnr-u \\n\\r\\t]', 'g'); +Sys.Serialization.JavaScriptSerializer._jsonStringRegEx = new RegExp('"(\\\\.|[^"\\\\])*"', 'g'); +Sys.Serialization.JavaScriptSerializer._serverTypeFieldName = '__type'; +Sys.Serialization.JavaScriptSerializer._init = function Sys$Serialization$JavaScriptSerializer$_init() { + var replaceChars = ['\\u0000','\\u0001','\\u0002','\\u0003','\\u0004','\\u0005','\\u0006','\\u0007', + '\\b','\\t','\\n','\\u000b','\\f','\\r','\\u000e','\\u000f','\\u0010','\\u0011', + '\\u0012','\\u0013','\\u0014','\\u0015','\\u0016','\\u0017','\\u0018','\\u0019', + '\\u001a','\\u001b','\\u001c','\\u001d','\\u001e','\\u001f']; + Sys.Serialization.JavaScriptSerializer._charsToEscape[0] = '\\'; + Sys.Serialization.JavaScriptSerializer._charsToEscapeRegExs['\\'] = new RegExp('\\\\', 'g'); + Sys.Serialization.JavaScriptSerializer._escapeChars['\\'] = '\\\\'; + Sys.Serialization.JavaScriptSerializer._charsToEscape[1] = '"'; + Sys.Serialization.JavaScriptSerializer._charsToEscapeRegExs['"'] = new RegExp('"', 'g'); + Sys.Serialization.JavaScriptSerializer._escapeChars['"'] = '\\"'; + for (var i = 0; i < 32; i++) { + var c = String.fromCharCode(i); + Sys.Serialization.JavaScriptSerializer._charsToEscape[i+2] = c; + Sys.Serialization.JavaScriptSerializer._charsToEscapeRegExs[c] = new RegExp(c, 'g'); + Sys.Serialization.JavaScriptSerializer._escapeChars[c] = replaceChars[i]; + } +} +Sys.Serialization.JavaScriptSerializer._serializeBooleanWithBuilder = function Sys$Serialization$JavaScriptSerializer$_serializeBooleanWithBuilder(object, stringBuilder) { + stringBuilder.append(object.toString()); +} +Sys.Serialization.JavaScriptSerializer._serializeNumberWithBuilder = function Sys$Serialization$JavaScriptSerializer$_serializeNumberWithBuilder(object, stringBuilder) { + if (isFinite(object)) { + stringBuilder.append(String(object)); + } + else { + throw Error.invalidOperation(Sys.Res.cannotSerializeNonFiniteNumbers); + } +} +Sys.Serialization.JavaScriptSerializer._serializeStringWithBuilder = function Sys$Serialization$JavaScriptSerializer$_serializeStringWithBuilder(string, stringBuilder) { + stringBuilder.append('"'); + if (Sys.Serialization.JavaScriptSerializer._escapeRegEx.test(string)) { + if (Sys.Serialization.JavaScriptSerializer._charsToEscape.length === 0) { + Sys.Serialization.JavaScriptSerializer._init(); + } + if (string.length < 128) { + string = string.replace(Sys.Serialization.JavaScriptSerializer._escapeRegExGlobal, + function(x) { return Sys.Serialization.JavaScriptSerializer._escapeChars[x]; }); + } + else { + for (var i = 0; i < 34; i++) { + var c = Sys.Serialization.JavaScriptSerializer._charsToEscape[i]; + if (string.indexOf(c) !== -1) { + if (Sys.Browser.agent === Sys.Browser.Opera || Sys.Browser.agent === Sys.Browser.FireFox) { + string = string.split(c).join(Sys.Serialization.JavaScriptSerializer._escapeChars[c]); + } + else { + string = string.replace(Sys.Serialization.JavaScriptSerializer._charsToEscapeRegExs[c], + Sys.Serialization.JavaScriptSerializer._escapeChars[c]); + } + } + } + } + } + stringBuilder.append(string); + stringBuilder.append('"'); +} +Sys.Serialization.JavaScriptSerializer._serializeWithBuilder = function Sys$Serialization$JavaScriptSerializer$_serializeWithBuilder(object, stringBuilder, sort, prevObjects) { + var i; + switch (typeof object) { + case 'object': + if (object) { + if (prevObjects){ + for( var j = 0; j < prevObjects.length; j++) { + if (prevObjects[j] === object) { + throw Error.invalidOperation(Sys.Res.cannotSerializeObjectWithCycle); + } + } + } + else { + prevObjects = new Array(); + } + try { + Array.add(prevObjects, object); + + if (Number.isInstanceOfType(object)){ + Sys.Serialization.JavaScriptSerializer._serializeNumberWithBuilder(object, stringBuilder); + } + else if (Boolean.isInstanceOfType(object)){ + Sys.Serialization.JavaScriptSerializer._serializeBooleanWithBuilder(object, stringBuilder); + } + else if (String.isInstanceOfType(object)){ + Sys.Serialization.JavaScriptSerializer._serializeStringWithBuilder(object, stringBuilder); + } + + else if (Array.isInstanceOfType(object)) { + stringBuilder.append('['); + + for (i = 0; i < object.length; ++i) { + if (i > 0) { + stringBuilder.append(','); + } + Sys.Serialization.JavaScriptSerializer._serializeWithBuilder(object[i], stringBuilder,false,prevObjects); + } + stringBuilder.append(']'); + } + else { + if (Date.isInstanceOfType(object)) { + stringBuilder.append('"\\/Date('); + stringBuilder.append(object.getTime()); + stringBuilder.append(')\\/"'); + break; + } + var properties = []; + var propertyCount = 0; + for (var name in object) { + if (name.startsWith('$')) { + continue; + } + if (name === Sys.Serialization.JavaScriptSerializer._serverTypeFieldName && propertyCount !== 0){ + properties[propertyCount++] = properties[0]; + properties[0] = name; + } + else{ + properties[propertyCount++] = name; + } + } + if (sort) properties.sort(); + stringBuilder.append('{'); + var needComma = false; + + for (i=0; i + /// + /// + var e = Function._validateParams(arguments, [ + {name: "object", mayBeNull: true} + ]); + if (e) throw e; + var stringBuilder = new Sys.StringBuilder(); + Sys.Serialization.JavaScriptSerializer._serializeWithBuilder(object, stringBuilder, false); + return stringBuilder.toString(); +} +Sys.Serialization.JavaScriptSerializer.deserialize = function Sys$Serialization$JavaScriptSerializer$deserialize(data, secure) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "data", type: String}, + {name: "secure", type: Boolean, optional: true} + ]); + if (e) throw e; + + if (data.length === 0) throw Error.argument('data', Sys.Res.cannotDeserializeEmptyString); + try { + var exp = data.replace(Sys.Serialization.JavaScriptSerializer._dateRegEx, "$1new Date($2)"); + + if (secure && Sys.Serialization.JavaScriptSerializer._jsonRegEx.test( + exp.replace(Sys.Serialization.JavaScriptSerializer._jsonStringRegEx, ''))) throw null; + return eval('(' + exp + ')'); + } + catch (e) { + throw Error.argument('data', Sys.Res.cannotDeserializeInvalidJson); + } +} +Type.registerNamespace('Sys.UI'); + +Sys.EventHandlerList = function Sys$EventHandlerList() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + this._list = {}; +} + function Sys$EventHandlerList$_addHandler(id, handler) { + Array.add(this._getEvent(id, true), handler); + } + function Sys$EventHandlerList$addHandler(id, handler) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "id", type: String}, + {name: "handler", type: Function} + ]); + if (e) throw e; + this._addHandler(id, handler); + } + function Sys$EventHandlerList$_removeHandler(id, handler) { + var evt = this._getEvent(id); + if (!evt) return; + Array.remove(evt, handler); + } + function Sys$EventHandlerList$removeHandler(id, handler) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "id", type: String}, + {name: "handler", type: Function} + ]); + if (e) throw e; + this._removeHandler(id, handler); + } + function Sys$EventHandlerList$getHandler(id) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "id", type: String} + ]); + if (e) throw e; + var evt = this._getEvent(id); + if (!evt || (evt.length === 0)) return null; + evt = Array.clone(evt); + return function(source, args) { + for (var i = 0, l = evt.length; i < l; i++) { + evt[i](source, args); + } + }; + } + function Sys$EventHandlerList$_getEvent(id, create) { + if (!this._list[id]) { + if (!create) return null; + this._list[id] = []; + } + return this._list[id]; + } +Sys.EventHandlerList.prototype = { + _addHandler: Sys$EventHandlerList$_addHandler, + addHandler: Sys$EventHandlerList$addHandler, + _removeHandler: Sys$EventHandlerList$_removeHandler, + removeHandler: Sys$EventHandlerList$removeHandler, + getHandler: Sys$EventHandlerList$getHandler, + _getEvent: Sys$EventHandlerList$_getEvent +} +Sys.EventHandlerList.registerClass('Sys.EventHandlerList'); +Sys.CommandEventArgs = function Sys$CommandEventArgs(commandName, commandArgument, commandSource) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "commandName", type: String}, + {name: "commandArgument", mayBeNull: true}, + {name: "commandSource", mayBeNull: true} + ]); + if (e) throw e; + Sys.CommandEventArgs.initializeBase(this); + this._commandName = commandName; + this._commandArgument = commandArgument; + this._commandSource = commandSource; +} + function Sys$CommandEventArgs$get_commandName() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._commandName; + } + function Sys$CommandEventArgs$get_commandArgument() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._commandArgument; + } + function Sys$CommandEventArgs$get_commandSource() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._commandSource; + } +Sys.CommandEventArgs.prototype = { + _commandName: null, + _commandArgument: null, + _commandSource: null, + get_commandName: Sys$CommandEventArgs$get_commandName, + get_commandArgument: Sys$CommandEventArgs$get_commandArgument, + get_commandSource: Sys$CommandEventArgs$get_commandSource +} +Sys.CommandEventArgs.registerClass("Sys.CommandEventArgs", Sys.CancelEventArgs); + +Sys.INotifyPropertyChange = function Sys$INotifyPropertyChange() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); +} + function Sys$INotifyPropertyChange$add_propertyChanged(handler) { + /// + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + throw Error.notImplemented(); + } + function Sys$INotifyPropertyChange$remove_propertyChanged(handler) { + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + throw Error.notImplemented(); + } +Sys.INotifyPropertyChange.prototype = { + add_propertyChanged: Sys$INotifyPropertyChange$add_propertyChanged, + remove_propertyChanged: Sys$INotifyPropertyChange$remove_propertyChanged +} +Sys.INotifyPropertyChange.registerInterface('Sys.INotifyPropertyChange'); + +Sys.PropertyChangedEventArgs = function Sys$PropertyChangedEventArgs(propertyName) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "propertyName", type: String} + ]); + if (e) throw e; + Sys.PropertyChangedEventArgs.initializeBase(this); + this._propertyName = propertyName; +} + + function Sys$PropertyChangedEventArgs$get_propertyName() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._propertyName; + } +Sys.PropertyChangedEventArgs.prototype = { + get_propertyName: Sys$PropertyChangedEventArgs$get_propertyName +} +Sys.PropertyChangedEventArgs.registerClass('Sys.PropertyChangedEventArgs', Sys.EventArgs); + +Sys.INotifyDisposing = function Sys$INotifyDisposing() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); +} + function Sys$INotifyDisposing$add_disposing(handler) { + /// + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + throw Error.notImplemented(); + } + function Sys$INotifyDisposing$remove_disposing(handler) { + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + throw Error.notImplemented(); + } +Sys.INotifyDisposing.prototype = { + add_disposing: Sys$INotifyDisposing$add_disposing, + remove_disposing: Sys$INotifyDisposing$remove_disposing +} +Sys.INotifyDisposing.registerInterface("Sys.INotifyDisposing"); + +Sys.Component = function Sys$Component() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (Sys.Application) Sys.Application.registerDisposableObject(this); +} + function Sys$Component$get_events() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (!this._events) { + this._events = new Sys.EventHandlerList(); + } + return this._events; + } + function Sys$Component$get_id() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._id; + } + function Sys$Component$set_id(value) { + var e = Function._validateParams(arguments, [{name: "value", type: String}]); + if (e) throw e; + if (this._idSet) throw Error.invalidOperation(Sys.Res.componentCantSetIdTwice); + this._idSet = true; + var oldId = this.get_id(); + if (oldId && Sys.Application.findComponent(oldId)) throw Error.invalidOperation(Sys.Res.componentCantSetIdAfterAddedToApp); + this._id = value; + } + function Sys$Component$get_isInitialized() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._initialized; + } + function Sys$Component$get_isUpdating() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._updating; + } + function Sys$Component$add_disposing(handler) { + /// + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this.get_events().addHandler("disposing", handler); + } + function Sys$Component$remove_disposing(handler) { + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this.get_events().removeHandler("disposing", handler); + } + function Sys$Component$add_propertyChanged(handler) { + /// + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this.get_events().addHandler("propertyChanged", handler); + } + function Sys$Component$remove_propertyChanged(handler) { + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this.get_events().removeHandler("propertyChanged", handler); + } + function Sys$Component$beginUpdate() { + this._updating = true; + } + function Sys$Component$dispose() { + if (this._events) { + var handler = this._events.getHandler("disposing"); + if (handler) { + handler(this, Sys.EventArgs.Empty); + } + } + delete this._events; + Sys.Application.unregisterDisposableObject(this); + Sys.Application.removeComponent(this); + } + function Sys$Component$endUpdate() { + this._updating = false; + if (!this._initialized) this.initialize(); + this.updated(); + } + function Sys$Component$initialize() { + this._initialized = true; + } + function Sys$Component$raisePropertyChanged(propertyName) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "propertyName", type: String} + ]); + if (e) throw e; + if (!this._events) return; + var handler = this._events.getHandler("propertyChanged"); + if (handler) { + handler(this, new Sys.PropertyChangedEventArgs(propertyName)); + } + } + function Sys$Component$updated() { + } +Sys.Component.prototype = { + _id: null, + _idSet: false, + _initialized: false, + _updating: false, + get_events: Sys$Component$get_events, + get_id: Sys$Component$get_id, + set_id: Sys$Component$set_id, + get_isInitialized: Sys$Component$get_isInitialized, + get_isUpdating: Sys$Component$get_isUpdating, + add_disposing: Sys$Component$add_disposing, + remove_disposing: Sys$Component$remove_disposing, + add_propertyChanged: Sys$Component$add_propertyChanged, + remove_propertyChanged: Sys$Component$remove_propertyChanged, + beginUpdate: Sys$Component$beginUpdate, + dispose: Sys$Component$dispose, + endUpdate: Sys$Component$endUpdate, + initialize: Sys$Component$initialize, + raisePropertyChanged: Sys$Component$raisePropertyChanged, + updated: Sys$Component$updated +} +Sys.Component.registerClass('Sys.Component', null, Sys.IDisposable, Sys.INotifyPropertyChange, Sys.INotifyDisposing); +function Sys$Component$_setProperties(target, properties) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target"}, + {name: "properties"} + ]); + if (e) throw e; + var current; + var targetType = Object.getType(target); + var isObject = (targetType === Object) || (targetType === Sys.UI.DomElement); + var isComponent = Sys.Component.isInstanceOfType(target) && !target.get_isUpdating(); + if (isComponent) target.beginUpdate(); + for (var name in properties) { + var val = properties[name]; + var getter = isObject ? null : target["get_" + name]; + if (isObject || typeof(getter) !== 'function') { + var targetVal = target[name]; + if (!isObject && typeof(targetVal) === 'undefined') throw Error.invalidOperation(String.format(Sys.Res.propertyUndefined, name)); + if (!val || (typeof(val) !== 'object') || (isObject && !targetVal)) { + target[name] = val; + } + else { + Sys$Component$_setProperties(targetVal, val); + } + } + else { + var setter = target["set_" + name]; + if (typeof(setter) === 'function') { + setter.apply(target, [val]); + } + else if (val instanceof Array) { + current = getter.apply(target); + if (!(current instanceof Array)) throw new Error.invalidOperation(String.format(Sys.Res.propertyNotAnArray, name)); + for (var i = 0, j = current.length, l= val.length; i < l; i++, j++) { + current[j] = val[i]; + } + } + else if ((typeof(val) === 'object') && (Object.getType(val) === Object)) { + current = getter.apply(target); + if ((typeof(current) === 'undefined') || (current === null)) throw new Error.invalidOperation(String.format(Sys.Res.propertyNullOrUndefined, name)); + Sys$Component$_setProperties(current, val); + } + else { + throw new Error.invalidOperation(String.format(Sys.Res.propertyNotWritable, name)); + } + } + } + if (isComponent) target.endUpdate(); +} +function Sys$Component$_setReferences(component, references) { + for (var name in references) { + var setter = component["set_" + name]; + var reference = $find(references[name]); + if (typeof(setter) !== 'function') throw new Error.invalidOperation(String.format(Sys.Res.propertyNotWritable, name)); + if (!reference) throw Error.invalidOperation(String.format(Sys.Res.referenceNotFound, references[name])); + setter.apply(component, [reference]); + } +} +var $create = Sys.Component.create = function Sys$Component$create(type, properties, events, references, element) { + /// + /// + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "type", type: Type}, + {name: "properties", mayBeNull: true, optional: true}, + {name: "events", mayBeNull: true, optional: true}, + {name: "references", mayBeNull: true, optional: true}, + {name: "element", mayBeNull: true, domElement: true, optional: true} + ]); + if (e) throw e; + if (!type.inheritsFrom(Sys.Component)) { + throw Error.argument('type', String.format(Sys.Res.createNotComponent, type.getName())); + } + if (type.inheritsFrom(Sys.UI.Behavior) || type.inheritsFrom(Sys.UI.Control)) { + if (!element) throw Error.argument('element', Sys.Res.createNoDom); + } + else if (element) throw Error.argument('element', Sys.Res.createComponentOnDom); + var component = (element ? new type(element): new type()); + var app = Sys.Application; + var creatingComponents = app.get_isCreatingComponents(); + component.beginUpdate(); + if (properties) { + Sys$Component$_setProperties(component, properties); + } + if (events) { + for (var name in events) { + if (!(component["add_" + name] instanceof Function)) throw new Error.invalidOperation(String.format(Sys.Res.undefinedEvent, name)); + if (!(events[name] instanceof Function)) throw new Error.invalidOperation(Sys.Res.eventHandlerNotFunction); + component["add_" + name](events[name]); + } + } + if (component.get_id()) { + app.addComponent(component); + } + if (creatingComponents) { + app._createdComponents[app._createdComponents.length] = component; + if (references) { + app._addComponentToSecondPass(component, references); + } + else { + component.endUpdate(); + } + } + else { + if (references) { + Sys$Component$_setReferences(component, references); + } + component.endUpdate(); + } + return component; +} + +Sys.UI.MouseButton = function Sys$UI$MouseButton() { + /// + /// + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); +} +Sys.UI.MouseButton.prototype = { + leftButton: 0, + middleButton: 1, + rightButton: 2 +} +Sys.UI.MouseButton.registerEnum("Sys.UI.MouseButton"); + +Sys.UI.Key = function Sys$UI$Key() { + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); +} +Sys.UI.Key.prototype = { + backspace: 8, + tab: 9, + enter: 13, + esc: 27, + space: 32, + pageUp: 33, + pageDown: 34, + end: 35, + home: 36, + left: 37, + up: 38, + right: 39, + down: 40, + del: 127 +} +Sys.UI.Key.registerEnum("Sys.UI.Key"); + +Sys.UI.Point = function Sys$UI$Point(x, y) { + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "x", type: Number, integer: true}, + {name: "y", type: Number, integer: true} + ]); + if (e) throw e; + this.x = x; + this.y = y; +} +Sys.UI.Point.registerClass('Sys.UI.Point'); + +Sys.UI.Bounds = function Sys$UI$Bounds(x, y, width, height) { + /// + /// + /// + /// + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "x", type: Number, integer: true}, + {name: "y", type: Number, integer: true}, + {name: "width", type: Number, integer: true}, + {name: "height", type: Number, integer: true} + ]); + if (e) throw e; + this.x = x; + this.y = y; + this.height = height; + this.width = width; +} +Sys.UI.Bounds.registerClass('Sys.UI.Bounds'); + +Sys.UI.DomEvent = function Sys$UI$DomEvent(eventObject) { + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "eventObject"} + ]); + if (e) throw e; + var ev = eventObject; + var etype = this.type = ev.type.toLowerCase(); + this.rawEvent = ev; + this.altKey = ev.altKey; + if (typeof(ev.button) !== 'undefined') { + this.button = (typeof(ev.which) !== 'undefined') ? ev.button : + (ev.button === 4) ? Sys.UI.MouseButton.middleButton : + (ev.button === 2) ? Sys.UI.MouseButton.rightButton : + Sys.UI.MouseButton.leftButton; + } + if (etype === 'keypress') { + this.charCode = ev.charCode || ev.keyCode; + } + else if (ev.keyCode && (ev.keyCode === 46)) { + this.keyCode = 127; + } + else { + this.keyCode = ev.keyCode; + } + this.clientX = ev.clientX; + this.clientY = ev.clientY; + this.ctrlKey = ev.ctrlKey; + this.target = ev.target ? ev.target : ev.srcElement; + if (!etype.startsWith('key')) { + if ((typeof(ev.offsetX) !== 'undefined') && (typeof(ev.offsetY) !== 'undefined')) { + this.offsetX = ev.offsetX; + this.offsetY = ev.offsetY; + } + else if (this.target && (this.target.nodeType !== 3) && (typeof(ev.clientX) === 'number')) { + var loc = Sys.UI.DomElement.getLocation(this.target); + var w = Sys.UI.DomElement._getWindow(this.target); + this.offsetX = (w.pageXOffset || 0) + ev.clientX - loc.x; + this.offsetY = (w.pageYOffset || 0) + ev.clientY - loc.y; + } + } + this.screenX = ev.screenX; + this.screenY = ev.screenY; + this.shiftKey = ev.shiftKey; +} + function Sys$UI$DomEvent$preventDefault() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (this.rawEvent.preventDefault) { + this.rawEvent.preventDefault(); + } + else if (window.event) { + this.rawEvent.returnValue = false; + } + } + function Sys$UI$DomEvent$stopPropagation() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (this.rawEvent.stopPropagation) { + this.rawEvent.stopPropagation(); + } + else if (window.event) { + this.rawEvent.cancelBubble = true; + } + } +Sys.UI.DomEvent.prototype = { + preventDefault: Sys$UI$DomEvent$preventDefault, + stopPropagation: Sys$UI$DomEvent$stopPropagation +} +Sys.UI.DomEvent.registerClass('Sys.UI.DomEvent'); +var $addHandler = Sys.UI.DomEvent.addHandler = function Sys$UI$DomEvent$addHandler(element, eventName, handler, autoRemove) { + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element"}, + {name: "eventName", type: String}, + {name: "handler", type: Function}, + {name: "autoRemove", type: Boolean, optional: true} + ]); + if (e) throw e; + Sys.UI.DomEvent._ensureDomNode(element); + if (eventName === "error") throw Error.invalidOperation(Sys.Res.addHandlerCantBeUsedForError); + if (!element._events) { + element._events = {}; + } + var eventCache = element._events[eventName]; + if (!eventCache) { + element._events[eventName] = eventCache = []; + } + var browserHandler; + if (element.addEventListener) { + browserHandler = function(e) { + return handler.call(element, new Sys.UI.DomEvent(e)); + } + element.addEventListener(eventName, browserHandler, false); + } + else if (element.attachEvent) { + browserHandler = function() { + var e = {}; + try {e = Sys.UI.DomElement._getWindow(element).event} catch(ex) {} + return handler.call(element, new Sys.UI.DomEvent(e)); + } + element.attachEvent('on' + eventName, browserHandler); + } + eventCache[eventCache.length] = {handler: handler, browserHandler: browserHandler, autoRemove: autoRemove }; + if (autoRemove) { + var d = element.dispose; + if (d !== Sys.UI.DomEvent._disposeHandlers) { + element.dispose = Sys.UI.DomEvent._disposeHandlers; + if (typeof(d) !== "undefined") { + element._chainDispose = d; + } + } + } +} +var $addHandlers = Sys.UI.DomEvent.addHandlers = function Sys$UI$DomEvent$addHandlers(element, events, handlerOwner, autoRemove) { + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element"}, + {name: "events", type: Object}, + {name: "handlerOwner", optional: true}, + {name: "autoRemove", type: Boolean, optional: true} + ]); + if (e) throw e; + Sys.UI.DomEvent._ensureDomNode(element); + for (var name in events) { + var handler = events[name]; + if (typeof(handler) !== 'function') throw Error.invalidOperation(Sys.Res.cantAddNonFunctionhandler); + if (handlerOwner) { + handler = Function.createDelegate(handlerOwner, handler); + } + $addHandler(element, name, handler, autoRemove || false); + } +} +var $clearHandlers = Sys.UI.DomEvent.clearHandlers = function Sys$UI$DomEvent$clearHandlers(element) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element"} + ]); + if (e) throw e; + Sys.UI.DomEvent._ensureDomNode(element); + Sys.UI.DomEvent._clearHandlers(element, false); +} +Sys.UI.DomEvent._clearHandlers = function Sys$UI$DomEvent$_clearHandlers(element, autoRemoving) { + if (element._events) { + var cache = element._events; + for (var name in cache) { + var handlers = cache[name]; + for (var i = handlers.length - 1; i >= 0; i--) { + var entry = handlers[i]; + if (!autoRemoving || entry.autoRemove) { + $removeHandler(element, name, entry.handler); + } + } + } + element._events = null; + } +} +Sys.UI.DomEvent._disposeHandlers = function Sys$UI$DomEvent$_disposeHandlers() { + Sys.UI.DomEvent._clearHandlers(this, true); + var d = this._chainDispose, type = typeof(d); + if (type !== "undefined") { + this.dispose = d; + this._chainDispose = null; + if (type === "function") { + this.dispose(); + } + } +} +var $removeHandler = Sys.UI.DomEvent.removeHandler = function Sys$UI$DomEvent$removeHandler(element, eventName, handler) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element"}, + {name: "eventName", type: String}, + {name: "handler", type: Function} + ]); + if (e) throw e; + Sys.UI.DomEvent._removeHandler(element, eventName, handler); +} +Sys.UI.DomEvent._removeHandler = function Sys$UI$DomEvent$_removeHandler(element, eventName, handler) { + Sys.UI.DomEvent._ensureDomNode(element); + var browserHandler = null; + if ((typeof(element._events) !== 'object') || !element._events) throw Error.invalidOperation(Sys.Res.eventHandlerInvalid); + var cache = element._events[eventName]; + if (!(cache instanceof Array)) throw Error.invalidOperation(Sys.Res.eventHandlerInvalid); + for (var i = 0, l = cache.length; i < l; i++) { + if (cache[i].handler === handler) { + browserHandler = cache[i].browserHandler; + break; + } + } + if (typeof(browserHandler) !== 'function') throw Error.invalidOperation(Sys.Res.eventHandlerInvalid); + if (element.removeEventListener) { + element.removeEventListener(eventName, browserHandler, false); + } + else if (element.detachEvent) { + element.detachEvent('on' + eventName, browserHandler); + } + cache.splice(i, 1); +} +Sys.UI.DomEvent._ensureDomNode = function Sys$UI$DomEvent$_ensureDomNode(element) { + if (element.tagName && (element.tagName.toUpperCase() === "SCRIPT")) return; + + var doc = element.ownerDocument || element.document || element; + if ((typeof(element.document) !== 'object') && (element != doc) && (typeof(element.nodeType) !== 'number')) { + throw Error.argument("element", Sys.Res.argumentDomNode); + } +} + +Sys.UI.DomElement = function Sys$UI$DomElement() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); +} +Sys.UI.DomElement.registerClass('Sys.UI.DomElement'); +Sys.UI.DomElement.addCssClass = function Sys$UI$DomElement$addCssClass(element, className) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true}, + {name: "className", type: String} + ]); + if (e) throw e; + if (!Sys.UI.DomElement.containsCssClass(element, className)) { + if (element.className === '') { + element.className = className; + } + else { + element.className += ' ' + className; + } + } +} +Sys.UI.DomElement.containsCssClass = function Sys$UI$DomElement$containsCssClass(element, className) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true}, + {name: "className", type: String} + ]); + if (e) throw e; + return Array.contains(element.className.split(' '), className); +} +Sys.UI.DomElement.getBounds = function Sys$UI$DomElement$getBounds(element) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true} + ]); + if (e) throw e; + var offset = Sys.UI.DomElement.getLocation(element); + return new Sys.UI.Bounds(offset.x, offset.y, element.offsetWidth || 0, element.offsetHeight || 0); +} +var $get = Sys.UI.DomElement.getElementById = function Sys$UI$DomElement$getElementById(id, element) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "id", type: String}, + {name: "element", mayBeNull: true, domElement: true, optional: true} + ]); + if (e) throw e; + if (!element) return document.getElementById(id); + if (element.getElementById) return element.getElementById(id); + var nodeQueue = []; + var childNodes = element.childNodes; + for (var i = 0; i < childNodes.length; i++) { + var node = childNodes[i]; + if (node.nodeType == 1) { + nodeQueue[nodeQueue.length] = node; + } + } + while (nodeQueue.length) { + node = nodeQueue.shift(); + if (node.id == id) { + return node; + } + childNodes = node.childNodes; + for (i = 0; i < childNodes.length; i++) { + node = childNodes[i]; + if (node.nodeType == 1) { + nodeQueue[nodeQueue.length] = node; + } + } + } + return null; +} +if (document.documentElement.getBoundingClientRect) { + Sys.UI.DomElement.getLocation = function Sys$UI$DomElement$getLocation(element) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true} + ]); + if (e) throw e; + if (element.self || element.nodeType === 9) return new Sys.UI.Point(0,0); + var clientRect = element.getBoundingClientRect(); + if (!clientRect) { + return new Sys.UI.Point(0,0); + } + var documentElement = element.ownerDocument.documentElement, + offsetX = Math.floor(clientRect.left + 0.5) + documentElement.scrollLeft, + offsetY = Math.floor(clientRect.top + 0.5) + documentElement.scrollTop; + if (Sys.Browser.agent === Sys.Browser.InternetExplorer) { + try { + var f = element.ownerDocument.parentWindow.frameElement || null; + if (f) { + var offset = (f.frameBorder === "0" || f.frameBorder === "no") ? 2 : 0; + offsetX += offset; + offsetY += offset; + } + } + catch(ex) { + } + if (Sys.Browser.version <= 7) { + + var multiplier, before, rect, d = document.createElement("div"); + d.style.cssText = "position:absolute !important;left:0px !important;right:0px !important;height:0px !important;width:1px !important;display:hidden !important"; + try { + before = document.body.childNodes[0]; + document.body.insertBefore(d, before); + rect = d.getBoundingClientRect(); + document.body.removeChild(d); + multiplier = (rect.right - rect.left); + } + catch (e) { + } + if (multiplier && (multiplier !== 1)) { + offsetX = Math.floor(offsetX / multiplier); + offsetY = Math.floor(offsetY / multiplier); + } + } + if ((document.documentMode || 0) < 8) { + offsetX -= 2; + offsetY -= 2; + } + } + return new Sys.UI.Point(offsetX, offsetY); + } +} +else if (Sys.Browser.agent === Sys.Browser.Safari) { + Sys.UI.DomElement.getLocation = function Sys$UI$DomElement$getLocation(element) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true} + ]); + if (e) throw e; + if ((element.window && (element.window === element)) || element.nodeType === 9) return new Sys.UI.Point(0,0); + var offsetX = 0, offsetY = 0, + parent, + previous = null, + previousStyle = null, + currentStyle; + for (parent = element; parent; previous = parent, previousStyle = currentStyle, parent = parent.offsetParent) { + currentStyle = Sys.UI.DomElement._getCurrentStyle(parent); + var tagName = parent.tagName ? parent.tagName.toUpperCase() : null; + if ((parent.offsetLeft || parent.offsetTop) && + ((tagName !== "BODY") || (!previousStyle || previousStyle.position !== "absolute"))) { + offsetX += parent.offsetLeft; + offsetY += parent.offsetTop; + } + if (previous && Sys.Browser.version >= 3) { + offsetX += parseInt(currentStyle.borderLeftWidth); + offsetY += parseInt(currentStyle.borderTopWidth); + } + } + currentStyle = Sys.UI.DomElement._getCurrentStyle(element); + var elementPosition = currentStyle ? currentStyle.position : null; + if (!elementPosition || (elementPosition !== "absolute")) { + for (parent = element.parentNode; parent; parent = parent.parentNode) { + tagName = parent.tagName ? parent.tagName.toUpperCase() : null; + if ((tagName !== "BODY") && (tagName !== "HTML") && (parent.scrollLeft || parent.scrollTop)) { + offsetX -= (parent.scrollLeft || 0); + offsetY -= (parent.scrollTop || 0); + } + currentStyle = Sys.UI.DomElement._getCurrentStyle(parent); + var parentPosition = currentStyle ? currentStyle.position : null; + if (parentPosition && (parentPosition === "absolute")) break; + } + } + return new Sys.UI.Point(offsetX, offsetY); + } +} +else { + Sys.UI.DomElement.getLocation = function Sys$UI$DomElement$getLocation(element) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true} + ]); + if (e) throw e; + if ((element.window && (element.window === element)) || element.nodeType === 9) return new Sys.UI.Point(0,0); + var offsetX = 0, offsetY = 0, + parent, + previous = null, + previousStyle = null, + currentStyle = null; + for (parent = element; parent; previous = parent, previousStyle = currentStyle, parent = parent.offsetParent) { + var tagName = parent.tagName ? parent.tagName.toUpperCase() : null; + currentStyle = Sys.UI.DomElement._getCurrentStyle(parent); + if ((parent.offsetLeft || parent.offsetTop) && + !((tagName === "BODY") && + (!previousStyle || previousStyle.position !== "absolute"))) { + offsetX += parent.offsetLeft; + offsetY += parent.offsetTop; + } + if (previous !== null && currentStyle) { + if ((tagName !== "TABLE") && (tagName !== "TD") && (tagName !== "HTML")) { + offsetX += parseInt(currentStyle.borderLeftWidth) || 0; + offsetY += parseInt(currentStyle.borderTopWidth) || 0; + } + if (tagName === "TABLE" && + (currentStyle.position === "relative" || currentStyle.position === "absolute")) { + offsetX += parseInt(currentStyle.marginLeft) || 0; + offsetY += parseInt(currentStyle.marginTop) || 0; + } + } + } + currentStyle = Sys.UI.DomElement._getCurrentStyle(element); + var elementPosition = currentStyle ? currentStyle.position : null; + if (!elementPosition || (elementPosition !== "absolute")) { + for (parent = element.parentNode; parent; parent = parent.parentNode) { + tagName = parent.tagName ? parent.tagName.toUpperCase() : null; + if ((tagName !== "BODY") && (tagName !== "HTML") && (parent.scrollLeft || parent.scrollTop)) { + offsetX -= (parent.scrollLeft || 0); + offsetY -= (parent.scrollTop || 0); + currentStyle = Sys.UI.DomElement._getCurrentStyle(parent); + if (currentStyle) { + offsetX += parseInt(currentStyle.borderLeftWidth) || 0; + offsetY += parseInt(currentStyle.borderTopWidth) || 0; + } + } + } + } + return new Sys.UI.Point(offsetX, offsetY); + } +} +Sys.UI.DomElement.isDomElement = function Sys$UI$DomElement$isDomElement(obj) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "obj"} + ]); + if (e) throw e; + return Sys._isDomElement(obj); +} +Sys.UI.DomElement.removeCssClass = function Sys$UI$DomElement$removeCssClass(element, className) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true}, + {name: "className", type: String} + ]); + if (e) throw e; + var currentClassName = ' ' + element.className + ' '; + var index = currentClassName.indexOf(' ' + className + ' '); + if (index >= 0) { + element.className = (currentClassName.substr(0, index) + ' ' + + currentClassName.substring(index + className.length + 1, currentClassName.length)).trim(); + } +} +Sys.UI.DomElement.resolveElement = function Sys$UI$DomElement$resolveElement(elementOrElementId, containerElement) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "elementOrElementId", mayBeNull: true}, + {name: "containerElement", mayBeNull: true, domElement: true, optional: true} + ]); + if (e) throw e; + var el = elementOrElementId; + if (!el) return null; + if (typeof(el) === "string") { + el = Sys.UI.DomElement.getElementById(el, containerElement); + if (!el) { + throw Error.argument("elementOrElementId", String.format(Sys.Res.elementNotFound, elementOrElementId)); + } + } + else if(!Sys.UI.DomElement.isDomElement(el)) { + throw Error.argument("elementOrElementId", Sys.Res.expectedElementOrId); + } + return el; +} +Sys.UI.DomElement.raiseBubbleEvent = function Sys$UI$DomElement$raiseBubbleEvent(source, args) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "source", domElement: true}, + {name: "args", type: Sys.EventArgs} + ]); + if (e) throw e; + var target = source; + while (target) { + var control = target.control; + if (control && control.onBubbleEvent && control.raiseBubbleEvent) { + Sys.UI.DomElement._raiseBubbleEventFromControl(control, source, args); + return; + } + target = target.parentNode; + } +} +Sys.UI.DomElement._raiseBubbleEventFromControl = function Sys$UI$DomElement$_raiseBubbleEventFromControl(control, source, args) { + if (!control.onBubbleEvent(source, args)) { + control._raiseBubbleEvent(source, args); + } +} +Sys.UI.DomElement.setLocation = function Sys$UI$DomElement$setLocation(element, x, y) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true}, + {name: "x", type: Number, integer: true}, + {name: "y", type: Number, integer: true} + ]); + if (e) throw e; + var style = element.style; + style.position = 'absolute'; + style.left = x + "px"; + style.top = y + "px"; +} +Sys.UI.DomElement.toggleCssClass = function Sys$UI$DomElement$toggleCssClass(element, className) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true}, + {name: "className", type: String} + ]); + if (e) throw e; + if (Sys.UI.DomElement.containsCssClass(element, className)) { + Sys.UI.DomElement.removeCssClass(element, className); + } + else { + Sys.UI.DomElement.addCssClass(element, className); + } +} +Sys.UI.DomElement.getVisibilityMode = function Sys$UI$DomElement$getVisibilityMode(element) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true} + ]); + if (e) throw e; + return (element._visibilityMode === Sys.UI.VisibilityMode.hide) ? + Sys.UI.VisibilityMode.hide : + Sys.UI.VisibilityMode.collapse; +} +Sys.UI.DomElement.setVisibilityMode = function Sys$UI$DomElement$setVisibilityMode(element, value) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true}, + {name: "value", type: Sys.UI.VisibilityMode} + ]); + if (e) throw e; + Sys.UI.DomElement._ensureOldDisplayMode(element); + if (element._visibilityMode !== value) { + element._visibilityMode = value; + if (Sys.UI.DomElement.getVisible(element) === false) { + if (element._visibilityMode === Sys.UI.VisibilityMode.hide) { + element.style.display = element._oldDisplayMode; + } + else { + element.style.display = 'none'; + } + } + element._visibilityMode = value; + } +} +Sys.UI.DomElement.getVisible = function Sys$UI$DomElement$getVisible(element) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true} + ]); + if (e) throw e; + var style = element.currentStyle || Sys.UI.DomElement._getCurrentStyle(element); + if (!style) return true; + return (style.visibility !== 'hidden') && (style.display !== 'none'); +} +Sys.UI.DomElement.setVisible = function Sys$UI$DomElement$setVisible(element, value) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true}, + {name: "value", type: Boolean} + ]); + if (e) throw e; + if (value !== Sys.UI.DomElement.getVisible(element)) { + Sys.UI.DomElement._ensureOldDisplayMode(element); + element.style.visibility = value ? 'visible' : 'hidden'; + if (value || (element._visibilityMode === Sys.UI.VisibilityMode.hide)) { + element.style.display = element._oldDisplayMode; + } + else { + element.style.display = 'none'; + } + } +} +Sys.UI.DomElement._ensureOldDisplayMode = function Sys$UI$DomElement$_ensureOldDisplayMode(element) { + if (!element._oldDisplayMode) { + var style = element.currentStyle || Sys.UI.DomElement._getCurrentStyle(element); + element._oldDisplayMode = style ? style.display : null; + if (!element._oldDisplayMode || element._oldDisplayMode === 'none') { + switch(element.tagName.toUpperCase()) { + case 'DIV': case 'P': case 'ADDRESS': case 'BLOCKQUOTE': case 'BODY': case 'COL': + case 'COLGROUP': case 'DD': case 'DL': case 'DT': case 'FIELDSET': case 'FORM': + case 'H1': case 'H2': case 'H3': case 'H4': case 'H5': case 'H6': case 'HR': + case 'IFRAME': case 'LEGEND': case 'OL': case 'PRE': case 'TABLE': case 'TD': + case 'TH': case 'TR': case 'UL': + element._oldDisplayMode = 'block'; + break; + case 'LI': + element._oldDisplayMode = 'list-item'; + break; + default: + element._oldDisplayMode = 'inline'; + } + } + } +} +Sys.UI.DomElement._getWindow = function Sys$UI$DomElement$_getWindow(element) { + var doc = element.ownerDocument || element.document || element; + return doc.defaultView || doc.parentWindow; +} +Sys.UI.DomElement._getCurrentStyle = function Sys$UI$DomElement$_getCurrentStyle(element) { + if (element.nodeType === 3) return null; + var w = Sys.UI.DomElement._getWindow(element); + if (element.documentElement) element = element.documentElement; + var computedStyle = (w && (element !== w) && w.getComputedStyle) ? + w.getComputedStyle(element, null) : + element.currentStyle || element.style; + if (!computedStyle && (Sys.Browser.agent === Sys.Browser.Safari) && element.style) { + var oldDisplay = element.style.display; + var oldPosition = element.style.position; + element.style.position = 'absolute'; + element.style.display = 'block'; + var style = w.getComputedStyle(element, null); + element.style.display = oldDisplay; + element.style.position = oldPosition; + computedStyle = {}; + for (var n in style) { + computedStyle[n] = style[n]; + } + computedStyle.display = 'none'; + } + return computedStyle; +} + +Sys.IContainer = function Sys$IContainer() { + throw Error.notImplemented(); +} + function Sys$IContainer$addComponent(component) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "component", type: Sys.Component} + ]); + if (e) throw e; + throw Error.notImplemented(); + } + function Sys$IContainer$removeComponent(component) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "component", type: Sys.Component} + ]); + if (e) throw e; + throw Error.notImplemented(); + } + function Sys$IContainer$findComponent(id) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "id", type: String} + ]); + if (e) throw e; + throw Error.notImplemented(); + } + function Sys$IContainer$getComponents() { + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); + } +Sys.IContainer.prototype = { + addComponent: Sys$IContainer$addComponent, + removeComponent: Sys$IContainer$removeComponent, + findComponent: Sys$IContainer$findComponent, + getComponents: Sys$IContainer$getComponents +} +Sys.IContainer.registerInterface("Sys.IContainer"); + +Sys.ApplicationLoadEventArgs = function Sys$ApplicationLoadEventArgs(components, isPartialLoad) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "components", type: Array, elementType: Sys.Component}, + {name: "isPartialLoad", type: Boolean} + ]); + if (e) throw e; + Sys.ApplicationLoadEventArgs.initializeBase(this); + this._components = components; + this._isPartialLoad = isPartialLoad; +} + + function Sys$ApplicationLoadEventArgs$get_components() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._components; + } + function Sys$ApplicationLoadEventArgs$get_isPartialLoad() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._isPartialLoad; + } +Sys.ApplicationLoadEventArgs.prototype = { + get_components: Sys$ApplicationLoadEventArgs$get_components, + get_isPartialLoad: Sys$ApplicationLoadEventArgs$get_isPartialLoad +} +Sys.ApplicationLoadEventArgs.registerClass('Sys.ApplicationLoadEventArgs', Sys.EventArgs); + +Sys._Application = function Sys$_Application() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + Sys._Application.initializeBase(this); + this._disposableObjects = []; + this._components = {}; + this._createdComponents = []; + this._secondPassComponents = []; + this._unloadHandlerDelegate = Function.createDelegate(this, this._unloadHandler); + Sys.UI.DomEvent.addHandler(window, "unload", this._unloadHandlerDelegate); + this._domReady(); +} + function Sys$_Application$get_isCreatingComponents() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._creatingComponents; + } + function Sys$_Application$get_isDisposing() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._disposing; + } + function Sys$_Application$add_init(handler) { + /// + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + if (this._initialized) { + handler(this, Sys.EventArgs.Empty); + } + else { + this.get_events().addHandler("init", handler); + } + } + function Sys$_Application$remove_init(handler) { + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this.get_events().removeHandler("init", handler); + } + function Sys$_Application$add_load(handler) { + /// + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this.get_events().addHandler("load", handler); + } + function Sys$_Application$remove_load(handler) { + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this.get_events().removeHandler("load", handler); + } + function Sys$_Application$add_unload(handler) { + /// + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this.get_events().addHandler("unload", handler); + } + function Sys$_Application$remove_unload(handler) { + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this.get_events().removeHandler("unload", handler); + } + function Sys$_Application$addComponent(component) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "component", type: Sys.Component} + ]); + if (e) throw e; + var id = component.get_id(); + if (!id) throw Error.invalidOperation(Sys.Res.cantAddWithoutId); + if (typeof(this._components[id]) !== 'undefined') throw Error.invalidOperation(String.format(Sys.Res.appDuplicateComponent, id)); + this._components[id] = component; + } + function Sys$_Application$beginCreateComponents() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + this._creatingComponents = true; + } + function Sys$_Application$dispose() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (!this._disposing) { + this._disposing = true; + if (this._timerCookie) { + window.clearTimeout(this._timerCookie); + delete this._timerCookie; + } + if (this._endRequestHandler) { + Sys.WebForms.PageRequestManager.getInstance().remove_endRequest(this._endRequestHandler); + delete this._endRequestHandler; + } + if (this._beginRequestHandler) { + Sys.WebForms.PageRequestManager.getInstance().remove_beginRequest(this._beginRequestHandler); + delete this._beginRequestHandler; + } + if (window.pageUnload) { + window.pageUnload(this, Sys.EventArgs.Empty); + } + var unloadHandler = this.get_events().getHandler("unload"); + if (unloadHandler) { + unloadHandler(this, Sys.EventArgs.Empty); + } + var disposableObjects = Array.clone(this._disposableObjects); + for (var i = 0, l = disposableObjects.length; i < l; i++) { + var object = disposableObjects[i]; + if (typeof(object) !== "undefined") { + object.dispose(); + } + } + Array.clear(this._disposableObjects); + Sys.UI.DomEvent.removeHandler(window, "unload", this._unloadHandlerDelegate); + if (Sys._ScriptLoader) { + var sl = Sys._ScriptLoader.getInstance(); + if(sl) { + sl.dispose(); + } + } + Sys._Application.callBaseMethod(this, 'dispose'); + } + } + function Sys$_Application$disposeElement(element, childNodesOnly) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element"}, + {name: "childNodesOnly", type: Boolean} + ]); + if (e) throw e; + if (element.nodeType === 1) { + var children = element.getElementsByTagName("*"); + for (var i = children.length - 1; i >= 0; i--) { + this._disposeElementInternal(children[i]); + } + if (!childNodesOnly) { + this._disposeElementInternal(element); + } + } + } + function Sys$_Application$endCreateComponents() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + var components = this._secondPassComponents; + for (var i = 0, l = components.length; i < l; i++) { + var component = components[i].component; + Sys$Component$_setReferences(component, components[i].references); + component.endUpdate(); + } + this._secondPassComponents = []; + this._creatingComponents = false; + } + function Sys$_Application$findComponent(id, parent) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "id", type: String}, + {name: "parent", mayBeNull: true, optional: true} + ]); + if (e) throw e; + return (parent ? + ((Sys.IContainer.isInstanceOfType(parent)) ? + parent.findComponent(id) : + parent[id] || null) : + Sys.Application._components[id] || null); + } + function Sys$_Application$getComponents() { + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + var res = []; + var components = this._components; + for (var name in components) { + res[res.length] = components[name]; + } + return res; + } + function Sys$_Application$initialize() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if(!this.get_isInitialized() && !this._disposing) { + Sys._Application.callBaseMethod(this, 'initialize'); + this._raiseInit(); + if (this.get_stateString) { + if (Sys.WebForms && Sys.WebForms.PageRequestManager) { + this._beginRequestHandler = Function.createDelegate(this, this._onPageRequestManagerBeginRequest); + Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(this._beginRequestHandler); + this._endRequestHandler = Function.createDelegate(this, this._onPageRequestManagerEndRequest); + Sys.WebForms.PageRequestManager.getInstance().add_endRequest(this._endRequestHandler); + } + var loadedEntry = this.get_stateString(); + if (loadedEntry !== this._currentEntry) { + this._navigate(loadedEntry); + } + else { + this._ensureHistory(); + } + } + this.raiseLoad(); + } + } + function Sys$_Application$notifyScriptLoaded() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + } + function Sys$_Application$registerDisposableObject(object) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "object", type: Sys.IDisposable} + ]); + if (e) throw e; + if (!this._disposing) { + var objects = this._disposableObjects, + i = objects.length; + objects[i] = object; + object.__msdisposeindex = i; + } + } + function Sys$_Application$raiseLoad() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + var h = this.get_events().getHandler("load"); + var args = new Sys.ApplicationLoadEventArgs(Array.clone(this._createdComponents), !!this._loaded); + this._loaded = true; + if (h) { + h(this, args); + } + if (window.pageLoad) { + window.pageLoad(this, args); + } + this._createdComponents = []; + } + function Sys$_Application$removeComponent(component) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "component", type: Sys.Component} + ]); + if (e) throw e; + var id = component.get_id(); + if (id) delete this._components[id]; + } + function Sys$_Application$unregisterDisposableObject(object) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "object", type: Sys.IDisposable} + ]); + if (e) throw e; + if (!this._disposing) { + var i = object.__msdisposeindex; + if (typeof(i) === "number") { + var disposableObjects = this._disposableObjects; + delete disposableObjects[i]; + delete object.__msdisposeindex; + if (++this._deleteCount > 1000) { + var newArray = []; + for (var j = 0, l = disposableObjects.length; j < l; j++) { + object = disposableObjects[j]; + if (typeof(object) !== "undefined") { + object.__msdisposeindex = newArray.length; + newArray.push(object); + } + } + this._disposableObjects = newArray; + this._deleteCount = 0; + } + } + } + } + function Sys$_Application$_addComponentToSecondPass(component, references) { + this._secondPassComponents[this._secondPassComponents.length] = {component: component, references: references}; + } + function Sys$_Application$_disposeComponents(list) { + if (list) { + for (var i = list.length - 1; i >= 0; i--) { + var item = list[i]; + if (typeof(item.dispose) === "function") { + item.dispose(); + } + } + } + } + function Sys$_Application$_disposeElementInternal(element) { + var d = element.dispose; + if (d && typeof(d) === "function") { + element.dispose(); + } + else { + var c = element.control; + if (c && typeof(c.dispose) === "function") { + c.dispose(); + } + } + var list = element._behaviors; + if (list) { + this._disposeComponents(list); + } + list = element._components; + if (list) { + this._disposeComponents(list); + element._components = null; + } + } + function Sys$_Application$_domReady() { + var check, er, app = this; + function init() { app.initialize(); } + var onload = function() { + Sys.UI.DomEvent.removeHandler(window, "load", onload); + init(); + } + Sys.UI.DomEvent.addHandler(window, "load", onload); + + if (document.addEventListener) { + try { + document.addEventListener("DOMContentLoaded", check = function() { + document.removeEventListener("DOMContentLoaded", check, false); + init(); + }, false); + } + catch (er) { } + } + else if (document.attachEvent) { + if ((window == window.top) && document.documentElement.doScroll) { + var timeout, el = document.createElement("div"); + check = function() { + try { + el.doScroll("left"); + } + catch (er) { + timeout = window.setTimeout(check, 0); + return; + } + el = null; + init(); + } + check(); + } + else { + document.attachEvent("onreadystatechange", check = function() { + if (document.readyState === "complete") { + document.detachEvent("onreadystatechange", check); + init(); + } + }); + } + } + } + function Sys$_Application$_raiseInit() { + var handler = this.get_events().getHandler("init"); + if (handler) { + this.beginCreateComponents(); + handler(this, Sys.EventArgs.Empty); + this.endCreateComponents(); + } + } + function Sys$_Application$_unloadHandler(event) { + this.dispose(); + } +Sys._Application.prototype = { + _creatingComponents: false, + _disposing: false, + _deleteCount: 0, + get_isCreatingComponents: Sys$_Application$get_isCreatingComponents, + get_isDisposing: Sys$_Application$get_isDisposing, + add_init: Sys$_Application$add_init, + remove_init: Sys$_Application$remove_init, + add_load: Sys$_Application$add_load, + remove_load: Sys$_Application$remove_load, + add_unload: Sys$_Application$add_unload, + remove_unload: Sys$_Application$remove_unload, + addComponent: Sys$_Application$addComponent, + beginCreateComponents: Sys$_Application$beginCreateComponents, + dispose: Sys$_Application$dispose, + disposeElement: Sys$_Application$disposeElement, + endCreateComponents: Sys$_Application$endCreateComponents, + findComponent: Sys$_Application$findComponent, + getComponents: Sys$_Application$getComponents, + initialize: Sys$_Application$initialize, + notifyScriptLoaded: Sys$_Application$notifyScriptLoaded, + registerDisposableObject: Sys$_Application$registerDisposableObject, + raiseLoad: Sys$_Application$raiseLoad, + removeComponent: Sys$_Application$removeComponent, + unregisterDisposableObject: Sys$_Application$unregisterDisposableObject, + _addComponentToSecondPass: Sys$_Application$_addComponentToSecondPass, + _disposeComponents: Sys$_Application$_disposeComponents, + _disposeElementInternal: Sys$_Application$_disposeElementInternal, + _domReady: Sys$_Application$_domReady, + _raiseInit: Sys$_Application$_raiseInit, + _unloadHandler: Sys$_Application$_unloadHandler +} +Sys._Application.registerClass('Sys._Application', Sys.Component, Sys.IContainer); +Sys.Application = new Sys._Application(); +var $find = Sys.Application.findComponent; + +Sys.UI.Behavior = function Sys$UI$Behavior(element) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true} + ]); + if (e) throw e; + Sys.UI.Behavior.initializeBase(this); + this._element = element; + var behaviors = element._behaviors; + if (!behaviors) { + element._behaviors = [this]; + } + else { + behaviors[behaviors.length] = this; + } +} + function Sys$UI$Behavior$get_element() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._element; + } + function Sys$UI$Behavior$get_id() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + var baseId = Sys.UI.Behavior.callBaseMethod(this, 'get_id'); + if (baseId) return baseId; + if (!this._element || !this._element.id) return ''; + return this._element.id + '$' + this.get_name(); + } + function Sys$UI$Behavior$get_name() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (this._name) return this._name; + var name = Object.getTypeName(this); + var i = name.lastIndexOf('.'); + if (i !== -1) name = name.substr(i + 1); + if (!this.get_isInitialized()) this._name = name; + return name; + } + function Sys$UI$Behavior$set_name(value) { + var e = Function._validateParams(arguments, [{name: "value", type: String}]); + if (e) throw e; + if ((value === '') || (value.charAt(0) === ' ') || (value.charAt(value.length - 1) === ' ')) + throw Error.argument('value', Sys.Res.invalidId); + if (typeof(this._element[value]) !== 'undefined') + throw Error.invalidOperation(String.format(Sys.Res.behaviorDuplicateName, value)); + if (this.get_isInitialized()) throw Error.invalidOperation(Sys.Res.cantSetNameAfterInit); + this._name = value; + } + function Sys$UI$Behavior$initialize() { + Sys.UI.Behavior.callBaseMethod(this, 'initialize'); + var name = this.get_name(); + if (name) this._element[name] = this; + } + function Sys$UI$Behavior$dispose() { + Sys.UI.Behavior.callBaseMethod(this, 'dispose'); + var e = this._element; + if (e) { + var name = this.get_name(); + if (name) { + e[name] = null; + } + var behaviors = e._behaviors; + Array.remove(behaviors, this); + if (behaviors.length === 0) { + e._behaviors = null; + } + delete this._element; + } + } +Sys.UI.Behavior.prototype = { + _name: null, + get_element: Sys$UI$Behavior$get_element, + get_id: Sys$UI$Behavior$get_id, + get_name: Sys$UI$Behavior$get_name, + set_name: Sys$UI$Behavior$set_name, + initialize: Sys$UI$Behavior$initialize, + dispose: Sys$UI$Behavior$dispose +} +Sys.UI.Behavior.registerClass('Sys.UI.Behavior', Sys.Component); +Sys.UI.Behavior.getBehaviorByName = function Sys$UI$Behavior$getBehaviorByName(element, name) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true}, + {name: "name", type: String} + ]); + if (e) throw e; + var b = element[name]; + return (b && Sys.UI.Behavior.isInstanceOfType(b)) ? b : null; +} +Sys.UI.Behavior.getBehaviors = function Sys$UI$Behavior$getBehaviors(element) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true} + ]); + if (e) throw e; + if (!element._behaviors) return []; + return Array.clone(element._behaviors); +} +Sys.UI.Behavior.getBehaviorsByType = function Sys$UI$Behavior$getBehaviorsByType(element, type) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true}, + {name: "type", type: Type} + ]); + if (e) throw e; + var behaviors = element._behaviors; + var results = []; + if (behaviors) { + for (var i = 0, l = behaviors.length; i < l; i++) { + if (type.isInstanceOfType(behaviors[i])) { + results[results.length] = behaviors[i]; + } + } + } + return results; +} + +Sys.UI.VisibilityMode = function Sys$UI$VisibilityMode() { + /// + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); +} +Sys.UI.VisibilityMode.prototype = { + hide: 0, + collapse: 1 +} +Sys.UI.VisibilityMode.registerEnum("Sys.UI.VisibilityMode"); + +Sys.UI.Control = function Sys$UI$Control(element) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true} + ]); + if (e) throw e; + if (typeof(element.control) !== 'undefined') throw Error.invalidOperation(Sys.Res.controlAlreadyDefined); + Sys.UI.Control.initializeBase(this); + this._element = element; + element.control = this; + var role = this.get_role(); + if (role) { + element.setAttribute("role", role); + } +} + function Sys$UI$Control$get_element() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._element; + } + function Sys$UI$Control$get_id() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (!this._element) return ''; + return this._element.id; + } + function Sys$UI$Control$set_id(value) { + var e = Function._validateParams(arguments, [{name: "value", type: String}]); + if (e) throw e; + throw Error.invalidOperation(Sys.Res.cantSetId); + } + function Sys$UI$Control$get_parent() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (this._parent) return this._parent; + if (!this._element) return null; + + var parentElement = this._element.parentNode; + while (parentElement) { + if (parentElement.control) { + return parentElement.control; + } + parentElement = parentElement.parentNode; + } + return null; + } + function Sys$UI$Control$set_parent(value) { + var e = Function._validateParams(arguments, [{name: "value", type: Sys.UI.Control}]); + if (e) throw e; + if (!this._element) throw Error.invalidOperation(Sys.Res.cantBeCalledAfterDispose); + var parents = [this]; + var current = value; + while (current) { + if (Array.contains(parents, current)) throw Error.invalidOperation(Sys.Res.circularParentChain); + parents[parents.length] = current; + current = current.get_parent(); + } + this._parent = value; + } + function Sys$UI$Control$get_role() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return null; + } + function Sys$UI$Control$get_visibilityMode() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (!this._element) throw Error.invalidOperation(Sys.Res.cantBeCalledAfterDispose); + return Sys.UI.DomElement.getVisibilityMode(this._element); + } + function Sys$UI$Control$set_visibilityMode(value) { + var e = Function._validateParams(arguments, [{name: "value", type: Sys.UI.VisibilityMode}]); + if (e) throw e; + if (!this._element) throw Error.invalidOperation(Sys.Res.cantBeCalledAfterDispose); + Sys.UI.DomElement.setVisibilityMode(this._element, value); + } + function Sys$UI$Control$get_visible() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (!this._element) throw Error.invalidOperation(Sys.Res.cantBeCalledAfterDispose); + return Sys.UI.DomElement.getVisible(this._element); + } + function Sys$UI$Control$set_visible(value) { + var e = Function._validateParams(arguments, [{name: "value", type: Boolean}]); + if (e) throw e; + if (!this._element) throw Error.invalidOperation(Sys.Res.cantBeCalledAfterDispose); + Sys.UI.DomElement.setVisible(this._element, value) + } + function Sys$UI$Control$addCssClass(className) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "className", type: String} + ]); + if (e) throw e; + if (!this._element) throw Error.invalidOperation(Sys.Res.cantBeCalledAfterDispose); + Sys.UI.DomElement.addCssClass(this._element, className); + } + function Sys$UI$Control$dispose() { + Sys.UI.Control.callBaseMethod(this, 'dispose'); + if (this._element) { + this._element.control = null; + delete this._element; + } + if (this._parent) delete this._parent; + } + function Sys$UI$Control$onBubbleEvent(source, args) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "source"}, + {name: "args", type: Sys.EventArgs} + ]); + if (e) throw e; + return false; + } + function Sys$UI$Control$raiseBubbleEvent(source, args) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "source"}, + {name: "args", type: Sys.EventArgs} + ]); + if (e) throw e; + this._raiseBubbleEvent(source, args); + } + function Sys$UI$Control$_raiseBubbleEvent(source, args) { + var currentTarget = this.get_parent(); + while (currentTarget) { + if (currentTarget.onBubbleEvent(source, args)) { + return; + } + currentTarget = currentTarget.get_parent(); + } + } + function Sys$UI$Control$removeCssClass(className) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "className", type: String} + ]); + if (e) throw e; + if (!this._element) throw Error.invalidOperation(Sys.Res.cantBeCalledAfterDispose); + Sys.UI.DomElement.removeCssClass(this._element, className); + } + function Sys$UI$Control$toggleCssClass(className) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "className", type: String} + ]); + if (e) throw e; + if (!this._element) throw Error.invalidOperation(Sys.Res.cantBeCalledAfterDispose); + Sys.UI.DomElement.toggleCssClass(this._element, className); + } +Sys.UI.Control.prototype = { + _parent: null, + _visibilityMode: Sys.UI.VisibilityMode.hide, + get_element: Sys$UI$Control$get_element, + get_id: Sys$UI$Control$get_id, + set_id: Sys$UI$Control$set_id, + get_parent: Sys$UI$Control$get_parent, + set_parent: Sys$UI$Control$set_parent, + get_role: Sys$UI$Control$get_role, + get_visibilityMode: Sys$UI$Control$get_visibilityMode, + set_visibilityMode: Sys$UI$Control$set_visibilityMode, + get_visible: Sys$UI$Control$get_visible, + set_visible: Sys$UI$Control$set_visible, + addCssClass: Sys$UI$Control$addCssClass, + dispose: Sys$UI$Control$dispose, + onBubbleEvent: Sys$UI$Control$onBubbleEvent, + raiseBubbleEvent: Sys$UI$Control$raiseBubbleEvent, + _raiseBubbleEvent: Sys$UI$Control$_raiseBubbleEvent, + removeCssClass: Sys$UI$Control$removeCssClass, + toggleCssClass: Sys$UI$Control$toggleCssClass +} +Sys.UI.Control.registerClass('Sys.UI.Control', Sys.Component); +Sys.HistoryEventArgs = function Sys$HistoryEventArgs(state) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "state", type: Object} + ]); + if (e) throw e; + Sys.HistoryEventArgs.initializeBase(this); + this._state = state; +} + function Sys$HistoryEventArgs$get_state() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._state; + } +Sys.HistoryEventArgs.prototype = { + get_state: Sys$HistoryEventArgs$get_state +} +Sys.HistoryEventArgs.registerClass('Sys.HistoryEventArgs', Sys.EventArgs); +Sys.Application._appLoadHandler = null; +Sys.Application._beginRequestHandler = null; +Sys.Application._clientId = null; +Sys.Application._currentEntry = ''; +Sys.Application._endRequestHandler = null; +Sys.Application._history = null; +Sys.Application._enableHistory = false; +Sys.Application._historyEnabledInScriptManager = false; +Sys.Application._historyFrame = null; +Sys.Application._historyInitialized = false; +Sys.Application._historyPointIsNew = false; +Sys.Application._ignoreTimer = false; +Sys.Application._initialState = null; +Sys.Application._state = {}; +Sys.Application._timerCookie = 0; +Sys.Application._timerHandler = null; +Sys.Application._uniqueId = null; +Sys._Application.prototype.get_stateString = function Sys$_Application$get_stateString() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + var hash = null; + + if (Sys.Browser.agent === Sys.Browser.Firefox) { + var href = window.location.href; + var hashIndex = href.indexOf('#'); + if (hashIndex !== -1) { + hash = href.substring(hashIndex + 1); + } + else { + hash = ""; + } + return hash; + } + else { + hash = window.location.hash; + } + + if ((hash.length > 0) && (hash.charAt(0) === '#')) { + hash = hash.substring(1); + } + return hash; +}; +Sys._Application.prototype.get_enableHistory = function Sys$_Application$get_enableHistory() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._enableHistory; +}; +Sys._Application.prototype.set_enableHistory = function Sys$_Application$set_enableHistory(value) { + if (this._initialized && !this._initializing) { + throw Error.invalidOperation(Sys.Res.historyCannotEnableHistory); + } + else if (this._historyEnabledInScriptManager && !value) { + throw Error.invalidOperation(Sys.Res.invalidHistorySettingCombination); + } + this._enableHistory = value; +}; +Sys._Application.prototype.add_navigate = function Sys$_Application$add_navigate(handler) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "handler", type: Function} + ]); + if (e) throw e; + this.get_events().addHandler("navigate", handler); +}; +Sys._Application.prototype.remove_navigate = function Sys$_Application$remove_navigate(handler) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "handler", type: Function} + ]); + if (e) throw e; + this.get_events().removeHandler("navigate", handler); +}; +Sys._Application.prototype.addHistoryPoint = function Sys$_Application$addHistoryPoint(state, title) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "state", type: Object}, + {name: "title", type: String, mayBeNull: true, optional: true} + ]); + if (e) throw e; + if (!this._enableHistory) throw Error.invalidOperation(Sys.Res.historyCannotAddHistoryPointWithHistoryDisabled); + for (var n in state) { + var v = state[n]; + var t = typeof(v); + if ((v !== null) && ((t === 'object') || (t === 'function') || (t === 'undefined'))) { + throw Error.argument('state', Sys.Res.stateMustBeStringDictionary); + } + } + this._ensureHistory(); + var initialState = this._state; + for (var key in state) { + var value = state[key]; + if (value === null) { + if (typeof(initialState[key]) !== 'undefined') { + delete initialState[key]; + } + } + else { + initialState[key] = value; + } + } + var entry = this._serializeState(initialState); + this._historyPointIsNew = true; + this._setState(entry, title); + this._raiseNavigate(); +}; +Sys._Application.prototype.setServerId = function Sys$_Application$setServerId(clientId, uniqueId) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "clientId", type: String}, + {name: "uniqueId", type: String} + ]); + if (e) throw e; + this._clientId = clientId; + this._uniqueId = uniqueId; +}; +Sys._Application.prototype.setServerState = function Sys$_Application$setServerState(value) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "value", type: String} + ]); + if (e) throw e; + this._ensureHistory(); + this._state.__s = value; + this._updateHiddenField(value); +}; +Sys._Application.prototype._deserializeState = function Sys$_Application$_deserializeState(entry) { + var result = {}; + entry = entry || ''; + var serverSeparator = entry.indexOf('&&'); + if ((serverSeparator !== -1) && (serverSeparator + 2 < entry.length)) { + result.__s = entry.substr(serverSeparator + 2); + entry = entry.substr(0, serverSeparator); + } + var tokens = entry.split('&'); + for (var i = 0, l = tokens.length; i < l; i++) { + var token = tokens[i]; + var equal = token.indexOf('='); + if ((equal !== -1) && (equal + 1 < token.length)) { + var name = token.substr(0, equal); + var value = token.substr(equal + 1); + result[name] = decodeURIComponent(value); + } + } + return result; +}; +Sys._Application.prototype._enableHistoryInScriptManager = function Sys$_Application$_enableHistoryInScriptManager() { + this._enableHistory = true; + this._historyEnabledInScriptManager = true; +}; +Sys._Application.prototype._ensureHistory = function Sys$_Application$_ensureHistory() { + if (!this._historyInitialized && this._enableHistory) { + if ((Sys.Browser.agent === Sys.Browser.InternetExplorer) && (Sys.Browser.documentMode < 8)) { + this._historyFrame = document.getElementById('__historyFrame'); + if (!this._historyFrame) throw Error.invalidOperation(Sys.Res.historyMissingFrame); + this._ignoreIFrame = true; + } + this._timerHandler = Function.createDelegate(this, this._onIdle); + this._timerCookie = window.setTimeout(this._timerHandler, 100); + + try { + this._initialState = this._deserializeState(this.get_stateString()); + } catch(e) {} + + this._historyInitialized = true; + } +}; +Sys._Application.prototype._navigate = function Sys$_Application$_navigate(entry) { + this._ensureHistory(); + var state = this._deserializeState(entry); + + if (this._uniqueId) { + var oldServerEntry = this._state.__s || ''; + var newServerEntry = state.__s || ''; + if (newServerEntry !== oldServerEntry) { + this._updateHiddenField(newServerEntry); + __doPostBack(this._uniqueId, newServerEntry); + this._state = state; + return; + } + } + this._setState(entry); + this._state = state; + this._raiseNavigate(); +}; +Sys._Application.prototype._onIdle = function Sys$_Application$_onIdle() { + delete this._timerCookie; + + var entry = this.get_stateString(); + if (entry !== this._currentEntry) { + if (!this._ignoreTimer) { + this._historyPointIsNew = false; + this._navigate(entry); + } + } + else { + this._ignoreTimer = false; + } + this._timerCookie = window.setTimeout(this._timerHandler, 100); +}; +Sys._Application.prototype._onIFrameLoad = function Sys$_Application$_onIFrameLoad(entry) { + this._ensureHistory(); + if (!this._ignoreIFrame) { + this._historyPointIsNew = false; + this._navigate(entry); + } + this._ignoreIFrame = false; +}; +Sys._Application.prototype._onPageRequestManagerBeginRequest = function Sys$_Application$_onPageRequestManagerBeginRequest(sender, args) { + this._ignoreTimer = true; +}; +Sys._Application.prototype._onPageRequestManagerEndRequest = function Sys$_Application$_onPageRequestManagerEndRequest(sender, args) { + var dataItem = args.get_dataItems()[this._clientId]; + var eventTarget = document.getElementById("__EVENTTARGET"); + if (eventTarget && eventTarget.value === this._uniqueId) { + eventTarget.value = ''; + } + if (typeof(dataItem) !== 'undefined') { + this.setServerState(dataItem); + this._historyPointIsNew = true; + } + else { + this._ignoreTimer = false; + } + var entry = this._serializeState(this._state); + if (entry !== this._currentEntry) { + this._ignoreTimer = true; + this._setState(entry); + this._raiseNavigate(); + } +}; +Sys._Application.prototype._raiseNavigate = function Sys$_Application$_raiseNavigate() { + var h = this.get_events().getHandler("navigate"); + var stateClone = {}; + for (var key in this._state) { + if (key !== '__s') { + stateClone[key] = this._state[key]; + } + } + var args = new Sys.HistoryEventArgs(stateClone); + if (h) { + h(this, args); + } + var err; + try { + if ((Sys.Browser.agent === Sys.Browser.Firefox) && window.location.hash && + (!window.frameElement || window.top.location.hash)) { + window.history.go(0); + } + } + catch(err) { + } +}; +Sys._Application.prototype._serializeState = function Sys$_Application$_serializeState(state) { + var serialized = []; + for (var key in state) { + var value = state[key]; + if (key === '__s') { + var serverState = value; + } + else { + if (key.indexOf('=') !== -1) throw Error.argument('state', Sys.Res.stateFieldNameInvalid); + serialized[serialized.length] = key + '=' + encodeURIComponent(value); + } + } + return serialized.join('&') + (serverState ? '&&' + serverState : ''); +}; +Sys._Application.prototype._setState = function Sys$_Application$_setState(entry, title) { + if (this._enableHistory) { + entry = entry || ''; + if (entry !== this._currentEntry) { + if (window.theForm) { + var action = window.theForm.action; + var hashIndex = action.indexOf('#'); + window.theForm.action = ((hashIndex !== -1) ? action.substring(0, hashIndex) : action) + '#' + entry; + } + + if (this._historyFrame && this._historyPointIsNew) { + this._ignoreIFrame = true; + var frameDoc = this._historyFrame.contentWindow.document; + frameDoc.open("javascript:''"); + frameDoc.write("" + (title || document.title) + + "parent.Sys.Application._onIFrameLoad(" + + Sys.Serialization.JavaScriptSerializer.serialize(entry) + + ");"); + frameDoc.close(); + } + this._ignoreTimer = false; + this._currentEntry = entry; + if (this._historyFrame || this._historyPointIsNew) { + var currentHash = this.get_stateString(); + if (entry !== currentHash) { + var loc = document.location; + if (loc.href.length - loc.hash.length + entry.length > 1024) { + throw Error.invalidOperation(Sys.Res.urlMustBeLessThan1024chars); + } + window.location.hash = entry; + this._currentEntry = this.get_stateString(); + if ((typeof(title) !== 'undefined') && (title !== null)) { + document.title = title; + } + } + } + this._historyPointIsNew = false; + } + } +}; +Sys._Application.prototype._updateHiddenField = function Sys$_Application$_updateHiddenField(value) { + if (this._clientId) { + var serverStateField = document.getElementById(this._clientId); + if (serverStateField) { + serverStateField.value = value; + } + } +}; + +if (!window.XMLHttpRequest) { + window.XMLHttpRequest = function window$XMLHttpRequest() { + var progIDs = [ 'Msxml2.XMLHTTP.3.0', 'Msxml2.XMLHTTP' ]; + for (var i = 0, l = progIDs.length; i < l; i++) { + try { + return new ActiveXObject(progIDs[i]); + } + catch (ex) { + } + } + return null; + } +} +Type.registerNamespace('Sys.Net'); + +Sys.Net.WebRequestExecutor = function Sys$Net$WebRequestExecutor() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + this._webRequest = null; + this._resultObject = null; +} + function Sys$Net$WebRequestExecutor$get_webRequest() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._webRequest; + } + function Sys$Net$WebRequestExecutor$_set_webRequest(value) { + if (this.get_started()) { + throw Error.invalidOperation(String.format(Sys.Res.cannotCallOnceStarted, 'set_webRequest')); + } + this._webRequest = value; + } + function Sys$Net$WebRequestExecutor$get_started() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); + } + function Sys$Net$WebRequestExecutor$get_responseAvailable() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); + } + function Sys$Net$WebRequestExecutor$get_timedOut() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); + } + function Sys$Net$WebRequestExecutor$get_aborted() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); + } + function Sys$Net$WebRequestExecutor$get_responseData() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); + } + function Sys$Net$WebRequestExecutor$get_statusCode() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); + } + function Sys$Net$WebRequestExecutor$get_statusText() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); + } + function Sys$Net$WebRequestExecutor$get_xml() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); + } + function Sys$Net$WebRequestExecutor$get_object() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (!this._resultObject) { + this._resultObject = Sys.Serialization.JavaScriptSerializer.deserialize(this.get_responseData()); + } + return this._resultObject; + } + function Sys$Net$WebRequestExecutor$executeRequest() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); + } + function Sys$Net$WebRequestExecutor$abort() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); + } + function Sys$Net$WebRequestExecutor$getResponseHeader(header) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "header", type: String} + ]); + if (e) throw e; + throw Error.notImplemented(); + } + function Sys$Net$WebRequestExecutor$getAllResponseHeaders() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); + } +Sys.Net.WebRequestExecutor.prototype = { + get_webRequest: Sys$Net$WebRequestExecutor$get_webRequest, + _set_webRequest: Sys$Net$WebRequestExecutor$_set_webRequest, + get_started: Sys$Net$WebRequestExecutor$get_started, + get_responseAvailable: Sys$Net$WebRequestExecutor$get_responseAvailable, + get_timedOut: Sys$Net$WebRequestExecutor$get_timedOut, + get_aborted: Sys$Net$WebRequestExecutor$get_aborted, + get_responseData: Sys$Net$WebRequestExecutor$get_responseData, + get_statusCode: Sys$Net$WebRequestExecutor$get_statusCode, + get_statusText: Sys$Net$WebRequestExecutor$get_statusText, + get_xml: Sys$Net$WebRequestExecutor$get_xml, + get_object: Sys$Net$WebRequestExecutor$get_object, + executeRequest: Sys$Net$WebRequestExecutor$executeRequest, + abort: Sys$Net$WebRequestExecutor$abort, + getResponseHeader: Sys$Net$WebRequestExecutor$getResponseHeader, + getAllResponseHeaders: Sys$Net$WebRequestExecutor$getAllResponseHeaders +} +Sys.Net.WebRequestExecutor.registerClass('Sys.Net.WebRequestExecutor'); + +Sys.Net.XMLDOM = function Sys$Net$XMLDOM(markup) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "markup", type: String} + ]); + if (e) throw e; + if (!window.DOMParser) { + var progIDs = [ 'Msxml2.DOMDocument.3.0', 'Msxml2.DOMDocument' ]; + for (var i = 0, l = progIDs.length; i < l; i++) { + try { + var xmlDOM = new ActiveXObject(progIDs[i]); + xmlDOM.async = false; + xmlDOM.loadXML(markup); + xmlDOM.setProperty('SelectionLanguage', 'XPath'); + return xmlDOM; + } + catch (ex) { + } + } + } + else { + try { + var domParser = new window.DOMParser(); + return domParser.parseFromString(markup, 'text/xml'); + } + catch (ex) { + } + } + return null; +} +Sys.Net.XMLHttpExecutor = function Sys$Net$XMLHttpExecutor() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + Sys.Net.XMLHttpExecutor.initializeBase(this); + var _this = this; + this._xmlHttpRequest = null; + this._webRequest = null; + this._responseAvailable = false; + this._timedOut = false; + this._timer = null; + this._aborted = false; + this._started = false; + this._onReadyStateChange = (function () { + + if (_this._xmlHttpRequest.readyState === 4 ) { + try { + if (typeof(_this._xmlHttpRequest.status) === "undefined") { + return; + } + } + catch(ex) { + return; + } + + _this._clearTimer(); + _this._responseAvailable = true; + _this._webRequest.completed(Sys.EventArgs.Empty); + if (_this._xmlHttpRequest != null) { + _this._xmlHttpRequest.onreadystatechange = Function.emptyMethod; + _this._xmlHttpRequest = null; + } + } + }); + this._clearTimer = (function() { + if (_this._timer != null) { + window.clearTimeout(_this._timer); + _this._timer = null; + } + }); + this._onTimeout = (function() { + if (!_this._responseAvailable) { + _this._clearTimer(); + _this._timedOut = true; + _this._xmlHttpRequest.onreadystatechange = Function.emptyMethod; + _this._xmlHttpRequest.abort(); + _this._webRequest.completed(Sys.EventArgs.Empty); + _this._xmlHttpRequest = null; + } + }); +} + function Sys$Net$XMLHttpExecutor$get_timedOut() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._timedOut; + } + function Sys$Net$XMLHttpExecutor$get_started() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._started; + } + function Sys$Net$XMLHttpExecutor$get_responseAvailable() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._responseAvailable; + } + function Sys$Net$XMLHttpExecutor$get_aborted() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._aborted; + } + function Sys$Net$XMLHttpExecutor$executeRequest() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + this._webRequest = this.get_webRequest(); + if (this._started) { + throw Error.invalidOperation(String.format(Sys.Res.cannotCallOnceStarted, 'executeRequest')); + } + if (this._webRequest === null) { + throw Error.invalidOperation(Sys.Res.nullWebRequest); + } + var body = this._webRequest.get_body(); + var headers = this._webRequest.get_headers(); + this._xmlHttpRequest = new XMLHttpRequest(); + this._xmlHttpRequest.onreadystatechange = this._onReadyStateChange; + var verb = this._webRequest.get_httpVerb(); + this._xmlHttpRequest.open(verb, this._webRequest.getResolvedUrl(), true ); + this._xmlHttpRequest.setRequestHeader("X-Requested-With", "XMLHttpRequest"); + if (headers) { + for (var header in headers) { + var val = headers[header]; + if (typeof(val) !== "function") + this._xmlHttpRequest.setRequestHeader(header, val); + } + } + if (verb.toLowerCase() === "post") { + if ((headers === null) || !headers['Content-Type']) { + this._xmlHttpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8'); + } + if (!body) { + body = ""; + } + } + var timeout = this._webRequest.get_timeout(); + if (timeout > 0) { + this._timer = window.setTimeout(Function.createDelegate(this, this._onTimeout), timeout); + } + this._xmlHttpRequest.send(body); + this._started = true; + } + function Sys$Net$XMLHttpExecutor$getResponseHeader(header) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "header", type: String} + ]); + if (e) throw e; + if (!this._responseAvailable) { + throw Error.invalidOperation(String.format(Sys.Res.cannotCallBeforeResponse, 'getResponseHeader')); + } + if (!this._xmlHttpRequest) { + throw Error.invalidOperation(String.format(Sys.Res.cannotCallOutsideHandler, 'getResponseHeader')); + } + var result; + try { + result = this._xmlHttpRequest.getResponseHeader(header); + } catch (e) { + } + if (!result) result = ""; + return result; + } + function Sys$Net$XMLHttpExecutor$getAllResponseHeaders() { + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (!this._responseAvailable) { + throw Error.invalidOperation(String.format(Sys.Res.cannotCallBeforeResponse, 'getAllResponseHeaders')); + } + if (!this._xmlHttpRequest) { + throw Error.invalidOperation(String.format(Sys.Res.cannotCallOutsideHandler, 'getAllResponseHeaders')); + } + return this._xmlHttpRequest.getAllResponseHeaders(); + } + function Sys$Net$XMLHttpExecutor$get_responseData() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (!this._responseAvailable) { + throw Error.invalidOperation(String.format(Sys.Res.cannotCallBeforeResponse, 'get_responseData')); + } + if (!this._xmlHttpRequest) { + throw Error.invalidOperation(String.format(Sys.Res.cannotCallOutsideHandler, 'get_responseData')); + } + return this._xmlHttpRequest.responseText; + } + function Sys$Net$XMLHttpExecutor$get_statusCode() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (!this._responseAvailable) { + throw Error.invalidOperation(String.format(Sys.Res.cannotCallBeforeResponse, 'get_statusCode')); + } + if (!this._xmlHttpRequest) { + throw Error.invalidOperation(String.format(Sys.Res.cannotCallOutsideHandler, 'get_statusCode')); + } + var result = 0; + try { + result = this._xmlHttpRequest.status; + } + catch(ex) { + } + return result; + } + function Sys$Net$XMLHttpExecutor$get_statusText() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (!this._responseAvailable) { + throw Error.invalidOperation(String.format(Sys.Res.cannotCallBeforeResponse, 'get_statusText')); + } + if (!this._xmlHttpRequest) { + throw Error.invalidOperation(String.format(Sys.Res.cannotCallOutsideHandler, 'get_statusText')); + } + return this._xmlHttpRequest.statusText; + } + function Sys$Net$XMLHttpExecutor$get_xml() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (!this._responseAvailable) { + throw Error.invalidOperation(String.format(Sys.Res.cannotCallBeforeResponse, 'get_xml')); + } + if (!this._xmlHttpRequest) { + throw Error.invalidOperation(String.format(Sys.Res.cannotCallOutsideHandler, 'get_xml')); + } + var xml = this._xmlHttpRequest.responseXML; + if (!xml || !xml.documentElement) { + xml = Sys.Net.XMLDOM(this._xmlHttpRequest.responseText); + if (!xml || !xml.documentElement) + return null; + } + else if (navigator.userAgent.indexOf('MSIE') !== -1) { + xml.setProperty('SelectionLanguage', 'XPath'); + } + if (xml.documentElement.namespaceURI === "http://www.mozilla.org/newlayout/xml/parsererror.xml" && + xml.documentElement.tagName === "parsererror") { + return null; + } + + if (xml.documentElement.firstChild && xml.documentElement.firstChild.tagName === "parsererror") { + return null; + } + + return xml; + } + function Sys$Net$XMLHttpExecutor$abort() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (!this._started) { + throw Error.invalidOperation(Sys.Res.cannotAbortBeforeStart); + } + if (this._aborted || this._responseAvailable || this._timedOut) + return; + this._aborted = true; + this._clearTimer(); + if (this._xmlHttpRequest && !this._responseAvailable) { + this._xmlHttpRequest.onreadystatechange = Function.emptyMethod; + this._xmlHttpRequest.abort(); + + this._xmlHttpRequest = null; + this._webRequest.completed(Sys.EventArgs.Empty); + } + } +Sys.Net.XMLHttpExecutor.prototype = { + get_timedOut: Sys$Net$XMLHttpExecutor$get_timedOut, + get_started: Sys$Net$XMLHttpExecutor$get_started, + get_responseAvailable: Sys$Net$XMLHttpExecutor$get_responseAvailable, + get_aborted: Sys$Net$XMLHttpExecutor$get_aborted, + executeRequest: Sys$Net$XMLHttpExecutor$executeRequest, + getResponseHeader: Sys$Net$XMLHttpExecutor$getResponseHeader, + getAllResponseHeaders: Sys$Net$XMLHttpExecutor$getAllResponseHeaders, + get_responseData: Sys$Net$XMLHttpExecutor$get_responseData, + get_statusCode: Sys$Net$XMLHttpExecutor$get_statusCode, + get_statusText: Sys$Net$XMLHttpExecutor$get_statusText, + get_xml: Sys$Net$XMLHttpExecutor$get_xml, + abort: Sys$Net$XMLHttpExecutor$abort +} +Sys.Net.XMLHttpExecutor.registerClass('Sys.Net.XMLHttpExecutor', Sys.Net.WebRequestExecutor); + +Sys.Net._WebRequestManager = function Sys$Net$_WebRequestManager() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + this._defaultTimeout = 0; + this._defaultExecutorType = "Sys.Net.XMLHttpExecutor"; +} + function Sys$Net$_WebRequestManager$add_invokingRequest(handler) { + /// + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this._get_eventHandlerList().addHandler("invokingRequest", handler); + } + function Sys$Net$_WebRequestManager$remove_invokingRequest(handler) { + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this._get_eventHandlerList().removeHandler("invokingRequest", handler); + } + function Sys$Net$_WebRequestManager$add_completedRequest(handler) { + /// + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this._get_eventHandlerList().addHandler("completedRequest", handler); + } + function Sys$Net$_WebRequestManager$remove_completedRequest(handler) { + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this._get_eventHandlerList().removeHandler("completedRequest", handler); + } + function Sys$Net$_WebRequestManager$_get_eventHandlerList() { + if (!this._events) { + this._events = new Sys.EventHandlerList(); + } + return this._events; + } + function Sys$Net$_WebRequestManager$get_defaultTimeout() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._defaultTimeout; + } + function Sys$Net$_WebRequestManager$set_defaultTimeout(value) { + var e = Function._validateParams(arguments, [{name: "value", type: Number}]); + if (e) throw e; + if (value < 0) { + throw Error.argumentOutOfRange("value", value, Sys.Res.invalidTimeout); + } + this._defaultTimeout = value; + } + function Sys$Net$_WebRequestManager$get_defaultExecutorType() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._defaultExecutorType; + } + function Sys$Net$_WebRequestManager$set_defaultExecutorType(value) { + var e = Function._validateParams(arguments, [{name: "value", type: String}]); + if (e) throw e; + this._defaultExecutorType = value; + } + function Sys$Net$_WebRequestManager$executeRequest(webRequest) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "webRequest", type: Sys.Net.WebRequest} + ]); + if (e) throw e; + var executor = webRequest.get_executor(); + if (!executor) { + var failed = false; + try { + var executorType = eval(this._defaultExecutorType); + executor = new executorType(); + } catch (e) { + failed = true; + } + if (failed || !Sys.Net.WebRequestExecutor.isInstanceOfType(executor) || !executor) { + throw Error.argument("defaultExecutorType", String.format(Sys.Res.invalidExecutorType, this._defaultExecutorType)); + } + webRequest.set_executor(executor); + } + if (executor.get_aborted()) { + return; + } + var evArgs = new Sys.Net.NetworkRequestEventArgs(webRequest); + var handler = this._get_eventHandlerList().getHandler("invokingRequest"); + if (handler) { + handler(this, evArgs); + } + if (!evArgs.get_cancel()) { + executor.executeRequest(); + } + } +Sys.Net._WebRequestManager.prototype = { + add_invokingRequest: Sys$Net$_WebRequestManager$add_invokingRequest, + remove_invokingRequest: Sys$Net$_WebRequestManager$remove_invokingRequest, + add_completedRequest: Sys$Net$_WebRequestManager$add_completedRequest, + remove_completedRequest: Sys$Net$_WebRequestManager$remove_completedRequest, + _get_eventHandlerList: Sys$Net$_WebRequestManager$_get_eventHandlerList, + get_defaultTimeout: Sys$Net$_WebRequestManager$get_defaultTimeout, + set_defaultTimeout: Sys$Net$_WebRequestManager$set_defaultTimeout, + get_defaultExecutorType: Sys$Net$_WebRequestManager$get_defaultExecutorType, + set_defaultExecutorType: Sys$Net$_WebRequestManager$set_defaultExecutorType, + executeRequest: Sys$Net$_WebRequestManager$executeRequest +} +Sys.Net._WebRequestManager.registerClass('Sys.Net._WebRequestManager'); +Sys.Net.WebRequestManager = new Sys.Net._WebRequestManager(); + +Sys.Net.NetworkRequestEventArgs = function Sys$Net$NetworkRequestEventArgs(webRequest) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "webRequest", type: Sys.Net.WebRequest} + ]); + if (e) throw e; + Sys.Net.NetworkRequestEventArgs.initializeBase(this); + this._webRequest = webRequest; +} + function Sys$Net$NetworkRequestEventArgs$get_webRequest() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._webRequest; + } +Sys.Net.NetworkRequestEventArgs.prototype = { + get_webRequest: Sys$Net$NetworkRequestEventArgs$get_webRequest +} +Sys.Net.NetworkRequestEventArgs.registerClass('Sys.Net.NetworkRequestEventArgs', Sys.CancelEventArgs); + +Sys.Net.WebRequest = function Sys$Net$WebRequest() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + this._url = ""; + this._headers = { }; + this._body = null; + this._userContext = null; + this._httpVerb = null; + this._executor = null; + this._invokeCalled = false; + this._timeout = 0; +} + function Sys$Net$WebRequest$add_completed(handler) { + /// + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this._get_eventHandlerList().addHandler("completed", handler); + } + function Sys$Net$WebRequest$remove_completed(handler) { + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this._get_eventHandlerList().removeHandler("completed", handler); + } + function Sys$Net$WebRequest$completed(eventArgs) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "eventArgs", type: Sys.EventArgs} + ]); + if (e) throw e; + var handler = Sys.Net.WebRequestManager._get_eventHandlerList().getHandler("completedRequest"); + if (handler) { + handler(this._executor, eventArgs); + } + handler = this._get_eventHandlerList().getHandler("completed"); + if (handler) { + handler(this._executor, eventArgs); + } + } + function Sys$Net$WebRequest$_get_eventHandlerList() { + if (!this._events) { + this._events = new Sys.EventHandlerList(); + } + return this._events; + } + function Sys$Net$WebRequest$get_url() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._url; + } + function Sys$Net$WebRequest$set_url(value) { + var e = Function._validateParams(arguments, [{name: "value", type: String}]); + if (e) throw e; + this._url = value; + } + function Sys$Net$WebRequest$get_headers() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._headers; + } + function Sys$Net$WebRequest$get_httpVerb() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (this._httpVerb === null) { + if (this._body === null) { + return "GET"; + } + return "POST"; + } + return this._httpVerb; + } + function Sys$Net$WebRequest$set_httpVerb(value) { + var e = Function._validateParams(arguments, [{name: "value", type: String}]); + if (e) throw e; + if (value.length === 0) { + throw Error.argument('value', Sys.Res.invalidHttpVerb); + } + this._httpVerb = value; + } + function Sys$Net$WebRequest$get_body() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._body; + } + function Sys$Net$WebRequest$set_body(value) { + var e = Function._validateParams(arguments, [{name: "value", mayBeNull: true}]); + if (e) throw e; + this._body = value; + } + function Sys$Net$WebRequest$get_userContext() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._userContext; + } + function Sys$Net$WebRequest$set_userContext(value) { + var e = Function._validateParams(arguments, [{name: "value", mayBeNull: true}]); + if (e) throw e; + this._userContext = value; + } + function Sys$Net$WebRequest$get_executor() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._executor; + } + function Sys$Net$WebRequest$set_executor(value) { + var e = Function._validateParams(arguments, [{name: "value", type: Sys.Net.WebRequestExecutor}]); + if (e) throw e; + if (this._executor !== null && this._executor.get_started()) { + throw Error.invalidOperation(Sys.Res.setExecutorAfterActive); + } + this._executor = value; + this._executor._set_webRequest(this); + } + function Sys$Net$WebRequest$get_timeout() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (this._timeout === 0) { + return Sys.Net.WebRequestManager.get_defaultTimeout(); + } + return this._timeout; + } + function Sys$Net$WebRequest$set_timeout(value) { + var e = Function._validateParams(arguments, [{name: "value", type: Number}]); + if (e) throw e; + if (value < 0) { + throw Error.argumentOutOfRange("value", value, Sys.Res.invalidTimeout); + } + this._timeout = value; + } + function Sys$Net$WebRequest$getResolvedUrl() { + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return Sys.Net.WebRequest._resolveUrl(this._url); + } + function Sys$Net$WebRequest$invoke() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (this._invokeCalled) { + throw Error.invalidOperation(Sys.Res.invokeCalledTwice); + } + Sys.Net.WebRequestManager.executeRequest(this); + this._invokeCalled = true; + } +Sys.Net.WebRequest.prototype = { + add_completed: Sys$Net$WebRequest$add_completed, + remove_completed: Sys$Net$WebRequest$remove_completed, + completed: Sys$Net$WebRequest$completed, + _get_eventHandlerList: Sys$Net$WebRequest$_get_eventHandlerList, + get_url: Sys$Net$WebRequest$get_url, + set_url: Sys$Net$WebRequest$set_url, + get_headers: Sys$Net$WebRequest$get_headers, + get_httpVerb: Sys$Net$WebRequest$get_httpVerb, + set_httpVerb: Sys$Net$WebRequest$set_httpVerb, + get_body: Sys$Net$WebRequest$get_body, + set_body: Sys$Net$WebRequest$set_body, + get_userContext: Sys$Net$WebRequest$get_userContext, + set_userContext: Sys$Net$WebRequest$set_userContext, + get_executor: Sys$Net$WebRequest$get_executor, + set_executor: Sys$Net$WebRequest$set_executor, + get_timeout: Sys$Net$WebRequest$get_timeout, + set_timeout: Sys$Net$WebRequest$set_timeout, + getResolvedUrl: Sys$Net$WebRequest$getResolvedUrl, + invoke: Sys$Net$WebRequest$invoke +} +Sys.Net.WebRequest._resolveUrl = function Sys$Net$WebRequest$_resolveUrl(url, baseUrl) { + if (url && url.indexOf('://') !== -1) { + return url; + } + if (!baseUrl || baseUrl.length === 0) { + var baseElement = document.getElementsByTagName('base')[0]; + if (baseElement && baseElement.href && baseElement.href.length > 0) { + baseUrl = baseElement.href; + } + else { + baseUrl = document.URL; + } + } + var qsStart = baseUrl.indexOf('?'); + if (qsStart !== -1) { + baseUrl = baseUrl.substr(0, qsStart); + } + qsStart = baseUrl.indexOf('#'); + if (qsStart !== -1) { + baseUrl = baseUrl.substr(0, qsStart); + } + baseUrl = baseUrl.substr(0, baseUrl.lastIndexOf('/') + 1); + if (!url || url.length === 0) { + return baseUrl; + } + if (url.charAt(0) === '/') { + var slashslash = baseUrl.indexOf('://'); + if (slashslash === -1) { + throw Error.argument("baseUrl", Sys.Res.badBaseUrl1); + } + var nextSlash = baseUrl.indexOf('/', slashslash + 3); + if (nextSlash === -1) { + throw Error.argument("baseUrl", Sys.Res.badBaseUrl2); + } + return baseUrl.substr(0, nextSlash) + url; + } + else { + var lastSlash = baseUrl.lastIndexOf('/'); + if (lastSlash === -1) { + throw Error.argument("baseUrl", Sys.Res.badBaseUrl3); + } + return baseUrl.substr(0, lastSlash+1) + url; + } +} +Sys.Net.WebRequest._createQueryString = function Sys$Net$WebRequest$_createQueryString(queryString, encodeMethod, addParams) { + encodeMethod = encodeMethod || encodeURIComponent; + var i = 0, obj, val, arg, sb = new Sys.StringBuilder(); + if (queryString) { + for (arg in queryString) { + obj = queryString[arg]; + if (typeof(obj) === "function") continue; + val = Sys.Serialization.JavaScriptSerializer.serialize(obj); + if (i++) { + sb.append('&'); + } + sb.append(arg); + sb.append('='); + sb.append(encodeMethod(val)); + } + } + if (addParams) { + if (i) { + sb.append('&'); + } + sb.append(addParams); + } + return sb.toString(); +} +Sys.Net.WebRequest._createUrl = function Sys$Net$WebRequest$_createUrl(url, queryString, addParams) { + if (!queryString && !addParams) { + return url; + } + var qs = Sys.Net.WebRequest._createQueryString(queryString, null, addParams); + return qs.length + ? url + ((url && url.indexOf('?') >= 0) ? "&" : "?") + qs + : url; +} +Sys.Net.WebRequest.registerClass('Sys.Net.WebRequest'); + +Sys._ScriptLoaderTask = function Sys$_ScriptLoaderTask(scriptElement, completedCallback) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "scriptElement", domElement: true}, + {name: "completedCallback", type: Function} + ]); + if (e) throw e; + this._scriptElement = scriptElement; + this._completedCallback = completedCallback; +} + function Sys$_ScriptLoaderTask$get_scriptElement() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._scriptElement; + } + function Sys$_ScriptLoaderTask$dispose() { + if(this._disposed) { + return; + } + this._disposed = true; + this._removeScriptElementHandlers(); + Sys._ScriptLoaderTask._clearScript(this._scriptElement); + this._scriptElement = null; + } + function Sys$_ScriptLoaderTask$execute() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + this._addScriptElementHandlers(); + var headElements = document.getElementsByTagName('head'); + if (headElements.length === 0) { + throw new Error.invalidOperation(Sys.Res.scriptLoadFailedNoHead); + } + else { + headElements[0].appendChild(this._scriptElement); + } + } + function Sys$_ScriptLoaderTask$_addScriptElementHandlers() { + this._scriptLoadDelegate = Function.createDelegate(this, this._scriptLoadHandler); + + if (Sys.Browser.agent !== Sys.Browser.InternetExplorer) { + this._scriptElement.readyState = 'loaded'; + $addHandler(this._scriptElement, 'load', this._scriptLoadDelegate); + } + else { + $addHandler(this._scriptElement, 'readystatechange', this._scriptLoadDelegate); + } + if (this._scriptElement.addEventListener) { + this._scriptErrorDelegate = Function.createDelegate(this, this._scriptErrorHandler); + this._scriptElement.addEventListener('error', this._scriptErrorDelegate, false); + } + } + function Sys$_ScriptLoaderTask$_removeScriptElementHandlers() { + if(this._scriptLoadDelegate) { + var scriptElement = this.get_scriptElement(); + if (Sys.Browser.agent !== Sys.Browser.InternetExplorer) { + $removeHandler(scriptElement, 'load', this._scriptLoadDelegate); + } + else { + $removeHandler(scriptElement, 'readystatechange', this._scriptLoadDelegate); + } + if (this._scriptErrorDelegate) { + this._scriptElement.removeEventListener('error', this._scriptErrorDelegate, false); + this._scriptErrorDelegate = null; + } + this._scriptLoadDelegate = null; + } + } + function Sys$_ScriptLoaderTask$_scriptErrorHandler() { + if(this._disposed) { + return; + } + + this._completedCallback(this.get_scriptElement(), false); + } + function Sys$_ScriptLoaderTask$_scriptLoadHandler() { + if(this._disposed) { + return; + } + var scriptElement = this.get_scriptElement(); + if ((scriptElement.readyState !== 'loaded') && + (scriptElement.readyState !== 'complete')) { + return; + } + + this._completedCallback(scriptElement, true); + } +Sys._ScriptLoaderTask.prototype = { + get_scriptElement: Sys$_ScriptLoaderTask$get_scriptElement, + dispose: Sys$_ScriptLoaderTask$dispose, + execute: Sys$_ScriptLoaderTask$execute, + _addScriptElementHandlers: Sys$_ScriptLoaderTask$_addScriptElementHandlers, + _removeScriptElementHandlers: Sys$_ScriptLoaderTask$_removeScriptElementHandlers, + _scriptErrorHandler: Sys$_ScriptLoaderTask$_scriptErrorHandler, + _scriptLoadHandler: Sys$_ScriptLoaderTask$_scriptLoadHandler +} +Sys._ScriptLoaderTask.registerClass("Sys._ScriptLoaderTask", null, Sys.IDisposable); +Sys._ScriptLoaderTask._clearScript = function Sys$_ScriptLoaderTask$_clearScript(scriptElement) { + if (!Sys.Debug.isDebug) { + scriptElement.parentNode.removeChild(scriptElement); + } +} +Type.registerNamespace('Sys.Net'); + +Sys.Net.WebServiceProxy = function Sys$Net$WebServiceProxy() { +} + function Sys$Net$WebServiceProxy$get_timeout() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._timeout || 0; + } + function Sys$Net$WebServiceProxy$set_timeout(value) { + var e = Function._validateParams(arguments, [{name: "value", type: Number}]); + if (e) throw e; + if (value < 0) { throw Error.argumentOutOfRange('value', value, Sys.Res.invalidTimeout); } + this._timeout = value; + } + function Sys$Net$WebServiceProxy$get_defaultUserContext() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return (typeof(this._userContext) === "undefined") ? null : this._userContext; + } + function Sys$Net$WebServiceProxy$set_defaultUserContext(value) { + var e = Function._validateParams(arguments, [{name: "value", mayBeNull: true}]); + if (e) throw e; + this._userContext = value; + } + function Sys$Net$WebServiceProxy$get_defaultSucceededCallback() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._succeeded || null; + } + function Sys$Net$WebServiceProxy$set_defaultSucceededCallback(value) { + var e = Function._validateParams(arguments, [{name: "value", type: Function, mayBeNull: true}]); + if (e) throw e; + this._succeeded = value; + } + function Sys$Net$WebServiceProxy$get_defaultFailedCallback() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._failed || null; + } + function Sys$Net$WebServiceProxy$set_defaultFailedCallback(value) { + var e = Function._validateParams(arguments, [{name: "value", type: Function, mayBeNull: true}]); + if (e) throw e; + this._failed = value; + } + function Sys$Net$WebServiceProxy$get_enableJsonp() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return !!this._jsonp; + } + function Sys$Net$WebServiceProxy$set_enableJsonp(value) { + var e = Function._validateParams(arguments, [{name: "value", type: Boolean}]); + if (e) throw e; + this._jsonp = value; + } + function Sys$Net$WebServiceProxy$get_path() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._path || null; + } + function Sys$Net$WebServiceProxy$set_path(value) { + var e = Function._validateParams(arguments, [{name: "value", type: String}]); + if (e) throw e; + this._path = value; + } + function Sys$Net$WebServiceProxy$get_jsonpCallbackParameter() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._callbackParameter || "callback"; + } + function Sys$Net$WebServiceProxy$set_jsonpCallbackParameter(value) { + var e = Function._validateParams(arguments, [{name: "value", type: String}]); + if (e) throw e; + this._callbackParameter = value; + } + function Sys$Net$WebServiceProxy$_invoke(servicePath, methodName, useGet, params, onSuccess, onFailure, userContext) { + /// + /// + /// + /// + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "servicePath", type: String}, + {name: "methodName", type: String}, + {name: "useGet", type: Boolean}, + {name: "params"}, + {name: "onSuccess", type: Function, mayBeNull: true, optional: true}, + {name: "onFailure", type: Function, mayBeNull: true, optional: true}, + {name: "userContext", mayBeNull: true, optional: true} + ]); + if (e) throw e; + onSuccess = onSuccess || this.get_defaultSucceededCallback(); + onFailure = onFailure || this.get_defaultFailedCallback(); + if (userContext === null || typeof userContext === 'undefined') userContext = this.get_defaultUserContext(); + return Sys.Net.WebServiceProxy.invoke(servicePath, methodName, useGet, params, onSuccess, onFailure, userContext, this.get_timeout(), this.get_enableJsonp(), this.get_jsonpCallbackParameter()); + } +Sys.Net.WebServiceProxy.prototype = { + get_timeout: Sys$Net$WebServiceProxy$get_timeout, + set_timeout: Sys$Net$WebServiceProxy$set_timeout, + get_defaultUserContext: Sys$Net$WebServiceProxy$get_defaultUserContext, + set_defaultUserContext: Sys$Net$WebServiceProxy$set_defaultUserContext, + get_defaultSucceededCallback: Sys$Net$WebServiceProxy$get_defaultSucceededCallback, + set_defaultSucceededCallback: Sys$Net$WebServiceProxy$set_defaultSucceededCallback, + get_defaultFailedCallback: Sys$Net$WebServiceProxy$get_defaultFailedCallback, + set_defaultFailedCallback: Sys$Net$WebServiceProxy$set_defaultFailedCallback, + get_enableJsonp: Sys$Net$WebServiceProxy$get_enableJsonp, + set_enableJsonp: Sys$Net$WebServiceProxy$set_enableJsonp, + get_path: Sys$Net$WebServiceProxy$get_path, + set_path: Sys$Net$WebServiceProxy$set_path, + get_jsonpCallbackParameter: Sys$Net$WebServiceProxy$get_jsonpCallbackParameter, + set_jsonpCallbackParameter: Sys$Net$WebServiceProxy$set_jsonpCallbackParameter, + _invoke: Sys$Net$WebServiceProxy$_invoke +} +Sys.Net.WebServiceProxy.registerClass('Sys.Net.WebServiceProxy'); +Sys.Net.WebServiceProxy.invoke = function Sys$Net$WebServiceProxy$invoke(servicePath, methodName, useGet, params, onSuccess, onFailure, userContext, timeout, enableJsonp, jsonpCallbackParameter) { + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "servicePath", type: String}, + {name: "methodName", type: String, mayBeNull: true, optional: true}, + {name: "useGet", type: Boolean, optional: true}, + {name: "params", mayBeNull: true, optional: true}, + {name: "onSuccess", type: Function, mayBeNull: true, optional: true}, + {name: "onFailure", type: Function, mayBeNull: true, optional: true}, + {name: "userContext", mayBeNull: true, optional: true}, + {name: "timeout", type: Number, optional: true}, + {name: "enableJsonp", type: Boolean, mayBeNull: true, optional: true}, + {name: "jsonpCallbackParameter", type: String, mayBeNull: true, optional: true} + ]); + if (e) throw e; + var schemeHost = (enableJsonp !== false) ? Sys.Net.WebServiceProxy._xdomain.exec(servicePath) : null, + tempCallback, jsonp = schemeHost && (schemeHost.length === 3) && + ((schemeHost[1] !== location.protocol) || (schemeHost[2] !== location.host)); + useGet = jsonp || useGet; + if (jsonp) { + jsonpCallbackParameter = jsonpCallbackParameter || "callback"; + tempCallback = "_jsonp" + Sys._jsonp++; + } + if (!params) params = {}; + var urlParams = params; + if (!useGet || !urlParams) urlParams = {}; + var script, error, timeoutcookie = null, loader, body = null, + url = Sys.Net.WebRequest._createUrl(methodName + ? (servicePath+"/"+encodeURIComponent(methodName)) + : servicePath, urlParams, jsonp ? (jsonpCallbackParameter + "=Sys." + tempCallback) : null); + if (jsonp) { + script = document.createElement("script"); + script.src = url; + loader = new Sys._ScriptLoaderTask(script, function(script, loaded) { + if (!loaded || tempCallback) { + jsonpComplete({ Message: String.format(Sys.Res.webServiceFailedNoMsg, methodName) }, -1); + } + }); + function jsonpComplete(data, statusCode) { + if (timeoutcookie !== null) { + window.clearTimeout(timeoutcookie); + timeoutcookie = null; + } + loader.dispose(); + delete Sys[tempCallback]; + tempCallback = null; + if ((typeof(statusCode) !== "undefined") && (statusCode !== 200)) { + if (onFailure) { + error = new Sys.Net.WebServiceError(false, + data.Message || String.format(Sys.Res.webServiceFailedNoMsg, methodName), + data.StackTrace || null, + data.ExceptionType || null, + data); + error._statusCode = statusCode; + onFailure(error, userContext, methodName); + } + else { + if (data.StackTrace && data.Message) { + error = data.StackTrace + "-- " + data.Message; + } + else { + error = data.StackTrace || data.Message; + } + error = String.format(error ? Sys.Res.webServiceFailed : Sys.Res.webServiceFailedNoMsg, methodName, error); + throw Sys.Net.WebServiceProxy._createFailedError(methodName, String.format(Sys.Res.webServiceFailed, methodName, error)); + } + } + else if (onSuccess) { + onSuccess(data, userContext, methodName); + } + } + Sys[tempCallback] = jsonpComplete; + loader.execute(); + return null; + } + var request = new Sys.Net.WebRequest(); + request.set_url(url); + request.get_headers()['Content-Type'] = 'application/json; charset=utf-8'; + if (!useGet) { + body = Sys.Serialization.JavaScriptSerializer.serialize(params); + if (body === "{}") body = ""; + } + request.set_body(body); + request.add_completed(onComplete); + if (timeout && timeout > 0) request.set_timeout(timeout); + request.invoke(); + + function onComplete(response, eventArgs) { + if (response.get_responseAvailable()) { + var statusCode = response.get_statusCode(); + var result = null; + + try { + var contentType = response.getResponseHeader("Content-Type"); + if (contentType.startsWith("application/json")) { + result = response.get_object(); + } + else if (contentType.startsWith("text/xml")) { + result = response.get_xml(); + } + else { + result = response.get_responseData(); + } + } catch (ex) { + } + var error = response.getResponseHeader("jsonerror"); + var errorObj = (error === "true"); + if (errorObj) { + if (result) { + result = new Sys.Net.WebServiceError(false, result.Message, result.StackTrace, result.ExceptionType, result); + } + } + else if (contentType.startsWith("application/json")) { + result = (!result || (typeof(result.d) === "undefined")) ? result : result.d; + } + if (((statusCode < 200) || (statusCode >= 300)) || errorObj) { + if (onFailure) { + if (!result || !errorObj) { + result = new Sys.Net.WebServiceError(false , String.format(Sys.Res.webServiceFailedNoMsg, methodName)); + } + result._statusCode = statusCode; + onFailure(result, userContext, methodName); + } + else { + if (result && errorObj) { + error = result.get_exceptionType() + "-- " + result.get_message(); + } + else { + error = response.get_responseData(); + } + throw Sys.Net.WebServiceProxy._createFailedError(methodName, String.format(Sys.Res.webServiceFailed, methodName, error)); + } + } + else if (onSuccess) { + onSuccess(result, userContext, methodName); + } + } + else { + var msg; + if (response.get_timedOut()) { + msg = String.format(Sys.Res.webServiceTimedOut, methodName); + } + else { + msg = String.format(Sys.Res.webServiceFailedNoMsg, methodName) + } + if (onFailure) { + onFailure(new Sys.Net.WebServiceError(response.get_timedOut(), msg, "", ""), userContext, methodName); + } + else { + throw Sys.Net.WebServiceProxy._createFailedError(methodName, msg); + } + } + } + return request; +} +Sys.Net.WebServiceProxy._createFailedError = function Sys$Net$WebServiceProxy$_createFailedError(methodName, errorMessage) { + var displayMessage = "Sys.Net.WebServiceFailedException: " + errorMessage; + var e = Error.create(displayMessage, { 'name': 'Sys.Net.WebServiceFailedException', 'methodName': methodName }); + e.popStackFrame(); + return e; +} +Sys.Net.WebServiceProxy._defaultFailedCallback = function Sys$Net$WebServiceProxy$_defaultFailedCallback(err, methodName) { + var error = err.get_exceptionType() + "-- " + err.get_message(); + throw Sys.Net.WebServiceProxy._createFailedError(methodName, String.format(Sys.Res.webServiceFailed, methodName, error)); +} +Sys.Net.WebServiceProxy._generateTypedConstructor = function Sys$Net$WebServiceProxy$_generateTypedConstructor(type) { + return function(properties) { + if (properties) { + for (var name in properties) { + this[name] = properties[name]; + } + } + this.__type = type; + } +} +Sys._jsonp = 0; +Sys.Net.WebServiceProxy._xdomain = /^\s*([a-zA-Z0-9\+\-\.]+\:)\/\/([^?#\/]+)/; + +Sys.Net.WebServiceError = function Sys$Net$WebServiceError(timedOut, message, stackTrace, exceptionType, errorObject) { + /// + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "timedOut", type: Boolean}, + {name: "message", type: String, mayBeNull: true}, + {name: "stackTrace", type: String, mayBeNull: true, optional: true}, + {name: "exceptionType", type: String, mayBeNull: true, optional: true}, + {name: "errorObject", type: Object, mayBeNull: true, optional: true} + ]); + if (e) throw e; + this._timedOut = timedOut; + this._message = message; + this._stackTrace = stackTrace; + this._exceptionType = exceptionType; + this._errorObject = errorObject; + this._statusCode = -1; +} + function Sys$Net$WebServiceError$get_timedOut() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._timedOut; + } + function Sys$Net$WebServiceError$get_statusCode() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._statusCode; + } + function Sys$Net$WebServiceError$get_message() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._message; + } + function Sys$Net$WebServiceError$get_stackTrace() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._stackTrace || ""; + } + function Sys$Net$WebServiceError$get_exceptionType() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._exceptionType || ""; + } + function Sys$Net$WebServiceError$get_errorObject() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._errorObject || null; + } +Sys.Net.WebServiceError.prototype = { + get_timedOut: Sys$Net$WebServiceError$get_timedOut, + get_statusCode: Sys$Net$WebServiceError$get_statusCode, + get_message: Sys$Net$WebServiceError$get_message, + get_stackTrace: Sys$Net$WebServiceError$get_stackTrace, + get_exceptionType: Sys$Net$WebServiceError$get_exceptionType, + get_errorObject: Sys$Net$WebServiceError$get_errorObject +} +Sys.Net.WebServiceError.registerClass('Sys.Net.WebServiceError'); + + +Type.registerNamespace('Sys'); + +Sys.Res={ +'urlMustBeLessThan1024chars':'The history state must be small enough to not make the url larger than 1024 characters.', +'argumentTypeName':'Value is not the name of an existing type.', +'cantBeCalledAfterDispose':'Can\'t be called after dispose.', +'componentCantSetIdAfterAddedToApp':'The id property of a component can\'t be set after it\'s been added to the Application object.', +'behaviorDuplicateName':'A behavior with name \'{0}\' already exists or it is the name of an existing property on the target element.', +'notATypeName':'Value is not a valid type name.', +'elementNotFound':'An element with id \'{0}\' could not be found.', +'stateMustBeStringDictionary':'The state object can only have null and string fields.', +'boolTrueOrFalse':'Value must be \'true\' or \'false\'.', +'scriptLoadFailedNoHead':'ScriptLoader requires pages to contain a element.', +'stringFormatInvalid':'The format string is invalid.', +'referenceNotFound':'Component \'{0}\' was not found.', +'enumReservedName':'\'{0}\' is a reserved name that can\'t be used as an enum value name.', +'circularParentChain':'The chain of control parents can\'t have circular references.', +'namespaceContainsNonObject':'Object {0} already exists and is not an object.', +'undefinedEvent':'\'{0}\' is not an event.', +'propertyUndefined':'\'{0}\' is not a property or an existing field.', +'observableConflict':'Object already contains a member with the name \'{0}\'.', +'historyCannotEnableHistory':'Cannot set enableHistory after initialization.', +'eventHandlerInvalid':'Handler was not added through the Sys.UI.DomEvent.addHandler method.', +'scriptLoadFailedDebug':'The script \'{0}\' failed to load. Check for:\r\n Inaccessible path.\r\n Script errors. (IE) Enable \'Display a notification about every script error\' under advanced settings.', +'propertyNotWritable':'\'{0}\' is not a writable property.', +'enumInvalidValueName':'\'{0}\' is not a valid name for an enum value.', +'controlAlreadyDefined':'A control is already associated with the element.', +'addHandlerCantBeUsedForError':'Can\'t add a handler for the error event using this method. Please set the window.onerror property instead.', +'cantAddNonFunctionhandler':'Can\'t add a handler that is not a function.', +'invalidNameSpace':'Value is not a valid namespace identifier.', +'notAnInterface':'Value is not a valid interface.', +'eventHandlerNotFunction':'Handler must be a function.', +'propertyNotAnArray':'\'{0}\' is not an Array property.', +'namespaceContainsClass':'Object {0} already exists as a class, enum, or interface.', +'typeRegisteredTwice':'Type {0} has already been registered. The type may be defined multiple times or the script file that defines it may have already been loaded. A possible cause is a change of settings during a partial update.', +'cantSetNameAfterInit':'The name property can\'t be set on this object after initialization.', +'historyMissingFrame':'For the history feature to work in IE, the page must have an iFrame element with id \'__historyFrame\' pointed to a page that gets its title from the \'title\' query string parameter and calls Sys.Application._onIFrameLoad() on the parent window. This can be done by setting EnableHistory to true on ScriptManager.', +'appDuplicateComponent':'Two components with the same id \'{0}\' can\'t be added to the application.', +'historyCannotAddHistoryPointWithHistoryDisabled':'A history point can only be added if enableHistory is set to true.', +'baseNotAClass':'Value is not a class.', +'expectedElementOrId':'Value must be a DOM element or DOM element Id.', +'methodNotFound':'No method found with name \'{0}\'.', +'arrayParseBadFormat':'Value must be a valid string representation for an array. It must start with a \'[\' and end with a \']\'.', +'stateFieldNameInvalid':'State field names must not contain any \'=\' characters.', +'cantSetId':'The id property can\'t be set on this object.', +'stringFormatBraceMismatch':'The format string contains an unmatched opening or closing brace.', +'enumValueNotInteger':'An enumeration definition can only contain integer values.', +'propertyNullOrUndefined':'Cannot set the properties of \'{0}\' because it returned a null value.', +'argumentDomNode':'Value must be a DOM element or a text node.', +'componentCantSetIdTwice':'The id property of a component can\'t be set more than once.', +'createComponentOnDom':'Value must be null for Components that are not Controls or Behaviors.', +'createNotComponent':'{0} does not derive from Sys.Component.', +'createNoDom':'Value must not be null for Controls and Behaviors.', +'cantAddWithoutId':'Can\'t add a component that doesn\'t have an id.', +'notObservable':'Instances of type \'{0}\' cannot be observed.', +'badTypeName':'Value is not the name of the type being registered or the name is a reserved word.', +'argumentInteger':'Value must be an integer.', +'invokeCalledTwice':'Cannot call invoke more than once.', +'webServiceFailed':'The server method \'{0}\' failed with the following error: {1}', +'argumentType':'Object cannot be converted to the required type.', +'argumentNull':'Value cannot be null.', +'scriptAlreadyLoaded':'The script \'{0}\' has been referenced multiple times. If referencing Microsoft AJAX scripts explicitly, set the MicrosoftAjaxMode property of the ScriptManager to Explicit.', +'scriptDependencyNotFound':'The script \'{0}\' failed to load because it is dependent on script \'{1}\'.', +'formatBadFormatSpecifier':'Format specifier was invalid.', +'requiredScriptReferenceNotIncluded':'\'{0}\' requires that you have included a script reference to \'{1}\'.', +'webServiceFailedNoMsg':'The server method \'{0}\' failed.', +'argumentDomElement':'Value must be a DOM element.', +'invalidExecutorType':'Could not create a valid Sys.Net.WebRequestExecutor from: {0}.', +'cannotCallBeforeResponse':'Cannot call {0} when responseAvailable is false.', +'actualValue':'Actual value was {0}.', +'enumInvalidValue':'\'{0}\' is not a valid value for enum {1}.', +'scriptLoadFailed':'The script \'{0}\' could not be loaded.', +'parameterCount':'Parameter count mismatch.', +'cannotDeserializeEmptyString':'Cannot deserialize empty string.', +'formatInvalidString':'Input string was not in a correct format.', +'invalidTimeout':'Value must be greater than or equal to zero.', +'cannotAbortBeforeStart':'Cannot abort when executor has not started.', +'argument':'Value does not fall within the expected range.', +'cannotDeserializeInvalidJson':'Cannot deserialize. The data does not correspond to valid JSON.', +'invalidHttpVerb':'httpVerb cannot be set to an empty or null string.', +'nullWebRequest':'Cannot call executeRequest with a null webRequest.', +'eventHandlerInvalid':'Handler was not added through the Sys.UI.DomEvent.addHandler method.', +'cannotSerializeNonFiniteNumbers':'Cannot serialize non finite numbers.', +'argumentUndefined':'Value cannot be undefined.', +'webServiceInvalidReturnType':'The server method \'{0}\' returned an invalid type. Expected type: {1}', +'servicePathNotSet':'The path to the web service has not been set.', +'argumentTypeWithTypes':'Object of type \'{0}\' cannot be converted to type \'{1}\'.', +'cannotCallOnceStarted':'Cannot call {0} once started.', +'badBaseUrl1':'Base URL does not contain ://.', +'badBaseUrl2':'Base URL does not contain another /.', +'badBaseUrl3':'Cannot find last / in base URL.', +'setExecutorAfterActive':'Cannot set executor after it has become active.', +'paramName':'Parameter name: {0}', +'nullReferenceInPath':'Null reference while evaluating data path: \'{0}\'.', +'cannotCallOutsideHandler':'Cannot call {0} outside of a completed event handler.', +'cannotSerializeObjectWithCycle':'Cannot serialize object with cyclic reference within child properties.', +'format':'One of the identified items was in an invalid format.', +'assertFailedCaller':'Assertion Failed: {0}\r\nat {1}', +'argumentOutOfRange':'Specified argument was out of the range of valid values.', +'webServiceTimedOut':'The server method \'{0}\' timed out.', +'notImplemented':'The method or operation is not implemented.', +'assertFailed':'Assertion Failed: {0}', +'invalidOperation':'Operation is not valid due to the current state of the object.', +'breakIntoDebugger':'{0}\r\n\r\nBreak into debugger?' +}; diff --git a/Azure/WebSite_WindowsAzure/Scripts/MicrosoftAjax.js b/Azure/WebSite_WindowsAzure/Scripts/MicrosoftAjax.js new file mode 100644 index 0000000..52e6626 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Scripts/MicrosoftAjax.js @@ -0,0 +1,6 @@ +//---------------------------------------------------------- +// Copyright (C) Microsoft Corporation. All rights reserved. +//---------------------------------------------------------- +// MicrosoftAjax.js +Function.__typeName="Function";Function.__class=true;Function.createCallback=function(b,a){return function(){var e=arguments.length;if(e>0){var d=[];for(var c=0;c=d)break;a=Function._validateParameter(g[b],f,h);if(a){a.popStackFrame();return a}}return null};Function._validateParameterCount=function(j,d,i){var a,c,b=d.length,e=j.length;if(eb){c=true;for(a=0;a0&&(d=0};Array.dequeue=function(a){return a.shift()};Array.forEach=function(b,e,d){for(var a=0,f=b.length;a=0)b.splice(a,1);return a>=0};Array.removeAt=function(a,b){a.splice(b,1)};Sys._indexOf=function(d,e,a){if(typeof e==="undefined")return -1;var c=d.length;if(c!==0){a=a-0;if(isNaN(a))a=0;else{if(isFinite(a))a=a-a%1;if(a<0)a=Math.max(0,c+a)}for(var b=a;b-1){Sys.Browser.agent=Sys.Browser.InternetExplorer;Sys.Browser.version=parseFloat(navigator.userAgent.match(/MSIE (\d+\.\d+)/)[1]);if(Sys.Browser.version>=8)if(document.documentMode>=7)Sys.Browser.documentMode=document.documentMode;Sys.Browser.hasDebuggerStatement=true}else if(navigator.userAgent.indexOf(" Firefox/")>-1){Sys.Browser.agent=Sys.Browser.Firefox;Sys.Browser.version=parseFloat(navigator.userAgent.match(/Firefox\/(\d+\.\d+)/)[1]);Sys.Browser.name="Firefox";Sys.Browser.hasDebuggerStatement=true}else if(navigator.userAgent.indexOf(" AppleWebKit/")>-1){Sys.Browser.agent=Sys.Browser.Safari;Sys.Browser.version=parseFloat(navigator.userAgent.match(/AppleWebKit\/(\d+(\.\d+)?)/)[1]);Sys.Browser.name="Safari"}else if(navigator.userAgent.indexOf("Opera/")>-1)Sys.Browser.agent=Sys.Browser.Opera;Sys.EventArgs=function(){};Sys.EventArgs.registerClass("Sys.EventArgs");Sys.EventArgs.Empty=new Sys.EventArgs;Sys.CancelEventArgs=function(){Sys.CancelEventArgs.initializeBase(this);this._cancel=false};Sys.CancelEventArgs.prototype={get_cancel:function(){return this._cancel},set_cancel:function(a){this._cancel=a}};Sys.CancelEventArgs.registerClass("Sys.CancelEventArgs",Sys.EventArgs);Type.registerNamespace("Sys.UI");Sys._Debug=function(){};Sys._Debug.prototype={_appendConsole:function(a){if(typeof Debug!=="undefined"&&Debug.writeln)Debug.writeln(a);if(window.console&&window.console.log)window.console.log(a);if(window.opera)window.opera.postError(a);if(window.debugService)window.debugService.trace(a)},_appendTrace:function(b){var a=document.getElementById("TraceConsole");if(a&&a.tagName.toUpperCase()==="TEXTAREA")a.value+=b+"\n"},assert:function(c,a,b){if(!c){a=b&&this.assert.caller?String.format(Sys.Res.assertFailedCaller,a,this.assert.caller):String.format(Sys.Res.assertFailed,a);if(confirm(String.format(Sys.Res.breakIntoDebugger,a)))this.fail(a)}},clearTrace:function(){var a=document.getElementById("TraceConsole");if(a&&a.tagName.toUpperCase()==="TEXTAREA")a.value=""},fail:function(message){this._appendConsole(message);if(Sys.Browser.hasDebuggerStatement)eval("debugger")},trace:function(a){this._appendConsole(a);this._appendTrace(a)},traceDump:function(a,b){var c=this._traceDump(a,b,true)},_traceDump:function(a,c,f,b,d){c=c?c:"traceDump";b=b?b:"";if(a===null){this.trace(b+c+": null");return}switch(typeof a){case "undefined":this.trace(b+c+": Undefined");break;case "number":case "string":case "boolean":this.trace(b+c+": "+a);break;default:if(Date.isInstanceOfType(a)||RegExp.isInstanceOfType(a)){this.trace(b+c+": "+a.toString());break}if(!d)d=[];else if(Array.contains(d,a)){this.trace(b+c+": ...");return}Array.add(d,a);if(a==window||a===document||window.HTMLElement&&a instanceof HTMLElement||typeof a.nodeName==="string"){var k=a.tagName?a.tagName:"DomElement";if(a.id)k+=" - "+a.id;this.trace(b+c+" {"+k+"}")}else{var i=Object.getTypeName(a);this.trace(b+c+(typeof i==="string"?" {"+i+"}":""));if(b===""||f){b+=" ";var e,j,l,g,h;if(Array.isInstanceOfType(a)){j=a.length;for(e=0;e=0;d--){var k=h[d].trim();b=a[k];if(typeof b!=="number")throw Error.argument("value",String.format(Sys.Res.enumInvalidValue,c.split(",")[d].trim(),this.__typeName));j|=b}return j}}function Sys$Enum$toString(c){if(typeof c==="undefined"||c===null)return this.__string;var d=this.prototype,a;if(!this.__flags||c===0){for(a in d)if(d[a]===c)return a}else{var b=this.__sortedValues;if(!b){b=[];for(a in d)b[b.length]={key:a,value:d[a]};b.sort(function(a,b){return a.value-b.value});this.__sortedValues=b}var e=[],g=c;for(a=b.length-1;a>=0;a--){var h=b[a],f=h.value;if(f===0)continue;if((f&c)===f){e[e.length]=h.key;g-=f;if(g===0)break}}if(e.length&&g===0)return e.reverse().join(", ")}return ""}Type.prototype.registerEnum=function(b,c){Sys.__upperCaseTypes[b.toUpperCase()]=this;for(var a in this.prototype)this[a]=this.prototype[a];this.__typeName=b;this.parse=Sys$Enum$parse;this.__string=this.toString();this.toString=Sys$Enum$toString;this.__flags=c;this.__enum=true};Type.isEnum=function(a){if(typeof a==="undefined"||a===null)return false;return !!a.__enum};Type.isFlags=function(a){if(typeof a==="undefined"||a===null)return false;return !!a.__flags};Sys.CollectionChange=function(e,a,c,b,d){this.action=e;if(a)if(!(a instanceof Array))a=[a];this.newItems=a||null;if(typeof c!=="number")c=-1;this.newStartingIndex=c;if(b)if(!(b instanceof Array))b=[b];this.oldItems=b||null;if(typeof d!=="number")d=-1;this.oldStartingIndex=d};Sys.CollectionChange.registerClass("Sys.CollectionChange");Sys.NotifyCollectionChangedAction=function(){throw Error.notImplemented()};Sys.NotifyCollectionChangedAction.prototype={add:0,remove:1,reset:2};Sys.NotifyCollectionChangedAction.registerEnum("Sys.NotifyCollectionChangedAction");Sys.NotifyCollectionChangedEventArgs=function(a){this._changes=a;Sys.NotifyCollectionChangedEventArgs.initializeBase(this)};Sys.NotifyCollectionChangedEventArgs.prototype={get_changes:function(){return this._changes||[]}};Sys.NotifyCollectionChangedEventArgs.registerClass("Sys.NotifyCollectionChangedEventArgs",Sys.EventArgs);Sys.Observer=function(){};Sys.Observer.registerClass("Sys.Observer");Sys.Observer.makeObservable=function(a){var c=a instanceof Array,b=Sys.Observer;if(a.setValue===b._observeMethods.setValue)return a;b._addMethods(a,b._observeMethods);if(c)b._addMethods(a,b._arrayMethods);return a};Sys.Observer._addMethods=function(c,b){for(var a in b)c[a]=b[a]};Sys.Observer._addEventHandler=function(c,a,b){Sys.Observer._getContext(c,true).events._addHandler(a,b)};Sys.Observer.addEventHandler=function(c,a,b){Sys.Observer._addEventHandler(c,a,b)};Sys.Observer._removeEventHandler=function(c,a,b){Sys.Observer._getContext(c,true).events._removeHandler(a,b)};Sys.Observer.removeEventHandler=function(c,a,b){Sys.Observer._removeEventHandler(c,a,b)};Sys.Observer.raiseEvent=function(b,e,d){var c=Sys.Observer._getContext(b);if(!c)return;var a=c.events.getHandler(e);if(a)a(b,d)};Sys.Observer.addPropertyChanged=function(b,a){Sys.Observer._addEventHandler(b,"propertyChanged",a)};Sys.Observer.removePropertyChanged=function(b,a){Sys.Observer._removeEventHandler(b,"propertyChanged",a)};Sys.Observer.beginUpdate=function(a){Sys.Observer._getContext(a,true).updating=true};Sys.Observer.endUpdate=function(b){var a=Sys.Observer._getContext(b);if(!a||!a.updating)return;a.updating=false;var d=a.dirty;a.dirty=false;if(d){if(b instanceof Array){var c=a.changes;a.changes=null;Sys.Observer.raiseCollectionChanged(b,c)}Sys.Observer.raisePropertyChanged(b,"")}};Sys.Observer.isUpdating=function(b){var a=Sys.Observer._getContext(b);return a?a.updating:false};Sys.Observer._setValue=function(a,j,g){var b,f,k=a,d=j.split(".");for(var i=0,m=d.length-1;i-1&&ac.Calendar.TwoDigitYearMax)a-=100}return a};Date._getEra=function(e,c){if(!c)return 0;var b,d=e.getTime();for(var a=0,f=c.length;a=b)return a}return 0};Date._getEraYear=function(d,b,e,c){var a=d.getFullYear();if(!c&&b.eras)a-=b.eras[e+3];return a};Date._getParseRegExp=function(b,e){if(!b._parseRegExp)b._parseRegExp={};else if(b._parseRegExp[e])return b._parseRegExp[e];var c=Date._expandFormat(b,e);c=c.replace(/([\^\$\.\*\+\?\|\[\]\(\)\{\}])/g,"\\\\$1");var a=new Sys.StringBuilder("^"),j=[],f=0,i=0,h=Date._getTokenRegExp(),d;while((d=h.exec(c))!==null){var l=c.slice(f,d.index);f=h.lastIndex;i+=Date._appendPreOrPostMatch(l,a);if(i%2===1){a.append(d[0]);continue}switch(d[0]){case "dddd":case "ddd":case "MMMM":case "MMM":case "gg":case "g":a.append("(\\D+)");break;case "tt":case "t":a.append("(\\D*)");break;case "yyyy":a.append("(\\d{4})");break;case "fff":a.append("(\\d{3})");break;case "ff":a.append("(\\d{2})");break;case "f":a.append("(\\d)");break;case "dd":case "d":case "MM":case "M":case "yy":case "y":case "HH":case "H":case "hh":case "h":case "mm":case "m":case "ss":case "s":a.append("(\\d\\d?)");break;case "zzz":a.append("([+-]?\\d\\d?:\\d{2})");break;case "zz":case "z":a.append("([+-]?\\d\\d?)");break;case "/":a.append("(\\"+b.DateSeparator+")")}Array.add(j,d[0])}Date._appendPreOrPostMatch(c.slice(f),a);a.append("$");var k=a.toString().replace(/\s+/g,"\\s+"),g={"regExp":k,"groups":j};b._parseRegExp[e]=g;return g};Date._getTokenRegExp=function(){return /\/|dddd|ddd|dd|d|MMMM|MMM|MM|M|yyyy|yy|y|hh|h|HH|H|mm|m|ss|s|tt|t|fff|ff|f|zzz|zz|z|gg|g/g};Date.parseLocale=function(a){return Date._parse(a,Sys.CultureInfo.CurrentCulture,arguments)};Date.parseInvariant=function(a){return Date._parse(a,Sys.CultureInfo.InvariantCulture,arguments)};Date._parse=function(h,d,i){var a,c,b,f,e,g=false;for(a=1,c=i.length;a31)return null;break;case "MMMM":c=k._getMonthIndex(a);if(c<0||c>11)return null;break;case "MMM":c=k._getAbbrMonthIndex(a);if(c<0||c>11)return null;break;case "M":case "MM":c=parseInt(a,10)-1;if(c<0||c>11)return null;break;case "y":case "yy":e=Date._expandYear(g,parseInt(a,10));if(e<0||e>9999)return null;break;case "yyyy":e=parseInt(a,10);if(e<0||e>9999)return null;break;case "h":case "hh":d=parseInt(a,10);if(d===12)d=0;if(d<0||d>11)return null;break;case "H":case "HH":d=parseInt(a,10);if(d<0||d>23)return null;break;case "m":case "mm":q=parseInt(a,10);if(q<0||q>59)return null;break;case "s":case "ss":r=parseInt(a,10);if(r<0||r>59)return null;break;case "tt":case "t":var z=a.toUpperCase();v=z===g.PMDesignator.toUpperCase();if(!v&&z!==g.AMDesignator.toUpperCase())return null;break;case "f":f=parseInt(a,10)*100;if(f<0||f>999)return null;break;case "ff":f=parseInt(a,10)*10;if(f<0||f>999)return null;break;case "fff":f=parseInt(a,10);if(f<0||f>999)return null;break;case "dddd":i=k._getDayIndex(a);if(i<0||i>6)return null;break;case "ddd":i=k._getAbbrDayIndex(a);if(i<0||i>6)return null;break;case "zzz":var u=a.split(/:/);if(u.length!==2)return null;h=parseInt(u[0],10);if(h<-12||h>13)return null;var o=parseInt(u[1],10);if(o<0||o>59)return null;n=h*60+(a.startsWith("-")?-o:o);break;case "z":case "zz":h=parseInt(a,10);if(h<-12||h>13)return null;n=h*60;break;case "g":case "gg":var p=a;if(!p||!g.eras)return null;p=p.toLowerCase().trim();for(var s=0,F=g.eras.length;s0)return this.toLocaleString();else return this.toString();var o=["n %","n%","%n"],n=["-n %","-n%","-%n"],p=["(n)","-n","- n","n-","n -"],m=["$n","n$","$ n","n $"],l=["($n)","-$n","$-n","$n-","(n$)","-n$","n-$","n$-","-n $","-$ n","n $-","$ n-","$ -n","n- $","($ n)","(n $)"];function g(a,c,d){for(var b=a.length;b1?parseInt(e[1]):0;e=b.split(".");b=e[0];a=e.length>1?e[1]:"";var q;if(c>0){a=g(a,c,false);b+=a.slice(0,c);a=a.substr(c)}else if(c<0){c=-c;b=g(b,c+1,true);a=b.slice(-c,b.length)+a;b=b.slice(0,-c)}if(i>0){if(a.length>i)a=a.slice(0,i);else a=g(a,i,false);a=p+a}else a="";var d=b.length-1,f="";while(d>=0){if(h===0||h>d)if(f.length>0)return b.slice(0,d+1)+n+f+a;else return b.slice(0,d+1)+a;if(f.length>0)f=b.slice(d-h+1,d+1)+n+f;else f=b.slice(d-h+1,d+1);d-=h;if(k1)b=parseInt(e.slice(1),10);var c;switch(e.charAt(0)){case "d":case "D":c="n";if(b!==-1)d=g(""+d,b,true);if(this<0)d=-d;break;case "c":case "C":if(this<0)c=l[a.CurrencyNegativePattern];else c=m[a.CurrencyPositivePattern];if(b===-1)b=a.CurrencyDecimalDigits;d=i(Math.abs(this),b,a.CurrencyGroupSizes,a.CurrencyGroupSeparator,a.CurrencyDecimalSeparator);break;case "n":case "N":if(this<0)c=p[a.NumberNegativePattern];else c="n";if(b===-1)b=a.NumberDecimalDigits;d=i(Math.abs(this),b,a.NumberGroupSizes,a.NumberGroupSeparator,a.NumberDecimalSeparator);break;case "p":case "P":if(this<0)c=n[a.PercentNegativePattern];else c=o[a.PercentPositivePattern];if(b===-1)b=a.PercentDecimalDigits;d=i(Math.abs(this)*100,b,a.PercentGroupSizes,a.PercentGroupSeparator,a.PercentDecimalSeparator);break;default:throw Error.format(Sys.Res.formatBadFormatSpecifier)}var k=/n|\$|-|%/g,f="";for(;true;){var q=k.lastIndex,h=k.exec(c);f+=c.slice(q,h?h.index:c.length);if(!h)break;switch(h[0]){case "n":f+=d;break;case "$":f+=a.CurrencySymbol;break;case "-":if(/[1-9]/.test(d))f+=a.NegativeSign;break;case "%":f+=a.PercentSymbol}}return f};Sys.CultureInfo=function(c,b,a){this.name=c;this.numberFormat=b;this.dateTimeFormat=a};Sys.CultureInfo.prototype={_getDateTimeFormats:function(){if(!this._dateTimeFormats){var a=this.dateTimeFormat;this._dateTimeFormats=[a.MonthDayPattern,a.YearMonthPattern,a.ShortDatePattern,a.ShortTimePattern,a.LongDatePattern,a.LongTimePattern,a.FullDateTimePattern,a.RFC1123Pattern,a.SortableDateTimePattern,a.UniversalSortableDateTimePattern]}return this._dateTimeFormats},_getIndex:function(c,d,e){var b=this._toUpper(c),a=Array.indexOf(d,b);if(a===-1)a=Array.indexOf(e,b);return a},_getMonthIndex:function(a){if(!this._upperMonths){this._upperMonths=this._toUpperArray(this.dateTimeFormat.MonthNames);this._upperMonthsGenitive=this._toUpperArray(this.dateTimeFormat.MonthGenitiveNames)}return this._getIndex(a,this._upperMonths,this._upperMonthsGenitive)},_getAbbrMonthIndex:function(a){if(!this._upperAbbrMonths){this._upperAbbrMonths=this._toUpperArray(this.dateTimeFormat.AbbreviatedMonthNames);this._upperAbbrMonthsGenitive=this._toUpperArray(this.dateTimeFormat.AbbreviatedMonthGenitiveNames)}return this._getIndex(a,this._upperAbbrMonths,this._upperAbbrMonthsGenitive)},_getDayIndex:function(a){if(!this._upperDays)this._upperDays=this._toUpperArray(this.dateTimeFormat.DayNames);return Array.indexOf(this._upperDays,this._toUpper(a))},_getAbbrDayIndex:function(a){if(!this._upperAbbrDays)this._upperAbbrDays=this._toUpperArray(this.dateTimeFormat.AbbreviatedDayNames);return Array.indexOf(this._upperAbbrDays,this._toUpper(a))},_toUpperArray:function(c){var b=[];for(var a=0,d=c.length;a0)a.append(",");Sys.Serialization.JavaScriptSerializer._serializeWithBuilder(b[c],a,false,g)}a.append("]")}else{if(Date.isInstanceOfType(b)){a.append('"\\/Date(');a.append(b.getTime());a.append(')\\/"');break}var d=[],f=0;for(var e in b){if(e.startsWith("$"))continue;if(e===Sys.Serialization.JavaScriptSerializer._serverTypeFieldName&&f!==0){d[f++]=d[0];d[0]=e}else d[f++]=e}if(i)d.sort();a.append("{");var j=false;for(c=0;c=0;c--){var f=d[c];if(!g||f.autoRemove)$removeHandler(a,b,f.handler)}}a._events=null}};Sys.UI.DomEvent._disposeHandlers=function(){Sys.UI.DomEvent._clearHandlers(this,true);var b=this._chainDispose,a=typeof b;if(a!=="undefined"){this.dispose=b;this._chainDispose=null;if(a==="function")this.dispose()}};var $removeHandler=Sys.UI.DomEvent.removeHandler=function(b,a,c){Sys.UI.DomEvent._removeHandler(b,a,c)};Sys.UI.DomEvent._removeHandler=function(a,e,f){var d=null,c=a._events[e];for(var b=0,g=c.length;b=3){d+=parseInt(b.borderLeftWidth);e+=parseInt(b.borderTopWidth)}}b=Sys.UI.DomElement._getCurrentStyle(c);var h=b?b.position:null;if(!h||h!=="absolute")for(a=c.parentNode;a;a=a.parentNode){f=a.tagName?a.tagName.toUpperCase():null;if(f!=="BODY"&&f!=="HTML"&&(a.scrollLeft||a.scrollTop)){d-=a.scrollLeft||0;e-=a.scrollTop||0}b=Sys.UI.DomElement._getCurrentStyle(a);var i=b?b.position:null;if(i&&i==="absolute")break}return new Sys.UI.Point(d,e)};else Sys.UI.DomElement.getLocation=function(d){if(d.window&&d.window===d||d.nodeType===9)return new Sys.UI.Point(0,0);var e=0,f=0,a,i=null,g=null,b=null;for(a=d;a;i=a,(g=b,a=a.offsetParent)){var c=a.tagName?a.tagName.toUpperCase():null;b=Sys.UI.DomElement._getCurrentStyle(a);if((a.offsetLeft||a.offsetTop)&&!(c==="BODY"&&(!g||g.position!=="absolute"))){e+=a.offsetLeft;f+=a.offsetTop}if(i!==null&&b){if(c!=="TABLE"&&c!=="TD"&&c!=="HTML"){e+=parseInt(b.borderLeftWidth)||0;f+=parseInt(b.borderTopWidth)||0}if(c==="TABLE"&&(b.position==="relative"||b.position==="absolute")){e+=parseInt(b.marginLeft)||0;f+=parseInt(b.marginTop)||0}}}b=Sys.UI.DomElement._getCurrentStyle(d);var h=b?b.position:null;if(!h||h!=="absolute")for(a=d.parentNode;a;a=a.parentNode){c=a.tagName?a.tagName.toUpperCase():null;if(c!=="BODY"&&c!=="HTML"&&(a.scrollLeft||a.scrollTop)){e-=a.scrollLeft||0;f-=a.scrollTop||0;b=Sys.UI.DomElement._getCurrentStyle(a);if(b){e+=parseInt(b.borderLeftWidth)||0;f+=parseInt(b.borderTopWidth)||0}}}return new Sys.UI.Point(e,f)};Sys.UI.DomElement.isDomElement=function(a){return Sys._isDomElement(a)};Sys.UI.DomElement.removeCssClass=function(d,c){var a=" "+d.className+" ",b=a.indexOf(" "+c+" ");if(b>=0)d.className=(a.substr(0,b)+" "+a.substring(b+c.length+1,a.length)).trim()};Sys.UI.DomElement.resolveElement=function(b,c){var a=b;if(!a)return null;if(typeof a==="string")a=Sys.UI.DomElement.getElementById(a,c);return a};Sys.UI.DomElement.raiseBubbleEvent=function(c,d){var b=c;while(b){var a=b.control;if(a&&a.onBubbleEvent&&a.raiseBubbleEvent){Sys.UI.DomElement._raiseBubbleEventFromControl(a,c,d);return}b=b.parentNode}};Sys.UI.DomElement._raiseBubbleEventFromControl=function(a,b,c){if(!a.onBubbleEvent(b,c))a._raiseBubbleEvent(b,c)};Sys.UI.DomElement.setLocation=function(b,c,d){var a=b.style;a.position="absolute";a.left=c+"px";a.top=d+"px"};Sys.UI.DomElement.toggleCssClass=function(b,a){if(Sys.UI.DomElement.containsCssClass(b,a))Sys.UI.DomElement.removeCssClass(b,a);else Sys.UI.DomElement.addCssClass(b,a)};Sys.UI.DomElement.getVisibilityMode=function(a){return a._visibilityMode===Sys.UI.VisibilityMode.hide?Sys.UI.VisibilityMode.hide:Sys.UI.VisibilityMode.collapse};Sys.UI.DomElement.setVisibilityMode=function(a,b){Sys.UI.DomElement._ensureOldDisplayMode(a);if(a._visibilityMode!==b){a._visibilityMode=b;if(Sys.UI.DomElement.getVisible(a)===false)if(a._visibilityMode===Sys.UI.VisibilityMode.hide)a.style.display=a._oldDisplayMode;else a.style.display="none";a._visibilityMode=b}};Sys.UI.DomElement.getVisible=function(b){var a=b.currentStyle||Sys.UI.DomElement._getCurrentStyle(b);if(!a)return true;return a.visibility!=="hidden"&&a.display!=="none"};Sys.UI.DomElement.setVisible=function(a,b){if(b!==Sys.UI.DomElement.getVisible(a)){Sys.UI.DomElement._ensureOldDisplayMode(a);a.style.visibility=b?"visible":"hidden";if(b||a._visibilityMode===Sys.UI.VisibilityMode.hide)a.style.display=a._oldDisplayMode;else a.style.display="none"}};Sys.UI.DomElement._ensureOldDisplayMode=function(a){if(!a._oldDisplayMode){var b=a.currentStyle||Sys.UI.DomElement._getCurrentStyle(a);a._oldDisplayMode=b?b.display:null;if(!a._oldDisplayMode||a._oldDisplayMode==="none")switch(a.tagName.toUpperCase()){case "DIV":case "P":case "ADDRESS":case "BLOCKQUOTE":case "BODY":case "COL":case "COLGROUP":case "DD":case "DL":case "DT":case "FIELDSET":case "FORM":case "H1":case "H2":case "H3":case "H4":case "H5":case "H6":case "HR":case "IFRAME":case "LEGEND":case "OL":case "PRE":case "TABLE":case "TD":case "TH":case "TR":case "UL":a._oldDisplayMode="block";break;case "LI":a._oldDisplayMode="list-item";break;default:a._oldDisplayMode="inline"}}};Sys.UI.DomElement._getWindow=function(a){var b=a.ownerDocument||a.document||a;return b.defaultView||b.parentWindow};Sys.UI.DomElement._getCurrentStyle=function(a){if(a.nodeType===3)return null;var c=Sys.UI.DomElement._getWindow(a);if(a.documentElement)a=a.documentElement;var b=c&&a!==c&&c.getComputedStyle?c.getComputedStyle(a,null):a.currentStyle||a.style;if(!b&&Sys.Browser.agent===Sys.Browser.Safari&&a.style){var g=a.style.display,f=a.style.position;a.style.position="absolute";a.style.display="block";var e=c.getComputedStyle(a,null);a.style.display=g;a.style.position=f;b={};for(var d in e)b[d]=e[d];b.display="none"}return b};Sys.IContainer=function(){};Sys.IContainer.prototype={};Sys.IContainer.registerInterface("Sys.IContainer");Sys.ApplicationLoadEventArgs=function(b,a){Sys.ApplicationLoadEventArgs.initializeBase(this);this._components=b;this._isPartialLoad=a};Sys.ApplicationLoadEventArgs.prototype={get_components:function(){return this._components},get_isPartialLoad:function(){return this._isPartialLoad}};Sys.ApplicationLoadEventArgs.registerClass("Sys.ApplicationLoadEventArgs",Sys.EventArgs);Sys._Application=function(){Sys._Application.initializeBase(this);this._disposableObjects=[];this._components={};this._createdComponents=[];this._secondPassComponents=[];this._unloadHandlerDelegate=Function.createDelegate(this,this._unloadHandler);Sys.UI.DomEvent.addHandler(window,"unload",this._unloadHandlerDelegate);this._domReady()};Sys._Application.prototype={_creatingComponents:false,_disposing:false,_deleteCount:0,get_isCreatingComponents:function(){return this._creatingComponents},get_isDisposing:function(){return this._disposing},add_init:function(a){if(this._initialized)a(this,Sys.EventArgs.Empty);else this.get_events().addHandler("init",a)},remove_init:function(a){this.get_events().removeHandler("init",a)},add_load:function(a){this.get_events().addHandler("load",a)},remove_load:function(a){this.get_events().removeHandler("load",a)},add_unload:function(a){this.get_events().addHandler("unload",a)},remove_unload:function(a){this.get_events().removeHandler("unload",a)},addComponent:function(a){this._components[a.get_id()]=a},beginCreateComponents:function(){this._creatingComponents=true},dispose:function(){if(!this._disposing){this._disposing=true;if(this._timerCookie){window.clearTimeout(this._timerCookie);delete this._timerCookie}if(this._endRequestHandler){Sys.WebForms.PageRequestManager.getInstance().remove_endRequest(this._endRequestHandler);delete this._endRequestHandler}if(this._beginRequestHandler){Sys.WebForms.PageRequestManager.getInstance().remove_beginRequest(this._beginRequestHandler);delete this._beginRequestHandler}if(window.pageUnload)window.pageUnload(this,Sys.EventArgs.Empty);var c=this.get_events().getHandler("unload");if(c)c(this,Sys.EventArgs.Empty);var b=Array.clone(this._disposableObjects);for(var a=0,f=b.length;a=0;b--)this._disposeElementInternal(c[b]);if(!d)this._disposeElementInternal(a)}},endCreateComponents:function(){var b=this._secondPassComponents;for(var a=0,d=b.length;a1000){var c=[];for(var d=0,f=b.length;d=0;b--){var c=a[b];if(typeof c.dispose==="function")c.dispose()}},_disposeElementInternal:function(a){var d=a.dispose;if(d&&typeof d==="function")a.dispose();else{var c=a.control;if(c&&typeof c.dispose==="function")c.dispose()}var b=a._behaviors;if(b)this._disposeComponents(b);b=a._components;if(b){this._disposeComponents(b);a._components=null}},_domReady:function(){var a,g,f=this;function b(){f.initialize()}var c=function(){Sys.UI.DomEvent.removeHandler(window,"load",c);b()};Sys.UI.DomEvent.addHandler(window,"load",c);if(document.addEventListener)try{document.addEventListener("DOMContentLoaded",a=function(){document.removeEventListener("DOMContentLoaded",a,false);b()},false)}catch(h){}else if(document.attachEvent)if(window==window.top&&document.documentElement.doScroll){var e,d=document.createElement("div");a=function(){try{d.doScroll("left")}catch(c){e=window.setTimeout(a,0);return}d=null;b()};a()}else document.attachEvent("onreadystatechange",a=function(){if(document.readyState==="complete"){document.detachEvent("onreadystatechange",a);b()}})},_raiseInit:function(){var a=this.get_events().getHandler("init");if(a){this.beginCreateComponents();a(this,Sys.EventArgs.Empty);this.endCreateComponents()}},_unloadHandler:function(){this.dispose()}};Sys._Application.registerClass("Sys._Application",Sys.Component,Sys.IContainer);Sys.Application=new Sys._Application;var $find=Sys.Application.findComponent;Sys.UI.Behavior=function(b){Sys.UI.Behavior.initializeBase(this);this._element=b;var a=b._behaviors;if(!a)b._behaviors=[this];else a[a.length]=this};Sys.UI.Behavior.prototype={_name:null,get_element:function(){return this._element},get_id:function(){var a=Sys.UI.Behavior.callBaseMethod(this,"get_id");if(a)return a;if(!this._element||!this._element.id)return "";return this._element.id+"$"+this.get_name()},get_name:function(){if(this._name)return this._name;var a=Object.getTypeName(this),b=a.lastIndexOf(".");if(b!==-1)a=a.substr(b+1);if(!this.get_isInitialized())this._name=a;return a},set_name:function(a){this._name=a},initialize:function(){Sys.UI.Behavior.callBaseMethod(this,"initialize");var a=this.get_name();if(a)this._element[a]=this},dispose:function(){Sys.UI.Behavior.callBaseMethod(this,"dispose");var a=this._element;if(a){var c=this.get_name();if(c)a[c]=null;var b=a._behaviors;Array.remove(b,this);if(b.length===0)a._behaviors=null;delete this._element}}};Sys.UI.Behavior.registerClass("Sys.UI.Behavior",Sys.Component);Sys.UI.Behavior.getBehaviorByName=function(b,c){var a=b[c];return a&&Sys.UI.Behavior.isInstanceOfType(a)?a:null};Sys.UI.Behavior.getBehaviors=function(a){if(!a._behaviors)return [];return Array.clone(a._behaviors)};Sys.UI.Behavior.getBehaviorsByType=function(d,e){var a=d._behaviors,c=[];if(a)for(var b=0,f=a.length;b0&&a.charAt(0)==="#")a=a.substring(1);return a};Sys._Application.prototype.get_enableHistory=function(){return this._enableHistory};Sys._Application.prototype.set_enableHistory=function(a){this._enableHistory=a};Sys._Application.prototype.add_navigate=function(a){this.get_events().addHandler("navigate",a)};Sys._Application.prototype.remove_navigate=function(a){this.get_events().removeHandler("navigate",a)};Sys._Application.prototype.addHistoryPoint=function(c,f){this._ensureHistory();var b=this._state;for(var a in c){var d=c[a];if(d===null){if(typeof b[a]!=="undefined")delete b[a]}else b[a]=d}var e=this._serializeState(b);this._historyPointIsNew=true;this._setState(e,f);this._raiseNavigate()};Sys._Application.prototype.setServerId=function(a,b){this._clientId=a;this._uniqueId=b};Sys._Application.prototype.setServerState=function(a){this._ensureHistory();this._state.__s=a;this._updateHiddenField(a)};Sys._Application.prototype._deserializeState=function(a){var e={};a=a||"";var b=a.indexOf("&&");if(b!==-1&&b+2'");c.write(""+(b||document.title)+"parent.Sys.Application._onIFrameLoad('+Sys.Serialization.JavaScriptSerializer.serialize(a)+");");c.close()}this._ignoreTimer=false;this._currentEntry=a;if(this._historyFrame||this._historyPointIsNew){var f=this.get_stateString();if(a!==f){window.location.hash=a;this._currentEntry=this.get_stateString();if(typeof b!=="undefined"&&b!==null)document.title=b}}this._historyPointIsNew=false}}};Sys._Application.prototype._updateHiddenField=function(b){if(this._clientId){var a=document.getElementById(this._clientId);if(a)a.value=b}};if(!window.XMLHttpRequest)window.XMLHttpRequest=function(){var b=["Msxml2.XMLHTTP.3.0","Msxml2.XMLHTTP"];for(var a=0,c=b.length;a0)this._timer=window.setTimeout(Function.createDelegate(this,this._onTimeout),d);this._xmlHttpRequest.send(c);this._started=true},getResponseHeader:function(b){var a;try{a=this._xmlHttpRequest.getResponseHeader(b)}catch(c){}if(!a)a="";return a},getAllResponseHeaders:function(){return this._xmlHttpRequest.getAllResponseHeaders()},get_responseData:function(){return this._xmlHttpRequest.responseText},get_statusCode:function(){var a=0;try{a=this._xmlHttpRequest.status}catch(b){}return a},get_statusText:function(){return this._xmlHttpRequest.statusText},get_xml:function(){var a=this._xmlHttpRequest.responseXML;if(!a||!a.documentElement){a=Sys.Net.XMLDOM(this._xmlHttpRequest.responseText);if(!a||!a.documentElement)return null}else if(navigator.userAgent.indexOf("MSIE")!==-1)a.setProperty("SelectionLanguage","XPath");if(a.documentElement.namespaceURI==="http://www.mozilla.org/newlayout/xml/parsererror.xml"&&a.documentElement.tagName==="parsererror")return null;if(a.documentElement.firstChild&&a.documentElement.firstChild.tagName==="parsererror")return null;return a},abort:function(){if(this._aborted||this._responseAvailable||this._timedOut)return;this._aborted=true;this._clearTimer();if(this._xmlHttpRequest&&!this._responseAvailable){this._xmlHttpRequest.onreadystatechange=Function.emptyMethod;this._xmlHttpRequest.abort();this._xmlHttpRequest=null;this._webRequest.completed(Sys.EventArgs.Empty)}}};Sys.Net.XMLHttpExecutor.registerClass("Sys.Net.XMLHttpExecutor",Sys.Net.WebRequestExecutor);Sys.Net._WebRequestManager=function(){this._defaultTimeout=0;this._defaultExecutorType="Sys.Net.XMLHttpExecutor"};Sys.Net._WebRequestManager.prototype={add_invokingRequest:function(a){this._get_eventHandlerList().addHandler("invokingRequest",a)},remove_invokingRequest:function(a){this._get_eventHandlerList().removeHandler("invokingRequest",a)},add_completedRequest:function(a){this._get_eventHandlerList().addHandler("completedRequest",a)},remove_completedRequest:function(a){this._get_eventHandlerList().removeHandler("completedRequest",a)},_get_eventHandlerList:function(){if(!this._events)this._events=new Sys.EventHandlerList;return this._events},get_defaultTimeout:function(){return this._defaultTimeout},set_defaultTimeout:function(a){this._defaultTimeout=a},get_defaultExecutorType:function(){return this._defaultExecutorType},set_defaultExecutorType:function(a){this._defaultExecutorType=a},executeRequest:function(webRequest){var executor=webRequest.get_executor();if(!executor){var failed=false;try{var executorType=eval(this._defaultExecutorType);executor=new executorType}catch(a){failed=true}webRequest.set_executor(executor)}if(executor.get_aborted())return;var evArgs=new Sys.Net.NetworkRequestEventArgs(webRequest),handler=this._get_eventHandlerList().getHandler("invokingRequest");if(handler)handler(this,evArgs);if(!evArgs.get_cancel())executor.executeRequest()}};Sys.Net._WebRequestManager.registerClass("Sys.Net._WebRequestManager");Sys.Net.WebRequestManager=new Sys.Net._WebRequestManager;Sys.Net.NetworkRequestEventArgs=function(a){Sys.Net.NetworkRequestEventArgs.initializeBase(this);this._webRequest=a};Sys.Net.NetworkRequestEventArgs.prototype={get_webRequest:function(){return this._webRequest}};Sys.Net.NetworkRequestEventArgs.registerClass("Sys.Net.NetworkRequestEventArgs",Sys.CancelEventArgs);Sys.Net.WebRequest=function(){this._url="";this._headers={};this._body=null;this._userContext=null;this._httpVerb=null;this._executor=null;this._invokeCalled=false;this._timeout=0};Sys.Net.WebRequest.prototype={add_completed:function(a){this._get_eventHandlerList().addHandler("completed",a)},remove_completed:function(a){this._get_eventHandlerList().removeHandler("completed",a)},completed:function(b){var a=Sys.Net.WebRequestManager._get_eventHandlerList().getHandler("completedRequest");if(a)a(this._executor,b);a=this._get_eventHandlerList().getHandler("completed");if(a)a(this._executor,b)},_get_eventHandlerList:function(){if(!this._events)this._events=new Sys.EventHandlerList;return this._events},get_url:function(){return this._url},set_url:function(a){this._url=a},get_headers:function(){return this._headers},get_httpVerb:function(){if(this._httpVerb===null){if(this._body===null)return "GET";return "POST"}return this._httpVerb},set_httpVerb:function(a){this._httpVerb=a},get_body:function(){return this._body},set_body:function(a){this._body=a},get_userContext:function(){return this._userContext},set_userContext:function(a){this._userContext=a},get_executor:function(){return this._executor},set_executor:function(a){this._executor=a;this._executor._set_webRequest(this)},get_timeout:function(){if(this._timeout===0)return Sys.Net.WebRequestManager.get_defaultTimeout();return this._timeout},set_timeout:function(a){this._timeout=a},getResolvedUrl:function(){return Sys.Net.WebRequest._resolveUrl(this._url)},invoke:function(){Sys.Net.WebRequestManager.executeRequest(this);this._invokeCalled=true}};Sys.Net.WebRequest._resolveUrl=function(b,a){if(b&&b.indexOf("://")!==-1)return b;if(!a||a.length===0){var d=document.getElementsByTagName("base")[0];if(d&&d.href&&d.href.length>0)a=d.href;else a=document.URL}var c=a.indexOf("?");if(c!==-1)a=a.substr(0,c);c=a.indexOf("#");if(c!==-1)a=a.substr(0,c);a=a.substr(0,a.lastIndexOf("/")+1);if(!b||b.length===0)return a;if(b.charAt(0)==="/"){var e=a.indexOf("://"),g=a.indexOf("/",e+3);return a.substr(0,g)+b}else{var f=a.lastIndexOf("/");return a.substr(0,f+1)+b}};Sys.Net.WebRequest._createQueryString=function(c,b,f){b=b||encodeURIComponent;var h=0,e,g,d,a=new Sys.StringBuilder;if(c)for(d in c){e=c[d];if(typeof e==="function")continue;g=Sys.Serialization.JavaScriptSerializer.serialize(e);if(h++)a.append("&");a.append(d);a.append("=");a.append(b(g))}if(f){if(h)a.append("&");a.append(f)}return a.toString()};Sys.Net.WebRequest._createUrl=function(a,b,c){if(!b&&!c)return a;var d=Sys.Net.WebRequest._createQueryString(b,null,c);return d.length?a+(a&&a.indexOf("?")>=0?"&":"?")+d:a};Sys.Net.WebRequest.registerClass("Sys.Net.WebRequest");Sys._ScriptLoaderTask=function(b,a){this._scriptElement=b;this._completedCallback=a};Sys._ScriptLoaderTask.prototype={get_scriptElement:function(){return this._scriptElement},dispose:function(){if(this._disposed)return;this._disposed=true;this._removeScriptElementHandlers();Sys._ScriptLoaderTask._clearScript(this._scriptElement);this._scriptElement=null},execute:function(){this._addScriptElementHandlers();document.getElementsByTagName("head")[0].appendChild(this._scriptElement)},_addScriptElementHandlers:function(){this._scriptLoadDelegate=Function.createDelegate(this,this._scriptLoadHandler);if(Sys.Browser.agent!==Sys.Browser.InternetExplorer){this._scriptElement.readyState="loaded";$addHandler(this._scriptElement,"load",this._scriptLoadDelegate)}else $addHandler(this._scriptElement,"readystatechange",this._scriptLoadDelegate);if(this._scriptElement.addEventListener){this._scriptErrorDelegate=Function.createDelegate(this,this._scriptErrorHandler);this._scriptElement.addEventListener("error",this._scriptErrorDelegate,false)}},_removeScriptElementHandlers:function(){if(this._scriptLoadDelegate){var a=this.get_scriptElement();if(Sys.Browser.agent!==Sys.Browser.InternetExplorer)$removeHandler(a,"load",this._scriptLoadDelegate);else $removeHandler(a,"readystatechange",this._scriptLoadDelegate);if(this._scriptErrorDelegate){this._scriptElement.removeEventListener("error",this._scriptErrorDelegate,false);this._scriptErrorDelegate=null}this._scriptLoadDelegate=null}},_scriptErrorHandler:function(){if(this._disposed)return;this._completedCallback(this.get_scriptElement(),false)},_scriptLoadHandler:function(){if(this._disposed)return;var a=this.get_scriptElement();if(a.readyState!=="loaded"&&a.readyState!=="complete")return;this._completedCallback(a,true)}};Sys._ScriptLoaderTask.registerClass("Sys._ScriptLoaderTask",null,Sys.IDisposable);Sys._ScriptLoaderTask._clearScript=function(a){if(!Sys.Debug.isDebug)a.parentNode.removeChild(a)};Type.registerNamespace("Sys.Net");Sys.Net.WebServiceProxy=function(){};Sys.Net.WebServiceProxy.prototype={get_timeout:function(){return this._timeout||0},set_timeout:function(a){if(a<0)throw Error.argumentOutOfRange("value",a,Sys.Res.invalidTimeout);this._timeout=a},get_defaultUserContext:function(){return typeof this._userContext==="undefined"?null:this._userContext},set_defaultUserContext:function(a){this._userContext=a},get_defaultSucceededCallback:function(){return this._succeeded||null},set_defaultSucceededCallback:function(a){this._succeeded=a},get_defaultFailedCallback:function(){return this._failed||null},set_defaultFailedCallback:function(a){this._failed=a},get_enableJsonp:function(){return !!this._jsonp},set_enableJsonp:function(a){this._jsonp=a},get_path:function(){return this._path||null},set_path:function(a){this._path=a},get_jsonpCallbackParameter:function(){return this._callbackParameter||"callback"},set_jsonpCallbackParameter:function(a){this._callbackParameter=a},_invoke:function(d,e,g,f,c,b,a){c=c||this.get_defaultSucceededCallback();b=b||this.get_defaultFailedCallback();if(a===null||typeof a==="undefined")a=this.get_defaultUserContext();return Sys.Net.WebServiceProxy.invoke(d,e,g,f,c,b,a,this.get_timeout(),this.get_enableJsonp(),this.get_jsonpCallbackParameter())}};Sys.Net.WebServiceProxy.registerClass("Sys.Net.WebServiceProxy");Sys.Net.WebServiceProxy.invoke=function(q,a,m,l,j,b,g,e,w,p){var i=w!==false?Sys.Net.WebServiceProxy._xdomain.exec(q):null,c,n=i&&i.length===3&&(i[1]!==location.protocol||i[2]!==location.host);m=n||m;if(n){p=p||"callback";c="_jsonp"+Sys._jsonp++}if(!l)l={};var r=l;if(!m||!r)r={};var s,h,f=null,k,o=null,u=Sys.Net.WebRequest._createUrl(a?q+"/"+encodeURIComponent(a):q,r,n?p+"=Sys."+c:null);if(n){s=document.createElement("script");s.src=u;k=new Sys._ScriptLoaderTask(s,function(d,b){if(!b||c)t({Message:String.format(Sys.Res.webServiceFailedNoMsg,a)},-1)});function v(){if(f===null)return;f=null;h=new Sys.Net.WebServiceError(true,String.format(Sys.Res.webServiceTimedOut,a));k.dispose();delete Sys[c];if(b)b(h,g,a)}function t(d,e){if(f!==null){window.clearTimeout(f);f=null}k.dispose();delete Sys[c];c=null;if(typeof e!=="undefined"&&e!==200){if(b){h=new Sys.Net.WebServiceError(false,d.Message||String.format(Sys.Res.webServiceFailedNoMsg,a),d.StackTrace||null,d.ExceptionType||null,d);h._statusCode=e;b(h,g,a)}}else if(j)j(d,g,a)}Sys[c]=t;e=e||Sys.Net.WebRequestManager.get_defaultTimeout();if(e>0)f=window.setTimeout(v,e);k.execute();return null}var d=new Sys.Net.WebRequest;d.set_url(u);d.get_headers()["Content-Type"]="application/json; charset=utf-8";if(!m){o=Sys.Serialization.JavaScriptSerializer.serialize(l);if(o==="{}")o=""}d.set_body(o);d.add_completed(x);if(e&&e>0)d.set_timeout(e);d.invoke();function x(d){if(d.get_responseAvailable()){var f=d.get_statusCode(),c=null;try{var e=d.getResponseHeader("Content-Type");if(e.startsWith("application/json"))c=d.get_object();else if(e.startsWith("text/xml"))c=d.get_xml();else c=d.get_responseData()}catch(m){}var k=d.getResponseHeader("jsonerror"),h=k==="true";if(h){if(c)c=new Sys.Net.WebServiceError(false,c.Message,c.StackTrace,c.ExceptionType,c)}else if(e.startsWith("application/json"))c=!c||typeof c.d==="undefined"?c:c.d;if(f<200||f>=300||h){if(b){if(!c||!h)c=new Sys.Net.WebServiceError(false,String.format(Sys.Res.webServiceFailedNoMsg,a));c._statusCode=f;b(c,g,a)}}else if(j)j(c,g,a)}else{var i;if(d.get_timedOut())i=String.format(Sys.Res.webServiceTimedOut,a);else i=String.format(Sys.Res.webServiceFailedNoMsg,a);if(b)b(new Sys.Net.WebServiceError(d.get_timedOut(),i,"",""),g,a)}}return d};Sys.Net.WebServiceProxy._generateTypedConstructor=function(a){return function(b){if(b)for(var c in b)this[c]=b[c];this.__type=a}};Sys._jsonp=0;Sys.Net.WebServiceProxy._xdomain=/^\s*([a-zA-Z0-9\+\-\.]+\:)\/\/([^?#\/]+)/;Sys.Net.WebServiceError=function(d,e,c,a,b){this._timedOut=d;this._message=e;this._stackTrace=c;this._exceptionType=a;this._errorObject=b;this._statusCode=-1};Sys.Net.WebServiceError.prototype={get_timedOut:function(){return this._timedOut},get_statusCode:function(){return this._statusCode},get_message:function(){return this._message},get_stackTrace:function(){return this._stackTrace||""},get_exceptionType:function(){return this._exceptionType||""},get_errorObject:function(){return this._errorObject||null}};Sys.Net.WebServiceError.registerClass("Sys.Net.WebServiceError"); +Type.registerNamespace('Sys');Sys.Res={'argumentInteger':'Value must be an integer.','invokeCalledTwice':'Cannot call invoke more than once.','webServiceFailed':'The server method \'{0}\' failed with the following error: {1}','argumentType':'Object cannot be converted to the required type.','argumentNull':'Value cannot be null.','scriptAlreadyLoaded':'The script \'{0}\' has been referenced multiple times. If referencing Microsoft AJAX scripts explicitly, set the MicrosoftAjaxMode property of the ScriptManager to Explicit.','scriptDependencyNotFound':'The script \'{0}\' failed to load because it is dependent on script \'{1}\'.','formatBadFormatSpecifier':'Format specifier was invalid.','requiredScriptReferenceNotIncluded':'\'{0}\' requires that you have included a script reference to \'{1}\'.','webServiceFailedNoMsg':'The server method \'{0}\' failed.','argumentDomElement':'Value must be a DOM element.','invalidExecutorType':'Could not create a valid Sys.Net.WebRequestExecutor from: {0}.','cannotCallBeforeResponse':'Cannot call {0} when responseAvailable is false.','actualValue':'Actual value was {0}.','enumInvalidValue':'\'{0}\' is not a valid value for enum {1}.','scriptLoadFailed':'The script \'{0}\' could not be loaded.','parameterCount':'Parameter count mismatch.','cannotDeserializeEmptyString':'Cannot deserialize empty string.','formatInvalidString':'Input string was not in a correct format.','invalidTimeout':'Value must be greater than or equal to zero.','cannotAbortBeforeStart':'Cannot abort when executor has not started.','argument':'Value does not fall within the expected range.','cannotDeserializeInvalidJson':'Cannot deserialize. The data does not correspond to valid JSON.','invalidHttpVerb':'httpVerb cannot be set to an empty or null string.','nullWebRequest':'Cannot call executeRequest with a null webRequest.','eventHandlerInvalid':'Handler was not added through the Sys.UI.DomEvent.addHandler method.','cannotSerializeNonFiniteNumbers':'Cannot serialize non finite numbers.','argumentUndefined':'Value cannot be undefined.','webServiceInvalidReturnType':'The server method \'{0}\' returned an invalid type. Expected type: {1}','servicePathNotSet':'The path to the web service has not been set.','argumentTypeWithTypes':'Object of type \'{0}\' cannot be converted to type \'{1}\'.','cannotCallOnceStarted':'Cannot call {0} once started.','badBaseUrl1':'Base URL does not contain ://.','badBaseUrl2':'Base URL does not contain another /.','badBaseUrl3':'Cannot find last / in base URL.','setExecutorAfterActive':'Cannot set executor after it has become active.','paramName':'Parameter name: {0}','nullReferenceInPath':'Null reference while evaluating data path: \'{0}\'.','cannotCallOutsideHandler':'Cannot call {0} outside of a completed event handler.','cannotSerializeObjectWithCycle':'Cannot serialize object with cyclic reference within child properties.','format':'One of the identified items was in an invalid format.','assertFailedCaller':'Assertion Failed: {0}\r\nat {1}','argumentOutOfRange':'Specified argument was out of the range of valid values.','webServiceTimedOut':'The server method \'{0}\' timed out.','notImplemented':'The method or operation is not implemented.','assertFailed':'Assertion Failed: {0}','invalidOperation':'Operation is not valid due to the current state of the object.','breakIntoDebugger':'{0}\r\n\r\nBreak into debugger?'}; diff --git a/Azure/WebSite_WindowsAzure/Scripts/MicrosoftMvcAjax.debug.js b/Azure/WebSite_WindowsAzure/Scripts/MicrosoftMvcAjax.debug.js new file mode 100644 index 0000000..eb68ba7 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Scripts/MicrosoftMvcAjax.debug.js @@ -0,0 +1,408 @@ +//!---------------------------------------------------------- +//! Copyright (C) Microsoft Corporation. All rights reserved. +//!---------------------------------------------------------- +//! MicrosoftMvcAjax.js + +Type.registerNamespace('Sys.Mvc'); + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.AjaxOptions + +Sys.Mvc.$create_AjaxOptions = function Sys_Mvc_AjaxOptions() { return {}; } + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.InsertionMode + +Sys.Mvc.InsertionMode = function() { + /// + /// + /// + /// + /// + /// +}; +Sys.Mvc.InsertionMode.prototype = { + replace: 0, + insertBefore: 1, + insertAfter: 2 +} +Sys.Mvc.InsertionMode.registerEnum('Sys.Mvc.InsertionMode', false); + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.AjaxContext + +Sys.Mvc.AjaxContext = function Sys_Mvc_AjaxContext(request, updateTarget, loadingElement, insertionMode) { + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + this._request = request; + this._updateTarget = updateTarget; + this._loadingElement = loadingElement; + this._insertionMode = insertionMode; +} +Sys.Mvc.AjaxContext.prototype = { + _insertionMode: 0, + _loadingElement: null, + _response: null, + _request: null, + _updateTarget: null, + + get_data: function Sys_Mvc_AjaxContext$get_data() { + /// + if (this._response) { + return this._response.get_responseData(); + } + else { + return null; + } + }, + + get_insertionMode: function Sys_Mvc_AjaxContext$get_insertionMode() { + /// + return this._insertionMode; + }, + + get_loadingElement: function Sys_Mvc_AjaxContext$get_loadingElement() { + /// + return this._loadingElement; + }, + + get_object: function Sys_Mvc_AjaxContext$get_object() { + /// + var executor = this.get_response(); + return (executor) ? executor.get_object() : null; + }, + + get_response: function Sys_Mvc_AjaxContext$get_response() { + /// + return this._response; + }, + set_response: function Sys_Mvc_AjaxContext$set_response(value) { + /// + this._response = value; + return value; + }, + + get_request: function Sys_Mvc_AjaxContext$get_request() { + /// + return this._request; + }, + + get_updateTarget: function Sys_Mvc_AjaxContext$get_updateTarget() { + /// + return this._updateTarget; + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.AsyncHyperlink + +Sys.Mvc.AsyncHyperlink = function Sys_Mvc_AsyncHyperlink() { +} +Sys.Mvc.AsyncHyperlink.handleClick = function Sys_Mvc_AsyncHyperlink$handleClick(anchor, evt, ajaxOptions) { + /// + /// + /// + /// + /// + /// + evt.preventDefault(); + Sys.Mvc.MvcHelpers._asyncRequest(anchor.href, 'post', '', anchor, ajaxOptions); +} + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.MvcHelpers + +Sys.Mvc.MvcHelpers = function Sys_Mvc_MvcHelpers() { +} +Sys.Mvc.MvcHelpers._serializeSubmitButton = function Sys_Mvc_MvcHelpers$_serializeSubmitButton(element, offsetX, offsetY) { + /// + /// + /// + /// + /// + /// + /// + if (element.disabled) { + return null; + } + var name = element.name; + if (name) { + var tagName = element.tagName.toUpperCase(); + var encodedName = encodeURIComponent(name); + var inputElement = element; + if (tagName === 'INPUT') { + var type = inputElement.type; + if (type === 'submit') { + return encodedName + '=' + encodeURIComponent(inputElement.value); + } + else if (type === 'image') { + return encodedName + '.x=' + offsetX + '&' + encodedName + '.y=' + offsetY; + } + } + else if ((tagName === 'BUTTON') && (name.length) && (inputElement.type === 'submit')) { + return encodedName + '=' + encodeURIComponent(inputElement.value); + } + } + return null; +} +Sys.Mvc.MvcHelpers._serializeForm = function Sys_Mvc_MvcHelpers$_serializeForm(form) { + /// + /// + /// + var formElements = form.elements; + var formBody = new Sys.StringBuilder(); + var count = formElements.length; + for (var i = 0; i < count; i++) { + var element = formElements[i]; + var name = element.name; + if (!name || !name.length) { + continue; + } + var tagName = element.tagName.toUpperCase(); + if (tagName === 'INPUT') { + var inputElement = element; + var type = inputElement.type; + if ((type === 'text') || (type === 'password') || (type === 'hidden') || (((type === 'checkbox') || (type === 'radio')) && element.checked)) { + formBody.append(encodeURIComponent(name)); + formBody.append('='); + formBody.append(encodeURIComponent(inputElement.value)); + formBody.append('&'); + } + } + else if (tagName === 'SELECT') { + var selectElement = element; + var optionCount = selectElement.options.length; + for (var j = 0; j < optionCount; j++) { + var optionElement = selectElement.options[j]; + if (optionElement.selected) { + formBody.append(encodeURIComponent(name)); + formBody.append('='); + formBody.append(encodeURIComponent(optionElement.value)); + formBody.append('&'); + } + } + } + else if (tagName === 'TEXTAREA') { + formBody.append(encodeURIComponent(name)); + formBody.append('='); + formBody.append(encodeURIComponent((element.value))); + formBody.append('&'); + } + } + var additionalInput = form._additionalInput; + if (additionalInput) { + formBody.append(additionalInput); + formBody.append('&'); + } + return formBody.toString(); +} +Sys.Mvc.MvcHelpers._asyncRequest = function Sys_Mvc_MvcHelpers$_asyncRequest(url, verb, body, triggerElement, ajaxOptions) { + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + if (ajaxOptions.confirm) { + if (!confirm(ajaxOptions.confirm)) { + return; + } + } + if (ajaxOptions.url) { + url = ajaxOptions.url; + } + if (ajaxOptions.httpMethod) { + verb = ajaxOptions.httpMethod; + } + if (body.length > 0 && !body.endsWith('&')) { + body += '&'; + } + body += 'X-Requested-With=XMLHttpRequest'; + var upperCaseVerb = verb.toUpperCase(); + var isGetOrPost = (upperCaseVerb === 'GET' || upperCaseVerb === 'POST'); + if (!isGetOrPost) { + body += '&'; + body += 'X-HTTP-Method-Override=' + upperCaseVerb; + } + var requestBody = ''; + if (upperCaseVerb === 'GET' || upperCaseVerb === 'DELETE') { + if (url.indexOf('?') > -1) { + if (!url.endsWith('&')) { + url += '&'; + } + url += body; + } + else { + url += '?'; + url += body; + } + } + else { + requestBody = body; + } + var request = new Sys.Net.WebRequest(); + request.set_url(url); + if (isGetOrPost) { + request.set_httpVerb(verb); + } + else { + request.set_httpVerb('POST'); + request.get_headers()['X-HTTP-Method-Override'] = upperCaseVerb; + } + request.set_body(requestBody); + if (verb.toUpperCase() === 'PUT') { + request.get_headers()['Content-Type'] = 'application/x-www-form-urlencoded;'; + } + request.get_headers()['X-Requested-With'] = 'XMLHttpRequest'; + var updateElement = null; + if (ajaxOptions.updateTargetId) { + updateElement = $get(ajaxOptions.updateTargetId); + } + var loadingElement = null; + if (ajaxOptions.loadingElementId) { + loadingElement = $get(ajaxOptions.loadingElementId); + } + var ajaxContext = new Sys.Mvc.AjaxContext(request, updateElement, loadingElement, ajaxOptions.insertionMode); + var continueRequest = true; + if (ajaxOptions.onBegin) { + continueRequest = ajaxOptions.onBegin(ajaxContext) !== false; + } + if (loadingElement) { + Sys.UI.DomElement.setVisible(ajaxContext.get_loadingElement(), true); + } + if (continueRequest) { + request.add_completed(Function.createDelegate(null, function(executor) { + Sys.Mvc.MvcHelpers._onComplete(request, ajaxOptions, ajaxContext); + })); + request.invoke(); + } +} +Sys.Mvc.MvcHelpers._onComplete = function Sys_Mvc_MvcHelpers$_onComplete(request, ajaxOptions, ajaxContext) { + /// + /// + /// + /// + /// + /// + ajaxContext.set_response(request.get_executor()); + if (ajaxOptions.onComplete && ajaxOptions.onComplete(ajaxContext) === false) { + return; + } + var statusCode = ajaxContext.get_response().get_statusCode(); + if ((statusCode >= 200 && statusCode < 300) || statusCode === 304 || statusCode === 1223) { + if (statusCode !== 204 && statusCode !== 304 && statusCode !== 1223) { + var contentType = ajaxContext.get_response().getResponseHeader('Content-Type'); + if ((contentType) && (contentType.indexOf('application/x-javascript') !== -1)) { + eval(ajaxContext.get_data()); + } + else { + Sys.Mvc.MvcHelpers.updateDomElement(ajaxContext.get_updateTarget(), ajaxContext.get_insertionMode(), ajaxContext.get_data()); + } + } + if (ajaxOptions.onSuccess) { + ajaxOptions.onSuccess(ajaxContext); + } + } + else { + if (ajaxOptions.onFailure) { + ajaxOptions.onFailure(ajaxContext); + } + } + if (ajaxContext.get_loadingElement()) { + Sys.UI.DomElement.setVisible(ajaxContext.get_loadingElement(), false); + } +} +Sys.Mvc.MvcHelpers.updateDomElement = function Sys_Mvc_MvcHelpers$updateDomElement(target, insertionMode, content) { + /// + /// + /// + /// + /// + /// + if (target) { + switch (insertionMode) { + case Sys.Mvc.InsertionMode.replace: + target.innerHTML = content; + break; + case Sys.Mvc.InsertionMode.insertBefore: + if (content && content.length > 0) { + target.innerHTML = content + target.innerHTML.trimStart(); + } + break; + case Sys.Mvc.InsertionMode.insertAfter: + if (content && content.length > 0) { + target.innerHTML = target.innerHTML.trimEnd() + content; + } + break; + } + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.AsyncForm + +Sys.Mvc.AsyncForm = function Sys_Mvc_AsyncForm() { +} +Sys.Mvc.AsyncForm.handleClick = function Sys_Mvc_AsyncForm$handleClick(form, evt) { + /// + /// + /// + /// + var additionalInput = Sys.Mvc.MvcHelpers._serializeSubmitButton(evt.target, evt.offsetX, evt.offsetY); + form._additionalInput = additionalInput; +} +Sys.Mvc.AsyncForm.handleSubmit = function Sys_Mvc_AsyncForm$handleSubmit(form, evt, ajaxOptions) { + /// + /// + /// + /// + /// + /// + evt.preventDefault(); + var validationCallbacks = form.validationCallbacks; + if (validationCallbacks) { + for (var i = 0; i < validationCallbacks.length; i++) { + var callback = validationCallbacks[i]; + if (!callback()) { + return; + } + } + } + var body = Sys.Mvc.MvcHelpers._serializeForm(form); + Sys.Mvc.MvcHelpers._asyncRequest(form.action, form.method || 'post', body, form, ajaxOptions); +} + + +Sys.Mvc.AjaxContext.registerClass('Sys.Mvc.AjaxContext'); +Sys.Mvc.AsyncHyperlink.registerClass('Sys.Mvc.AsyncHyperlink'); +Sys.Mvc.MvcHelpers.registerClass('Sys.Mvc.MvcHelpers'); +Sys.Mvc.AsyncForm.registerClass('Sys.Mvc.AsyncForm'); + +// ---- Do not remove this footer ---- +// Generated using Script# v0.5.0.0 (http://projects.nikhilk.net) +// ----------------------------------- diff --git a/Azure/WebSite_WindowsAzure/Scripts/MicrosoftMvcAjax.js b/Azure/WebSite_WindowsAzure/Scripts/MicrosoftMvcAjax.js new file mode 100644 index 0000000..c5a6165 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Scripts/MicrosoftMvcAjax.js @@ -0,0 +1,25 @@ +//---------------------------------------------------------- +// Copyright (C) Microsoft Corporation. All rights reserved. +//---------------------------------------------------------- +// MicrosoftMvcAjax.js + +Type.registerNamespace('Sys.Mvc');Sys.Mvc.$create_AjaxOptions=function(){return {};} +Sys.Mvc.InsertionMode=function(){};Sys.Mvc.InsertionMode.prototype = {replace:0,insertBefore:1,insertAfter:2} +Sys.Mvc.InsertionMode.registerEnum('Sys.Mvc.InsertionMode',false);Sys.Mvc.AjaxContext=function(request,updateTarget,loadingElement,insertionMode){this.$3=request;this.$4=updateTarget;this.$1=loadingElement;this.$0=insertionMode;} +Sys.Mvc.AjaxContext.prototype={$0:0,$1:null,$2:null,$3:null,$4:null,get_data:function(){if(this.$2){return this.$2.get_responseData();}else{return null;}},get_insertionMode:function(){return this.$0;},get_loadingElement:function(){return this.$1;},get_object:function(){var $0=this.get_response();return ($0)?$0.get_object():null;},get_response:function(){return this.$2;},set_response:function(value){this.$2=value;return value;},get_request:function(){return this.$3;},get_updateTarget:function(){return this.$4;}} +Sys.Mvc.AsyncHyperlink=function(){} +Sys.Mvc.AsyncHyperlink.handleClick=function(anchor,evt,ajaxOptions){evt.preventDefault();Sys.Mvc.MvcHelpers.$2(anchor.href,'post','',anchor,ajaxOptions);} +Sys.Mvc.MvcHelpers=function(){} +Sys.Mvc.MvcHelpers.$0=function($p0,$p1,$p2){if($p0.disabled){return null;}var $0=$p0.name;if($0){var $1=$p0.tagName.toUpperCase();var $2=encodeURIComponent($0);var $3=$p0;if($1==='INPUT'){var $4=$3.type;if($4==='submit'){return $2+'='+encodeURIComponent($3.value);}else if($4==='image'){return $2+'.x='+$p1+'&'+$2+'.y='+$p2;}}else if(($1==='BUTTON')&&($0.length)&&($3.type==='submit')){return $2+'='+encodeURIComponent($3.value);}}return null;} +Sys.Mvc.MvcHelpers.$1=function($p0){var $0=$p0.elements;var $1=new Sys.StringBuilder();var $2=$0.length;for(var $4=0;$4<$2;$4++){var $5=$0[$4];var $6=$5.name;if(!$6||!$6.length){continue;}var $7=$5.tagName.toUpperCase();if($7==='INPUT'){var $8=$5;var $9=$8.type;if(($9==='text')||($9==='password')||($9==='hidden')||((($9==='checkbox')||($9==='radio'))&&$5.checked)){$1.append(encodeURIComponent($6));$1.append('=');$1.append(encodeURIComponent($8.value));$1.append('&');}}else if($7==='SELECT'){var $A=$5;var $B=$A.options.length;for(var $C=0;$C<$B;$C++){var $D=$A.options[$C];if($D.selected){$1.append(encodeURIComponent($6));$1.append('=');$1.append(encodeURIComponent($D.value));$1.append('&');}}}else if($7==='TEXTAREA'){$1.append(encodeURIComponent($6));$1.append('=');$1.append(encodeURIComponent(($5.value)));$1.append('&');}}var $3=$p0._additionalInput;if($3){$1.append($3);$1.append('&');}return $1.toString();} +Sys.Mvc.MvcHelpers.$2=function($p0,$p1,$p2,$p3,$p4){if($p4.confirm){if(!confirm($p4.confirm)){return;}}if($p4.url){$p0=$p4.url;}if($p4.httpMethod){$p1=$p4.httpMethod;}if($p2.length>0&&!$p2.endsWith('&')){$p2+='&';}$p2+='X-Requested-With=XMLHttpRequest';var $0=$p1.toUpperCase();var $1=($0==='GET'||$0==='POST');if(!$1){$p2+='&';$p2+='X-HTTP-Method-Override='+$0;}var $2='';if($0==='GET'||$0==='DELETE'){if($p0.indexOf('?')>-1){if(!$p0.endsWith('&')){$p0+='&';}$p0+=$p2;}else{$p0+='?';$p0+=$p2;}}else{$2=$p2;}var $3=new Sys.Net.WebRequest();$3.set_url($p0);if($1){$3.set_httpVerb($p1);}else{$3.set_httpVerb('POST');$3.get_headers()['X-HTTP-Method-Override']=$0;}$3.set_body($2);if($p1.toUpperCase()==='PUT'){$3.get_headers()['Content-Type']='application/x-www-form-urlencoded;';}$3.get_headers()['X-Requested-With']='XMLHttpRequest';var $4=null;if($p4.updateTargetId){$4=$get($p4.updateTargetId);}var $5=null;if($p4.loadingElementId){$5=$get($p4.loadingElementId);}var $6=new Sys.Mvc.AjaxContext($3,$4,$5,$p4.insertionMode);var $7=true;if($p4.onBegin){$7=$p4.onBegin($6)!==false;}if($5){Sys.UI.DomElement.setVisible($6.get_loadingElement(),true);}if($7){$3.add_completed(Function.createDelegate(null,function($p1_0){ +Sys.Mvc.MvcHelpers.$3($3,$p4,$6);}));$3.invoke();}} +Sys.Mvc.MvcHelpers.$3=function($p0,$p1,$p2){$p2.set_response($p0.get_executor());if($p1.onComplete&&$p1.onComplete($p2)===false){return;}var $0=$p2.get_response().get_statusCode();if(($0>=200&&$0<300)||$0===304||$0===1223){if($0!==204&&$0!==304&&$0!==1223){var $1=$p2.get_response().getResponseHeader('Content-Type');if(($1)&&($1.indexOf('application/x-javascript')!==-1)){eval($p2.get_data());}else{Sys.Mvc.MvcHelpers.updateDomElement($p2.get_updateTarget(),$p2.get_insertionMode(),$p2.get_data());}}if($p1.onSuccess){$p1.onSuccess($p2);}}else{if($p1.onFailure){$p1.onFailure($p2);}}if($p2.get_loadingElement()){Sys.UI.DomElement.setVisible($p2.get_loadingElement(),false);}} +Sys.Mvc.MvcHelpers.updateDomElement=function(target,insertionMode,content){if(target){switch(insertionMode){case 0:target.innerHTML=content;break;case 1:if(content&&content.length>0){target.innerHTML=content+target.innerHTML.trimStart();}break;case 2:if(content&&content.length>0){target.innerHTML=target.innerHTML.trimEnd()+content;}break;}}} +Sys.Mvc.AsyncForm=function(){} +Sys.Mvc.AsyncForm.handleClick=function(form,evt){var $0=Sys.Mvc.MvcHelpers.$0(evt.target,evt.offsetX,evt.offsetY);form._additionalInput = $0;} +Sys.Mvc.AsyncForm.handleSubmit=function(form,evt,ajaxOptions){evt.preventDefault();var $0=form.validationCallbacks;if($0){for(var $2=0;$2<$0.length;$2++){var $3=$0[$2];if(!$3()){return;}}}var $1=Sys.Mvc.MvcHelpers.$1(form);Sys.Mvc.MvcHelpers.$2(form.action,form.method||'post',$1,form,ajaxOptions);} +Sys.Mvc.AjaxContext.registerClass('Sys.Mvc.AjaxContext');Sys.Mvc.AsyncHyperlink.registerClass('Sys.Mvc.AsyncHyperlink');Sys.Mvc.MvcHelpers.registerClass('Sys.Mvc.MvcHelpers');Sys.Mvc.AsyncForm.registerClass('Sys.Mvc.AsyncForm'); +// ---- Do not remove this footer ---- +// Generated using Script# v0.5.0.0 (http://projects.nikhilk.net) +// ----------------------------------- diff --git a/Azure/WebSite_WindowsAzure/Scripts/MicrosoftMvcValidation.debug.js b/Azure/WebSite_WindowsAzure/Scripts/MicrosoftMvcValidation.debug.js new file mode 100644 index 0000000..346ba48 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Scripts/MicrosoftMvcValidation.debug.js @@ -0,0 +1,883 @@ +//!---------------------------------------------------------- +//! Copyright (C) Microsoft Corporation. All rights reserved. +//!---------------------------------------------------------- +//! MicrosoftMvcValidation.js + + +Type.registerNamespace('Sys.Mvc'); + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.Validation + +Sys.Mvc.$create_Validation = function Sys_Mvc_Validation() { return {}; } + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.JsonValidationField + +Sys.Mvc.$create_JsonValidationField = function Sys_Mvc_JsonValidationField() { return {}; } + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.JsonValidationOptions + +Sys.Mvc.$create_JsonValidationOptions = function Sys_Mvc_JsonValidationOptions() { return {}; } + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.JsonValidationRule + +Sys.Mvc.$create_JsonValidationRule = function Sys_Mvc_JsonValidationRule() { return {}; } + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.ValidationContext + +Sys.Mvc.$create_ValidationContext = function Sys_Mvc_ValidationContext() { return {}; } + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.NumberValidator + +Sys.Mvc.NumberValidator = function Sys_Mvc_NumberValidator() { +} +Sys.Mvc.NumberValidator.create = function Sys_Mvc_NumberValidator$create(rule) { + /// + /// + /// + return Function.createDelegate(new Sys.Mvc.NumberValidator(), new Sys.Mvc.NumberValidator().validate); +} +Sys.Mvc.NumberValidator.prototype = { + + validate: function Sys_Mvc_NumberValidator$validate(value, context) { + /// + /// + /// + /// + /// + if (Sys.Mvc._validationUtil.stringIsNullOrEmpty(value)) { + return true; + } + var n = Number.parseLocale(value); + return (!isNaN(n)); + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.FormContext + +Sys.Mvc.FormContext = function Sys_Mvc_FormContext(formElement, validationSummaryElement) { + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + this._errors = []; + this.fields = new Array(0); + this._formElement = formElement; + this._validationSummaryElement = validationSummaryElement; + formElement[Sys.Mvc.FormContext._formValidationTag] = this; + if (validationSummaryElement) { + var ulElements = validationSummaryElement.getElementsByTagName('ul'); + if (ulElements.length > 0) { + this._validationSummaryULElement = ulElements[0]; + } + } + this._onClickHandler = Function.createDelegate(this, this._form_OnClick); + this._onSubmitHandler = Function.createDelegate(this, this._form_OnSubmit); +} +Sys.Mvc.FormContext._Application_Load = function Sys_Mvc_FormContext$_Application_Load() { + var allFormOptions = window.mvcClientValidationMetadata; + if (allFormOptions) { + while (allFormOptions.length > 0) { + var thisFormOptions = allFormOptions.pop(); + Sys.Mvc.FormContext._parseJsonOptions(thisFormOptions); + } + } +} +Sys.Mvc.FormContext._getFormElementsWithName = function Sys_Mvc_FormContext$_getFormElementsWithName(formElement, name) { + /// + /// + /// + /// + /// + var allElementsWithNameInForm = []; + var allElementsWithName = document.getElementsByName(name); + for (var i = 0; i < allElementsWithName.length; i++) { + var thisElement = allElementsWithName[i]; + if (Sys.Mvc.FormContext._isElementInHierarchy(formElement, thisElement)) { + Array.add(allElementsWithNameInForm, thisElement); + } + } + return allElementsWithNameInForm; +} +Sys.Mvc.FormContext.getValidationForForm = function Sys_Mvc_FormContext$getValidationForForm(formElement) { + /// + /// + /// + return formElement[Sys.Mvc.FormContext._formValidationTag]; +} +Sys.Mvc.FormContext._isElementInHierarchy = function Sys_Mvc_FormContext$_isElementInHierarchy(parent, child) { + /// + /// + /// + /// + /// + while (child) { + if (parent === child) { + return true; + } + child = child.parentNode; + } + return false; +} +Sys.Mvc.FormContext._parseJsonOptions = function Sys_Mvc_FormContext$_parseJsonOptions(options) { + /// + /// + /// + var formElement = $get(options.FormId); + var validationSummaryElement = (!Sys.Mvc._validationUtil.stringIsNullOrEmpty(options.ValidationSummaryId)) ? $get(options.ValidationSummaryId) : null; + var formContext = new Sys.Mvc.FormContext(formElement, validationSummaryElement); + formContext.enableDynamicValidation(); + formContext.replaceValidationSummary = options.ReplaceValidationSummary; + for (var i = 0; i < options.Fields.length; i++) { + var field = options.Fields[i]; + var fieldElements = Sys.Mvc.FormContext._getFormElementsWithName(formElement, field.FieldName); + var validationMessageElement = (!Sys.Mvc._validationUtil.stringIsNullOrEmpty(field.ValidationMessageId)) ? $get(field.ValidationMessageId) : null; + var fieldContext = new Sys.Mvc.FieldContext(formContext); + Array.addRange(fieldContext.elements, fieldElements); + fieldContext.validationMessageElement = validationMessageElement; + fieldContext.replaceValidationMessageContents = field.ReplaceValidationMessageContents; + for (var j = 0; j < field.ValidationRules.length; j++) { + var rule = field.ValidationRules[j]; + var validator = Sys.Mvc.ValidatorRegistry.getValidator(rule); + if (validator) { + var validation = Sys.Mvc.$create_Validation(); + validation.fieldErrorMessage = rule.ErrorMessage; + validation.validator = validator; + Array.add(fieldContext.validations, validation); + } + } + fieldContext.enableDynamicValidation(); + Array.add(formContext.fields, fieldContext); + } + var registeredValidatorCallbacks = formElement.validationCallbacks; + if (!registeredValidatorCallbacks) { + registeredValidatorCallbacks = []; + formElement.validationCallbacks = registeredValidatorCallbacks; + } + registeredValidatorCallbacks.push(Function.createDelegate(null, function() { + return Sys.Mvc._validationUtil.arrayIsNullOrEmpty(formContext.validate('submit')); + })); + return formContext; +} +Sys.Mvc.FormContext.prototype = { + _onClickHandler: null, + _onSubmitHandler: null, + _submitButtonClicked: null, + _validationSummaryElement: null, + _validationSummaryULElement: null, + _formElement: null, + replaceValidationSummary: false, + + addError: function Sys_Mvc_FormContext$addError(message) { + /// + /// + this.addErrors([ message ]); + }, + + addErrors: function Sys_Mvc_FormContext$addErrors(messages) { + /// + /// + if (!Sys.Mvc._validationUtil.arrayIsNullOrEmpty(messages)) { + Array.addRange(this._errors, messages); + this._onErrorCountChanged(); + } + }, + + clearErrors: function Sys_Mvc_FormContext$clearErrors() { + Array.clear(this._errors); + this._onErrorCountChanged(); + }, + + _displayError: function Sys_Mvc_FormContext$_displayError() { + if (this._validationSummaryElement) { + if (this._validationSummaryULElement) { + Sys.Mvc._validationUtil.removeAllChildren(this._validationSummaryULElement); + for (var i = 0; i < this._errors.length; i++) { + var liElement = document.createElement('li'); + Sys.Mvc._validationUtil.setInnerText(liElement, this._errors[i]); + this._validationSummaryULElement.appendChild(liElement); + } + } + Sys.UI.DomElement.removeCssClass(this._validationSummaryElement, Sys.Mvc.FormContext._validationSummaryValidCss); + Sys.UI.DomElement.addCssClass(this._validationSummaryElement, Sys.Mvc.FormContext._validationSummaryErrorCss); + } + }, + + _displaySuccess: function Sys_Mvc_FormContext$_displaySuccess() { + var validationSummaryElement = this._validationSummaryElement; + if (validationSummaryElement) { + var validationSummaryULElement = this._validationSummaryULElement; + if (validationSummaryULElement) { + validationSummaryULElement.innerHTML = ''; + } + Sys.UI.DomElement.removeCssClass(validationSummaryElement, Sys.Mvc.FormContext._validationSummaryErrorCss); + Sys.UI.DomElement.addCssClass(validationSummaryElement, Sys.Mvc.FormContext._validationSummaryValidCss); + } + }, + + enableDynamicValidation: function Sys_Mvc_FormContext$enableDynamicValidation() { + Sys.UI.DomEvent.addHandler(this._formElement, 'click', this._onClickHandler); + Sys.UI.DomEvent.addHandler(this._formElement, 'submit', this._onSubmitHandler); + }, + + _findSubmitButton: function Sys_Mvc_FormContext$_findSubmitButton(element) { + /// + /// + /// + if (element.disabled) { + return null; + } + var tagName = element.tagName.toUpperCase(); + var inputElement = element; + if (tagName === 'INPUT') { + var type = inputElement.type; + if (type === 'submit' || type === 'image') { + return inputElement; + } + } + else if ((tagName === 'BUTTON') && (inputElement.type === 'submit')) { + return inputElement; + } + return null; + }, + + _form_OnClick: function Sys_Mvc_FormContext$_form_OnClick(e) { + /// + /// + this._submitButtonClicked = this._findSubmitButton(e.target); + }, + + _form_OnSubmit: function Sys_Mvc_FormContext$_form_OnSubmit(e) { + /// + /// + var form = e.target; + var submitButton = this._submitButtonClicked; + if (submitButton && submitButton.disableValidation) { + return; + } + var errorMessages = this.validate('submit'); + if (!Sys.Mvc._validationUtil.arrayIsNullOrEmpty(errorMessages)) { + e.preventDefault(); + } + }, + + _onErrorCountChanged: function Sys_Mvc_FormContext$_onErrorCountChanged() { + if (!this._errors.length) { + this._displaySuccess(); + } + else { + this._displayError(); + } + }, + + validate: function Sys_Mvc_FormContext$validate(eventName) { + /// + /// + /// + var fields = this.fields; + var errors = []; + for (var i = 0; i < fields.length; i++) { + var field = fields[i]; + if (!field.elements[0].disabled) { + var thisErrors = field.validate(eventName); + if (thisErrors) { + Array.addRange(errors, thisErrors); + } + } + } + if (this.replaceValidationSummary) { + this.clearErrors(); + this.addErrors(errors); + } + return errors; + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.FieldContext + +Sys.Mvc.FieldContext = function Sys_Mvc_FieldContext(formContext) { + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + this._errors = []; + this.elements = new Array(0); + this.validations = new Array(0); + this.formContext = formContext; + this._onBlurHandler = Function.createDelegate(this, this._element_OnBlur); + this._onChangeHandler = Function.createDelegate(this, this._element_OnChange); + this._onInputHandler = Function.createDelegate(this, this._element_OnInput); + this._onPropertyChangeHandler = Function.createDelegate(this, this._element_OnPropertyChange); +} +Sys.Mvc.FieldContext.prototype = { + _onBlurHandler: null, + _onChangeHandler: null, + _onInputHandler: null, + _onPropertyChangeHandler: null, + defaultErrorMessage: null, + formContext: null, + replaceValidationMessageContents: false, + validationMessageElement: null, + + addError: function Sys_Mvc_FieldContext$addError(message) { + /// + /// + this.addErrors([ message ]); + }, + + addErrors: function Sys_Mvc_FieldContext$addErrors(messages) { + /// + /// + if (!Sys.Mvc._validationUtil.arrayIsNullOrEmpty(messages)) { + Array.addRange(this._errors, messages); + this._onErrorCountChanged(); + } + }, + + clearErrors: function Sys_Mvc_FieldContext$clearErrors() { + Array.clear(this._errors); + this._onErrorCountChanged(); + }, + + _displayError: function Sys_Mvc_FieldContext$_displayError() { + var validationMessageElement = this.validationMessageElement; + if (validationMessageElement) { + if (this.replaceValidationMessageContents) { + Sys.Mvc._validationUtil.setInnerText(validationMessageElement, this._errors[0]); + } + Sys.UI.DomElement.removeCssClass(validationMessageElement, Sys.Mvc.FieldContext._validationMessageValidCss); + Sys.UI.DomElement.addCssClass(validationMessageElement, Sys.Mvc.FieldContext._validationMessageErrorCss); + } + var elements = this.elements; + for (var i = 0; i < elements.length; i++) { + var element = elements[i]; + Sys.UI.DomElement.removeCssClass(element, Sys.Mvc.FieldContext._inputElementValidCss); + Sys.UI.DomElement.addCssClass(element, Sys.Mvc.FieldContext._inputElementErrorCss); + } + }, + + _displaySuccess: function Sys_Mvc_FieldContext$_displaySuccess() { + var validationMessageElement = this.validationMessageElement; + if (validationMessageElement) { + if (this.replaceValidationMessageContents) { + Sys.Mvc._validationUtil.setInnerText(validationMessageElement, ''); + } + Sys.UI.DomElement.removeCssClass(validationMessageElement, Sys.Mvc.FieldContext._validationMessageErrorCss); + Sys.UI.DomElement.addCssClass(validationMessageElement, Sys.Mvc.FieldContext._validationMessageValidCss); + } + var elements = this.elements; + for (var i = 0; i < elements.length; i++) { + var element = elements[i]; + Sys.UI.DomElement.removeCssClass(element, Sys.Mvc.FieldContext._inputElementErrorCss); + Sys.UI.DomElement.addCssClass(element, Sys.Mvc.FieldContext._inputElementValidCss); + } + }, + + _element_OnBlur: function Sys_Mvc_FieldContext$_element_OnBlur(e) { + /// + /// + if (e.target[Sys.Mvc.FieldContext._hasTextChangedTag] || e.target[Sys.Mvc.FieldContext._hasValidationFiredTag]) { + this.validate('blur'); + } + }, + + _element_OnChange: function Sys_Mvc_FieldContext$_element_OnChange(e) { + /// + /// + e.target[Sys.Mvc.FieldContext._hasTextChangedTag] = true; + }, + + _element_OnInput: function Sys_Mvc_FieldContext$_element_OnInput(e) { + /// + /// + e.target[Sys.Mvc.FieldContext._hasTextChangedTag] = true; + if (e.target[Sys.Mvc.FieldContext._hasValidationFiredTag]) { + this.validate('input'); + } + }, + + _element_OnPropertyChange: function Sys_Mvc_FieldContext$_element_OnPropertyChange(e) { + /// + /// + if (e.rawEvent.propertyName === 'value') { + e.target[Sys.Mvc.FieldContext._hasTextChangedTag] = true; + if (e.target[Sys.Mvc.FieldContext._hasValidationFiredTag]) { + this.validate('input'); + } + } + }, + + enableDynamicValidation: function Sys_Mvc_FieldContext$enableDynamicValidation() { + var elements = this.elements; + for (var i = 0; i < elements.length; i++) { + var element = elements[i]; + if (Sys.Mvc._validationUtil.elementSupportsEvent(element, 'onpropertychange')) { + var compatMode = document.documentMode; + if (compatMode && compatMode >= 8) { + Sys.UI.DomEvent.addHandler(element, 'propertychange', this._onPropertyChangeHandler); + } + } + else { + Sys.UI.DomEvent.addHandler(element, 'input', this._onInputHandler); + } + Sys.UI.DomEvent.addHandler(element, 'change', this._onChangeHandler); + Sys.UI.DomEvent.addHandler(element, 'blur', this._onBlurHandler); + } + }, + + _getErrorString: function Sys_Mvc_FieldContext$_getErrorString(validatorReturnValue, fieldErrorMessage) { + /// + /// + /// + /// + /// + var fallbackErrorMessage = fieldErrorMessage || this.defaultErrorMessage; + if (Boolean.isInstanceOfType(validatorReturnValue)) { + return (validatorReturnValue) ? null : fallbackErrorMessage; + } + if (String.isInstanceOfType(validatorReturnValue)) { + return ((validatorReturnValue).length) ? validatorReturnValue : fallbackErrorMessage; + } + return null; + }, + + _getStringValue: function Sys_Mvc_FieldContext$_getStringValue() { + /// + var elements = this.elements; + return (elements.length > 0) ? elements[0].value : null; + }, + + _markValidationFired: function Sys_Mvc_FieldContext$_markValidationFired() { + var elements = this.elements; + for (var i = 0; i < elements.length; i++) { + var element = elements[i]; + element[Sys.Mvc.FieldContext._hasValidationFiredTag] = true; + } + }, + + _onErrorCountChanged: function Sys_Mvc_FieldContext$_onErrorCountChanged() { + if (!this._errors.length) { + this._displaySuccess(); + } + else { + this._displayError(); + } + }, + + validate: function Sys_Mvc_FieldContext$validate(eventName) { + /// + /// + /// + var validations = this.validations; + var errors = []; + var value = this._getStringValue(); + for (var i = 0; i < validations.length; i++) { + var validation = validations[i]; + var context = Sys.Mvc.$create_ValidationContext(); + context.eventName = eventName; + context.fieldContext = this; + context.validation = validation; + var retVal = validation.validator(value, context); + var errorMessage = this._getErrorString(retVal, validation.fieldErrorMessage); + if (!Sys.Mvc._validationUtil.stringIsNullOrEmpty(errorMessage)) { + Array.add(errors, errorMessage); + } + } + this._markValidationFired(); + this.clearErrors(); + this.addErrors(errors); + return errors; + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.RangeValidator + +Sys.Mvc.RangeValidator = function Sys_Mvc_RangeValidator(minimum, maximum) { + /// + /// + /// + /// + /// + /// + /// + /// + this._minimum = minimum; + this._maximum = maximum; +} +Sys.Mvc.RangeValidator.create = function Sys_Mvc_RangeValidator$create(rule) { + /// + /// + /// + var min = rule.ValidationParameters['min']; + var max = rule.ValidationParameters['max']; + return Function.createDelegate(new Sys.Mvc.RangeValidator(min, max), new Sys.Mvc.RangeValidator(min, max).validate); +} +Sys.Mvc.RangeValidator.prototype = { + _minimum: null, + _maximum: null, + + validate: function Sys_Mvc_RangeValidator$validate(value, context) { + /// + /// + /// + /// + /// + if (Sys.Mvc._validationUtil.stringIsNullOrEmpty(value)) { + return true; + } + var n = Number.parseLocale(value); + return (!isNaN(n) && this._minimum <= n && n <= this._maximum); + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.RegularExpressionValidator + +Sys.Mvc.RegularExpressionValidator = function Sys_Mvc_RegularExpressionValidator(pattern) { + /// + /// + /// + /// + this._pattern = pattern; +} +Sys.Mvc.RegularExpressionValidator.create = function Sys_Mvc_RegularExpressionValidator$create(rule) { + /// + /// + /// + var pattern = rule.ValidationParameters['pattern']; + return Function.createDelegate(new Sys.Mvc.RegularExpressionValidator(pattern), new Sys.Mvc.RegularExpressionValidator(pattern).validate); +} +Sys.Mvc.RegularExpressionValidator.prototype = { + _pattern: null, + + validate: function Sys_Mvc_RegularExpressionValidator$validate(value, context) { + /// + /// + /// + /// + /// + if (Sys.Mvc._validationUtil.stringIsNullOrEmpty(value)) { + return true; + } + var regExp = new RegExp(this._pattern); + var matches = regExp.exec(value); + return (!Sys.Mvc._validationUtil.arrayIsNullOrEmpty(matches) && matches[0].length === value.length); + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.RequiredValidator + +Sys.Mvc.RequiredValidator = function Sys_Mvc_RequiredValidator() { +} +Sys.Mvc.RequiredValidator.create = function Sys_Mvc_RequiredValidator$create(rule) { + /// + /// + /// + return Function.createDelegate(new Sys.Mvc.RequiredValidator(), new Sys.Mvc.RequiredValidator().validate); +} +Sys.Mvc.RequiredValidator._isRadioInputElement = function Sys_Mvc_RequiredValidator$_isRadioInputElement(element) { + /// + /// + /// + if (element.tagName.toUpperCase() === 'INPUT') { + var inputType = (element.type).toUpperCase(); + if (inputType === 'RADIO') { + return true; + } + } + return false; +} +Sys.Mvc.RequiredValidator._isSelectInputElement = function Sys_Mvc_RequiredValidator$_isSelectInputElement(element) { + /// + /// + /// + if (element.tagName.toUpperCase() === 'SELECT') { + return true; + } + return false; +} +Sys.Mvc.RequiredValidator._isTextualInputElement = function Sys_Mvc_RequiredValidator$_isTextualInputElement(element) { + /// + /// + /// + if (element.tagName.toUpperCase() === 'INPUT') { + var inputType = (element.type).toUpperCase(); + switch (inputType) { + case 'TEXT': + case 'PASSWORD': + case 'FILE': + return true; + } + } + if (element.tagName.toUpperCase() === 'TEXTAREA') { + return true; + } + return false; +} +Sys.Mvc.RequiredValidator._validateRadioInput = function Sys_Mvc_RequiredValidator$_validateRadioInput(elements) { + /// + /// + /// + for (var i = 0; i < elements.length; i++) { + var element = elements[i]; + if (element.checked) { + return true; + } + } + return false; +} +Sys.Mvc.RequiredValidator._validateSelectInput = function Sys_Mvc_RequiredValidator$_validateSelectInput(optionElements) { + /// + /// + /// + for (var i = 0; i < optionElements.length; i++) { + var element = optionElements[i]; + if (element.selected) { + if (!Sys.Mvc._validationUtil.stringIsNullOrEmpty(element.value)) { + return true; + } + } + } + return false; +} +Sys.Mvc.RequiredValidator._validateTextualInput = function Sys_Mvc_RequiredValidator$_validateTextualInput(element) { + /// + /// + /// + return (!Sys.Mvc._validationUtil.stringIsNullOrEmpty(element.value)); +} +Sys.Mvc.RequiredValidator.prototype = { + + validate: function Sys_Mvc_RequiredValidator$validate(value, context) { + /// + /// + /// + /// + /// + var elements = context.fieldContext.elements; + if (!elements.length) { + return true; + } + var sampleElement = elements[0]; + if (Sys.Mvc.RequiredValidator._isTextualInputElement(sampleElement)) { + return Sys.Mvc.RequiredValidator._validateTextualInput(sampleElement); + } + if (Sys.Mvc.RequiredValidator._isRadioInputElement(sampleElement)) { + return Sys.Mvc.RequiredValidator._validateRadioInput(elements); + } + if (Sys.Mvc.RequiredValidator._isSelectInputElement(sampleElement)) { + return Sys.Mvc.RequiredValidator._validateSelectInput((sampleElement).options); + } + return true; + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.StringLengthValidator + +Sys.Mvc.StringLengthValidator = function Sys_Mvc_StringLengthValidator(minLength, maxLength) { + /// + /// + /// + /// + /// + /// + /// + /// + this._minLength = minLength; + this._maxLength = maxLength; +} +Sys.Mvc.StringLengthValidator.create = function Sys_Mvc_StringLengthValidator$create(rule) { + /// + /// + /// + var minLength = (rule.ValidationParameters['min'] || 0); + var maxLength = (rule.ValidationParameters['max'] || Number.MAX_VALUE); + return Function.createDelegate(new Sys.Mvc.StringLengthValidator(minLength, maxLength), new Sys.Mvc.StringLengthValidator(minLength, maxLength).validate); +} +Sys.Mvc.StringLengthValidator.prototype = { + _maxLength: 0, + _minLength: 0, + + validate: function Sys_Mvc_StringLengthValidator$validate(value, context) { + /// + /// + /// + /// + /// + if (Sys.Mvc._validationUtil.stringIsNullOrEmpty(value)) { + return true; + } + return (this._minLength <= value.length && value.length <= this._maxLength); + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc._validationUtil + +Sys.Mvc._validationUtil = function Sys_Mvc__validationUtil() { +} +Sys.Mvc._validationUtil.arrayIsNullOrEmpty = function Sys_Mvc__validationUtil$arrayIsNullOrEmpty(array) { + /// + /// + /// + return (!array || !array.length); +} +Sys.Mvc._validationUtil.stringIsNullOrEmpty = function Sys_Mvc__validationUtil$stringIsNullOrEmpty(value) { + /// + /// + /// + return (!value || !value.length); +} +Sys.Mvc._validationUtil.elementSupportsEvent = function Sys_Mvc__validationUtil$elementSupportsEvent(element, eventAttributeName) { + /// + /// + /// + /// + /// + return (eventAttributeName in element); +} +Sys.Mvc._validationUtil.removeAllChildren = function Sys_Mvc__validationUtil$removeAllChildren(element) { + /// + /// + while (element.firstChild) { + element.removeChild(element.firstChild); + } +} +Sys.Mvc._validationUtil.setInnerText = function Sys_Mvc__validationUtil$setInnerText(element, innerText) { + /// + /// + /// + /// + var textNode = document.createTextNode(innerText); + Sys.Mvc._validationUtil.removeAllChildren(element); + element.appendChild(textNode); +} + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.ValidatorRegistry + +Sys.Mvc.ValidatorRegistry = function Sys_Mvc_ValidatorRegistry() { + /// + /// +} +Sys.Mvc.ValidatorRegistry.getValidator = function Sys_Mvc_ValidatorRegistry$getValidator(rule) { + /// + /// + /// + var creator = Sys.Mvc.ValidatorRegistry.validators[rule.ValidationType]; + return (creator) ? creator(rule) : null; +} +Sys.Mvc.ValidatorRegistry._getDefaultValidators = function Sys_Mvc_ValidatorRegistry$_getDefaultValidators() { + /// + return { required: Function.createDelegate(null, Sys.Mvc.RequiredValidator.create), length: Function.createDelegate(null, Sys.Mvc.StringLengthValidator.create), regex: Function.createDelegate(null, Sys.Mvc.RegularExpressionValidator.create), range: Function.createDelegate(null, Sys.Mvc.RangeValidator.create), number: Function.createDelegate(null, Sys.Mvc.NumberValidator.create) }; +} + + +Sys.Mvc.NumberValidator.registerClass('Sys.Mvc.NumberValidator'); +Sys.Mvc.FormContext.registerClass('Sys.Mvc.FormContext'); +Sys.Mvc.FieldContext.registerClass('Sys.Mvc.FieldContext'); +Sys.Mvc.RangeValidator.registerClass('Sys.Mvc.RangeValidator'); +Sys.Mvc.RegularExpressionValidator.registerClass('Sys.Mvc.RegularExpressionValidator'); +Sys.Mvc.RequiredValidator.registerClass('Sys.Mvc.RequiredValidator'); +Sys.Mvc.StringLengthValidator.registerClass('Sys.Mvc.StringLengthValidator'); +Sys.Mvc._validationUtil.registerClass('Sys.Mvc._validationUtil'); +Sys.Mvc.ValidatorRegistry.registerClass('Sys.Mvc.ValidatorRegistry'); +Sys.Mvc.FormContext._validationSummaryErrorCss = 'validation-summary-errors'; +Sys.Mvc.FormContext._validationSummaryValidCss = 'validation-summary-valid'; +Sys.Mvc.FormContext._formValidationTag = '__MVC_FormValidation'; +Sys.Mvc.FieldContext._hasTextChangedTag = '__MVC_HasTextChanged'; +Sys.Mvc.FieldContext._hasValidationFiredTag = '__MVC_HasValidationFired'; +Sys.Mvc.FieldContext._inputElementErrorCss = 'input-validation-error'; +Sys.Mvc.FieldContext._inputElementValidCss = 'input-validation-valid'; +Sys.Mvc.FieldContext._validationMessageErrorCss = 'field-validation-error'; +Sys.Mvc.FieldContext._validationMessageValidCss = 'field-validation-valid'; +Sys.Mvc.ValidatorRegistry.validators = Sys.Mvc.ValidatorRegistry._getDefaultValidators(); + +// ---- Do not remove this footer ---- +// Generated using Script# v0.5.0.0 (http://projects.nikhilk.net) +// ----------------------------------- + +// register validation +Sys.Application.add_load(function() { + Sys.Application.remove_load(arguments.callee); + Sys.Mvc.FormContext._Application_Load(); +}); diff --git a/Azure/WebSite_WindowsAzure/Scripts/MicrosoftMvcValidation.js b/Azure/WebSite_WindowsAzure/Scripts/MicrosoftMvcValidation.js new file mode 100644 index 0000000..9483492 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Scripts/MicrosoftMvcValidation.js @@ -0,0 +1,55 @@ +//---------------------------------------------------------- +// Copyright (C) Microsoft Corporation. All rights reserved. +//---------------------------------------------------------- +// MicrosoftMvcValidation.js + +Type.registerNamespace('Sys.Mvc');Sys.Mvc.$create_Validation=function(){return {};} +Sys.Mvc.$create_JsonValidationField=function(){return {};} +Sys.Mvc.$create_JsonValidationOptions=function(){return {};} +Sys.Mvc.$create_JsonValidationRule=function(){return {};} +Sys.Mvc.$create_ValidationContext=function(){return {};} +Sys.Mvc.NumberValidator=function(){} +Sys.Mvc.NumberValidator.create=function(rule){return Function.createDelegate(new Sys.Mvc.NumberValidator(),new Sys.Mvc.NumberValidator().validate);} +Sys.Mvc.NumberValidator.prototype={validate:function(value,context){if(Sys.Mvc._ValidationUtil.$1(value)){return true;}var $0=Number.parseLocale(value);return (!isNaN($0));}} +Sys.Mvc.FormContext=function(formElement,validationSummaryElement){this.$5=[];this.fields=new Array(0);this.$9=formElement;this.$7=validationSummaryElement;formElement['__MVC_FormValidation'] = this;if(validationSummaryElement){var $0=validationSummaryElement.getElementsByTagName('ul');if($0.length>0){this.$8=$0[0];}}this.$3=Function.createDelegate(this,this.$D);this.$4=Function.createDelegate(this,this.$E);} +Sys.Mvc.FormContext._Application_Load=function(){var $0=window.mvcClientValidationMetadata;if($0){while($0.length>0){var $1=$0.pop();Sys.Mvc.FormContext.$12($1);}}} +Sys.Mvc.FormContext.$F=function($p0,$p1){var $0=[];var $1=document.getElementsByName($p1);for(var $2=0;$2<$1.length;$2++){var $3=$1[$2];if(Sys.Mvc.FormContext.$10($p0,$3)){Array.add($0,$3);}}return $0;} +Sys.Mvc.FormContext.getValidationForForm=function(formElement){return formElement['__MVC_FormValidation'];} +Sys.Mvc.FormContext.$10=function($p0,$p1){while($p1){if($p0===$p1){return true;}$p1=$p1.parentNode;}return false;} +Sys.Mvc.FormContext.$12=function($p0){var $0=$get($p0.FormId);var $1=(!Sys.Mvc._ValidationUtil.$1($p0.ValidationSummaryId))?$get($p0.ValidationSummaryId):null;var $2=new Sys.Mvc.FormContext($0,$1);$2.enableDynamicValidation();$2.replaceValidationSummary=$p0.ReplaceValidationSummary;for(var $4=0;$4<$p0.Fields.length;$4++){var $5=$p0.Fields[$4];var $6=Sys.Mvc.FormContext.$F($0,$5.FieldName);var $7=(!Sys.Mvc._ValidationUtil.$1($5.ValidationMessageId))?$get($5.ValidationMessageId):null;var $8=new Sys.Mvc.FieldContext($2);Array.addRange($8.elements,$6);$8.validationMessageElement=$7;$8.replaceValidationMessageContents=$5.ReplaceValidationMessageContents;for(var $9=0;$9<$5.ValidationRules.length;$9++){var $A=$5.ValidationRules[$9];var $B=Sys.Mvc.ValidatorRegistry.getValidator($A);if($B){var $C=Sys.Mvc.$create_Validation();$C.fieldErrorMessage=$A.ErrorMessage;$C.validator=$B;Array.add($8.validations,$C);}}$8.enableDynamicValidation();Array.add($2.fields,$8);}var $3=$0.validationCallbacks;if(!$3){$3=[];$0.validationCallbacks = $3;}$3.push(Function.createDelegate(null,function(){ +return Sys.Mvc._ValidationUtil.$0($2.validate('submit'));}));return $2;} +Sys.Mvc.FormContext.prototype={$3:null,$4:null,$6:null,$7:null,$8:null,$9:null,replaceValidationSummary:false,addError:function(message){this.addErrors([message]);},addErrors:function(messages){if(!Sys.Mvc._ValidationUtil.$0(messages)){Array.addRange(this.$5,messages);this.$11();}},clearErrors:function(){Array.clear(this.$5);this.$11();},$A:function(){if(this.$7){if(this.$8){Sys.Mvc._ValidationUtil.$3(this.$8);for(var $0=0;$0=8){Sys.UI.DomEvent.addHandler($2,'propertychange',this.$9);}}else{Sys.UI.DomEvent.addHandler($2,'input',this.$8);}Sys.UI.DomEvent.addHandler($2,'change',this.$7);Sys.UI.DomEvent.addHandler($2,'blur',this.$6);}},$11:function($p0,$p1){var $0=$p1||this.defaultErrorMessage;if(Boolean.isInstanceOfType($p0)){return ($p0)?null:$0;}if(String.isInstanceOfType($p0)){return (($p0).length)?$p0:$0;}return null;},$12:function(){var $0=this.elements;return ($0.length>0)?$0[0].value:null;},$13:function(){var $0=this.elements;for(var $1=0;$1<$0.length;$1++){var $2=$0[$1];$2['__MVC_HasValidationFired'] = true;}},$14:function(){if(!this.$A.length){this.$C();}else{this.$B();}},validate:function(eventName){var $0=this.validations;var $1=[];var $2=this.$12();for(var $3=0;$3<$0.length;$3++){var $4=$0[$3];var $5=Sys.Mvc.$create_ValidationContext();$5.eventName=eventName;$5.fieldContext=this;$5.validation=$4;var $6=$4.validator($2,$5);var $7=this.$11($6,$4.fieldErrorMessage);if(!Sys.Mvc._ValidationUtil.$1($7)){Array.add($1,$7);}}this.$13();this.clearErrors();this.addErrors($1);return $1;}} +Sys.Mvc.RangeValidator=function(minimum,maximum){this.$0=minimum;this.$1=maximum;} +Sys.Mvc.RangeValidator.create=function(rule){var $0=rule.ValidationParameters['min'];var $1=rule.ValidationParameters['max'];return Function.createDelegate(new Sys.Mvc.RangeValidator($0,$1),new Sys.Mvc.RangeValidator($0,$1).validate);} +Sys.Mvc.RangeValidator.prototype={$0:null,$1:null,validate:function(value,context){if(Sys.Mvc._ValidationUtil.$1(value)){return true;}var $0=Number.parseLocale(value);return (!isNaN($0)&&this.$0<=$0&&$0<=this.$1);}} +Sys.Mvc.RegularExpressionValidator=function(pattern){this.$0=pattern;} +Sys.Mvc.RegularExpressionValidator.create=function(rule){var $0=rule.ValidationParameters['pattern'];return Function.createDelegate(new Sys.Mvc.RegularExpressionValidator($0),new Sys.Mvc.RegularExpressionValidator($0).validate);} +Sys.Mvc.RegularExpressionValidator.prototype={$0:null,validate:function(value,context){if(Sys.Mvc._ValidationUtil.$1(value)){return true;}var $0=new RegExp(this.$0);var $1=$0.exec(value);return (!Sys.Mvc._ValidationUtil.$0($1)&&$1[0].length===value.length);}} +Sys.Mvc.RequiredValidator=function(){} +Sys.Mvc.RequiredValidator.create=function(rule){return Function.createDelegate(new Sys.Mvc.RequiredValidator(),new Sys.Mvc.RequiredValidator().validate);} +Sys.Mvc.RequiredValidator.$0=function($p0){if($p0.tagName.toUpperCase()==='INPUT'){var $0=($p0.type).toUpperCase();if($0==='RADIO'){return true;}}return false;} +Sys.Mvc.RequiredValidator.$1=function($p0){if($p0.tagName.toUpperCase()==='SELECT'){return true;}return false;} +Sys.Mvc.RequiredValidator.$2=function($p0){if($p0.tagName.toUpperCase()==='INPUT'){var $0=($p0.type).toUpperCase();switch($0){case 'TEXT':case 'PASSWORD':case 'FILE':return true;}}if($p0.tagName.toUpperCase()==='TEXTAREA'){return true;}return false;} +Sys.Mvc.RequiredValidator.$3=function($p0){for(var $0=0;$0<$p0.length;$0++){var $1=$p0[$0];if($1.checked){return true;}}return false;} +Sys.Mvc.RequiredValidator.$4=function($p0){for(var $0=0;$0<$p0.length;$0++){var $1=$p0[$0];if($1.selected){if(!Sys.Mvc._ValidationUtil.$1($1.value)){return true;}}}return false;} +Sys.Mvc.RequiredValidator.$5=function($p0){return (!Sys.Mvc._ValidationUtil.$1($p0.value));} +Sys.Mvc.RequiredValidator.prototype={validate:function(value,context){var $0=context.fieldContext.elements;if(!$0.length){return true;}var $1=$0[0];if(Sys.Mvc.RequiredValidator.$2($1)){return Sys.Mvc.RequiredValidator.$5($1);}if(Sys.Mvc.RequiredValidator.$0($1)){return Sys.Mvc.RequiredValidator.$3($0);}if(Sys.Mvc.RequiredValidator.$1($1)){return Sys.Mvc.RequiredValidator.$4(($1).options);}return true;}} +Sys.Mvc.StringLengthValidator=function(minLength,maxLength){this.$1=minLength;this.$0=maxLength;} +Sys.Mvc.StringLengthValidator.create=function(rule){var $0=(rule.ValidationParameters['min']||0);var $1=(rule.ValidationParameters['max']||Number.MAX_VALUE);return Function.createDelegate(new Sys.Mvc.StringLengthValidator($0,$1),new Sys.Mvc.StringLengthValidator($0,$1).validate);} +Sys.Mvc.StringLengthValidator.prototype={$0:0,$1:0,validate:function(value,context){if(Sys.Mvc._ValidationUtil.$1(value)){return true;}return (this.$1<=value.length&&value.length<=this.$0);}} +Sys.Mvc._ValidationUtil=function(){} +Sys.Mvc._ValidationUtil.$0=function($p0){return (!$p0||!$p0.length);} +Sys.Mvc._ValidationUtil.$1=function($p0){return (!$p0||!$p0.length);} +Sys.Mvc._ValidationUtil.$2=function($p0,$p1){return ($p1 in $p0);} +Sys.Mvc._ValidationUtil.$3=function($p0){while($p0.firstChild){$p0.removeChild($p0.firstChild);}} +Sys.Mvc._ValidationUtil.$4=function($p0,$p1){var $0=document.createTextNode($p1);Sys.Mvc._ValidationUtil.$3($p0);$p0.appendChild($0);} +Sys.Mvc.ValidatorRegistry=function(){} +Sys.Mvc.ValidatorRegistry.getValidator=function(rule){var $0=Sys.Mvc.ValidatorRegistry.validators[rule.ValidationType];return ($0)?$0(rule):null;} +Sys.Mvc.ValidatorRegistry.$0=function(){return {required:Function.createDelegate(null,Sys.Mvc.RequiredValidator.create),length:Function.createDelegate(null,Sys.Mvc.StringLengthValidator.create),regex:Function.createDelegate(null,Sys.Mvc.RegularExpressionValidator.create),range:Function.createDelegate(null,Sys.Mvc.RangeValidator.create),number:Function.createDelegate(null,Sys.Mvc.NumberValidator.create)};} +Sys.Mvc.NumberValidator.registerClass('Sys.Mvc.NumberValidator');Sys.Mvc.FormContext.registerClass('Sys.Mvc.FormContext');Sys.Mvc.FieldContext.registerClass('Sys.Mvc.FieldContext');Sys.Mvc.RangeValidator.registerClass('Sys.Mvc.RangeValidator');Sys.Mvc.RegularExpressionValidator.registerClass('Sys.Mvc.RegularExpressionValidator');Sys.Mvc.RequiredValidator.registerClass('Sys.Mvc.RequiredValidator');Sys.Mvc.StringLengthValidator.registerClass('Sys.Mvc.StringLengthValidator');Sys.Mvc._ValidationUtil.registerClass('Sys.Mvc._ValidationUtil');Sys.Mvc.ValidatorRegistry.registerClass('Sys.Mvc.ValidatorRegistry');Sys.Mvc.ValidatorRegistry.validators=Sys.Mvc.ValidatorRegistry.$0(); +// ---- Do not remove this footer ---- +// Generated using Script# v0.5.0.0 (http://projects.nikhilk.net) +// ----------------------------------- +Sys.Application.add_load(function(){Sys.Application.remove_load(arguments.callee);Sys.Mvc.FormContext._Application_Load();}); \ No newline at end of file diff --git a/Azure/WebSite_WindowsAzure/Scripts/jquery-1.6.4-vsdoc.js b/Azure/WebSite_WindowsAzure/Scripts/jquery-1.6.4-vsdoc.js new file mode 100644 index 0000000..f9e47c8 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Scripts/jquery-1.6.4-vsdoc.js @@ -0,0 +1,7024 @@ +/* +* This file has been generated 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.6.4 +*/ + +/*! +* jQuery JavaScript Library v1.6.4 +* http://jquery.com/ +* +* Distributed in whole under the terms of the MIT +* +* Copyright 2010, John Resig +* +* 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. +* +* Includes Sizzle.js +* http://sizzlejs.com/ +* Copyright 2010, The Dojo Foundation +* Released under the MIT and BSD Licenses. +*/ + +(function ( window, undefined ) { +var jQuery = function( selector, context ) { +/// +/// 1: Accepts a string containing a CSS selector which is then used to match a set of elements. +/// 1.1 - $(selector, context) +/// 1.2 - $(element) +/// 1.3 - $(elementArray) +/// 1.4 - $(jQuery object) +/// 1.5 - $() +/// 2: Creates DOM elements on the fly from the provided string of raw HTML. +/// 2.1 - $(html, ownerDocument) +/// 2.2 - $(html, props) +/// 3: Binds a function to be executed when the DOM has finished loading. +/// 3.1 - $(callback) +/// +/// +/// A string containing a selector expression +/// +/// +/// A DOM Element, Document, or jQuery to use as context +/// +/// + + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }; +jQuery.Deferred = function( func ) { + + var deferred = jQuery._Deferred(), + failDeferred = jQuery._Deferred(), + promise; + // Add errorDeferred methods, then and promise + jQuery.extend( deferred, { + then: function( doneCallbacks, failCallbacks ) { + deferred.done( doneCallbacks ).fail( failCallbacks ); + return this; + }, + always: function() { + return deferred.done.apply( deferred, arguments ).fail.apply( this, arguments ); + }, + fail: failDeferred.done, + rejectWith: failDeferred.resolveWith, + reject: failDeferred.resolve, + isRejected: failDeferred.isResolved, + pipe: function( fnDone, fnFail ) { + return jQuery.Deferred(function( newDefer ) { + jQuery.each( { + done: [ fnDone, "resolve" ], + fail: [ fnFail, "reject" ] + }, function( handler, data ) { + var fn = data[ 0 ], + action = data[ 1 ], + returned; + if ( jQuery.isFunction( fn ) ) { + deferred[ handler ](function() { + returned = fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise().then( newDefer.resolve, newDefer.reject ); + } else { + newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] ); + } + }); + } else { + deferred[ handler ]( newDefer[ action ] ); + } + }); + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + if ( obj == null ) { + if ( promise ) { + return promise; + } + promise = obj = {}; + } + var i = promiseMethods.length; + while( i-- ) { + obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ]; + } + return obj; + } + }); + // Make sure only one callback list will be used + deferred.done( failDeferred.cancel ).fail( deferred.cancel ); + // Unexpose cancel + delete deferred.cancel; + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + return deferred; + }; +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !this.preventDefault ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // timeStamp is buggy for some events on Firefox(#3843) + // So we won't rely on the native value + this.timeStamp = jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; +jQuery._Deferred = function() { + + var // callbacks list + callbacks = [], + // stored [ context , args ] + fired, + // to avoid firing when already doing so + firing, + // flag to know if the deferred has been cancelled + cancelled, + // the deferred itself + deferred = { + + // done( f1, f2, ...) + done: function() { + if ( !cancelled ) { + var args = arguments, + i, + length, + elem, + type, + _fired; + if ( fired ) { + _fired = fired; + fired = 0; + } + for ( i = 0, length = args.length; i < length; i++ ) { + elem = args[ i ]; + type = jQuery.type( elem ); + if ( type === "array" ) { + deferred.done.apply( deferred, elem ); + } else if ( type === "function" ) { + callbacks.push( elem ); + } + } + if ( _fired ) { + deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] ); + } + } + return this; + }, + + // resolve with given context and args + resolveWith: function( context, args ) { + if ( !cancelled && !fired && !firing ) { + // make sure args are available (#8421) + args = args || []; + firing = 1; + try { + while( callbacks[ 0 ] ) { + callbacks.shift().apply( context, args ); + } + } + finally { + fired = [ context, args ]; + firing = 0; + } + } + return this; + }, + + // resolve with this as context and given arguments + resolve: function() { + deferred.resolveWith( this, arguments ); + return this; + }, + + // Has this deferred been resolved? + isResolved: function() { + return !!( firing || fired ); + }, + + // Cancel + cancel: function() { + cancelled = 1; + callbacks = []; + return this; + } + }; + + return deferred; + }; +jQuery._data = function( elem, name, data ) { + + return jQuery.data( elem, name, data, true ); + }; +jQuery._mark = function( elem, type ) { + + if ( elem ) { + type = (type || "fx") + "mark"; + jQuery.data( elem, type, (jQuery.data(elem,type,undefined,true) || 0) + 1, true ); + } + }; +jQuery._unmark = function( force, elem, type ) { + + if ( force !== true ) { + type = elem; + elem = force; + force = false; + } + if ( elem ) { + type = type || "fx"; + var key = type + "mark", + count = force ? 0 : ( (jQuery.data( elem, key, undefined, true) || 1 ) - 1 ); + if ( count ) { + jQuery.data( elem, key, count, true ); + } else { + jQuery.removeData( elem, key, true ); + handleQueueMarkDefer( elem, type, "mark" ); + } + } + }; +jQuery.acceptData = function( elem ) { + + if ( elem.nodeName ) { + var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; + + if ( match ) { + return !(match === true || elem.getAttribute("classid") !== match); + } + } + + return true; + }; +jQuery.access = function( elems, key, value, exec, fn, pass ) { + + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + jQuery.access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : undefined; + }; +jQuery.active = 0; +jQuery.ajax = function( url, options ) { +/// +/// Perform an asynchronous HTTP (Ajax) request. +/// 1 - jQuery.ajax(url, settings) +/// 2 - jQuery.ajax(settings) +/// +/// +/// A string containing the URL to which the request is sent. +/// +/// +/// A set of key/value pairs that configure the Ajax request. All settings are optional. A default can be set for any option with $.ajaxSetup(). See jQuery.ajax( settings ) below for a complete list of all settings. +/// + + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + // Callbacks context + callbackContext = s.context || s, + // Context for global events + // It's the callbackContext if one was provided in the options + // and if it's a DOM node or a jQuery collection + globalEventContext = callbackContext !== s && + ( callbackContext.nodeType || callbackContext instanceof jQuery ) ? + jQuery( callbackContext ) : jQuery.event, + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery._Deferred(), + // Status-dependent callbacks + statusCode = s.statusCode || {}, + // ifModified key + ifModifiedKey, + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + // Response headers + responseHeadersString, + responseHeaders, + // transport + transport, + // timeout handle + timeoutTimer, + // Cross-domain detection vars + parts, + // The jqXHR state + state = 0, + // To know if global events are to be dispatched + fireGlobals, + // Loop variable + i, + // Fake xhr + jqXHR = { + + readyState: 0, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( !state ) { + var lname = name.toLowerCase(); + name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Raw string + getAllResponseHeaders: function() { + return state === 2 ? responseHeadersString : null; + }, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( state === 2 ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[1].toLowerCase() ] = match[ 2 ]; + } + } + match = responseHeaders[ key.toLowerCase() ]; + } + return match === undefined ? null : match; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( !state ) { + s.mimeType = type; + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + statusText = statusText || "abort"; + if ( transport ) { + transport.abort( statusText ); + } + done( 0, statusText ); + return this; + } + }; + + // Callback for when everything is done + // It is defined here because jslint complains if it is declared + // at the end of the function (which would be more logical and readable) + function done( status, nativeStatusText, responses, headers ) { + + // Called once + if ( state === 2 ) { + return; + } + + // State is "done" now + state = 2; + + // Clear timeout if it exists + if ( timeoutTimer ) { + clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + var isSuccess, + success, + error, + statusText = nativeStatusText, + response = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined, + lastModified, + etag; + + // If successful, handle type chaining + if ( status >= 200 && status < 300 || status === 304 ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + + if ( ( lastModified = jqXHR.getResponseHeader( "Last-Modified" ) ) ) { + jQuery.lastModified[ ifModifiedKey ] = lastModified; + } + if ( ( etag = jqXHR.getResponseHeader( "Etag" ) ) ) { + jQuery.etag[ ifModifiedKey ] = etag; + } + } + + // If not modified + if ( status === 304 ) { + + statusText = "notmodified"; + isSuccess = true; + + // If we have data + } else { + + try { + success = ajaxConvert( s, response ); + statusText = "success"; + isSuccess = true; + } catch(e) { + // We have a parsererror + statusText = "parsererror"; + error = e; + } + } + } else { + // We extract error from statusText + // then normalize statusText and status for non-aborts + error = statusText; + if( !statusText || status ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = "" + ( nativeStatusText || statusText ); + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ), + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.resolveWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + // Attach deferreds + deferred.promise( jqXHR ); + jqXHR.success = jqXHR.done; + jqXHR.error = jqXHR.fail; + jqXHR.complete = completeDeferred.done; + + // Status-dependent callbacks + jqXHR.statusCode = function( map ) { + if ( map ) { + var tmp; + if ( state < 2 ) { + for( tmp in map ) { + statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ]; + } + } else { + tmp = map[ jqXHR.status ]; + jqXHR.then( tmp, tmp ); + } + } + return this; + }; + + // Remove hash character (#7531: and string promotion) + // Add protocol if not provided (#5866: IE7 issue with protocol-less urls) + // We also use the url parameter if available + s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" ); + + // Extract dataTypes list + s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax ); + + // Determine if a cross-domain request is in order + if ( s.crossDomain == null ) { + parts = rurl.exec( s.url.toLowerCase() ); + s.crossDomain = !!( parts && + ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] || + ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) != + ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) ) + ); + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefiler, stop there + if ( state === 2 ) { + return false; + } + + // We can fire global events as of now if asked to + fireGlobals = s.global; + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // If data is available, append data to url + if ( s.data ) { + s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data; + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Get ifModifiedKey before adding the anti-cache parameter + ifModifiedKey = s.url; + + // Add anti-cache in url if needed + if ( s.cache === false ) { + + var ts = jQuery.now(), + // try replacing _= if it is there + ret = s.url.replace( rts, "$1_=" + ts ); + + // if nothing was replaced, add timestamp to the end + s.url = ret + ( (ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + ifModifiedKey = ifModifiedKey || s.url; + if ( jQuery.lastModified[ ifModifiedKey ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] ); + } + if ( jQuery.etag[ ifModifiedKey ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] ); + } + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ? + s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) { + // Abort if not done already + jqXHR.abort(); + return false; + + } + + // Install callbacks on deferreds + for ( i in { success: 1, error: 1, complete: 1 } ) { + jqXHR[ i ]( s[ i ] ); + } + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = setTimeout( function(){ + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + state = 1; + transport.send( requestHeaders, done ); + } catch (e) { + // Propagate exception as error if not done + if ( state < 2 ) { + done( -1, e ); + // Simply rethrow otherwise + } else { + jQuery.error( e ); + } + } + } + + return jqXHR; + }; +jQuery.ajaxPrefilter = function( dataTypeExpression, func ) { +/// +/// Handle custom Ajax options or modify existing options before each request is sent and before they are processed by $.ajax(). +/// +/// +/// An optional string containing one or more space-separated dataTypes +/// +/// +/// A handler to set default values for future Ajax requests. +/// +/// + + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + if ( jQuery.isFunction( func ) ) { + var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ), + i = 0, + length = dataTypes.length, + dataType, + list, + placeBefore; + + // For each dataType in the dataTypeExpression + for(; i < length; i++ ) { + dataType = dataTypes[ i ]; + // We control if we're asked to add before + // any existing element + placeBefore = /^\+/.test( dataType ); + if ( placeBefore ) { + dataType = dataType.substr( 1 ) || "*"; + } + list = structure[ dataType ] = structure[ dataType ] || []; + // then we add to the structure accordingly + list[ placeBefore ? "unshift" : "push" ]( func ); + } + } + }; +jQuery.ajaxSettings = { "url": 'http://localhost:25813/', +"isLocal": false, +"global": true, +"type": 'GET', +"contentType": 'application/x-www-form-urlencoded', +"processData": true, +"async": true, +"accepts": {}, +"contents": {}, +"responseFields": {}, +"converters": {}, +"flatOptions": {}, +"jsonp": 'callback' }; +jQuery.ajaxSetup = function( target, settings ) { +/// +/// Set default values for future Ajax requests. +/// +/// +/// A set of key/value pairs that configure the default Ajax request. All options are optional. +/// + + if ( settings ) { + // Building a settings object + ajaxExtend( target, jQuery.ajaxSettings ); + } else { + // Extending ajaxSettings + settings = target; + target = jQuery.ajaxSettings; + } + ajaxExtend( target, settings ); + return target; + }; +jQuery.ajaxTransport = function( dataTypeExpression, func ) { + + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + if ( jQuery.isFunction( func ) ) { + var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ), + i = 0, + length = dataTypes.length, + dataType, + list, + placeBefore; + + // For each dataType in the dataTypeExpression + for(; i < length; i++ ) { + dataType = dataTypes[ i ]; + // We control if we're asked to add before + // any existing element + placeBefore = /^\+/.test( dataType ); + if ( placeBefore ) { + dataType = dataType.substr( 1 ) || "*"; + } + list = structure[ dataType ] = structure[ dataType ] || []; + // then we add to the structure accordingly + list[ placeBefore ? "unshift" : "push" ]( func ); + } + } + }; +jQuery.attr = function( elem, name, value, pass ) { + + var nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return undefined; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery( elem )[ name ]( value ); + } + + // Fallback to prop when attributes are not supported + if ( !("getAttribute" in elem) ) { + return jQuery.prop( elem, name, value ); + } + + var ret, hooks, + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + // Normalize the name if needed + if ( notxml ) { + name = jQuery.attrFix[ name ] || name; + + hooks = jQuery.attrHooks[ name ]; + + if ( !hooks ) { + // Use boolHook for boolean attributes + if ( rboolean.test( name ) ) { + hooks = boolHook; + + // Use nodeHook if available( IE6/7 ) + } else if ( nodeHook ) { + hooks = nodeHook; + } + } + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return undefined; + + } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, "" + value ); + return value; + } + + } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + + ret = elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return ret === null ? + undefined : + ret; + } + }; +jQuery.attrFix = { "tabindex": 'tabIndex' }; +jQuery.attrFn = { "val": true, +"css": true, +"html": true, +"text": true, +"data": true, +"width": true, +"height": true, +"offset": true, +"blur": true, +"focus": true, +"focusin": true, +"focusout": true, +"load": true, +"resize": true, +"scroll": true, +"unload": true, +"click": true, +"dblclick": true, +"mousedown": true, +"mouseup": true, +"mousemove": true, +"mouseover": true, +"mouseout": true, +"mouseenter": true, +"mouseleave": true, +"change": true, +"select": true, +"submit": true, +"keydown": true, +"keypress": true, +"keyup": true, +"error": true }; +jQuery.attrHooks = { "type": {}, +"value": {}, +"tabIndex": {} }; +jQuery.bindReady = function() { + + if ( readyList ) { + return; + } + + readyList = jQuery._Deferred(); + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + return setTimeout( jQuery.ready, 1 ); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", DOMContentLoaded ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }; +jQuery.boxModel = true; +jQuery.browser = { "msie": true, +"version": '9.0' }; +jQuery.buildFragment = function( args, nodes, scripts ) { + + var fragment, cacheable, cacheresults, doc; + + // nodes may contain either an explicit document object, + // a jQuery collection or context object. + // If nodes[0] contains a valid object to assign to doc + if ( nodes && nodes[0] ) { + doc = nodes[0].ownerDocument || nodes[0]; + } + + // Ensure that an attr object doesn't incorrectly stand in as a document object + // Chrome and Firefox seem to allow this to occur and will throw exception + // Fixes #8950 + if ( !doc.createDocumentFragment ) { + doc = document; + } + + // Only cache "small" (1/2 KB) HTML strings that are associated with the main document + // Cloning options loses the selected state, so don't cache them + // IE 6 doesn't like it when you put or elements in a fragment + // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache + if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document && + args[0].charAt(0) === "<" && !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) { + + cacheable = true; + + cacheresults = jQuery.fragments[ args[0] ]; + if ( cacheresults && cacheresults !== 1 ) { + fragment = cacheresults; + } + } + + if ( !fragment ) { + fragment = doc.createDocumentFragment(); + jQuery.clean( args, doc, fragment, scripts ); + } + + if ( cacheable ) { + jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1; + } + + return { fragment: fragment, cacheable: cacheable }; +}; +jQuery.cache = {}; +jQuery.camelCase = function( string ) { + + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }; +jQuery.clean = function( elems, context, fragment, scripts ) { + + var checkScriptType; + + context = context || document; + + // !context.createElement fails in IE with an error but returns typeof 'object' + if ( typeof context.createElement === "undefined" ) { + context = context.ownerDocument || context[0] && context[0].ownerDocument || document; + } + + var ret = [], j; + + for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { + if ( typeof elem === "number" ) { + elem += ""; + } + + if ( !elem ) { + continue; + } + + // Convert html string into DOM nodes + if ( typeof elem === "string" ) { + if ( !rhtml.test( elem ) ) { + elem = context.createTextNode( elem ); + } else { + // Fix "XHTML"-style tags in all browsers + elem = elem.replace(rxhtmlTag, "<$1>"); + + // Trim whitespace, otherwise indexOf won't work as expected + var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(), + wrap = wrapMap[ tag ] || wrapMap._default, + depth = wrap[0], + div = context.createElement("div"); + + // Go to html and back, then peel off extra wrappers + div.innerHTML = wrap[1] + elem + wrap[2]; + + // Move to the right depth + while ( depth-- ) { + div = div.lastChild; + } + + // Remove IE's autoinserted from table fragments + if ( !jQuery.support.tbody ) { + + // String was a , *may* have spurious + var hasBody = rtbody.test(elem), + tbody = tag === "table" && !hasBody ? + div.firstChild && div.firstChild.childNodes : + + // String was a bare or + wrap[1] === "
" && !hasBody ? + div.childNodes : + []; + + for ( j = tbody.length - 1; j >= 0 ; --j ) { + if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) { + tbody[ j ].parentNode.removeChild( tbody[ j ] ); + } + } + } + + // IE completely kills leading whitespace when innerHTML is used + if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { + div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild ); + } + + elem = div.childNodes; + } + } + + // Resets defaultChecked for any radios and checkboxes + // about to be appended to the DOM in IE 6/7 (#8060) + var len; + if ( !jQuery.support.appendChecked ) { + if ( elem[0] && typeof (len = elem.length) === "number" ) { + for ( j = 0; j < len; j++ ) { + findInputs( elem[j] ); + } + } else { + findInputs( elem ); + } + } + + if ( elem.nodeType ) { + ret.push( elem ); + } else { + ret = jQuery.merge( ret, elem ); + } + } + + if ( fragment ) { + checkScriptType = function( elem ) { + return !elem.type || rscriptType.test( elem.type ); + }; + for ( i = 0; ret[i]; i++ ) { + if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) { + scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] ); + + } else { + if ( ret[i].nodeType === 1 ) { + var jsTags = jQuery.grep( ret[i].getElementsByTagName( "script" ), checkScriptType ); + + ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) ); + } + fragment.appendChild( ret[i] ); + } + } + } + + return ret; + }; +jQuery.cleanData = function( elems ) { + + var data, id, cache = jQuery.cache, internalKey = jQuery.expando, special = jQuery.event.special, + deleteExpando = jQuery.support.deleteExpando; + + for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { + if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) { + continue; + } + + id = elem[ jQuery.expando ]; + + if ( id ) { + data = cache[ id ] && cache[ id ][ internalKey ]; + + if ( data && data.events ) { + for ( var type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + + // Null the DOM reference to avoid IE6/7/8 leak (#7054) + if ( data.handle ) { + data.handle.elem = null; + } + } + + if ( deleteExpando ) { + delete elem[ jQuery.expando ]; + + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); + } + + delete cache[ id ]; + } + } + }; +jQuery.clone = function( elem, dataAndEvents, deepDataAndEvents ) { + + var clone = elem.cloneNode(true), + srcElements, + destElements, + i; + + if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) && + (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { + // IE copies events bound via attachEvent when using cloneNode. + // Calling detachEvent on the clone will also remove the events + // from the original. In order to get around this, we use some + // proprietary methods to clear the events. Thanks to MooTools + // guys for this hotness. + + cloneFixAttributes( elem, clone ); + + // Using Sizzle here is crazy slow, so we use getElementsByTagName + // instead + srcElements = getAll( elem ); + destElements = getAll( clone ); + + // Weird iteration because IE will replace the length property + // with an element if you are cloning the body and one of the + // elements on the page has a name or id of "length" + for ( i = 0; srcElements[i]; ++i ) { + // Ensure that the destination node is not null; Fixes #9587 + if ( destElements[i] ) { + cloneFixAttributes( srcElements[i], destElements[i] ); + } + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + cloneCopyEvent( elem, clone ); + + if ( deepDataAndEvents ) { + srcElements = getAll( elem ); + destElements = getAll( clone ); + + for ( i = 0; srcElements[i]; ++i ) { + cloneCopyEvent( srcElements[i], destElements[i] ); + } + } + } + + srcElements = destElements = null; + + // Return the cloned set + return clone; + }; +jQuery.contains = function( a, b ) { +/// +/// Check to see if a DOM element is within another DOM element. +/// +/// +/// The DOM element that may contain the other element. +/// +/// +/// The DOM element that may be contained by the other element. +/// +/// + + return a !== b && (a.contains ? a.contains(b) : true); + }; +jQuery.css = function( elem, name, extra ) { + + var ret, hooks; + + // Make sure that we're working with the right name + name = jQuery.camelCase( name ); + hooks = jQuery.cssHooks[ name ]; + name = jQuery.cssProps[ name ] || name; + + // cssFloat needs a special treatment + if ( name === "cssFloat" ) { + name = "float"; + } + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) { + return ret; + + // Otherwise, if a way to get the computed value exists, use that + } else if ( curCSS ) { + return curCSS( elem, name ); + } + }; +jQuery.cssHooks = { "opacity": {}, +"height": {}, +"width": {} }; +jQuery.cssNumber = { "fillOpacity": true, +"fontWeight": true, +"lineHeight": true, +"opacity": true, +"orphans": true, +"widows": true, +"zIndex": true, +"zoom": true }; +jQuery.cssProps = { "float": 'cssFloat' }; +jQuery.curCSS = function( elem, name, extra ) { + + var ret, hooks; + + // Make sure that we're working with the right name + name = jQuery.camelCase( name ); + hooks = jQuery.cssHooks[ name ]; + name = jQuery.cssProps[ name ] || name; + + // cssFloat needs a special treatment + if ( name === "cssFloat" ) { + name = "float"; + } + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) { + return ret; + + // Otherwise, if a way to get the computed value exists, use that + } else if ( curCSS ) { + return curCSS( elem, name ); + } + }; +jQuery.data = function( elem, name, data, pvt /* Internal Use Only */ ) { +/// +/// 1: Store arbitrary data associated with the specified element. Returns the value that was set. +/// 1.1 - jQuery.data(element, key, value) +/// 2: Returns value at named data store for the element, as set by jQuery.data(element, name, value), or the full data store for the element. +/// 2.1 - jQuery.data(element, key) +/// 2.2 - jQuery.data(element) +/// +/// +/// The DOM element to associate with the data. +/// +/// +/// A string naming the piece of data to set. +/// +/// +/// The new data value. +/// +/// + + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, ret, + internalKey = jQuery.expando, + getByName = typeof name === "string", + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || (pvt && id && (cache[ id ] && !cache[ id ][ internalKey ]))) && getByName && data === undefined ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + elem[ jQuery.expando ] = id = ++jQuery.uuid; + } else { + id = jQuery.expando; + } + } + + if ( !cache[ id ] ) { + cache[ id ] = {}; + + // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery + // metadata on plain JS objects when the object is serialized using + // JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name); + } else { + cache[ id ] = jQuery.extend(cache[ id ], name); + } + } + + thisCache = cache[ id ]; + + // Internal jQuery data is stored in a separate object inside the object's data + // cache in order to avoid key collisions between internal data and user-defined + // data + if ( pvt ) { + if ( !thisCache[ internalKey ] ) { + thisCache[ internalKey ] = {}; + } + + thisCache = thisCache[ internalKey ]; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should + // not attempt to inspect the internal events object using jQuery.data, as this + // internal data object is undocumented and subject to change. + if ( name === "events" && !thisCache[name] ) { + return thisCache[ internalKey ] && thisCache[ internalKey ].events; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( getByName ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; + }; +jQuery.dequeue = function( elem, type ) { +/// +/// Execute the next function on the queue for the matched element. +/// +/// +/// A DOM element from which to remove and execute a queued function. +/// +/// +/// A string containing the name of the queue. Defaults to fx, the standard effects queue. +/// +/// + + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + fn = queue.shift(), + defer; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift("inprogress"); + } + + fn.call(elem, function() { + jQuery.dequeue(elem, type); + }); + } + + if ( !queue.length ) { + jQuery.removeData( elem, type + "queue", true ); + handleQueueMarkDefer( elem, type, "queue" ); + } + }; +jQuery.dir = function( elem, dir, until ) { + + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }; +jQuery.each = function( object, callback, args ) { +/// +/// A generic iterator function, which can be used to seamlessly iterate over both objects and arrays. Arrays and array-like objects with a length property (such as a function's arguments object) are iterated by numeric index, from 0 to length-1. Other objects are iterated via their named properties. +/// +/// +/// The object or array to iterate over. +/// +/// +/// The function that will be executed on every object. +/// +/// + + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction( object ); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { + break; + } + } + } + } + + return object; + }; +jQuery.easing = {}; +jQuery.error = function( msg ) { +/// +/// Takes a string and throws an exception containing it. +/// +/// +/// The message to send out. +/// + + throw msg; + }; +jQuery.etag = {}; +jQuery.event = { "global": {}, +"customEvent": {}, +"props": ['altKey','attrChange','attrName','bubbles','button','cancelable','charCode','clientX','clientY','ctrlKey','currentTarget','data','detail','eventPhase','fromElement','handler','keyCode','layerX','layerY','metaKey','newValue','offsetX','offsetY','pageX','pageY','prevValue','relatedNode','relatedTarget','screenX','screenY','shiftKey','srcElement','target','toElement','view','wheelDelta','which'], +"guid": 100000000, +"special": {}, +"triggered": false}; +jQuery.expr = { "order": ['ID','CLASS','NAME','TAG'], +"match": {}, +"leftMatch": {}, +"attrMap": {}, +"attrHandle": {}, +"relative": {}, +"find": {}, +"preFilter": {}, +"filters": {}, +"setFilters": {}, +"filter": {}, +":": {} }; +jQuery.extend = function() { +/// +/// Merge the contents of two or more objects together into the first object. +/// 1 - jQuery.extend(target, object1, objectN) +/// 2 - jQuery.extend(deep, target, object1, objectN) +/// +/// +/// If true, the merge becomes recursive (aka. deep copy). +/// +/// +/// The object to extend. It will receive the new properties. +/// +/// +/// An object containing additional properties to merge in. +/// +/// +/// Additional objects containing properties to merge in. +/// +/// + + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; +jQuery.filter = function( expr, elems, not ) { + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }; +jQuery.find = function( query, context, extra, seed ) { + + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && !Sizzle.isXML(context) ) { + // See if we find a selector to speed up + var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); + + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { + // Speed-up: Sizzle("TAG") + if ( match[1] ) { + return makeArray( context.getElementsByTagName( query ), extra ); + + // Speed-up: Sizzle(".CLASS") + } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { + return makeArray( context.getElementsByClassName( match[2] ), extra ); + } + } + + if ( context.nodeType === 9 ) { + // Speed-up: Sizzle("body") + // The body element only exists once, optimize finding it + if ( query === "body" && context.body ) { + return makeArray( [ context.body ], extra ); + + // Speed-up: Sizzle("#ID") + } else if ( match && match[3] ) { + var elem = context.getElementById( match[3] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id === match[3] ) { + return makeArray( [ elem ], extra ); + } + + } else { + return makeArray( [], extra ); + } + } + + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(qsaError) {} + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + var oldContext = context, + old = context.getAttribute( "id" ), + nid = old || id, + hasParent = context.parentNode, + relativeHierarchySelector = /^\s*[+~]/.test( query ); + + if ( !old ) { + context.setAttribute( "id", nid ); + } else { + nid = nid.replace( /'/g, "\\$&" ); + } + if ( relativeHierarchySelector && hasParent ) { + context = context.parentNode; + } + + try { + if ( !relativeHierarchySelector || hasParent ) { + return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); + } + + } catch(pseudoError) { + } finally { + if ( !old ) { + oldContext.removeAttribute( "id" ); + } + } + } + } + + return oldSizzle(query, context, extra, seed); + }; +jQuery.fn = { "selector": '', +"jquery": '1.6.4', +"length": 0 }; +jQuery.fragments = {}; +jQuery.fx = function( elem, options, prop ) { + + this.options = options; + this.elem = elem; + this.prop = prop; + + options.orig = options.orig || {}; + }; +jQuery.get = function( url, data, callback, type ) { +/// +/// Load data from the server using a HTTP GET request. +/// +/// +/// A string containing the URL to which the request is sent. +/// +/// +/// A map or string that is sent to the server with the request. +/// +/// +/// A callback function that is executed if the request succeeds. +/// +/// +/// The type of data expected from the server. Default: Intelligent Guess (xml, json, script, or html). +/// + + // shift arguments if data argument was omitted + if ( jQuery.isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + return jQuery.ajax({ + type: method, + url: url, + data: data, + success: callback, + dataType: type + }); + }; +jQuery.getJSON = function( url, data, callback ) { +/// +/// Load JSON-encoded data from the server using a GET HTTP request. +/// +/// +/// A string containing the URL to which the request is sent. +/// +/// +/// A map or string that is sent to the server with the request. +/// +/// +/// A callback function that is executed if the request succeeds. +/// + + return jQuery.get( url, data, callback, "json" ); + }; +jQuery.getScript = function( url, callback ) { +/// +/// Load a JavaScript file from the server using a GET HTTP request, then execute it. +/// +/// +/// A string containing the URL to which the request is sent. +/// +/// +/// A callback function that is executed if the request succeeds. +/// + + return jQuery.get( url, undefined, callback, "script" ); + }; +jQuery.globalEval = function( data ) { +/// +/// Execute some JavaScript code globally. +/// +/// +/// The JavaScript code to execute. +/// + + if ( data && rnotwhite.test( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }; +jQuery.grep = function( elems, callback, inv ) { +/// +/// Finds the elements of an array which satisfy a filter function. The original array is not affected. +/// +/// +/// The array to search through. +/// +/// +/// The function to process each item against. The first argument to the function is the item, and the second argument is the index. The function should return a Boolean value. this will be the global window object. +/// +/// +/// If "invert" is false, or not provided, then the function returns an array consisting of all elements for which "callback" returns true. If "invert" is true, then the function returns an array consisting of all elements for which "callback" returns false. +/// +/// + + var ret = [], retVal; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }; +jQuery.guid = 1; +jQuery.hasData = function( elem ) { +/// +/// Determine whether an element has any jQuery data associated with it. +/// +/// +/// A DOM element to be checked for data. +/// +/// + + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + + return !!elem && !isEmptyDataObject( elem ); + }; +jQuery.holdReady = function( hold ) { +/// +/// Holds or releases the execution of jQuery's ready event. +/// +/// +/// Indicates whether the ready hold is being requested or released +/// +/// + + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }; +jQuery.inArray = function( elem, array ) { +/// +/// Search for a specified value within an array and return its index (or -1 if not found). +/// +/// +/// The value to search for. +/// +/// +/// An array through which to search. +/// +/// + + if ( !array ) { + return -1; + } + + if ( indexOf ) { + return indexOf.call( array, elem ); + } + + for ( var i = 0, length = array.length; i < length; i++ ) { + if ( array[ i ] === elem ) { + return i; + } + } + + return -1; + }; +jQuery.isEmptyObject = function( obj ) { +/// +/// Check to see if an object is empty (contains no properties). +/// +/// +/// The object that will be checked to see if it's empty. +/// +/// + + for ( var name in obj ) { + return false; + } + return true; + }; +jQuery.isFunction = function( obj ) { +/// +/// Determine if the argument passed is a Javascript function object. +/// +/// +/// Object to test whether or not it is a function. +/// +/// + + return jQuery.type(obj) === "function"; + }; +jQuery.isNaN = function( obj ) { + + return obj == null || !rdigit.test( obj ) || isNaN( obj ); + }; +jQuery.isPlainObject = function( obj ) { +/// +/// Check to see if an object is a plain object (created using "{}" or "new Object"). +/// +/// +/// The object that will be checked to see if it's a plain object. +/// +/// + + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }; +jQuery.isReady = true; +jQuery.isWindow = function( obj ) { +/// +/// Determine whether the argument is a window. +/// +/// +/// Object to test whether or not it is a window. +/// +/// + + return obj && typeof obj === "object" && "setInterval" in obj; + }; +jQuery.isXMLDoc = function( elem ) { +/// +/// Check to see if a DOM node is within an XML document (or is an XML document). +/// +/// +/// The DOM node that will be checked to see if it's in an XML document. +/// +/// + + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; +jQuery.lastModified = {}; +jQuery.makeArray = function( array, results ) { +/// +/// Convert an array-like object into a true JavaScript array. +/// +/// +/// Any object to turn into a native Array. +/// +/// + + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // The extra typeof function check is to prevent crashes + // in Safari 2 (See: #3039) + // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 + var type = jQuery.type( array ); + + if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }; +jQuery.map = function( elems, callback, arg ) { +/// +/// Translate all items in an array or object to new array of items. +/// 1 - jQuery.map(array, callback(elementOfArray, indexInArray)) +/// 2 - jQuery.map(arrayOrObject, callback( value, indexOrKey )) +/// +/// +/// The Array to translate. +/// +/// +/// The function to process each item against. The first argument to the function is the array item, the second argument is the index in array The function can return any value. Within the function, this refers to the global (window) object. +/// +/// + + var value, key, ret = [], + i = 0, + length = elems.length, + // jquery objects are treated as arrays + isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( key in elems ) { + value = callback( elems[ key ], key, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return ret.concat.apply( [], ret ); + }; +jQuery.merge = function( first, second ) { +/// +/// Merge the contents of two arrays together into the first array. +/// +/// +/// The first array to merge, the elements of second added. +/// +/// +/// The second array to merge into the first, unaltered. +/// +/// + + var i = first.length, + j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }; +jQuery.noConflict = function( deep ) { +/// +/// Relinquish jQuery's control of the $ variable. +/// +/// +/// A Boolean indicating whether to remove all jQuery variables from the global scope (including jQuery itself). +/// +/// + + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }; +jQuery.noData = { "embed": true, +"object": 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000', +"applet": true }; +jQuery.nodeName = function( elem, name ) { + + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }; +jQuery.noop = function() { +/// +/// An empty function. +/// +/// +}; +jQuery.now = function() { +/// +/// Return a number representing the current time. +/// +/// + + return (new Date()).getTime(); + }; +jQuery.nth = function( cur, result, dir, elem ) { + + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }; +jQuery.offset = {}; +jQuery.param = function( a, traditional ) { +/// +/// Create a serialized representation of an array or object, suitable for use in a URL query string or Ajax request. +/// 1 - jQuery.param(obj) +/// 2 - jQuery.param(obj, traditional) +/// +/// +/// An array or object to serialize. +/// +/// +/// A Boolean indicating whether to perform a traditional "shallow" serialization. +/// +/// + + var s = [], + add = function( key, value ) { + // If value is a function, invoke it and return its value + value = jQuery.isFunction( value ) ? value() : value; + s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value ); + }; + + // Set traditional to true for jQuery <= 1.3.2 behavior. + if ( traditional === undefined ) { + traditional = jQuery.ajaxSettings.traditional; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + }); + + } else { + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( var prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ).replace( r20, "+" ); + }; +jQuery.parseJSON = function( data ) { +/// +/// Takes a well-formed JSON string and returns the resulting JavaScript object. +/// +/// +/// The JSON string to parse. +/// +/// + + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return (new Function( "return " + data ))(); + + } + jQuery.error( "Invalid JSON: " + data ); + }; +jQuery.parseXML = function( data ) { +/// +/// Parses a string into an XML document. +/// +/// +/// a well-formed XML string to be parsed +/// +/// + + var xml, tmp; + try { + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + } catch( e ) { + xml = undefined; + } + if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; + }; +jQuery.post = function( url, data, callback, type ) { +/// +/// Load data from the server using a HTTP POST request. +/// +/// +/// A string containing the URL to which the request is sent. +/// +/// +/// A map or string that is sent to the server with the request. +/// +/// +/// A callback function that is executed if the request succeeds. +/// +/// +/// The type of data expected from the server. Default: Intelligent Guess (xml, json, script, or html). +/// + + // shift arguments if data argument was omitted + if ( jQuery.isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + return jQuery.ajax({ + type: method, + url: url, + data: data, + success: callback, + dataType: type + }); + }; +jQuery.prop = function( elem, name, value ) { + + var nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return undefined; + } + + var ret, hooks, + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + return (elem[ name ] = value); + } + + } else { + if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + return elem[ name ]; + } + } + }; +jQuery.propFix = { "tabindex": 'tabIndex', +"readonly": 'readOnly', +"for": 'htmlFor', +"class": 'className', +"maxlength": 'maxLength', +"cellspacing": 'cellSpacing', +"cellpadding": 'cellPadding', +"rowspan": 'rowSpan', +"colspan": 'colSpan', +"usemap": 'useMap', +"frameborder": 'frameBorder', +"contenteditable": 'contentEditable' }; +jQuery.propHooks = { "tabIndex": {}, +"selected": {} }; +jQuery.proxy = function( fn, context ) { +/// +/// Takes a function and returns a new one that will always have a particular context. +/// 1 - jQuery.proxy(function, context) +/// 2 - jQuery.proxy(context, name) +/// +/// +/// The function whose context will be changed. +/// +/// +/// The object to which the context (this) of the function should be set. +/// +/// + + if ( typeof context === "string" ) { + var tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + var args = slice.call( arguments, 2 ), + proxy = function() { + return fn.apply( context, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + + return proxy; + }; +jQuery.queue = function( elem, type, data ) { +/// +/// 1: Show the queue of functions to be executed on the matched element. +/// 1.1 - jQuery.queue(element, queueName) +/// 2: Manipulate the queue of functions to be executed on the matched element. +/// 2.1 - jQuery.queue(element, queueName, newQueue) +/// 2.2 - jQuery.queue(element, queueName, callback()) +/// +/// +/// A DOM element where the array of queued functions is attached. +/// +/// +/// A string containing the name of the queue. Defaults to fx, the standard effects queue. +/// +/// +/// An array of functions to replace the current queue contents. +/// +/// + + if ( elem ) { + type = (type || "fx") + "queue"; + var q = jQuery.data( elem, type, undefined, true ); + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !q || jQuery.isArray(data) ) { + q = jQuery.data( elem, type, jQuery.makeArray(data), true ); + } else { + q.push( data ); + } + } + return q || []; + } + }; +jQuery.ready = function( wait ) { + + // Either a released hold or an DOMready/load event and not yet ready + if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 1 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger( "ready" ).unbind( "ready" ); + } + } + }; +jQuery.readyWait = 0; +jQuery.removeAttr = function( elem, name ) { + + var propName; + if ( elem.nodeType === 1 ) { + name = jQuery.attrFix[ name ] || name; + + jQuery.attr( elem, name, "" ); + elem.removeAttribute( name ); + + // Set corresponding property to false for boolean attributes + if ( rboolean.test( name ) && (propName = jQuery.propFix[ name ] || name) in elem ) { + elem[ propName ] = false; + } + } + }; +jQuery.removeData = function( elem, name, pvt /* Internal Use Only */ ) { +/// +/// Remove a previously-stored piece of data. +/// +/// +/// A DOM element from which to remove data. +/// +/// +/// A string naming the piece of data to remove. +/// +/// + + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, + + // Reference to internal data cache key + internalKey = jQuery.expando, + + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + + // See jQuery.data for more information + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ]; + + if ( thisCache ) { + + // Support interoperable removal of hyphenated or camelcased keys + if ( !thisCache[ name ] ) { + name = jQuery.camelCase( name ); + } + + delete thisCache[ name ]; + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( !isEmptyDataObject(thisCache) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( pvt ) { + delete cache[ id ][ internalKey ]; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject(cache[ id ]) ) { + return; + } + } + + var internalCache = cache[ id ][ internalKey ]; + + // Browsers that fail expando deletion also refuse to delete expandos on + // the window, but it will allow it on all other JS objects; other browsers + // don't care + // Ensure that `cache` is not a window object #10080 + if ( jQuery.support.deleteExpando || !cache.setInterval ) { + delete cache[ id ]; + } else { + cache[ id ] = null; + } + + // We destroyed the entire user cache at once because it's faster than + // iterating through each key, but we need to continue to persist internal + // data if it existed + if ( internalCache ) { + cache[ id ] = {}; + // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery + // metadata on plain JS objects when the object is serialized using + // JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + + cache[ id ][ internalKey ] = internalCache; + + // Otherwise, we need to eliminate the expando on the node to avoid + // false lookups in the cache for entries that no longer exist + } else if ( isNode ) { + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( jQuery.support.deleteExpando ) { + delete elem[ jQuery.expando ]; + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); + } else { + elem[ jQuery.expando ] = null; + } + } + }; +jQuery.removeEvent = function( elem, type, handle ) { + + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + }; +jQuery.sibling = function( n, elem ) { + + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + }; +jQuery.speed = function( speed, easing, fn ) { + + var opt = speed && typeof speed === "object" ? jQuery.extend({}, speed) : { + complete: fn || !fn && easing || + jQuery.isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !jQuery.isFunction(easing) && easing + }; + + opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration : + opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[opt.duration] : jQuery.fx.speeds._default; + + // Queueing + opt.old = opt.complete; + opt.complete = function( noUnmark ) { + if ( jQuery.isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue !== false ) { + jQuery.dequeue( this ); + } else if ( noUnmark !== false ) { + jQuery._unmark( this ); + } + }; + + return opt; + }; +jQuery.style = function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, origName = jQuery.camelCase( name ), + style = elem.style, hooks = jQuery.cssHooks[ origName ]; + + name = jQuery.cssProps[ origName ] || origName; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // convert relative number strings (+= or -=) to relative numbers. #7345 + if ( type === "string" && (ret = rrelNum.exec( value )) ) { + value = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) ); + // Fixes bug #9237 + type = "number"; + } + + // Make sure that NaN and null values aren't set. See: #7116 + if ( value == null || type === "number" && isNaN( value ) ) { + return; + } + + // If a number was passed in, add 'px' to the (except for certain CSS properties) + if ( type === "number" && !jQuery.cssNumber[ origName ] ) { + value += "px"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) { + // Wrapped to prevent IE from throwing errors when 'invalid' values are provided + // Fixes bug #5509 + try { + style[ name ] = value; + } catch(e) {} + } + + } else { + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }; +jQuery.sub = function() { +/// +/// Creates a new copy of jQuery whose properties and methods can be modified without affecting the original jQuery object. +/// +/// + + function jQuerySub( selector, context ) { + return new jQuerySub.fn.init( selector, context ); + } + jQuery.extend( true, jQuerySub, this ); + jQuerySub.superclass = this; + jQuerySub.fn = jQuerySub.prototype = this(); + jQuerySub.fn.constructor = jQuerySub; + jQuerySub.sub = this.sub; + jQuerySub.fn.init = function init( selector, context ) { + if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { + context = jQuerySub( context ); + } + + return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); + }; + jQuerySub.fn.init.prototype = jQuerySub.fn; + var rootjQuerySub = jQuerySub(document); + return jQuerySub; + }; +jQuery.support = { "leadingWhitespace": true, +"tbody": true, +"htmlSerialize": true, +"style": true, +"hrefNormalized": true, +"opacity": true, +"cssFloat": true, +"checkOn": true, +"optSelected": false, +"getSetAttribute": true, +"submitBubbles": true, +"changeBubbles": true, +"focusinBubbles": true, +"deleteExpando": true, +"noCloneEvent": true, +"inlineBlockNeedsLayout": false, +"shrinkWrapBlocks": false, +"reliableMarginRight": true, +"noCloneChecked": false, +"optDisabled": true, +"radioValue": false, +"checkClone": false, +"appendChecked": true, +"boxModel": true, +"reliableHiddenOffsets": true, +"ajax": true, +"cors": false }; +jQuery.swap = function( elem, options, callback ) { + + var old = {}; + + // Remember the old values, and insert the new ones + for ( var name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + }; +jQuery.text = function( elems ) { + + var ret = "", elem; + + for ( var i = 0; elems[i]; i++ ) { + elem = elems[i]; + + // Get the text from text nodes and CDATA nodes + if ( elem.nodeType === 3 || elem.nodeType === 4 ) { + ret += elem.nodeValue; + + // Traverse everything else, except comment nodes + } else if ( elem.nodeType !== 8 ) { + ret += Sizzle.getText( elem.childNodes ); + } + } + + return ret; +}; +jQuery.trim = function( text ) { +/// +/// Remove the whitespace from the beginning and end of a string. +/// +/// +/// The string to trim. +/// +/// + + return text == null ? + "" : + trim.call( text ); + }; +jQuery.type = function( obj ) { +/// +/// Determine the internal JavaScript [[Class]] of an object. +/// +/// +/// Object to get the internal JavaScript [[Class]] of. +/// +/// + + return obj == null ? + String( obj ) : + class2type[ toString.call(obj) ] || "object"; + }; +jQuery.uaMatch = function( ua ) { + + ua = ua.toLowerCase(); + + var match = rwebkit.exec( ua ) || + ropera.exec( ua ) || + rmsie.exec( ua ) || + ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }; +jQuery.unique = function( results ) { +/// +/// Sorts an array of DOM elements, in place, with the duplicates removed. Note that this only works on arrays of DOM elements, not strings or numbers. +/// +/// +/// The Array of DOM elements. +/// +/// + + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[ i - 1 ] ) { + results.splice( i--, 1 ); + } + } + } + } + + return results; +}; +jQuery.uuid = 0; +jQuery.valHooks = { "option": {}, +"select": {}, +"radio": {}, +"checkbox": {} }; +jQuery.when = function( firstParam ) { +/// +/// Provides a way to execute callback functions based on one or more objects, usually Deferred objects that represent asynchronous events. +/// +/// +/// One or more Deferred objects, or plain JavaScript objects. +/// +/// + + var args = arguments, + i = 0, + length = args.length, + count = length, + deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? + firstParam : + jQuery.Deferred(); + function resolveFunc( i ) { + return function( value ) { + args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + if ( !( --count ) ) { + // Strange bug in FF4: + // Values changed onto the arguments object sometimes end up as undefined values + // outside the $.when method. Cloning the object into a fresh array solves the issue + deferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) ); + } + }; + } + if ( length > 1 ) { + for( ; i < length; i++ ) { + if ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) { + args[ i ].promise().then( resolveFunc(i), deferred.reject ); + } else { + --count; + } + } + if ( !count ) { + deferred.resolveWith( deferred, args ); + } + } else if ( deferred !== firstParam ) { + deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); + } + return deferred.promise(); + }; +jQuery.Event.prototype.isDefaultPrevented = function returnFalse() { +/// +/// Returns whether event.preventDefault() was ever called on this event object. +/// +/// + + return false; +}; +jQuery.Event.prototype.isImmediatePropagationStopped = function returnFalse() { +/// +/// Returns whether event.stopImmediatePropagation() was ever called on this event object. +/// +/// + + return false; +}; +jQuery.Event.prototype.isPropagationStopped = function returnFalse() { +/// +/// Returns whether event.stopPropagation() was ever called on this event object. +/// +/// + + return false; +}; +jQuery.Event.prototype.preventDefault = function() { +/// +/// If this method is called, the default action of the event will not be triggered. +/// +/// + + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // otherwise set the returnValue property of the original event to false (IE) + } else { + e.returnValue = false; + } + }; +jQuery.Event.prototype.stopImmediatePropagation = function() { +/// +/// Keeps the rest of the handlers from being executed and prevents the event from bubbling up the DOM tree. +/// + + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }; +jQuery.Event.prototype.stopPropagation = function() { +/// +/// Prevents the event from bubbling up the DOM tree, preventing any parent handlers from being notified of the event. +/// + + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }; +jQuery.prototype._toggle = function( fn ) { + + // Save reference to arguments for access in closure + var args = arguments, + guid = fn.guid || jQuery.guid++, + i = 0, + toggler = function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + }; + + // link all the functions, so any of them can unbind this click handler + toggler.guid = guid; + while ( i < args.length ) { + args[ i++ ].guid = guid; + } + + return this.click( toggler ); + }; +jQuery.prototype.add = function( selector, context ) { +/// +/// Add elements to the set of matched elements. +/// 1 - add(selector) +/// 2 - add(elements) +/// 3 - add(html) +/// 4 - add(jQuery object) +/// 5 - add(selector, context) +/// +/// +/// A string representing a selector expression to find additional elements to add to the set of matched elements. +/// +/// +/// The point in the document at which the selector should begin matching; similar to the context argument of the $(selector, context) method. +/// +/// + + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }; +jQuery.prototype.addClass = function( value ) { +/// +/// Adds the specified class(es) to each of the set of matched elements. +/// 1 - addClass(className) +/// 2 - addClass(function(index, currentClass)) +/// +/// +/// One or more class names to be added to the class attribute of each matched element. +/// +/// + + var classNames, i, l, elem, + setClass, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call(this, j, this.className) ); + }); + } + + if ( value && typeof value === "string" ) { + classNames = value.split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className && classNames.length === 1 ) { + elem.className = value; + + } else { + setClass = " " + elem.className + " "; + + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { + setClass += classNames[ c ] + " "; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }; +jQuery.prototype.after = function() { +/// +/// Insert content, specified by the parameter, after each element in the set of matched elements. +/// 1 - after(content, content) +/// 2 - after(function(index)) +/// +/// +/// HTML string, DOM element, or jQuery object to insert after each element in the set of matched elements. +/// +/// +/// One or more additional DOM elements, arrays of elements, HTML strings, or jQuery objects to insert after each element in the set of matched elements. +/// +/// + + if ( this[0] && this[0].parentNode ) { + return this.domManip(arguments, false, function( elem ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + }); + } else if ( arguments.length ) { + var set = this.pushStack( this, "after", arguments ); + set.push.apply( set, jQuery(arguments[0]).toArray() ); + return set; + } + }; +jQuery.prototype.ajaxComplete = function( f ){ +/// +/// Register a handler to be called when Ajax requests complete. This is an Ajax Event. +/// +/// +/// The function to be invoked. +/// +/// + + return this.bind( o, f ); + }; +jQuery.prototype.ajaxError = function( f ){ +/// +/// Register a handler to be called when Ajax requests complete with an error. This is an Ajax Event. +/// +/// +/// The function to be invoked. +/// +/// + + return this.bind( o, f ); + }; +jQuery.prototype.ajaxSend = function( f ){ +/// +/// Attach a function to be executed before an Ajax request is sent. This is an Ajax Event. +/// +/// +/// The function to be invoked. +/// +/// + + return this.bind( o, f ); + }; +jQuery.prototype.ajaxStart = function( f ){ +/// +/// Register a handler to be called when the first Ajax request begins. This is an Ajax Event. +/// +/// +/// The function to be invoked. +/// +/// + + return this.bind( o, f ); + }; +jQuery.prototype.ajaxStop = function( f ){ +/// +/// Register a handler to be called when all Ajax requests have completed. This is an Ajax Event. +/// +/// +/// The function to be invoked. +/// +/// + + return this.bind( o, f ); + }; +jQuery.prototype.ajaxSuccess = function( f ){ +/// +/// Attach a function to be executed whenever an Ajax request completes successfully. This is an Ajax Event. +/// +/// +/// The function to be invoked. +/// +/// + + return this.bind( o, f ); + }; +jQuery.prototype.andSelf = function() { +/// +/// Add the previous set of elements on the stack to the current set. +/// +/// + + return this.add( this.prevObject ); + }; +jQuery.prototype.animate = function( prop, speed, easing, callback ) { +/// +/// Perform a custom animation of a set of CSS properties. +/// 1 - animate(properties, duration, easing, complete) +/// 2 - animate(properties, options) +/// +/// +/// A map of CSS properties that the animation will move toward. +/// +/// +/// A string or number determining how long the animation will run. +/// +/// +/// A string indicating which easing function to use for the transition. +/// +/// +/// A function to call once the animation is complete. +/// +/// + + var optall = jQuery.speed(speed, easing, callback); + + if ( jQuery.isEmptyObject( prop ) ) { + return this.each( optall.complete, [ false ] ); + } + + // Do not change referenced properties as per-property easing will be lost + prop = jQuery.extend( {}, prop ); + + return this[ optall.queue === false ? "each" : "queue" ](function() { + // XXX 'this' does not always have a nodeName when running the + // test suite + + if ( optall.queue === false ) { + jQuery._mark( this ); + } + + var opt = jQuery.extend( {}, optall ), + isElement = this.nodeType === 1, + hidden = isElement && jQuery(this).is(":hidden"), + name, val, p, + display, e, + parts, start, end, unit; + + // will store per property easing and be used to determine when an animation is complete + opt.animatedProperties = {}; + + for ( p in prop ) { + + // property name normalization + name = jQuery.camelCase( p ); + if ( p !== name ) { + prop[ name ] = prop[ p ]; + delete prop[ p ]; + } + + val = prop[ name ]; + + // easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default) + if ( jQuery.isArray( val ) ) { + opt.animatedProperties[ name ] = val[ 1 ]; + val = prop[ name ] = val[ 0 ]; + } else { + opt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing'; + } + + if ( val === "hide" && hidden || val === "show" && !hidden ) { + return opt.complete.call( this ); + } + + if ( isElement && ( name === "height" || name === "width" ) ) { + // Make sure that nothing sneaks out + // Record all 3 overflow attributes because IE does not + // change the overflow attribute when overflowX and + // overflowY are set to the same value + opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ]; + + // Set display property to inline-block for height/width + // animations on inline elements that are having width/height + // animated + if ( jQuery.css( this, "display" ) === "inline" && + jQuery.css( this, "float" ) === "none" ) { + if ( !jQuery.support.inlineBlockNeedsLayout ) { + this.style.display = "inline-block"; + + } else { + display = defaultDisplay( this.nodeName ); + + // inline-level elements accept inline-block; + // block-level elements need to be inline with layout + if ( display === "inline" ) { + this.style.display = "inline-block"; + + } else { + this.style.display = "inline"; + this.style.zoom = 1; + } + } + } + } + } + + if ( opt.overflow != null ) { + this.style.overflow = "hidden"; + } + + for ( p in prop ) { + e = new jQuery.fx( this, opt, p ); + val = prop[ p ]; + + if ( rfxtypes.test(val) ) { + e[ val === "toggle" ? hidden ? "show" : "hide" : val ](); + + } else { + parts = rfxnum.exec( val ); + start = e.cur(); + + if ( parts ) { + end = parseFloat( parts[2] ); + unit = parts[3] || ( jQuery.cssNumber[ p ] ? "" : "px" ); + + // We need to compute starting value + if ( unit !== "px" ) { + jQuery.style( this, p, (end || 1) + unit); + start = ((end || 1) / e.cur()) * start; + jQuery.style( this, p, start + unit); + } + + // If a +=/-= token was provided, we're doing a relative animation + if ( parts[1] ) { + end = ( (parts[ 1 ] === "-=" ? -1 : 1) * end ) + start; + } + + e.custom( start, end, unit ); + + } else { + e.custom( start, val, "" ); + } + } + } + + // For JS strict compliance + return true; + }); + }; +jQuery.prototype.append = function() { +/// +/// Insert content, specified by the parameter, to the end of each element in the set of matched elements. +/// 1 - append(content, content) +/// 2 - append(function(index, html)) +/// +/// +/// DOM element, HTML string, or jQuery object to insert at the end of each element in the set of matched elements. +/// +/// +/// One or more additional DOM elements, arrays of elements, HTML strings, or jQuery objects to insert at the end of each element in the set of matched elements. +/// +/// + + return this.domManip(arguments, true, function( elem ) { + if ( this.nodeType === 1 ) { + this.appendChild( elem ); + } + }); + }; +jQuery.prototype.appendTo = function( selector ) { +/// +/// Insert every element in the set of matched elements to the end of the target. +/// +/// +/// A selector, element, HTML string, or jQuery object; the matched set of elements will be inserted at the end of the element(s) specified by this parameter. +/// +/// + + var ret = [], + insert = jQuery( selector ), + parent = this.length === 1 && this[0].parentNode; + + if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) { + insert[ original ]( this[0] ); + return this; + + } else { + for ( var i = 0, l = insert.length; i < l; i++ ) { + var elems = (i > 0 ? this.clone(true) : this).get(); + jQuery( insert[i] )[ original ]( elems ); + ret = ret.concat( elems ); + } + + return this.pushStack( ret, name, insert.selector ); + } + }; +jQuery.prototype.attr = function( name, value ) { +/// +/// 1: Get the value of an attribute for the first element in the set of matched elements. +/// 1.1 - attr(attributeName) +/// 2: Set one or more attributes for the set of matched elements. +/// 2.1 - attr(attributeName, value) +/// 2.2 - attr(map) +/// 2.3 - attr(attributeName, function(index, attr)) +/// +/// +/// The name of the attribute to set. +/// +/// +/// A value to set for the attribute. +/// +/// + + return jQuery.access( this, name, value, true, jQuery.attr ); + }; +jQuery.prototype.before = function() { +/// +/// Insert content, specified by the parameter, before each element in the set of matched elements. +/// 1 - before(content, content) +/// 2 - before(function) +/// +/// +/// HTML string, DOM element, or jQuery object to insert before each element in the set of matched elements. +/// +/// +/// One or more additional DOM elements, arrays of elements, HTML strings, or jQuery objects to insert before each element in the set of matched elements. +/// +/// + + if ( this[0] && this[0].parentNode ) { + return this.domManip(arguments, false, function( elem ) { + this.parentNode.insertBefore( elem, this ); + }); + } else if ( arguments.length ) { + var set = jQuery(arguments[0]); + set.push.apply( set, this.toArray() ); + return this.pushStack( set, "before", arguments ); + } + }; +jQuery.prototype.bind = function( type, data, fn ) { +/// +/// Attach a handler to an event for the elements. +/// 1 - bind(eventType, eventData, handler(eventObject)) +/// 2 - bind(eventType, eventData, preventBubble) +/// 3 - bind(events) +/// +/// +/// A string containing one or more JavaScript event types, such as "click" or "submit," or custom event names. +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + var handler; + + // Handle object literals + if ( typeof type === "object" ) { + for ( var key in type ) { + this[ name ](key, data, type[key], fn); + } + return this; + } + + if ( arguments.length === 2 || data === false ) { + fn = data; + data = undefined; + } + + if ( name === "one" ) { + handler = function( event ) { + jQuery( this ).unbind( event, handler ); + return fn.apply( this, arguments ); + }; + handler.guid = fn.guid || jQuery.guid++; + } else { + handler = fn; + } + + if ( type === "unload" && name !== "one" ) { + this.one( type, data, fn ); + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.add( this[i], type, handler, data ); + } + } + + return this; + }; +jQuery.prototype.blur = function( data, fn ) { +/// +/// Bind an event handler to the "blur" JavaScript event, or trigger that event on an element. +/// 1 - blur(handler(eventObject)) +/// 2 - blur(eventData, handler(eventObject)) +/// 3 - blur() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.change = function( data, fn ) { +/// +/// Bind an event handler to the "change" JavaScript event, or trigger that event on an element. +/// 1 - change(handler(eventObject)) +/// 2 - change(eventData, handler(eventObject)) +/// 3 - change() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.children = function( until, selector ) { +/// +/// Get the children of each element in the set of matched elements, optionally filtered by a selector. +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + var ret = jQuery.map( this, fn, until ), + // The variable 'args' was introduced in + // https://github.com/jquery/jquery/commit/52a0238 + // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. + // http://code.google.com/p/v8/issues/detail?id=1050 + args = slice.call(arguments); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, args.join(",") ); + }; +jQuery.prototype.clearQueue = function( type ) { +/// +/// Remove from the queue all items that have not yet been run. +/// +/// +/// A string containing the name of the queue. Defaults to fx, the standard effects queue. +/// +/// + + return this.queue( type || "fx", [] ); + }; +jQuery.prototype.click = function( data, fn ) { +/// +/// Bind an event handler to the "click" JavaScript event, or trigger that event on an element. +/// 1 - click(handler(eventObject)) +/// 2 - click(eventData, handler(eventObject)) +/// 3 - click() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.clone = function( dataAndEvents, deepDataAndEvents ) { +/// +/// Create a deep copy of the set of matched elements. +/// 1 - clone(withDataAndEvents) +/// 2 - clone(withDataAndEvents, deepWithDataAndEvents) +/// +/// +/// A Boolean indicating whether event handlers and data should be copied along with the elements. The default value is false. *In jQuery 1.5.0 the default value was incorrectly true; it was changed back to false in 1.5.1 and up. +/// +/// +/// A Boolean indicating whether event handlers and data for all children of the cloned element should be copied. By default its value matches the first argument's value (which defaults to false). +/// +/// + + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function () { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + }); + }; +jQuery.prototype.closest = function( selectors, context ) { +/// +/// 1: Get the first ancestor element that matches the selector, beginning at the current element and progressing up through the DOM tree. +/// 1.1 - closest(selector) +/// 1.2 - closest(selector, context) +/// 1.3 - closest(jQuery object) +/// 1.4 - closest(element) +/// 2: Gets an array of all the elements and selectors matched against the current element up through the DOM tree. +/// 2.1 - closest(selectors, context) +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// +/// A DOM element within which a matching element may be found. If no context is passed in then the context of the jQuery set will be used instead. +/// +/// + + var ret = [], i, l, cur = this[0]; + + // Array + if ( jQuery.isArray( selectors ) ) { + var match, selector, + matches = {}, + level = 1; + + if ( cur && selectors.length ) { + for ( i = 0, l = selectors.length; i < l; i++ ) { + selector = selectors[i]; + + if ( !matches[ selector ] ) { + matches[ selector ] = POS.test( selector ) ? + jQuery( selector, context || this.context ) : + selector; + } + } + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( selector in matches ) { + match = matches[ selector ]; + + if ( match.jquery ? match.index( cur ) > -1 : jQuery( cur ).is( match ) ) { + ret.push({ selector: selector, elem: cur, level: level }); + } + } + + cur = cur.parentNode; + level++; + } + } + + return ret; + } + + // String + var pos = POS.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( i = 0, l = this.length; i < l; i++ ) { + cur = this[i]; + + while ( cur ) { + if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + + } else { + cur = cur.parentNode; + if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { + break; + } + } + } + } + + ret = ret.length > 1 ? jQuery.unique( ret ) : ret; + + return this.pushStack( ret, "closest", selectors ); + }; +jQuery.prototype.constructor = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }; +jQuery.prototype.contents = function( until, selector ) { +/// +/// Get the children of each element in the set of matched elements, including text and comment nodes. +/// +/// + + var ret = jQuery.map( this, fn, until ), + // The variable 'args' was introduced in + // https://github.com/jquery/jquery/commit/52a0238 + // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. + // http://code.google.com/p/v8/issues/detail?id=1050 + args = slice.call(arguments); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, args.join(",") ); + }; +jQuery.prototype.css = function( name, value ) { +/// +/// 1: Get the value of a style property for the first element in the set of matched elements. +/// 1.1 - css(propertyName) +/// 2: Set one or more CSS properties for the set of matched elements. +/// 2.1 - css(propertyName, value) +/// 2.2 - css(propertyName, function(index, value)) +/// 2.3 - css(map) +/// +/// +/// A CSS property name. +/// +/// +/// A value to set for the property. +/// +/// + + // Setting 'undefined' is a no-op + if ( arguments.length === 2 && value === undefined ) { + return this; + } + + return jQuery.access( this, name, value, true, function( elem, name, value ) { + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }); +}; +jQuery.prototype.data = function( key, value ) { +/// +/// 1: Store arbitrary data associated with the matched elements. +/// 1.1 - data(key, value) +/// 1.2 - data(obj) +/// 2: Returns value at named data store for the first element in the jQuery collection, as set by data(name, value). +/// 2.1 - data(key) +/// 2.2 - data() +/// +/// +/// A string naming the piece of data to set. +/// +/// +/// The new data value; it can be any Javascript type including Array or Object. +/// +/// + + var data = null; + + if ( typeof key === "undefined" ) { + if ( this.length ) { + data = jQuery.data( this[0] ); + + if ( this[0].nodeType === 1 ) { + var attr = this[0].attributes, name; + for ( var i = 0, l = attr.length; i < l; i++ ) { + name = attr[i].name; + + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.substring(5) ); + + dataAttr( this[0], name, data[ name ] ); + } + } + } + } + + return data; + + } else if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + var parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value === undefined ) { + data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + // Try to fetch any internally stored data first + if ( data === undefined && this.length ) { + data = jQuery.data( this[0], key ); + data = dataAttr( this[0], key, data ); + } + + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + + } else { + return this.each(function() { + var $this = jQuery( this ), + args = [ parts[0], value ]; + + $this.triggerHandler( "setData" + parts[1] + "!", args ); + jQuery.data( this, key, value ); + $this.triggerHandler( "changeData" + parts[1] + "!", args ); + }); + } + }; +jQuery.prototype.dblclick = function( data, fn ) { +/// +/// Bind an event handler to the "dblclick" JavaScript event, or trigger that event on an element. +/// 1 - dblclick(handler(eventObject)) +/// 2 - dblclick(eventData, handler(eventObject)) +/// 3 - dblclick() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.delay = function( time, type ) { +/// +/// Set a timer to delay execution of subsequent items in the queue. +/// +/// +/// An integer indicating the number of milliseconds to delay execution of the next item in the queue. +/// +/// +/// A string containing the name of the queue. Defaults to fx, the standard effects queue. +/// +/// + + time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; + type = type || "fx"; + + return this.queue( type, function() { + var elem = this; + setTimeout(function() { + jQuery.dequeue( elem, type ); + }, time ); + }); + }; +jQuery.prototype.delegate = function( selector, types, data, fn ) { +/// +/// Attach a handler to one or more events for all elements that match the selector, now or in the future, based on a specific set of root elements. +/// 1 - delegate(selector, eventType, handler) +/// 2 - delegate(selector, eventType, eventData, handler) +/// 3 - delegate(selector, events) +/// +/// +/// A selector to filter the elements that trigger the event. +/// +/// +/// A string containing one or more space-separated JavaScript event types, such as "click" or "keydown," or custom event names. +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute at the time the event is triggered. +/// +/// + + return this.live( types, data, fn, selector ); + }; +jQuery.prototype.dequeue = function( type ) { +/// +/// Execute the next function on the queue for the matched elements. +/// +/// +/// A string containing the name of the queue. Defaults to fx, the standard effects queue. +/// +/// + + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }; +jQuery.prototype.detach = function( selector ) { +/// +/// Remove the set of matched elements from the DOM. +/// +/// +/// A selector expression that filters the set of matched elements to be removed. +/// +/// + + return this.remove( selector, true ); + }; +jQuery.prototype.die = function( types, data, fn, origSelector /* Internal Use Only */ ) { +/// +/// 1: Remove all event handlers previously attached using .live() from the elements. +/// 1.1 - die() +/// 2: Remove an event handler previously attached using .live() from the elements. +/// 2.1 - die(eventType, handler) +/// 2.2 - die(eventTypes) +/// +/// +/// A string containing a JavaScript event type, such as click or keydown. +/// +/// +/// The function that is no longer to be executed. +/// +/// + + var type, i = 0, match, namespaces, preType, + selector = origSelector || this.selector, + context = origSelector ? this : jQuery( this.context ); + + if ( typeof types === "object" && !types.preventDefault ) { + for ( var key in types ) { + context[ name ]( key, data, types[key], selector ); + } + + return this; + } + + if ( name === "die" && !types && + origSelector && origSelector.charAt(0) === "." ) { + + context.unbind( origSelector ); + + return this; + } + + if ( data === false || jQuery.isFunction( data ) ) { + fn = data || returnFalse; + data = undefined; + } + + types = (types || "").split(" "); + + while ( (type = types[ i++ ]) != null ) { + match = rnamespaces.exec( type ); + namespaces = ""; + + if ( match ) { + namespaces = match[0]; + type = type.replace( rnamespaces, "" ); + } + + if ( type === "hover" ) { + types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); + continue; + } + + preType = type; + + if ( liveMap[ type ] ) { + types.push( liveMap[ type ] + namespaces ); + type = type + namespaces; + + } else { + type = (liveMap[ type ] || type) + namespaces; + } + + if ( name === "live" ) { + // bind live handler + for ( var j = 0, l = context.length; j < l; j++ ) { + jQuery.event.add( context[j], "live." + liveConvert( type, selector ), + { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); + } + + } else { + // unbind live handler + context.unbind( "live." + liveConvert( type, selector ), fn ); + } + } + + return this; + }; +jQuery.prototype.domManip = function( args, table, callback ) { + + var results, first, fragment, parent, + value = args[0], + scripts = []; + + // We can't cloneNode fragments that contain checked, in WebKit + if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) { + return this.each(function() { + jQuery(this).domManip( args, table, callback, true ); + }); + } + + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + args[0] = value.call(this, i, table ? self.html() : undefined); + self.domManip( args, table, callback ); + }); + } + + if ( this[0] ) { + parent = value && value.parentNode; + + // If we're in a fragment, just use that instead of building a new one + if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) { + results = { fragment: parent }; + + } else { + results = jQuery.buildFragment( args, this, scripts ); + } + + fragment = results.fragment; + + if ( fragment.childNodes.length === 1 ) { + first = fragment = fragment.firstChild; + } else { + first = fragment.firstChild; + } + + if ( first ) { + table = table && jQuery.nodeName( first, "tr" ); + + for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) { + callback.call( + table ? + root(this[i], first) : + this[i], + // Make sure that we do not leak memory by inadvertently discarding + // the original fragment (which might have attached data) instead of + // using it; in addition, use the original fragment object for the last + // item instead of first because it can end up being emptied incorrectly + // in certain situations (Bug #8070). + // Fragments from the fragment cache must always be cloned and never used + // in place. + results.cacheable || (l > 1 && i < lastIndex) ? + jQuery.clone( fragment, true, true ) : + fragment + ); + } + } + + if ( scripts.length ) { + jQuery.each( scripts, evalScript ); + } + } + + return this; + }; +jQuery.prototype.each = function( callback, args ) { +/// +/// Iterate over a jQuery object, executing a function for each matched element. +/// +/// +/// A function to execute for each matched element. +/// +/// + + return jQuery.each( this, callback, args ); + }; +jQuery.prototype.empty = function() { +/// +/// Remove all child nodes of the set of matched elements from the DOM. +/// +/// + + for ( var i = 0, elem; (elem = this[i]) != null; i++ ) { + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( elem.getElementsByTagName("*") ); + } + + // Remove any remaining nodes + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + } + + return this; + }; +jQuery.prototype.end = function() { +/// +/// End the most recent filtering operation in the current chain and return the set of matched elements to its previous state. +/// +/// + + return this.prevObject || this.constructor(null); + }; +jQuery.prototype.eq = function( i ) { +/// +/// Reduce the set of matched elements to the one at the specified index. +/// 1 - eq(index) +/// 2 - eq(-index) +/// +/// +/// An integer indicating the 0-based position of the element. +/// +/// + + return i === -1 ? + this.slice( i ) : + this.slice( i, +i + 1 ); + }; +jQuery.prototype.error = function( data, fn ) { +/// +/// Bind an event handler to the "error" JavaScript event. +/// 1 - error(handler(eventObject)) +/// 2 - error(eventData, handler(eventObject)) +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.extend = function() { + + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; +jQuery.prototype.fadeIn = function( speed, easing, callback ) { +/// +/// Display the matched elements by fading them to opaque. +/// 1 - fadeIn(duration, callback) +/// 2 - fadeIn(duration, easing, callback) +/// +/// +/// A string or number determining how long the animation will run. +/// +/// +/// A string indicating which easing function to use for the transition. +/// +/// +/// A function to call once the animation is complete. +/// +/// + + return this.animate( props, speed, easing, callback ); + }; +jQuery.prototype.fadeOut = function( speed, easing, callback ) { +/// +/// Hide the matched elements by fading them to transparent. +/// 1 - fadeOut(duration, callback) +/// 2 - fadeOut(duration, easing, callback) +/// +/// +/// A string or number determining how long the animation will run. +/// +/// +/// A string indicating which easing function to use for the transition. +/// +/// +/// A function to call once the animation is complete. +/// +/// + + return this.animate( props, speed, easing, callback ); + }; +jQuery.prototype.fadeTo = function( speed, to, easing, callback ) { +/// +/// Adjust the opacity of the matched elements. +/// 1 - fadeTo(duration, opacity, callback) +/// 2 - fadeTo(duration, opacity, easing, callback) +/// +/// +/// A string or number determining how long the animation will run. +/// +/// +/// A number between 0 and 1 denoting the target opacity. +/// +/// +/// A string indicating which easing function to use for the transition. +/// +/// +/// A function to call once the animation is complete. +/// +/// + + return this.filter(":hidden").css("opacity", 0).show().end() + .animate({opacity: to}, speed, easing, callback); + }; +jQuery.prototype.fadeToggle = function( speed, easing, callback ) { +/// +/// Display or hide the matched elements by animating their opacity. +/// +/// +/// A string or number determining how long the animation will run. +/// +/// +/// A string indicating which easing function to use for the transition. +/// +/// +/// A function to call once the animation is complete. +/// +/// + + return this.animate( props, speed, easing, callback ); + }; +jQuery.prototype.filter = function( selector ) { +/// +/// Reduce the set of matched elements to those that match the selector or pass the function's test. +/// 1 - filter(selector) +/// 2 - filter(function(index)) +/// 3 - filter(element) +/// 4 - filter(jQuery object) +/// +/// +/// A string containing a selector expression to match the current set of elements against. +/// +/// + + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }; +jQuery.prototype.find = function( selector ) { +/// +/// Get the descendants of each element in the current set of matched elements, filtered by a selector, jQuery object, or element. +/// 1 - find(selector) +/// 2 - find(jQuery object) +/// 3 - find(element) +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + var self = this, + i, l; + + if ( typeof selector !== "string" ) { + return jQuery( selector ).filter(function() { + for ( i = 0, l = self.length; i < l; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }); + } + + var ret = this.pushStack( "", "find", selector ), + length, n, r; + + for ( i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( n = length; n < ret.length; n++ ) { + for ( r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }; +jQuery.prototype.first = function() { +/// +/// Reduce the set of matched elements to the first in the set. +/// +/// + + return this.eq( 0 ); + }; +jQuery.prototype.focus = function( data, fn ) { +/// +/// Bind an event handler to the "focus" JavaScript event, or trigger that event on an element. +/// 1 - focus(handler(eventObject)) +/// 2 - focus(eventData, handler(eventObject)) +/// 3 - focus() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.focusin = function( data, fn ) { +/// +/// Bind an event handler to the "focusin" JavaScript event. +/// 1 - focusin(handler(eventObject)) +/// 2 - focusin(eventData, handler(eventObject)) +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.focusout = function( data, fn ) { +/// +/// Bind an event handler to the "focusout" JavaScript event. +/// 1 - focusout(handler(eventObject)) +/// 2 - focusout(eventData, handler(eventObject)) +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.get = function( num ) { +/// +/// Retrieve the DOM elements matched by the jQuery object. +/// +/// +/// A zero-based integer indicating which element to retrieve. +/// +/// + + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }; +jQuery.prototype.has = function( target ) { +/// +/// Reduce the set of matched elements to those that have a descendant that matches the selector or DOM element. +/// 1 - has(selector) +/// 2 - has(contained) +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }; +jQuery.prototype.hasClass = function( selector ) { +/// +/// Determine whether any of the matched elements are assigned the given class. +/// +/// +/// The class name to search for. +/// +/// + + var className = " " + selector + " "; + for ( var i = 0, l = this.length; i < l; i++ ) { + if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }; +jQuery.prototype.height = function( size ) { +/// +/// 1: Get the current computed height for the first element in the set of matched elements. +/// 1.1 - height() +/// 2: Set the CSS height of every matched element. +/// 2.1 - height(value) +/// 2.2 - height(function(index, height)) +/// +/// +/// An integer representing the number of pixels, or an integer with an optional unit of measure appended (as a string). +/// +/// + + // Get window width or height + var elem = this[0]; + if ( !elem ) { + return size == null ? null : this; + } + + if ( jQuery.isFunction( size ) ) { + return this.each(function( i ) { + var self = jQuery( this ); + self[ type ]( size.call( this, i, self[ type ]() ) ); + }); + } + + if ( jQuery.isWindow( elem ) ) { + // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode + // 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat + var docElemProp = elem.document.documentElement[ "client" + name ], + body = elem.document.body; + return elem.document.compatMode === "CSS1Compat" && docElemProp || + body && body[ "client" + name ] || docElemProp; + + // Get document width or height + } else if ( elem.nodeType === 9 ) { + // Either scroll[Width/Height] or offset[Width/Height], whichever is greater + return Math.max( + elem.documentElement["client" + name], + elem.body["scroll" + name], elem.documentElement["scroll" + name], + elem.body["offset" + name], elem.documentElement["offset" + name] + ); + + // Get or set width or height on the element + } else if ( size === undefined ) { + var orig = jQuery.css( elem, type ), + ret = parseFloat( orig ); + + return jQuery.isNaN( ret ) ? orig : ret; + + // Set the width or height on the element (default to pixels if value is unitless) + } else { + return this.css( type, typeof size === "string" ? size : size + "px" ); + } + }; +jQuery.prototype.hide = function( speed, easing, callback ) { +/// +/// Hide the matched elements. +/// 1 - hide() +/// 2 - hide(duration, callback) +/// 3 - hide(duration, easing, callback) +/// +/// +/// A string or number determining how long the animation will run. +/// +/// +/// A string indicating which easing function to use for the transition. +/// +/// +/// A function to call once the animation is complete. +/// +/// + + if ( speed || speed === 0 ) { + return this.animate( genFx("hide", 3), speed, easing, callback); + + } else { + for ( var i = 0, j = this.length; i < j; i++ ) { + if ( this[i].style ) { + var display = jQuery.css( this[i], "display" ); + + if ( display !== "none" && !jQuery._data( this[i], "olddisplay" ) ) { + jQuery._data( this[i], "olddisplay", display ); + } + } + } + + // Set the display of the elements in a second loop + // to avoid the constant reflow + for ( i = 0; i < j; i++ ) { + if ( this[i].style ) { + this[i].style.display = "none"; + } + } + + return this; + } + }; +jQuery.prototype.hover = function( fnOver, fnOut ) { +/// +/// 1: Bind two handlers to the matched elements, to be executed when the mouse pointer enters and leaves the elements. +/// 1.1 - hover(handlerIn(eventObject), handlerOut(eventObject)) +/// 2: Bind a single handler to the matched elements, to be executed when the mouse pointer enters or leaves the elements. +/// 2.1 - hover(handlerInOut(eventObject)) +/// +/// +/// A function to execute when the mouse pointer enters the element. +/// +/// +/// A function to execute when the mouse pointer leaves the element. +/// +/// + + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + }; +jQuery.prototype.html = function( value ) { +/// +/// 1: Get the HTML contents of the first element in the set of matched elements. +/// 1.1 - html() +/// 2: Set the HTML contents of each element in the set of matched elements. +/// 2.1 - html(htmlString) +/// 2.2 - html(function(index, oldhtml)) +/// +/// +/// A string of HTML to set as the content of each matched element. +/// +/// + + if ( value === undefined ) { + return this[0] && this[0].nodeType === 1 ? + this[0].innerHTML.replace(rinlinejQuery, "") : + null; + + // See if we can take a shortcut and just use innerHTML + } else if ( typeof value === "string" && !rnocache.test( value ) && + (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) && + !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) { + + value = value.replace(rxhtmlTag, "<$1>"); + + try { + for ( var i = 0, l = this.length; i < l; i++ ) { + // Remove element nodes and prevent memory leaks + if ( this[i].nodeType === 1 ) { + jQuery.cleanData( this[i].getElementsByTagName("*") ); + this[i].innerHTML = value; + } + } + + // If using innerHTML throws an exception, use the fallback method + } catch(e) { + this.empty().append( value ); + } + + } else if ( jQuery.isFunction( value ) ) { + this.each(function(i){ + var self = jQuery( this ); + + self.html( value.call(this, i, self.html()) ); + }); + + } else { + this.empty().append( value ); + } + + return this; + }; +jQuery.prototype.index = function( elem ) { +/// +/// Search for a given element from among the matched elements. +/// 1 - index() +/// 2 - index(selector) +/// 3 - index(element) +/// +/// +/// A selector representing a jQuery collection in which to look for an element. +/// +/// + + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }; +jQuery.prototype.init = function( selector, context, rootjQuery ) { + + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context && document.body ) { + this.context = document; + this[0] = document.body; + this.selector = selector; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = quickExpr.exec( selector ); + } + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + doc = (context ? context.ownerDocument || context : document); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return (context || rootjQuery).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if (selector.selector !== undefined) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }; +jQuery.prototype.innerHeight = function() { +/// +/// Get the current computed height for the first element in the set of matched elements, including padding but not border. +/// +/// + + var elem = this[0]; + return elem && elem.style ? + parseFloat( jQuery.css( elem, type, "padding" ) ) : + null; + }; +jQuery.prototype.innerWidth = function() { +/// +/// Get the current computed width for the first element in the set of matched elements, including padding but not border. +/// +/// + + var elem = this[0]; + return elem && elem.style ? + parseFloat( jQuery.css( elem, type, "padding" ) ) : + null; + }; +jQuery.prototype.insertAfter = function( selector ) { +/// +/// Insert every element in the set of matched elements after the target. +/// +/// +/// A selector, element, HTML string, or jQuery object; the matched set of elements will be inserted after the element(s) specified by this parameter. +/// +/// + + var ret = [], + insert = jQuery( selector ), + parent = this.length === 1 && this[0].parentNode; + + if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) { + insert[ original ]( this[0] ); + return this; + + } else { + for ( var i = 0, l = insert.length; i < l; i++ ) { + var elems = (i > 0 ? this.clone(true) : this).get(); + jQuery( insert[i] )[ original ]( elems ); + ret = ret.concat( elems ); + } + + return this.pushStack( ret, name, insert.selector ); + } + }; +jQuery.prototype.insertBefore = function( selector ) { +/// +/// Insert every element in the set of matched elements before the target. +/// +/// +/// A selector, element, HTML string, or jQuery object; the matched set of elements will be inserted before the element(s) specified by this parameter. +/// +/// + + var ret = [], + insert = jQuery( selector ), + parent = this.length === 1 && this[0].parentNode; + + if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) { + insert[ original ]( this[0] ); + return this; + + } else { + for ( var i = 0, l = insert.length; i < l; i++ ) { + var elems = (i > 0 ? this.clone(true) : this).get(); + jQuery( insert[i] )[ original ]( elems ); + ret = ret.concat( elems ); + } + + return this.pushStack( ret, name, insert.selector ); + } + }; +jQuery.prototype.is = function( selector ) { +/// +/// Check the current matched set of elements against a selector, element, or jQuery object and return true if at least one of these elements matches the given arguments. +/// 1 - is(selector) +/// 2 - is(function(index)) +/// 3 - is(jQuery object) +/// 4 - is(element) +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + return !!selector && ( typeof selector === "string" ? + jQuery.filter( selector, this ).length > 0 : + this.filter( selector ).length > 0 ); + }; +jQuery.prototype.keydown = function( data, fn ) { +/// +/// Bind an event handler to the "keydown" JavaScript event, or trigger that event on an element. +/// 1 - keydown(handler(eventObject)) +/// 2 - keydown(eventData, handler(eventObject)) +/// 3 - keydown() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.keypress = function( data, fn ) { +/// +/// Bind an event handler to the "keypress" JavaScript event, or trigger that event on an element. +/// 1 - keypress(handler(eventObject)) +/// 2 - keypress(eventData, handler(eventObject)) +/// 3 - keypress() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.keyup = function( data, fn ) { +/// +/// Bind an event handler to the "keyup" JavaScript event, or trigger that event on an element. +/// 1 - keyup(handler(eventObject)) +/// 2 - keyup(eventData, handler(eventObject)) +/// 3 - keyup() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.last = function() { +/// +/// Reduce the set of matched elements to the final one in the set. +/// +/// + + return this.eq( -1 ); + }; +jQuery.prototype.length = 0; +jQuery.prototype.live = function( types, data, fn, origSelector /* Internal Use Only */ ) { +/// +/// Attach a handler to the event for all elements which match the current selector, now and in the future. +/// 1 - live(eventType, handler) +/// 2 - live(eventType, eventData, handler) +/// 3 - live(events) +/// +/// +/// A string containing a JavaScript event type, such as "click" or "keydown." As of jQuery 1.4 the string can contain multiple, space-separated event types or custom event names, as well. +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute at the time the event is triggered. +/// +/// + + var type, i = 0, match, namespaces, preType, + selector = origSelector || this.selector, + context = origSelector ? this : jQuery( this.context ); + + if ( typeof types === "object" && !types.preventDefault ) { + for ( var key in types ) { + context[ name ]( key, data, types[key], selector ); + } + + return this; + } + + if ( name === "die" && !types && + origSelector && origSelector.charAt(0) === "." ) { + + context.unbind( origSelector ); + + return this; + } + + if ( data === false || jQuery.isFunction( data ) ) { + fn = data || returnFalse; + data = undefined; + } + + types = (types || "").split(" "); + + while ( (type = types[ i++ ]) != null ) { + match = rnamespaces.exec( type ); + namespaces = ""; + + if ( match ) { + namespaces = match[0]; + type = type.replace( rnamespaces, "" ); + } + + if ( type === "hover" ) { + types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); + continue; + } + + preType = type; + + if ( liveMap[ type ] ) { + types.push( liveMap[ type ] + namespaces ); + type = type + namespaces; + + } else { + type = (liveMap[ type ] || type) + namespaces; + } + + if ( name === "live" ) { + // bind live handler + for ( var j = 0, l = context.length; j < l; j++ ) { + jQuery.event.add( context[j], "live." + liveConvert( type, selector ), + { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); + } + + } else { + // unbind live handler + context.unbind( "live." + liveConvert( type, selector ), fn ); + } + } + + return this; + }; +jQuery.prototype.load = function( url, params, callback ) { +/// +/// 1: Bind an event handler to the "load" JavaScript event. +/// 1.1 - load(handler(eventObject)) +/// 1.2 - load(eventData, handler(eventObject)) +/// 2: Load data from the server and place the returned HTML into the matched element. +/// 2.1 - load(url, data, complete(responseText, textStatus, XMLHttpRequest)) +/// +/// +/// A string containing the URL to which the request is sent. +/// +/// +/// A map or string that is sent to the server with the request. +/// +/// +/// A callback function that is executed when the request completes. +/// +/// + + if ( typeof url !== "string" && _load ) { + return _load.apply( this, arguments ); + + // Don't do a request if no elements are being requested + } else if ( !this.length ) { + return this; + } + + var off = url.indexOf( " " ); + if ( off >= 0 ) { + var selector = url.slice( off, url.length ); + url = url.slice( 0, off ); + } + + // Default to a GET request + var type = "GET"; + + // If the second parameter was provided + if ( params ) { + // If it's a function + if ( jQuery.isFunction( params ) ) { + // We assume that it's the callback + callback = params; + params = undefined; + + // Otherwise, build a param string + } else if ( typeof params === "object" ) { + params = jQuery.param( params, jQuery.ajaxSettings.traditional ); + type = "POST"; + } + } + + var self = this; + + // Request the remote document + jQuery.ajax({ + url: url, + type: type, + dataType: "html", + data: params, + // Complete callback (responseText is used internally) + complete: function( jqXHR, status, responseText ) { + // Store the response as specified by the jqXHR object + responseText = jqXHR.responseText; + // If successful, inject the HTML into all the matched elements + if ( jqXHR.isResolved() ) { + // #4825: Get the actual response in case + // a dataFilter is present in ajaxSettings + jqXHR.done(function( r ) { + responseText = r; + }); + // See if a selector was specified + self.html( selector ? + // Create a dummy div to hold the results + jQuery("
") + // inject the contents of the document in, removing the scripts + // to avoid any 'Permission Denied' errors in IE + .append(responseText.replace(rscript, "")) + + // Locate the specified elements + .find(selector) : + + // If not, just inject the full result + responseText ); + } + + if ( callback ) { + self.each( callback, [ responseText, status, jqXHR ] ); + } + } + }); + + return this; + }; +jQuery.prototype.map = function( callback ) { +/// +/// Pass each element in the current matched set through a function, producing a new jQuery object containing the return values. +/// +/// +/// A function object that will be invoked for each element in the current set. +/// +/// + + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }; +jQuery.prototype.mousedown = function( data, fn ) { +/// +/// Bind an event handler to the "mousedown" JavaScript event, or trigger that event on an element. +/// 1 - mousedown(handler(eventObject)) +/// 2 - mousedown(eventData, handler(eventObject)) +/// 3 - mousedown() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.mouseenter = function( data, fn ) { +/// +/// Bind an event handler to be fired when the mouse enters an element, or trigger that handler on an element. +/// 1 - mouseenter(handler(eventObject)) +/// 2 - mouseenter(eventData, handler(eventObject)) +/// 3 - mouseenter() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.mouseleave = function( data, fn ) { +/// +/// Bind an event handler to be fired when the mouse leaves an element, or trigger that handler on an element. +/// 1 - mouseleave(handler(eventObject)) +/// 2 - mouseleave(eventData, handler(eventObject)) +/// 3 - mouseleave() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.mousemove = function( data, fn ) { +/// +/// Bind an event handler to the "mousemove" JavaScript event, or trigger that event on an element. +/// 1 - mousemove(handler(eventObject)) +/// 2 - mousemove(eventData, handler(eventObject)) +/// 3 - mousemove() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.mouseout = function( data, fn ) { +/// +/// Bind an event handler to the "mouseout" JavaScript event, or trigger that event on an element. +/// 1 - mouseout(handler(eventObject)) +/// 2 - mouseout(eventData, handler(eventObject)) +/// 3 - mouseout() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.mouseover = function( data, fn ) { +/// +/// Bind an event handler to the "mouseover" JavaScript event, or trigger that event on an element. +/// 1 - mouseover(handler(eventObject)) +/// 2 - mouseover(eventData, handler(eventObject)) +/// 3 - mouseover() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.mouseup = function( data, fn ) { +/// +/// Bind an event handler to the "mouseup" JavaScript event, or trigger that event on an element. +/// 1 - mouseup(handler(eventObject)) +/// 2 - mouseup(eventData, handler(eventObject)) +/// 3 - mouseup() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.next = function( until, selector ) { +/// +/// Get the immediately following sibling of each element in the set of matched elements. If a selector is provided, it retrieves the next sibling only if it matches that selector. +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + var ret = jQuery.map( this, fn, until ), + // The variable 'args' was introduced in + // https://github.com/jquery/jquery/commit/52a0238 + // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. + // http://code.google.com/p/v8/issues/detail?id=1050 + args = slice.call(arguments); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, args.join(",") ); + }; +jQuery.prototype.nextAll = function( until, selector ) { +/// +/// Get all following siblings of each element in the set of matched elements, optionally filtered by a selector. +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + var ret = jQuery.map( this, fn, until ), + // The variable 'args' was introduced in + // https://github.com/jquery/jquery/commit/52a0238 + // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. + // http://code.google.com/p/v8/issues/detail?id=1050 + args = slice.call(arguments); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, args.join(",") ); + }; +jQuery.prototype.nextUntil = function( until, selector ) { +/// +/// Get all following siblings of each element up to but not including the element matched by the selector, DOM node, or jQuery object passed. +/// 1 - nextUntil(selector, filter) +/// 2 - nextUntil(element, filter) +/// +/// +/// A string containing a selector expression to indicate where to stop matching following sibling elements. +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + var ret = jQuery.map( this, fn, until ), + // The variable 'args' was introduced in + // https://github.com/jquery/jquery/commit/52a0238 + // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. + // http://code.google.com/p/v8/issues/detail?id=1050 + args = slice.call(arguments); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, args.join(",") ); + }; +jQuery.prototype.not = function( selector ) { +/// +/// Remove elements from the set of matched elements. +/// 1 - not(selector) +/// 2 - not(elements) +/// 3 - not(function(index)) +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + return this.pushStack( winnow(this, selector, false), "not", selector); + }; +jQuery.prototype.offset = function( options ) { +/// +/// 1: Get the current coordinates of the first element in the set of matched elements, relative to the document. +/// 1.1 - offset() +/// 2: Set the current coordinates of every element in the set of matched elements, relative to the document. +/// 2.1 - offset(coordinates) +/// 2.2 - offset(function(index, coords)) +/// +/// +/// An object containing the properties top and left, which are integers indicating the new top and left coordinates for the elements. +/// +/// + + var elem = this[0], box; + + if ( options ) { + return this.each(function( i ) { + jQuery.offset.setOffset( this, options, i ); + }); + } + + if ( !elem || !elem.ownerDocument ) { + return null; + } + + if ( elem === elem.ownerDocument.body ) { + return jQuery.offset.bodyOffset( elem ); + } + + try { + box = elem.getBoundingClientRect(); + } catch(e) {} + + var doc = elem.ownerDocument, + docElem = doc.documentElement; + + // Make sure we're not dealing with a disconnected DOM node + if ( !box || !jQuery.contains( docElem, elem ) ) { + return box ? { top: box.top, left: box.left } : { top: 0, left: 0 }; + } + + var body = doc.body, + win = getWindow(doc), + clientTop = docElem.clientTop || body.clientTop || 0, + clientLeft = docElem.clientLeft || body.clientLeft || 0, + scrollTop = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop, + scrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft, + top = box.top + scrollTop - clientTop, + left = box.left + scrollLeft - clientLeft; + + return { top: top, left: left }; + }; +jQuery.prototype.offsetParent = function() { +/// +/// Get the closest ancestor element that is positioned. +/// +/// + + return this.map(function() { + var offsetParent = this.offsetParent || document.body; + while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) { + offsetParent = offsetParent.offsetParent; + } + return offsetParent; + }); + }; +jQuery.prototype.one = function( type, data, fn ) { +/// +/// Attach a handler to an event for the elements. The handler is executed at most once per element. +/// +/// +/// A string containing one or more JavaScript event types, such as "click" or "submit," or custom event names. +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute at the time the event is triggered. +/// +/// + + var handler; + + // Handle object literals + if ( typeof type === "object" ) { + for ( var key in type ) { + this[ name ](key, data, type[key], fn); + } + return this; + } + + if ( arguments.length === 2 || data === false ) { + fn = data; + data = undefined; + } + + if ( name === "one" ) { + handler = function( event ) { + jQuery( this ).unbind( event, handler ); + return fn.apply( this, arguments ); + }; + handler.guid = fn.guid || jQuery.guid++; + } else { + handler = fn; + } + + if ( type === "unload" && name !== "one" ) { + this.one( type, data, fn ); + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.add( this[i], type, handler, data ); + } + } + + return this; + }; +jQuery.prototype.outerHeight = function( margin ) { +/// +/// Get the current computed height for the first element in the set of matched elements, including padding, border, and optionally margin. +/// +/// +/// A Boolean indicating whether to include the element's margin in the calculation. +/// +/// + + var elem = this[0]; + return elem && elem.style ? + parseFloat( jQuery.css( elem, type, margin ? "margin" : "border" ) ) : + null; + }; +jQuery.prototype.outerWidth = function( margin ) { +/// +/// Get the current computed width for the first element in the set of matched elements, including padding and border. +/// +/// +/// A Boolean indicating whether to include the element's margin in the calculation. +/// +/// + + var elem = this[0]; + return elem && elem.style ? + parseFloat( jQuery.css( elem, type, margin ? "margin" : "border" ) ) : + null; + }; +jQuery.prototype.parent = function( until, selector ) { +/// +/// Get the parent of each element in the current set of matched elements, optionally filtered by a selector. +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + var ret = jQuery.map( this, fn, until ), + // The variable 'args' was introduced in + // https://github.com/jquery/jquery/commit/52a0238 + // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. + // http://code.google.com/p/v8/issues/detail?id=1050 + args = slice.call(arguments); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, args.join(",") ); + }; +jQuery.prototype.parents = function( until, selector ) { +/// +/// Get the ancestors of each element in the current set of matched elements, optionally filtered by a selector. +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + var ret = jQuery.map( this, fn, until ), + // The variable 'args' was introduced in + // https://github.com/jquery/jquery/commit/52a0238 + // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. + // http://code.google.com/p/v8/issues/detail?id=1050 + args = slice.call(arguments); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, args.join(",") ); + }; +jQuery.prototype.parentsUntil = function( until, selector ) { +/// +/// Get the ancestors of each element in the current set of matched elements, up to but not including the element matched by the selector, DOM node, or jQuery object. +/// 1 - parentsUntil(selector, filter) +/// 2 - parentsUntil(element, filter) +/// +/// +/// A string containing a selector expression to indicate where to stop matching ancestor elements. +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + var ret = jQuery.map( this, fn, until ), + // The variable 'args' was introduced in + // https://github.com/jquery/jquery/commit/52a0238 + // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. + // http://code.google.com/p/v8/issues/detail?id=1050 + args = slice.call(arguments); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, args.join(",") ); + }; +jQuery.prototype.position = function() { +/// +/// Get the current coordinates of the first element in the set of matched elements, relative to the offset parent. +/// +/// + + if ( !this[0] ) { + return null; + } + + var elem = this[0], + + // Get *real* offsetParent + offsetParent = this.offsetParent(), + + // Get correct offsets + offset = this.offset(), + parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset(); + + // Subtract element margins + // note: when an element has margin: auto the offsetLeft and marginLeft + // are the same in Safari causing offset.left to incorrectly be 0 + offset.top -= parseFloat( jQuery.css(elem, "marginTop") ) || 0; + offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0; + + // Add offsetParent borders + parentOffset.top += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0; + parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0; + + // Subtract the two offsets + return { + top: offset.top - parentOffset.top, + left: offset.left - parentOffset.left + }; + }; +jQuery.prototype.prepend = function() { +/// +/// Insert content, specified by the parameter, to the beginning of each element in the set of matched elements. +/// 1 - prepend(content, content) +/// 2 - prepend(function(index, html)) +/// +/// +/// DOM element, array of elements, HTML string, or jQuery object to insert at the beginning of each element in the set of matched elements. +/// +/// +/// One or more additional DOM elements, arrays of elements, HTML strings, or jQuery objects to insert at the beginning of each element in the set of matched elements. +/// +/// + + return this.domManip(arguments, true, function( elem ) { + if ( this.nodeType === 1 ) { + this.insertBefore( elem, this.firstChild ); + } + }); + }; +jQuery.prototype.prependTo = function( selector ) { +/// +/// Insert every element in the set of matched elements to the beginning of the target. +/// +/// +/// A selector, element, HTML string, or jQuery object; the matched set of elements will be inserted at the beginning of the element(s) specified by this parameter. +/// +/// + + var ret = [], + insert = jQuery( selector ), + parent = this.length === 1 && this[0].parentNode; + + if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) { + insert[ original ]( this[0] ); + return this; + + } else { + for ( var i = 0, l = insert.length; i < l; i++ ) { + var elems = (i > 0 ? this.clone(true) : this).get(); + jQuery( insert[i] )[ original ]( elems ); + ret = ret.concat( elems ); + } + + return this.pushStack( ret, name, insert.selector ); + } + }; +jQuery.prototype.prev = function( until, selector ) { +/// +/// Get the immediately preceding sibling of each element in the set of matched elements, optionally filtered by a selector. +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + var ret = jQuery.map( this, fn, until ), + // The variable 'args' was introduced in + // https://github.com/jquery/jquery/commit/52a0238 + // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. + // http://code.google.com/p/v8/issues/detail?id=1050 + args = slice.call(arguments); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, args.join(",") ); + }; +jQuery.prototype.prevAll = function( until, selector ) { +/// +/// Get all preceding siblings of each element in the set of matched elements, optionally filtered by a selector. +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + var ret = jQuery.map( this, fn, until ), + // The variable 'args' was introduced in + // https://github.com/jquery/jquery/commit/52a0238 + // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. + // http://code.google.com/p/v8/issues/detail?id=1050 + args = slice.call(arguments); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, args.join(",") ); + }; +jQuery.prototype.prevUntil = function( until, selector ) { +/// +/// Get all preceding siblings of each element up to but not including the element matched by the selector, DOM node, or jQuery object. +/// 1 - prevUntil(selector, filter) +/// 2 - prevUntil(element, filter) +/// +/// +/// A string containing a selector expression to indicate where to stop matching preceding sibling elements. +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + var ret = jQuery.map( this, fn, until ), + // The variable 'args' was introduced in + // https://github.com/jquery/jquery/commit/52a0238 + // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. + // http://code.google.com/p/v8/issues/detail?id=1050 + args = slice.call(arguments); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, args.join(",") ); + }; +jQuery.prototype.promise = function( type, object ) { +/// +/// Return a Promise object to observe when all actions of a certain type bound to the collection, queued or not, have finished. +/// +/// +/// The type of queue that needs to be observed. +/// +/// +/// Object onto which the promise methods have to be attached +/// +/// + + if ( typeof type !== "string" ) { + object = type; + type = undefined; + } + type = type || "fx"; + var defer = jQuery.Deferred(), + elements = this, + i = elements.length, + count = 1, + deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + tmp; + function resolve() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + } + while( i-- ) { + if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || + ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || + jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && + jQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) { + count++; + tmp.done( resolve ); + } + } + resolve(); + return defer.promise(); + }; +jQuery.prototype.prop = function( name, value ) { +/// +/// 1: Get the value of a property for the first element in the set of matched elements. +/// 1.1 - prop(propertyName) +/// 2: Set one or more properties for the set of matched elements. +/// 2.1 - prop(propertyName, value) +/// 2.2 - prop(map) +/// 2.3 - prop(propertyName, function(index, oldPropertyValue)) +/// +/// +/// The name of the property to set. +/// +/// +/// A value to set for the property. +/// +/// + + return jQuery.access( this, name, value, true, jQuery.prop ); + }; +jQuery.prototype.pushStack = function( elems, name, selector ) { +/// +/// Add a collection of DOM elements onto the jQuery stack. +/// 1 - pushStack(elements) +/// 2 - pushStack(elements, name, arguments) +/// +/// +/// An array of elements to push onto the stack and make into a new jQuery object. +/// +/// +/// The name of a jQuery method that generated the array of elements. +/// +/// +/// The arguments that were passed in to the jQuery method (for serialization). +/// +/// + + // Build a new jQuery matched element set + var ret = this.constructor(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + (this.selector ? " " : "") + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }; +jQuery.prototype.queue = function( type, data ) { +/// +/// 1: Show the queue of functions to be executed on the matched elements. +/// 1.1 - queue(queueName) +/// 2: Manipulate the queue of functions to be executed on the matched elements. +/// 2.1 - queue(queueName, newQueue) +/// 2.2 - queue(queueName, callback( next )) +/// +/// +/// A string containing the name of the queue. Defaults to fx, the standard effects queue. +/// +/// +/// An array of functions to replace the current queue contents. +/// +/// + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + } + + if ( data === undefined ) { + return jQuery.queue( this[0], type ); + } + return this.each(function() { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }; +jQuery.prototype.ready = function( fn ) { +/// +/// Specify a function to execute when the DOM is fully loaded. +/// +/// +/// A function to execute after the DOM is ready. +/// +/// + + // Attach the listeners + jQuery.bindReady(); + + // Add the callback + readyList.done( fn ); + + return this; + }; +jQuery.prototype.remove = function( selector, keepData ) { +/// +/// Remove the set of matched elements from the DOM. +/// +/// +/// A selector expression that filters the set of matched elements to be removed. +/// +/// + + for ( var i = 0, elem; (elem = this[i]) != null; i++ ) { + if ( !selector || jQuery.filter( selector, [ elem ] ).length ) { + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( elem.getElementsByTagName("*") ); + jQuery.cleanData( [ elem ] ); + } + + if ( elem.parentNode ) { + elem.parentNode.removeChild( elem ); + } + } + } + + return this; + }; +jQuery.prototype.removeAttr = function( name ) { +/// +/// Remove an attribute from each element in the set of matched elements. +/// +/// +/// An attribute to remove. +/// +/// + + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }; +jQuery.prototype.removeClass = function( value ) { +/// +/// Remove a single class, multiple classes, or all classes from each element in the set of matched elements. +/// 1 - removeClass(className) +/// 2 - removeClass(function(index, class)) +/// +/// +/// One or more space-separated classes to be removed from the class attribute of each matched element. +/// +/// + + var classNames, i, l, elem, className, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call(this, j, this.className) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + classNames = (value || "").split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + className = (" " + elem.className + " ").replace( rclass, " " ); + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[ c ] + " ", " "); + } + elem.className = jQuery.trim( className ); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }; +jQuery.prototype.removeData = function( key ) { +/// +/// Remove a previously-stored piece of data. +/// +/// +/// A string naming the piece of data to delete. +/// +/// + + return this.each(function() { + jQuery.removeData( this, key ); + }); + }; +jQuery.prototype.removeProp = function( name ) { +/// +/// Remove a property for the set of matched elements. +/// +/// +/// The name of the property to set. +/// +/// + + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }; +jQuery.prototype.replaceAll = function( selector ) { +/// +/// Replace each target element with the set of matched elements. +/// +/// +/// A selector expression indicating which element(s) to replace. +/// +/// + + var ret = [], + insert = jQuery( selector ), + parent = this.length === 1 && this[0].parentNode; + + if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) { + insert[ original ]( this[0] ); + return this; + + } else { + for ( var i = 0, l = insert.length; i < l; i++ ) { + var elems = (i > 0 ? this.clone(true) : this).get(); + jQuery( insert[i] )[ original ]( elems ); + ret = ret.concat( elems ); + } + + return this.pushStack( ret, name, insert.selector ); + } + }; +jQuery.prototype.replaceWith = function( value ) { +/// +/// Replace each element in the set of matched elements with the provided new content. +/// 1 - replaceWith(newContent) +/// 2 - replaceWith(function) +/// +/// +/// The content to insert. May be an HTML string, DOM element, or jQuery object. +/// +/// + + if ( this[0] && this[0].parentNode ) { + // Make sure that the elements are removed from the DOM before they are inserted + // this can help fix replacing a parent with child elements + if ( jQuery.isFunction( value ) ) { + return this.each(function(i) { + var self = jQuery(this), old = self.html(); + self.replaceWith( value.call( this, i, old ) ); + }); + } + + if ( typeof value !== "string" ) { + value = jQuery( value ).detach(); + } + + return this.each(function() { + var next = this.nextSibling, + parent = this.parentNode; + + jQuery( this ).remove(); + + if ( next ) { + jQuery(next).before( value ); + } else { + jQuery(parent).append( value ); + } + }); + } else { + return this.length ? + this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) : + this; + } + }; +jQuery.prototype.resize = function( data, fn ) { +/// +/// Bind an event handler to the "resize" JavaScript event, or trigger that event on an element. +/// 1 - resize(handler(eventObject)) +/// 2 - resize(eventData, handler(eventObject)) +/// 3 - resize() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.scroll = function( data, fn ) { +/// +/// Bind an event handler to the "scroll" JavaScript event, or trigger that event on an element. +/// 1 - scroll(handler(eventObject)) +/// 2 - scroll(eventData, handler(eventObject)) +/// 3 - scroll() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.scrollLeft = function( val ) { +/// +/// 1: Get the current horizontal position of the scroll bar for the first element in the set of matched elements. +/// 1.1 - scrollLeft() +/// 2: Set the current horizontal position of the scroll bar for each of the set of matched elements. +/// 2.1 - scrollLeft(value) +/// +/// +/// An integer indicating the new position to set the scroll bar to. +/// +/// + + var elem, win; + + if ( val === undefined ) { + elem = this[ 0 ]; + + if ( !elem ) { + return null; + } + + win = getWindow( elem ); + + // Return the scroll offset + return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] : + jQuery.support.boxModel && win.document.documentElement[ method ] || + win.document.body[ method ] : + elem[ method ]; + } + + // Set the scroll offset + return this.each(function() { + win = getWindow( this ); + + if ( win ) { + win.scrollTo( + !i ? val : jQuery( win ).scrollLeft(), + i ? val : jQuery( win ).scrollTop() + ); + + } else { + this[ method ] = val; + } + }); + }; +jQuery.prototype.scrollTop = function( val ) { +/// +/// 1: Get the current vertical position of the scroll bar for the first element in the set of matched elements. +/// 1.1 - scrollTop() +/// 2: Set the current vertical position of the scroll bar for each of the set of matched elements. +/// 2.1 - scrollTop(value) +/// +/// +/// An integer indicating the new position to set the scroll bar to. +/// +/// + + var elem, win; + + if ( val === undefined ) { + elem = this[ 0 ]; + + if ( !elem ) { + return null; + } + + win = getWindow( elem ); + + // Return the scroll offset + return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] : + jQuery.support.boxModel && win.document.documentElement[ method ] || + win.document.body[ method ] : + elem[ method ]; + } + + // Set the scroll offset + return this.each(function() { + win = getWindow( this ); + + if ( win ) { + win.scrollTo( + !i ? val : jQuery( win ).scrollLeft(), + i ? val : jQuery( win ).scrollTop() + ); + + } else { + this[ method ] = val; + } + }); + }; +jQuery.prototype.select = function( data, fn ) { +/// +/// Bind an event handler to the "select" JavaScript event, or trigger that event on an element. +/// 1 - select(handler(eventObject)) +/// 2 - select(eventData, handler(eventObject)) +/// 3 - select() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.serialize = function() { +/// +/// Encode a set of form elements as a string for submission. +/// +/// + + return jQuery.param( this.serializeArray() ); + }; +jQuery.prototype.serializeArray = function() { +/// +/// Encode a set of form elements as an array of names and values. +/// +/// + + return this.map(function(){ + return this.elements ? jQuery.makeArray( this.elements ) : this; + }) + .filter(function(){ + return this.name && !this.disabled && + ( this.checked || rselectTextarea.test( this.nodeName ) || + rinput.test( this.type ) ); + }) + .map(function( i, elem ){ + var val = jQuery( this ).val(); + + return val == null ? + null : + jQuery.isArray( val ) ? + jQuery.map( val, function( val, i ){ + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + }) : + { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + }).get(); + }; +jQuery.prototype.show = function( speed, easing, callback ) { +/// +/// Display the matched elements. +/// 1 - show() +/// 2 - show(duration, callback) +/// 3 - show(duration, easing, callback) +/// +/// +/// A string or number determining how long the animation will run. +/// +/// +/// A string indicating which easing function to use for the transition. +/// +/// +/// A function to call once the animation is complete. +/// +/// + + var elem, display; + + if ( speed || speed === 0 ) { + return this.animate( genFx("show", 3), speed, easing, callback); + + } else { + for ( var i = 0, j = this.length; i < j; i++ ) { + elem = this[i]; + + if ( elem.style ) { + display = elem.style.display; + + // Reset the inline display of this element to learn if it is + // being hidden by cascaded rules or not + if ( !jQuery._data(elem, "olddisplay") && display === "none" ) { + display = elem.style.display = ""; + } + + // Set elements which have been overridden with display: none + // in a stylesheet to whatever the default browser style is + // for such an element + if ( display === "" && jQuery.css( elem, "display" ) === "none" ) { + jQuery._data(elem, "olddisplay", defaultDisplay(elem.nodeName)); + } + } + } + + // Set the display of most of the elements in a second loop + // to avoid the constant reflow + for ( i = 0; i < j; i++ ) { + elem = this[i]; + + if ( elem.style ) { + display = elem.style.display; + + if ( display === "" || display === "none" ) { + elem.style.display = jQuery._data(elem, "olddisplay") || ""; + } + } + } + + return this; + } + }; +jQuery.prototype.siblings = function( until, selector ) { +/// +/// Get the siblings of each element in the set of matched elements, optionally filtered by a selector. +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + var ret = jQuery.map( this, fn, until ), + // The variable 'args' was introduced in + // https://github.com/jquery/jquery/commit/52a0238 + // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. + // http://code.google.com/p/v8/issues/detail?id=1050 + args = slice.call(arguments); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, args.join(",") ); + }; +jQuery.prototype.size = function() { +/// +/// Return the number of elements in the jQuery object. +/// +/// + + return this.length; + }; +jQuery.prototype.slice = function() { +/// +/// Reduce the set of matched elements to a subset specified by a range of indices. +/// +/// +/// An integer indicating the 0-based position at which the elements begin to be selected. If negative, it indicates an offset from the end of the set. +/// +/// +/// An integer indicating the 0-based position at which the elements stop being selected. If negative, it indicates an offset from the end of the set. If omitted, the range continues until the end of the set. +/// +/// + + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }; +jQuery.prototype.slideDown = function( speed, easing, callback ) { +/// +/// Display the matched elements with a sliding motion. +/// 1 - slideDown(duration, callback) +/// 2 - slideDown(duration, easing, callback) +/// +/// +/// A string or number determining how long the animation will run. +/// +/// +/// A string indicating which easing function to use for the transition. +/// +/// +/// A function to call once the animation is complete. +/// +/// + + return this.animate( props, speed, easing, callback ); + }; +jQuery.prototype.slideToggle = function( speed, easing, callback ) { +/// +/// Display or hide the matched elements with a sliding motion. +/// 1 - slideToggle(duration, callback) +/// 2 - slideToggle(duration, easing, callback) +/// +/// +/// A string or number determining how long the animation will run. +/// +/// +/// A string indicating which easing function to use for the transition. +/// +/// +/// A function to call once the animation is complete. +/// +/// + + return this.animate( props, speed, easing, callback ); + }; +jQuery.prototype.slideUp = function( speed, easing, callback ) { +/// +/// Hide the matched elements with a sliding motion. +/// 1 - slideUp(duration, callback) +/// 2 - slideUp(duration, easing, callback) +/// +/// +/// A string or number determining how long the animation will run. +/// +/// +/// A string indicating which easing function to use for the transition. +/// +/// +/// A function to call once the animation is complete. +/// +/// + + return this.animate( props, speed, easing, callback ); + }; +jQuery.prototype.stop = function( clearQueue, gotoEnd ) { +/// +/// Stop the currently-running animation on the matched elements. +/// +/// +/// A Boolean indicating whether to remove queued animation as well. Defaults to false. +/// +/// +/// A Boolean indicating whether to complete the current animation immediately. Defaults to false. +/// +/// + + if ( clearQueue ) { + this.queue([]); + } + + this.each(function() { + var timers = jQuery.timers, + i = timers.length; + // clear marker counters if we know they won't be + if ( !gotoEnd ) { + jQuery._unmark( true, this ); + } + while ( i-- ) { + if ( timers[i].elem === this ) { + if (gotoEnd) { + // force the next step to be the last + timers[i](true); + } + + timers.splice(i, 1); + } + } + }); + + // start the next in the queue if the last step wasn't forced + if ( !gotoEnd ) { + this.dequeue(); + } + + return this; + }; +jQuery.prototype.submit = function( data, fn ) { +/// +/// Bind an event handler to the "submit" JavaScript event, or trigger that event on an element. +/// 1 - submit(handler(eventObject)) +/// 2 - submit(eventData, handler(eventObject)) +/// 3 - submit() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.text = function( text ) { +/// +/// 1: Get the combined text contents of each element in the set of matched elements, including their descendants. +/// 1.1 - text() +/// 2: Set the content of each element in the set of matched elements to the specified text. +/// 2.1 - text(textString) +/// 2.2 - text(function(index, text)) +/// +/// +/// A string of text to set as the content of each matched element. +/// +/// + + if ( jQuery.isFunction(text) ) { + return this.each(function(i) { + var self = jQuery( this ); + + self.text( text.call(this, i, self.text()) ); + }); + } + + if ( typeof text !== "object" && text !== undefined ) { + return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) ); + } + + return jQuery.text( this ); + }; +jQuery.prototype.toArray = function() { +/// +/// Retrieve all the DOM elements contained in the jQuery set, as an array. +/// +/// + + return slice.call( this, 0 ); + }; +jQuery.prototype.toggle = function( fn, fn2, callback ) { +/// +/// 1: Bind two or more handlers to the matched elements, to be executed on alternate clicks. +/// 1.1 - toggle(handler(eventObject), handler(eventObject), handler(eventObject)) +/// 2: Display or hide the matched elements. +/// 2.1 - toggle(duration, callback) +/// 2.2 - toggle(duration, easing, callback) +/// 2.3 - toggle(showOrHide) +/// +/// +/// A function to execute every even time the element is clicked. +/// +/// +/// A function to execute every odd time the element is clicked. +/// +/// +/// Additional handlers to cycle through after clicks. +/// +/// + + var bool = typeof fn === "boolean"; + + if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) { + this._toggle.apply( this, arguments ); + + } else if ( fn == null || bool ) { + this.each(function() { + var state = bool ? fn : jQuery(this).is(":hidden"); + jQuery(this)[ state ? "show" : "hide" ](); + }); + + } else { + this.animate(genFx("toggle", 3), fn, fn2, callback); + } + + return this; + }; +jQuery.prototype.toggleClass = function( value, stateVal ) { +/// +/// Add or remove one or more classes from each element in the set of matched elements, depending on either the class's presence or the value of the switch argument. +/// 1 - toggleClass(className) +/// 2 - toggleClass(className, switch) +/// 3 - toggleClass(switch) +/// 4 - toggleClass(function(index, class, switch), switch) +/// +/// +/// One or more class names (separated by spaces) to be toggled for each element in the matched set. +/// +/// +/// A Boolean (not just truthy/falsy) value to determine whether the class should be added or removed. +/// +/// + + var type = typeof value, + isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + state = stateVal, + classNames = value.split( rspace ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }; +jQuery.prototype.trigger = function( type, data ) { +/// +/// Execute all handlers and behaviors attached to the matched elements for the given event type. +/// 1 - trigger(eventType, extraParameters) +/// 2 - trigger(event) +/// +/// +/// A string containing a JavaScript event type, such as click or submit. +/// +/// +/// Additional parameters to pass along to the event handler. +/// +/// + + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }; +jQuery.prototype.triggerHandler = function( type, data ) { +/// +/// Execute all handlers attached to an element for an event. +/// +/// +/// A string containing a JavaScript event type, such as click or submit. +/// +/// +/// An array of additional parameters to pass along to the event handler. +/// +/// + + if ( this[0] ) { + return jQuery.event.trigger( type, data, this[0], true ); + } + }; +jQuery.prototype.unbind = function( type, fn ) { +/// +/// Remove a previously-attached event handler from the elements. +/// 1 - unbind(eventType, handler(eventObject)) +/// 2 - unbind(eventType, false) +/// 3 - unbind(event) +/// +/// +/// A string containing a JavaScript event type, such as click or submit. +/// +/// +/// The function that is to be no longer executed. +/// +/// + + // Handle object literals + if ( typeof type === "object" && !type.preventDefault ) { + for ( var key in type ) { + this.unbind(key, type[key]); + } + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.remove( this[i], type, fn ); + } + } + + return this; + }; +jQuery.prototype.undelegate = function( selector, types, fn ) { +/// +/// Remove a handler from the event for all elements which match the current selector, now or in the future, based upon a specific set of root elements. +/// 1 - undelegate() +/// 2 - undelegate(selector, eventType) +/// 3 - undelegate(selector, eventType, handler) +/// 4 - undelegate(selector, events) +/// 5 - undelegate(namespace) +/// +/// +/// A selector which will be used to filter the event results. +/// +/// +/// A string containing a JavaScript event type, such as "click" or "keydown" +/// +/// +/// A function to execute at the time the event is triggered. +/// +/// + + if ( arguments.length === 0 ) { + return this.unbind( "live" ); + + } else { + return this.die( types, null, fn, selector ); + } + }; +jQuery.prototype.unload = function( data, fn ) { +/// +/// Bind an event handler to the "unload" JavaScript event. +/// 1 - unload(handler(eventObject)) +/// 2 - unload(eventData, handler(eventObject)) +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.unwrap = function() { +/// +/// Remove the parents of the set of matched elements from the DOM, leaving the matched elements in their place. +/// +/// + + return this.parent().each(function() { + if ( !jQuery.nodeName( this, "body" ) ) { + jQuery( this ).replaceWith( this.childNodes ); + } + }).end(); + }; +jQuery.prototype.val = function( value ) { +/// +/// 1: Get the current value of the first element in the set of matched elements. +/// 1.1 - val() +/// 2: Set the value of each element in the set of matched elements. +/// 2.1 - val(value) +/// 2.2 - val(function(index, value)) +/// +/// +/// A string of text or an array of strings corresponding to the value of each matched element to set as selected/checked. +/// +/// + + var hooks, ret, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return undefined; + } + + var isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var self = jQuery(this), val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, self.val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + }; +jQuery.prototype.width = function( size ) { +/// +/// 1: Get the current computed width for the first element in the set of matched elements. +/// 1.1 - width() +/// 2: Set the CSS width of each element in the set of matched elements. +/// 2.1 - width(value) +/// 2.2 - width(function(index, width)) +/// +/// +/// An integer representing the number of pixels, or an integer along with an optional unit of measure appended (as a string). +/// +/// + + // Get window width or height + var elem = this[0]; + if ( !elem ) { + return size == null ? null : this; + } + + if ( jQuery.isFunction( size ) ) { + return this.each(function( i ) { + var self = jQuery( this ); + self[ type ]( size.call( this, i, self[ type ]() ) ); + }); + } + + if ( jQuery.isWindow( elem ) ) { + // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode + // 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat + var docElemProp = elem.document.documentElement[ "client" + name ], + body = elem.document.body; + return elem.document.compatMode === "CSS1Compat" && docElemProp || + body && body[ "client" + name ] || docElemProp; + + // Get document width or height + } else if ( elem.nodeType === 9 ) { + // Either scroll[Width/Height] or offset[Width/Height], whichever is greater + return Math.max( + elem.documentElement["client" + name], + elem.body["scroll" + name], elem.documentElement["scroll" + name], + elem.body["offset" + name], elem.documentElement["offset" + name] + ); + + // Get or set width or height on the element + } else if ( size === undefined ) { + var orig = jQuery.css( elem, type ), + ret = parseFloat( orig ); + + return jQuery.isNaN( ret ) ? orig : ret; + + // Set the width or height on the element (default to pixels if value is unitless) + } else { + return this.css( type, typeof size === "string" ? size : size + "px" ); + } + }; +jQuery.prototype.wrap = function( html ) { +/// +/// Wrap an HTML structure around each element in the set of matched elements. +/// 1 - wrap(wrappingElement) +/// 2 - wrap(function(index)) +/// +/// +/// An HTML snippet, selector expression, jQuery object, or DOM element specifying the structure to wrap around the matched elements. +/// +/// + + return this.each(function() { + jQuery( this ).wrapAll( html ); + }); + }; +jQuery.prototype.wrapAll = function( html ) { +/// +/// Wrap an HTML structure around all elements in the set of matched elements. +/// +/// +/// An HTML snippet, selector expression, jQuery object, or DOM element specifying the structure to wrap around the matched elements. +/// +/// + + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapAll( html.call(this, i) ); + }); + } + + if ( this[0] ) { + // The elements to wrap the target around + var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); + + if ( this[0].parentNode ) { + wrap.insertBefore( this[0] ); + } + + wrap.map(function() { + var elem = this; + + while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { + elem = elem.firstChild; + } + + return elem; + }).append( this ); + } + + return this; + }; +jQuery.prototype.wrapInner = function( html ) { +/// +/// Wrap an HTML structure around the content of each element in the set of matched elements. +/// 1 - wrapInner(wrappingElement) +/// 2 - wrapInner(function(index)) +/// +/// +/// An HTML snippet, selector expression, jQuery object, or DOM element specifying the structure to wrap around the content of the matched elements. +/// +/// + + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapInner( html.call(this, i) ); + }); + } + + return this.each(function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + }); + }; +jQuery.fn = jQuery.prototype; +jQuery.fn.init.prototype = jQuery.fn; +window.jQuery = window.$ = jQuery; +})(window); \ No newline at end of file diff --git a/Azure/WebSite_WindowsAzure/Scripts/jquery-1.6.4.js b/Azure/WebSite_WindowsAzure/Scripts/jquery-1.6.4.js new file mode 100644 index 0000000..11e6d06 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Scripts/jquery-1.6.4.js @@ -0,0 +1,9046 @@ +/*! + * jQuery JavaScript Library v1.6.4 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Mon Sep 12 18:54:48 2011 -0400 + */ +(function( window, undefined ) { + +// Use the correct document accordingly with window argument (sandbox) +var document = window.document, + navigator = window.navigator, + location = window.location; +var jQuery = (function() { + +// Define a local copy of jQuery +var jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // A central reference to the root jQuery(document) + rootjQuery, + + // A simple way to check for HTML strings or ID strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + + // Used for trimming whitespace + trimLeft = /^\s+/, + trimRight = /\s+$/, + + // Check for digits + rdigit = /\d/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, + rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + + // Useragent RegExp + rwebkit = /(webkit)[ \/]([\w.]+)/, + ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, + rmsie = /(msie) ([\w.]+)/, + rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, + + // Matches dashed string for camelizing + rdashAlpha = /-([a-z]|[0-9])/ig, + rmsPrefix = /^-ms-/, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return ( letter + "" ).toUpperCase(); + }, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // The deferred used on DOM ready + readyList, + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + trim = String.prototype.trim, + indexOf = Array.prototype.indexOf, + + // [[Class]] -> type pairs + class2type = {}; + +jQuery.fn = jQuery.prototype = { + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context && document.body ) { + this.context = document; + this[0] = document.body; + this.selector = selector; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = quickExpr.exec( selector ); + } + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + doc = (context ? context.ownerDocument || context : document); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return (context || rootjQuery).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if (selector.selector !== undefined) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.6.4", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = this.constructor(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + (this.selector ? " " : "") + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // Add the callback + readyList.done( fn ); + + return this; + }, + + eq: function( i ) { + return i === -1 ? + this.slice( i ) : + this.slice( i, +i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + // Either a released hold or an DOMready/load event and not yet ready + if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 1 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger( "ready" ).unbind( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyList ) { + return; + } + + readyList = jQuery._Deferred(); + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + return setTimeout( jQuery.ready, 1 ); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", DOMContentLoaded ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + // A crude way of determining if an object is a window + isWindow: function( obj ) { + return obj && typeof obj === "object" && "setInterval" in obj; + }, + + isNaN: function( obj ) { + return obj == null || !rdigit.test( obj ) || isNaN( obj ); + }, + + type: function( obj ) { + return obj == null ? + String( obj ) : + class2type[ toString.call(obj) ] || "object"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw msg; + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return (new Function( "return " + data ))(); + + } + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + parseXML: function( data ) { + var xml, tmp; + try { + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + } catch( e ) { + xml = undefined; + } + if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && rnotwhite.test( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction( object ); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { + break; + } + } + } + } + + return object; + }, + + // Use native String.trim function wherever possible + trim: trim ? + function( text ) { + return text == null ? + "" : + trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // The extra typeof function check is to prevent crashes + // in Safari 2 (See: #3039) + // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 + var type = jQuery.type( array ); + + if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array ) { + if ( !array ) { + return -1; + } + + if ( indexOf ) { + return indexOf.call( array, elem ); + } + + for ( var i = 0, length = array.length; i < length; i++ ) { + if ( array[ i ] === elem ) { + return i; + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, + j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = [], retVal; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, key, ret = [], + i = 0, + length = elems.length, + // jquery objects are treated as arrays + isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( key in elems ) { + value = callback( elems[ key ], key, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + if ( typeof context === "string" ) { + var tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + var args = slice.call( arguments, 2 ), + proxy = function() { + return fn.apply( context, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + + return proxy; + }, + + // Mutifunctional method to get and set values to a collection + // The value/s can optionally be executed if it's a function + access: function( elems, key, value, exec, fn, pass ) { + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + jQuery.access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : undefined; + }, + + now: function() { + return (new Date()).getTime(); + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = rwebkit.exec( ua ) || + ropera.exec( ua ) || + rmsie.exec( ua ) || + ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + sub: function() { + function jQuerySub( selector, context ) { + return new jQuerySub.fn.init( selector, context ); + } + jQuery.extend( true, jQuerySub, this ); + jQuerySub.superclass = this; + jQuerySub.fn = jQuerySub.prototype = this(); + jQuerySub.fn.constructor = jQuerySub; + jQuerySub.sub = this.sub; + jQuerySub.fn.init = function init( selector, context ) { + if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { + context = jQuerySub( context ); + } + + return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); + }; + jQuerySub.fn.init.prototype = jQuerySub.fn; + var rootjQuerySub = jQuerySub(document); + return jQuerySub; + }, + + browser: {} +}); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +// IE doesn't match non-breaking spaces with \s +if ( rnotwhite.test( "\xA0" ) ) { + trimLeft = /^[\s\xA0]+/; + trimRight = /[\s\xA0]+$/; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch(e) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +return jQuery; + +})(); + + +var // Promise methods + promiseMethods = "done fail isResolved isRejected promise then always pipe".split( " " ), + // Static reference to slice + sliceDeferred = [].slice; + +jQuery.extend({ + // Create a simple deferred (one callbacks list) + _Deferred: function() { + var // callbacks list + callbacks = [], + // stored [ context , args ] + fired, + // to avoid firing when already doing so + firing, + // flag to know if the deferred has been cancelled + cancelled, + // the deferred itself + deferred = { + + // done( f1, f2, ...) + done: function() { + if ( !cancelled ) { + var args = arguments, + i, + length, + elem, + type, + _fired; + if ( fired ) { + _fired = fired; + fired = 0; + } + for ( i = 0, length = args.length; i < length; i++ ) { + elem = args[ i ]; + type = jQuery.type( elem ); + if ( type === "array" ) { + deferred.done.apply( deferred, elem ); + } else if ( type === "function" ) { + callbacks.push( elem ); + } + } + if ( _fired ) { + deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] ); + } + } + return this; + }, + + // resolve with given context and args + resolveWith: function( context, args ) { + if ( !cancelled && !fired && !firing ) { + // make sure args are available (#8421) + args = args || []; + firing = 1; + try { + while( callbacks[ 0 ] ) { + callbacks.shift().apply( context, args ); + } + } + finally { + fired = [ context, args ]; + firing = 0; + } + } + return this; + }, + + // resolve with this as context and given arguments + resolve: function() { + deferred.resolveWith( this, arguments ); + return this; + }, + + // Has this deferred been resolved? + isResolved: function() { + return !!( firing || fired ); + }, + + // Cancel + cancel: function() { + cancelled = 1; + callbacks = []; + return this; + } + }; + + return deferred; + }, + + // Full fledged deferred (two callbacks list) + Deferred: function( func ) { + var deferred = jQuery._Deferred(), + failDeferred = jQuery._Deferred(), + promise; + // Add errorDeferred methods, then and promise + jQuery.extend( deferred, { + then: function( doneCallbacks, failCallbacks ) { + deferred.done( doneCallbacks ).fail( failCallbacks ); + return this; + }, + always: function() { + return deferred.done.apply( deferred, arguments ).fail.apply( this, arguments ); + }, + fail: failDeferred.done, + rejectWith: failDeferred.resolveWith, + reject: failDeferred.resolve, + isRejected: failDeferred.isResolved, + pipe: function( fnDone, fnFail ) { + return jQuery.Deferred(function( newDefer ) { + jQuery.each( { + done: [ fnDone, "resolve" ], + fail: [ fnFail, "reject" ] + }, function( handler, data ) { + var fn = data[ 0 ], + action = data[ 1 ], + returned; + if ( jQuery.isFunction( fn ) ) { + deferred[ handler ](function() { + returned = fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise().then( newDefer.resolve, newDefer.reject ); + } else { + newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] ); + } + }); + } else { + deferred[ handler ]( newDefer[ action ] ); + } + }); + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + if ( obj == null ) { + if ( promise ) { + return promise; + } + promise = obj = {}; + } + var i = promiseMethods.length; + while( i-- ) { + obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ]; + } + return obj; + } + }); + // Make sure only one callback list will be used + deferred.done( failDeferred.cancel ).fail( deferred.cancel ); + // Unexpose cancel + delete deferred.cancel; + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + return deferred; + }, + + // Deferred helper + when: function( firstParam ) { + var args = arguments, + i = 0, + length = args.length, + count = length, + deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? + firstParam : + jQuery.Deferred(); + function resolveFunc( i ) { + return function( value ) { + args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + if ( !( --count ) ) { + // Strange bug in FF4: + // Values changed onto the arguments object sometimes end up as undefined values + // outside the $.when method. Cloning the object into a fresh array solves the issue + deferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) ); + } + }; + } + if ( length > 1 ) { + for( ; i < length; i++ ) { + if ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) { + args[ i ].promise().then( resolveFunc(i), deferred.reject ); + } else { + --count; + } + } + if ( !count ) { + deferred.resolveWith( deferred, args ); + } + } else if ( deferred !== firstParam ) { + deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); + } + return deferred.promise(); + } +}); + + + +jQuery.support = (function() { + + var div = document.createElement( "div" ), + documentElement = document.documentElement, + all, + a, + select, + opt, + input, + marginDiv, + support, + fragment, + body, + testElementParent, + testElement, + testElementStyle, + tds, + events, + eventName, + i, + isSupported; + + // Preliminary tests + div.setAttribute("className", "t"); + div.innerHTML = "
a"; + + + all = div.getElementsByTagName( "*" ); + a = div.getElementsByTagName( "a" )[ 0 ]; + + // Can't get basic test support + if ( !all || !all.length || !a ) { + return {}; + } + + // First batch of supports tests + select = document.createElement( "select" ); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName( "input" )[ 0 ]; + + support = { + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: ( div.firstChild.nodeType === 3 ), + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName( "tbody" ).length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName( "link" ).length, + + // Get the style information from getAttribute + // (IE uses .cssText instead) + style: /top/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: ( a.getAttribute( "href" ) === "/a" ), + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.55$/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Make sure that if no value is specified for a checkbox + // that it defaults to "on". + // (WebKit defaults to "" instead) + checkOn: ( input.value === "on" ), + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: opt.selected, + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + getSetAttribute: div.className !== "t", + + // Will be defined later + submitBubbles: true, + changeBubbles: true, + focusinBubbles: false, + deleteExpando: true, + noCloneEvent: true, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableMarginRight: true + }; + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Test to see if it's possible to delete an expando from an element + // Fails in Internet Explorer + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { + div.attachEvent( "onclick", function() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + support.noCloneEvent = false; + }); + div.cloneNode( true ).fireEvent( "onclick" ); + } + + // Check if a radio maintains it's value + // after being appended to the DOM + input = document.createElement("input"); + input.value = "t"; + input.setAttribute("type", "radio"); + support.radioValue = input.value === "t"; + + input.setAttribute("checked", "checked"); + div.appendChild( input ); + fragment = document.createDocumentFragment(); + fragment.appendChild( div.firstChild ); + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + div.innerHTML = ""; + + // Figure out if the W3C box model works as expected + div.style.width = div.style.paddingLeft = "1px"; + + body = document.getElementsByTagName( "body" )[ 0 ]; + // We use our own, invisible, body unless the body is already present + // in which case we use a div (#9239) + testElement = document.createElement( body ? "div" : "body" ); + testElementStyle = { + visibility: "hidden", + width: 0, + height: 0, + border: 0, + margin: 0, + background: "none" + }; + if ( body ) { + jQuery.extend( testElementStyle, { + position: "absolute", + left: "-1000px", + top: "-1000px" + }); + } + for ( i in testElementStyle ) { + testElement.style[ i ] = testElementStyle[ i ]; + } + testElement.appendChild( div ); + testElementParent = body || documentElement; + testElementParent.insertBefore( testElement, testElementParent.firstChild ); + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + support.boxModel = div.offsetWidth === 2; + + if ( "zoom" in div.style ) { + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + // (IE < 8 does this) + div.style.display = "inline"; + div.style.zoom = 1; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 ); + + // Check if elements with layout shrink-wrap their children + // (IE 6 does this) + div.style.display = ""; + div.innerHTML = "
"; + support.shrinkWrapBlocks = ( div.offsetWidth !== 2 ); + } + + div.innerHTML = "
t
"; + tds = div.getElementsByTagName( "td" ); + + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + // (only IE 8 fails this test) + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Check if empty table cells still have offsetWidth/Height + // (IE < 8 fail this test) + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + div.innerHTML = ""; + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. For more + // info see bug #3333 + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + if ( document.defaultView && document.defaultView.getComputedStyle ) { + marginDiv = document.createElement( "div" ); + marginDiv.style.width = "0"; + marginDiv.style.marginRight = "0"; + div.appendChild( marginDiv ); + support.reliableMarginRight = + ( parseInt( ( document.defaultView.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; + } + + // Remove the body element we added + testElement.innerHTML = ""; + testElementParent.removeChild( testElement ); + + // Technique from Juriy Zaytsev + // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ + // We only care about the case where non-standard event systems + // are used, namely in IE. Short-circuiting here helps us to + // avoid an eval call (in setAttribute) which can cause CSP + // to go haywire. See: https://developer.mozilla.org/en/Security/CSP + if ( div.attachEvent ) { + for( i in { + submit: 1, + change: 1, + focusin: 1 + } ) { + eventName = "on" + i; + isSupported = ( eventName in div ); + if ( !isSupported ) { + div.setAttribute( eventName, "return;" ); + isSupported = ( typeof div[ eventName ] === "function" ); + } + support[ i + "Bubbles" ] = isSupported; + } + } + + // Null connected elements to avoid leaks in IE + testElement = fragment = select = opt = body = marginDiv = div = input = null; + + return support; +})(); + +// Keep track of boxModel +jQuery.boxModel = jQuery.support.boxModel; + + + + +var rbrace = /^(?:\{.*\}|\[.*\])$/, + rmultiDash = /([A-Z])/g; + +jQuery.extend({ + cache: {}, + + // Please use with caution + uuid: 0, + + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", + "applet": true + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, ret, + internalKey = jQuery.expando, + getByName = typeof name === "string", + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || (pvt && id && (cache[ id ] && !cache[ id ][ internalKey ]))) && getByName && data === undefined ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + elem[ jQuery.expando ] = id = ++jQuery.uuid; + } else { + id = jQuery.expando; + } + } + + if ( !cache[ id ] ) { + cache[ id ] = {}; + + // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery + // metadata on plain JS objects when the object is serialized using + // JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name); + } else { + cache[ id ] = jQuery.extend(cache[ id ], name); + } + } + + thisCache = cache[ id ]; + + // Internal jQuery data is stored in a separate object inside the object's data + // cache in order to avoid key collisions between internal data and user-defined + // data + if ( pvt ) { + if ( !thisCache[ internalKey ] ) { + thisCache[ internalKey ] = {}; + } + + thisCache = thisCache[ internalKey ]; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should + // not attempt to inspect the internal events object using jQuery.data, as this + // internal data object is undocumented and subject to change. + if ( name === "events" && !thisCache[name] ) { + return thisCache[ internalKey ] && thisCache[ internalKey ].events; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( getByName ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; + }, + + removeData: function( elem, name, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, + + // Reference to internal data cache key + internalKey = jQuery.expando, + + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + + // See jQuery.data for more information + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ]; + + if ( thisCache ) { + + // Support interoperable removal of hyphenated or camelcased keys + if ( !thisCache[ name ] ) { + name = jQuery.camelCase( name ); + } + + delete thisCache[ name ]; + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( !isEmptyDataObject(thisCache) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( pvt ) { + delete cache[ id ][ internalKey ]; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject(cache[ id ]) ) { + return; + } + } + + var internalCache = cache[ id ][ internalKey ]; + + // Browsers that fail expando deletion also refuse to delete expandos on + // the window, but it will allow it on all other JS objects; other browsers + // don't care + // Ensure that `cache` is not a window object #10080 + if ( jQuery.support.deleteExpando || !cache.setInterval ) { + delete cache[ id ]; + } else { + cache[ id ] = null; + } + + // We destroyed the entire user cache at once because it's faster than + // iterating through each key, but we need to continue to persist internal + // data if it existed + if ( internalCache ) { + cache[ id ] = {}; + // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery + // metadata on plain JS objects when the object is serialized using + // JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + + cache[ id ][ internalKey ] = internalCache; + + // Otherwise, we need to eliminate the expando on the node to avoid + // false lookups in the cache for entries that no longer exist + } else if ( isNode ) { + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( jQuery.support.deleteExpando ) { + delete elem[ jQuery.expando ]; + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); + } else { + elem[ jQuery.expando ] = null; + } + } + }, + + // For internal use only. + _data: function( elem, name, data ) { + return jQuery.data( elem, name, data, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + if ( elem.nodeName ) { + var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; + + if ( match ) { + return !(match === true || elem.getAttribute("classid") !== match); + } + } + + return true; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var data = null; + + if ( typeof key === "undefined" ) { + if ( this.length ) { + data = jQuery.data( this[0] ); + + if ( this[0].nodeType === 1 ) { + var attr = this[0].attributes, name; + for ( var i = 0, l = attr.length; i < l; i++ ) { + name = attr[i].name; + + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.substring(5) ); + + dataAttr( this[0], name, data[ name ] ); + } + } + } + } + + return data; + + } else if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + var parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value === undefined ) { + data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + // Try to fetch any internally stored data first + if ( data === undefined && this.length ) { + data = jQuery.data( this[0], key ); + data = dataAttr( this[0], key, data ); + } + + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + + } else { + return this.each(function() { + var $this = jQuery( this ), + args = [ parts[0], value ]; + + $this.triggerHandler( "setData" + parts[1] + "!", args ); + jQuery.data( this, key, value ); + $this.triggerHandler( "changeData" + parts[1] + "!", args ); + }); + } + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + + var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + !jQuery.isNaN( data ) ? parseFloat( data ) : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON +// property to be considered empty objects; this property always exists in +// order to make sure JSON.stringify does not expose internal metadata +function isEmptyDataObject( obj ) { + for ( var name in obj ) { + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} + + + + +function handleQueueMarkDefer( elem, type, src ) { + var deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + defer = jQuery.data( elem, deferDataKey, undefined, true ); + if ( defer && + ( src === "queue" || !jQuery.data( elem, queueDataKey, undefined, true ) ) && + ( src === "mark" || !jQuery.data( elem, markDataKey, undefined, true ) ) ) { + // Give room for hard-coded callbacks to fire first + // and eventually mark/queue something else on the element + setTimeout( function() { + if ( !jQuery.data( elem, queueDataKey, undefined, true ) && + !jQuery.data( elem, markDataKey, undefined, true ) ) { + jQuery.removeData( elem, deferDataKey, true ); + defer.resolve(); + } + }, 0 ); + } +} + +jQuery.extend({ + + _mark: function( elem, type ) { + if ( elem ) { + type = (type || "fx") + "mark"; + jQuery.data( elem, type, (jQuery.data(elem,type,undefined,true) || 0) + 1, true ); + } + }, + + _unmark: function( force, elem, type ) { + if ( force !== true ) { + type = elem; + elem = force; + force = false; + } + if ( elem ) { + type = type || "fx"; + var key = type + "mark", + count = force ? 0 : ( (jQuery.data( elem, key, undefined, true) || 1 ) - 1 ); + if ( count ) { + jQuery.data( elem, key, count, true ); + } else { + jQuery.removeData( elem, key, true ); + handleQueueMarkDefer( elem, type, "mark" ); + } + } + }, + + queue: function( elem, type, data ) { + if ( elem ) { + type = (type || "fx") + "queue"; + var q = jQuery.data( elem, type, undefined, true ); + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !q || jQuery.isArray(data) ) { + q = jQuery.data( elem, type, jQuery.makeArray(data), true ); + } else { + q.push( data ); + } + } + return q || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + fn = queue.shift(), + defer; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift("inprogress"); + } + + fn.call(elem, function() { + jQuery.dequeue(elem, type); + }); + } + + if ( !queue.length ) { + jQuery.removeData( elem, type + "queue", true ); + handleQueueMarkDefer( elem, type, "queue" ); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + } + + if ( data === undefined ) { + return jQuery.queue( this[0], type ); + } + return this.each(function() { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; + type = type || "fx"; + + return this.queue( type, function() { + var elem = this; + setTimeout(function() { + jQuery.dequeue( elem, type ); + }, time ); + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, object ) { + if ( typeof type !== "string" ) { + object = type; + type = undefined; + } + type = type || "fx"; + var defer = jQuery.Deferred(), + elements = this, + i = elements.length, + count = 1, + deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + tmp; + function resolve() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + } + while( i-- ) { + if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || + ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || + jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && + jQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) { + count++; + tmp.done( resolve ); + } + } + resolve(); + return defer.promise(); + } +}); + + + + +var rclass = /[\n\t\r]/g, + rspace = /\s+/, + rreturn = /\r/g, + rtype = /^(?:button|input)$/i, + rfocusable = /^(?:button|input|object|select|textarea)$/i, + rclickable = /^a(?:rea)?$/i, + rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, + nodeHook, boolHook; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.attr ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.prop ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + var classNames, i, l, elem, + setClass, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call(this, j, this.className) ); + }); + } + + if ( value && typeof value === "string" ) { + classNames = value.split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className && classNames.length === 1 ) { + elem.className = value; + + } else { + setClass = " " + elem.className + " "; + + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { + setClass += classNames[ c ] + " "; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classNames, i, l, elem, className, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call(this, j, this.className) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + classNames = (value || "").split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + className = (" " + elem.className + " ").replace( rclass, " " ); + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[ c ] + " ", " "); + } + elem.className = jQuery.trim( className ); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + state = stateVal, + classNames = value.split( rspace ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " "; + for ( var i = 0, l = this.length; i < l; i++ ) { + if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var hooks, ret, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return undefined; + } + + var isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var self = jQuery(this), val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, self.val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // attributes.value is undefined in Blackberry 4.7 but + // uses .value. See #6932 + var val = elem.attributes.value; + return !val || val.specified ? elem.value : elem.text; + } + }, + select: { + get: function( elem ) { + var value, + index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type === "select-one"; + + // Nothing was selected + if ( index < 0 ) { + return null; + } + + // Loop through all the selected options + for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { + var option = options[ i ]; + + // Don't return options that are disabled or in a disabled optgroup + if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && + (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + // Fixes Bug #2551 -- select.val() broken in IE after form.reset() + if ( one && !values.length && options.length ) { + return jQuery( options[ index ] ).val(); + } + + return values; + }, + + set: function( elem, value ) { + var values = jQuery.makeArray( value ); + + jQuery(elem).find("option").each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attrFn: { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true + }, + + attrFix: { + // Always normalize to ensure hook usage + tabindex: "tabIndex" + }, + + attr: function( elem, name, value, pass ) { + var nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return undefined; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery( elem )[ name ]( value ); + } + + // Fallback to prop when attributes are not supported + if ( !("getAttribute" in elem) ) { + return jQuery.prop( elem, name, value ); + } + + var ret, hooks, + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + // Normalize the name if needed + if ( notxml ) { + name = jQuery.attrFix[ name ] || name; + + hooks = jQuery.attrHooks[ name ]; + + if ( !hooks ) { + // Use boolHook for boolean attributes + if ( rboolean.test( name ) ) { + hooks = boolHook; + + // Use nodeHook if available( IE6/7 ) + } else if ( nodeHook ) { + hooks = nodeHook; + } + } + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return undefined; + + } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, "" + value ); + return value; + } + + } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + + ret = elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return ret === null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, name ) { + var propName; + if ( elem.nodeType === 1 ) { + name = jQuery.attrFix[ name ] || name; + + jQuery.attr( elem, name, "" ); + elem.removeAttribute( name ); + + // Set corresponding property to false for boolean attributes + if ( rboolean.test( name ) && (propName = jQuery.propFix[ name ] || name) in elem ) { + elem[ propName ] = false; + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( rtype.test( elem.nodeName ) && elem.parentNode ) { + jQuery.error( "type property can't be changed" ); + } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to it's default in case type is set after value + // This is for element creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + }, + // Use the value property for back compat + // Use the nodeHook for button elements in IE6/7 (#1954) + value: { + get: function( elem, name ) { + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.get( elem, name ); + } + return name in elem ? + elem.value : + null; + }, + set: function( elem, value, name ) { + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.set( elem, value, name ); + } + // Does not return so that setAttribute is also used + elem.value = value; + } + } + }, + + propFix: { + tabindex: "tabIndex", + readonly: "readOnly", + "for": "htmlFor", + "class": "className", + maxlength: "maxLength", + cellspacing: "cellSpacing", + cellpadding: "cellPadding", + rowspan: "rowSpan", + colspan: "colSpan", + usemap: "useMap", + frameborder: "frameBorder", + contenteditable: "contentEditable" + }, + + prop: function( elem, name, value ) { + var nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return undefined; + } + + var ret, hooks, + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + return (elem[ name ] = value); + } + + } else { + if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + return elem[ name ]; + } + } + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + var attributeNode = elem.getAttributeNode("tabindex"); + + return attributeNode && attributeNode.specified ? + parseInt( attributeNode.value, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + } + } +}); + +// Add the tabindex propHook to attrHooks for back-compat +jQuery.attrHooks.tabIndex = jQuery.propHooks.tabIndex; + +// Hook for boolean attributes +boolHook = { + get: function( elem, name ) { + // Align boolean attributes with corresponding properties + // Fall back to attribute presence where some booleans are not supported + var attrNode; + return jQuery.prop( elem, name ) === true || ( attrNode = elem.getAttributeNode( name ) ) && attrNode.nodeValue !== false ? + name.toLowerCase() : + undefined; + }, + set: function( elem, value, name ) { + var propName; + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + // value is true since we know at this point it's type boolean and not false + // Set boolean attributes to the same name and set the DOM property + propName = jQuery.propFix[ name ] || name; + if ( propName in elem ) { + // Only set the IDL specifically if it already exists on the element + elem[ propName ] = true; + } + + elem.setAttribute( name, name.toLowerCase() ); + } + return name; + } +}; + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !jQuery.support.getSetAttribute ) { + + // Use this for any attribute in IE6/7 + // This fixes almost every IE6/7 issue + nodeHook = jQuery.valHooks.button = { + get: function( elem, name ) { + var ret; + ret = elem.getAttributeNode( name ); + // Return undefined if nodeValue is empty string + return ret && ret.nodeValue !== "" ? + ret.nodeValue : + undefined; + }, + set: function( elem, value, name ) { + // Set the existing or create a new attribute node + var ret = elem.getAttributeNode( name ); + if ( !ret ) { + ret = document.createAttribute( name ); + elem.setAttributeNode( ret ); + } + return (ret.nodeValue = value + ""); + } + }; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }); + }); +} + + +// Some attributes require a special call on IE +if ( !jQuery.support.hrefNormalized ) { + jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + get: function( elem ) { + var ret = elem.getAttribute( name, 2 ); + return ret === null ? undefined : ret; + } + }); + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Normalize to lowercase since IE uppercases css property names + return elem.style.cssText.toLowerCase() || undefined; + }, + set: function( elem, value ) { + return (elem.style.cssText = "" + value); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + return null; + } + }); +} + +// Radios and checkboxes getter/setter +if ( !jQuery.support.checkOn ) { + jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + get: function( elem ) { + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + } + }; + }); +} +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return (elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0); + } + } + }); +}); + + + + +var rnamespaces = /\.(.*)$/, + rformElems = /^(?:textarea|input|select)$/i, + rperiod = /\./g, + rspaces = / /g, + rescape = /[^\w\s.|`]/g, + fcleanup = function( nm ) { + return nm.replace(rescape, "\\$&"); + }; + +/* + * A number of helper functions used for managing events. + * Many of the ideas behind this code originated from + * Dean Edwards' addEvent library. + */ +jQuery.event = { + + // Bind an event to an element + // Original by Dean Edwards + add: function( elem, types, handler, data ) { + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + if ( handler === false ) { + handler = returnFalse; + } else if ( !handler ) { + // Fixes bug #7229. Fix recommended by jdalton + return; + } + + var handleObjIn, handleObj; + + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + } + + // Make sure that the function being executed has a unique ID + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure + var elemData = jQuery._data( elem ); + + // If no elemData is found then we must be trying to bind to one of the + // banned noData elements + if ( !elemData ) { + return; + } + + var events = elemData.events, + eventHandle = elemData.handle; + + if ( !events ) { + elemData.events = events = {}; + } + + if ( !eventHandle ) { + elemData.handle = eventHandle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.handle.apply( eventHandle.elem, arguments ) : + undefined; + }; + } + + // Add elem as a property of the handle function + // This is to prevent a memory leak with non-native events in IE. + eventHandle.elem = elem; + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = types.split(" "); + + var type, i = 0, namespaces; + + while ( (type = types[ i++ ]) ) { + handleObj = handleObjIn ? + jQuery.extend({}, handleObjIn) : + { handler: handler, data: data }; + + // Namespaced event handlers + if ( type.indexOf(".") > -1 ) { + namespaces = type.split("."); + type = namespaces.shift(); + handleObj.namespace = namespaces.slice(0).sort().join("."); + + } else { + namespaces = []; + handleObj.namespace = ""; + } + + handleObj.type = type; + if ( !handleObj.guid ) { + handleObj.guid = handler.guid; + } + + // Get the current list of functions bound to this event + var handlers = events[ type ], + special = jQuery.event.special[ type ] || {}; + + // Init the event handler queue + if ( !handlers ) { + handlers = events[ type ] = []; + + // Check for a special event handler + // Only use addEventListener/attachEvent if the special + // events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add the function to the element's handler list + handlers.push( handleObj ); + + // Keep track of which events have been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + global: {}, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, pos ) { + // don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + if ( handler === false ) { + handler = returnFalse; + } + + var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ), + events = elemData && elemData.events; + + if ( !elemData || !events ) { + return; + } + + // types is actually an event object here + if ( types && types.type ) { + handler = types.handler; + types = types.type; + } + + // Unbind all events for the element + if ( !types || typeof types === "string" && types.charAt(0) === "." ) { + types = types || ""; + + for ( type in events ) { + jQuery.event.remove( elem, type + types ); + } + + return; + } + + // Handle multiple events separated by a space + // jQuery(...).unbind("mouseover mouseout", fn); + types = types.split(" "); + + while ( (type = types[ i++ ]) ) { + origType = type; + handleObj = null; + all = type.indexOf(".") < 0; + namespaces = []; + + if ( !all ) { + // Namespaced event handlers + namespaces = type.split("."); + type = namespaces.shift(); + + namespace = new RegExp("(^|\\.)" + + jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + eventType = events[ type ]; + + if ( !eventType ) { + continue; + } + + if ( !handler ) { + for ( j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( all || namespace.test( handleObj.namespace ) ) { + jQuery.event.remove( elem, origType, handleObj.handler, j ); + eventType.splice( j--, 1 ); + } + } + + continue; + } + + special = jQuery.event.special[ type ] || {}; + + for ( j = pos || 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( handler.guid === handleObj.guid ) { + // remove the given handler for the given type + if ( all || namespace.test( handleObj.namespace ) ) { + if ( pos == null ) { + eventType.splice( j--, 1 ); + } + + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + + if ( pos != null ) { + break; + } + } + } + + // remove generic event handler if no more handlers exist + if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + ret = null; + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + var handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + delete elemData.events; + delete elemData.handle; + + if ( jQuery.isEmptyObject( elemData ) ) { + jQuery.removeData( elem, undefined, true ); + } + } + }, + + // Events that are safe to short-circuit if no handlers are attached. + // Native DOM events should not be added, they may have inline handlers. + customEvent: { + "getData": true, + "setData": true, + "changeData": true + }, + + trigger: function( event, data, elem, onlyHandlers ) { + // Event object or event type + var type = event.type || event, + namespaces = [], + exclusive; + + if ( type.indexOf("!") >= 0 ) { + // Exclusive events trigger only for the exact event (no namespaces) + type = type.slice(0, -1); + exclusive = true; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + + if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { + // No jQuery handlers for this event type, and it can't have inline handlers + return; + } + + // Caller can pass in an Event, Object, or just an event type string + event = typeof event === "object" ? + // jQuery.Event object + event[ jQuery.expando ] ? event : + // Object literal + new jQuery.Event( type, event ) : + // Just the event type (string) + new jQuery.Event( type ); + + event.type = type; + event.exclusive = exclusive; + event.namespace = namespaces.join("."); + event.namespace_re = new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)"); + + // triggerHandler() and global events don't bubble or run the default action + if ( onlyHandlers || !elem ) { + event.preventDefault(); + event.stopPropagation(); + } + + // Handle a global trigger + if ( !elem ) { + // TODO: Stop taunting the data cache; remove global events and always attach to document + jQuery.each( jQuery.cache, function() { + // internalKey variable is just used to make it easier to find + // and potentially change this stuff later; currently it just + // points to jQuery.expando + var internalKey = jQuery.expando, + internalCache = this[ internalKey ]; + if ( internalCache && internalCache.events && internalCache.events[ type ] ) { + jQuery.event.trigger( event, data, internalCache.handle.elem ); + } + }); + return; + } + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // Clean up the event in case it is being reused + event.result = undefined; + event.target = elem; + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data != null ? jQuery.makeArray( data ) : []; + data.unshift( event ); + + var cur = elem, + // IE doesn't like method names with a colon (#3533, #8272) + ontype = type.indexOf(":") < 0 ? "on" + type : ""; + + // Fire event on the current element, then bubble up the DOM tree + do { + var handle = jQuery._data( cur, "handle" ); + + event.currentTarget = cur; + if ( handle ) { + handle.apply( cur, data ); + } + + // Trigger an inline bound script + if ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) { + event.result = false; + event.preventDefault(); + } + + // Bubble up to document, then to window + cur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window; + } while ( cur && !event.isPropagationStopped() ); + + // If nobody prevented the default action, do it now + if ( !event.isDefaultPrevented() ) { + var old, + special = jQuery.event.special[ type ] || {}; + + if ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) && + !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction)() check here because IE6/7 fails that test. + // IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch. + try { + if ( ontype && elem[ type ] ) { + // Don't re-trigger an onFOO event when we call its FOO() method + old = elem[ ontype ]; + + if ( old ) { + elem[ ontype ] = null; + } + + jQuery.event.triggered = type; + elem[ type ](); + } + } catch ( ieError ) {} + + if ( old ) { + elem[ ontype ] = old; + } + + jQuery.event.triggered = undefined; + } + } + + return event.result; + }, + + handle: function( event ) { + event = jQuery.event.fix( event || window.event ); + // Snapshot the handlers list since a called handler may add/remove events. + var handlers = ((jQuery._data( this, "events" ) || {})[ event.type ] || []).slice(0), + run_all = !event.exclusive && !event.namespace, + args = Array.prototype.slice.call( arguments, 0 ); + + // Use the fix-ed Event rather than the (read-only) native event + args[0] = event; + event.currentTarget = this; + + for ( var j = 0, l = handlers.length; j < l; j++ ) { + var handleObj = handlers[ j ]; + + // Triggered event must 1) be non-exclusive and have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event. + if ( run_all || event.namespace_re.test( handleObj.namespace ) ) { + // Pass in a reference to the handler function itself + // So that we can later remove it + event.handler = handleObj.handler; + event.data = handleObj.data; + event.handleObj = handleObj; + + var ret = handleObj.handler.apply( this, args ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + return event.result; + }, + + props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // store a copy of the original event object + // and "clone" to set read-only properties + var originalEvent = event; + event = jQuery.Event( originalEvent ); + + for ( var i = this.props.length, prop; i; ) { + prop = this.props[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary + if ( !event.target ) { + // Fixes #1925 where srcElement might not be defined either + event.target = event.srcElement || document; + } + + // check if target is a textnode (safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && event.fromElement ) { + event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; + } + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && event.clientX != null ) { + var eventDocument = event.target.ownerDocument || document, + doc = eventDocument.documentElement, + body = eventDocument.body; + + event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); + event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); + } + + // Add which for key events + if ( event.which == null && (event.charCode != null || event.keyCode != null) ) { + event.which = event.charCode != null ? event.charCode : event.keyCode; + } + + // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) + if ( !event.metaKey && event.ctrlKey ) { + event.metaKey = event.ctrlKey; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && event.button !== undefined ) { + event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); + } + + return event; + }, + + // Deprecated, use jQuery.guid instead + guid: 1E8, + + // Deprecated, use jQuery.proxy instead + proxy: jQuery.proxy, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady, + teardown: jQuery.noop + }, + + live: { + add: function( handleObj ) { + jQuery.event.add( this, + liveConvert( handleObj.origType, handleObj.selector ), + jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); + }, + + remove: function( handleObj ) { + jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj ); + } + }, + + beforeunload: { + setup: function( data, namespaces, eventHandle ) { + // We only want to do this special case on windows + if ( jQuery.isWindow( this ) ) { + this.onbeforeunload = eventHandle; + } + }, + + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { + this.onbeforeunload = null; + } + } + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + if ( elem.detachEvent ) { + elem.detachEvent( "on" + type, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !this.preventDefault ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // timeStamp is buggy for some events on Firefox(#3843) + // So we won't rely on the native value + this.timeStamp = jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +function returnFalse() { + return false; +} +function returnTrue() { + return true; +} + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + preventDefault: function() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // otherwise set the returnValue property of the original event to false (IE) + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +// Checks if an event happened on an element within another element +// Used in jQuery.event.special.mouseenter and mouseleave handlers +var withinElement = function( event ) { + + // Check if mouse(over|out) are still within the same parent element + var related = event.relatedTarget, + inside = false, + eventType = event.type; + + event.type = event.data; + + if ( related !== this ) { + + if ( related ) { + inside = jQuery.contains( this, related ); + } + + if ( !inside ) { + + jQuery.event.handle.apply( this, arguments ); + + event.type = eventType; + } + } +}, + +// In case of event delegation, we only need to rename the event.type, +// liveHandler will take care of the rest. +delegate = function( event ) { + event.type = event.data; + jQuery.event.handle.apply( this, arguments ); +}; + +// Create mouseenter and mouseleave events +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + setup: function( data ) { + jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); + }, + teardown: function( data ) { + jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); + } + }; +}); + +// submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function( data, namespaces ) { + if ( !jQuery.nodeName( this, "form" ) ) { + jQuery.event.add(this, "click.specialSubmit", function( e ) { + // Avoid triggering error on non-existent type attribute in IE VML (#7071) + var elem = e.target, + type = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.type : ""; + + if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { + trigger( "submit", this, arguments ); + } + }); + + jQuery.event.add(this, "keypress.specialSubmit", function( e ) { + var elem = e.target, + type = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.type : ""; + + if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { + trigger( "submit", this, arguments ); + } + }); + + } else { + return false; + } + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialSubmit" ); + } + }; + +} + +// change delegation, happens here so we have bind. +if ( !jQuery.support.changeBubbles ) { + + var changeFilters, + + getVal = function( elem ) { + var type = jQuery.nodeName( elem, "input" ) ? elem.type : "", + val = elem.value; + + if ( type === "radio" || type === "checkbox" ) { + val = elem.checked; + + } else if ( type === "select-multiple" ) { + val = elem.selectedIndex > -1 ? + jQuery.map( elem.options, function( elem ) { + return elem.selected; + }).join("-") : + ""; + + } else if ( jQuery.nodeName( elem, "select" ) ) { + val = elem.selectedIndex; + } + + return val; + }, + + testChange = function testChange( e ) { + var elem = e.target, data, val; + + if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) { + return; + } + + data = jQuery._data( elem, "_change_data" ); + val = getVal(elem); + + // the current data will be also retrieved by beforeactivate + if ( e.type !== "focusout" || elem.type !== "radio" ) { + jQuery._data( elem, "_change_data", val ); + } + + if ( data === undefined || val === data ) { + return; + } + + if ( data != null || val ) { + e.type = "change"; + e.liveFired = undefined; + jQuery.event.trigger( e, arguments[1], elem ); + } + }; + + jQuery.event.special.change = { + filters: { + focusout: testChange, + + beforedeactivate: testChange, + + click: function( e ) { + var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; + + if ( type === "radio" || type === "checkbox" || jQuery.nodeName( elem, "select" ) ) { + testChange.call( this, e ); + } + }, + + // Change has to be called before submit + // Keydown will be called before keypress, which is used in submit-event delegation + keydown: function( e ) { + var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; + + if ( (e.keyCode === 13 && !jQuery.nodeName( elem, "textarea" ) ) || + (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || + type === "select-multiple" ) { + testChange.call( this, e ); + } + }, + + // Beforeactivate happens also before the previous element is blurred + // with this event you can't trigger a change event, but you can store + // information + beforeactivate: function( e ) { + var elem = e.target; + jQuery._data( elem, "_change_data", getVal(elem) ); + } + }, + + setup: function( data, namespaces ) { + if ( this.type === "file" ) { + return false; + } + + for ( var type in changeFilters ) { + jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); + } + + return rformElems.test( this.nodeName ); + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialChange" ); + + return rformElems.test( this.nodeName ); + } + }; + + changeFilters = jQuery.event.special.change.filters; + + // Handle when the input is .focus()'d + changeFilters.focus = changeFilters.beforeactivate; +} + +function trigger( type, elem, args ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + // Don't pass args or remember liveFired; they apply to the donor event. + var event = jQuery.extend( {}, args[ 0 ] ); + event.type = type; + event.originalEvent = {}; + event.liveFired = undefined; + jQuery.event.handle.call( elem, event ); + if ( event.isDefaultPrevented() ) { + args[ 0 ].preventDefault(); + } +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + + function handler( donor ) { + // Donor event is always a native one; fix it and switch its type. + // Let focusin/out handler cancel the donor focus/blur event. + var e = jQuery.event.fix( donor ); + e.type = fix; + e.originalEvent = {}; + jQuery.event.trigger( e, null, e.target ); + if ( e.isDefaultPrevented() ) { + donor.preventDefault(); + } + } + }); +} + +jQuery.each(["bind", "one"], function( i, name ) { + jQuery.fn[ name ] = function( type, data, fn ) { + var handler; + + // Handle object literals + if ( typeof type === "object" ) { + for ( var key in type ) { + this[ name ](key, data, type[key], fn); + } + return this; + } + + if ( arguments.length === 2 || data === false ) { + fn = data; + data = undefined; + } + + if ( name === "one" ) { + handler = function( event ) { + jQuery( this ).unbind( event, handler ); + return fn.apply( this, arguments ); + }; + handler.guid = fn.guid || jQuery.guid++; + } else { + handler = fn; + } + + if ( type === "unload" && name !== "one" ) { + this.one( type, data, fn ); + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.add( this[i], type, handler, data ); + } + } + + return this; + }; +}); + +jQuery.fn.extend({ + unbind: function( type, fn ) { + // Handle object literals + if ( typeof type === "object" && !type.preventDefault ) { + for ( var key in type ) { + this.unbind(key, type[key]); + } + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.remove( this[i], type, fn ); + } + } + + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.live( types, data, fn, selector ); + }, + + undelegate: function( selector, types, fn ) { + if ( arguments.length === 0 ) { + return this.unbind( "live" ); + + } else { + return this.die( types, null, fn, selector ); + } + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + + triggerHandler: function( type, data ) { + if ( this[0] ) { + return jQuery.event.trigger( type, data, this[0], true ); + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, + guid = fn.guid || jQuery.guid++, + i = 0, + toggler = function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + }; + + // link all the functions, so any of them can unbind this click handler + toggler.guid = guid; + while ( i < args.length ) { + args[ i++ ].guid = guid; + } + + return this.click( toggler ); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +var liveMap = { + focus: "focusin", + blur: "focusout", + mouseenter: "mouseover", + mouseleave: "mouseout" +}; + +jQuery.each(["live", "die"], function( i, name ) { + jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { + var type, i = 0, match, namespaces, preType, + selector = origSelector || this.selector, + context = origSelector ? this : jQuery( this.context ); + + if ( typeof types === "object" && !types.preventDefault ) { + for ( var key in types ) { + context[ name ]( key, data, types[key], selector ); + } + + return this; + } + + if ( name === "die" && !types && + origSelector && origSelector.charAt(0) === "." ) { + + context.unbind( origSelector ); + + return this; + } + + if ( data === false || jQuery.isFunction( data ) ) { + fn = data || returnFalse; + data = undefined; + } + + types = (types || "").split(" "); + + while ( (type = types[ i++ ]) != null ) { + match = rnamespaces.exec( type ); + namespaces = ""; + + if ( match ) { + namespaces = match[0]; + type = type.replace( rnamespaces, "" ); + } + + if ( type === "hover" ) { + types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); + continue; + } + + preType = type; + + if ( liveMap[ type ] ) { + types.push( liveMap[ type ] + namespaces ); + type = type + namespaces; + + } else { + type = (liveMap[ type ] || type) + namespaces; + } + + if ( name === "live" ) { + // bind live handler + for ( var j = 0, l = context.length; j < l; j++ ) { + jQuery.event.add( context[j], "live." + liveConvert( type, selector ), + { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); + } + + } else { + // unbind live handler + context.unbind( "live." + liveConvert( type, selector ), fn ); + } + } + + return this; + }; +}); + +function liveHandler( event ) { + var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret, + elems = [], + selectors = [], + events = jQuery._data( this, "events" ); + + // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911) + if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) { + return; + } + + if ( event.namespace ) { + namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + event.liveFired = this; + + var live = events.live.slice(0); + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { + selectors.push( handleObj.selector ); + + } else { + live.splice( j--, 1 ); + } + } + + match = jQuery( event.target ).closest( selectors, event.currentTarget ); + + for ( i = 0, l = match.length; i < l; i++ ) { + close = match[i]; + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) { + elem = close.elem; + related = null; + + // Those two events require additional checking + if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { + event.type = handleObj.preType; + related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; + + // Make sure not to accidentally match a child element with the same selector + if ( related && jQuery.contains( elem, related ) ) { + related = elem; + } + } + + if ( !related || related !== elem ) { + elems.push({ elem: elem, handleObj: handleObj, level: close.level }); + } + } + } + } + + for ( i = 0, l = elems.length; i < l; i++ ) { + match = elems[i]; + + if ( maxLevel && match.level > maxLevel ) { + break; + } + + event.currentTarget = match.elem; + event.data = match.handleObj.data; + event.handleObj = match.handleObj; + + ret = match.handleObj.origHandler.apply( match.elem, arguments ); + + if ( ret === false || event.isPropagationStopped() ) { + maxLevel = match.level; + + if ( ret === false ) { + stop = false; + } + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + + return stop; +} + +function liveConvert( type, selector ) { + return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspaces, "&"); +} + +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } +}); + + + +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true, + rBackslash = /\\/g, + rNonWord = /\W/; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function() { + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function( selector, context, results, seed ) { + results = results || []; + context = context || document; + + var origContext = context; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var m, set, checkSet, extra, ret, cur, pop, i, + prune = true, + contextXML = Sizzle.isXML( context ), + parts = [], + soFar = selector; + + // Reset the position of the chunker regexp (start from head) + do { + chunker.exec( "" ); + m = chunker.exec( soFar ); + + if ( m ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + } while ( m ); + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context ); + + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set ); + } + } + + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + + ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? + Sizzle.filter( ret.expr, ret.set )[0] : + ret.set[0]; + } + + if ( context ) { + ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + + set = ret.expr ? + Sizzle.filter( ret.expr, ret.set ) : + ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray( set ); + + } else { + prune = false; + } + + while ( parts.length ) { + cur = parts.pop(); + pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + Sizzle.error( cur || selector ); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + + } else if ( context && context.nodeType === 1 ) { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + + } else { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function( results ) { + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[ i - 1 ] ) { + results.splice( i--, 1 ); + } + } + } + } + + return results; +}; + +Sizzle.matches = function( expr, set ) { + return Sizzle( expr, null, null, set ); +}; + +Sizzle.matchesSelector = function( node, expr ) { + return Sizzle( expr, null, null, [node] ).length > 0; +}; + +Sizzle.find = function( expr, context, isXML ) { + var set; + + if ( !expr ) { + return []; + } + + for ( var i = 0, l = Expr.order.length; i < l; i++ ) { + var match, + type = Expr.order[i]; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + var left = match[1]; + match.splice( 1, 1 ); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace( rBackslash, "" ); + set = Expr.find[ type ]( match, context, isXML ); + + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = typeof context.getElementsByTagName !== "undefined" ? + context.getElementsByTagName( "*" ) : + []; + } + + return { set: set, expr: expr }; +}; + +Sizzle.filter = function( expr, set, inplace, not ) { + var match, anyFound, + old = expr, + result = [], + curLoop = set, + isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); + + while ( expr && set.length ) { + for ( var type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + var found, item, + filter = Expr.filter[ type ], + left = match[1]; + + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( var i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + var pass = not ^ !!found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + + } else { + curLoop[i] = false; + } + + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw "Syntax error, unrecognized expression: " + msg; +}; + +var Expr = Sizzle.selectors = { + order: [ "ID", "NAME", "TAG" ], + + match: { + ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, + ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, + TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, + CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, + POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, + PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ + }, + + leftMatch: {}, + + attrMap: { + "class": "className", + "for": "htmlFor" + }, + + attrHandle: { + href: function( elem ) { + return elem.getAttribute( "href" ); + }, + type: function( elem ) { + return elem.getAttribute( "type" ); + } + }, + + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !rNonWord.test( part ), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + + ">": function( checkSet, part ) { + var elem, + isPartStr = typeof part === "string", + i = 0, + l = checkSet.length; + + if ( isPartStr && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + + } else { + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + + "": function(checkSet, part, isXML){ + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); + }, + + "~": function( checkSet, part, isXML ) { + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); + } + }, + + find: { + ID: function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }, + + NAME: function( match, context ) { + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], + results = context.getElementsByName( match[1] ); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + + TAG: function( match, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( match[1] ); + } + } + }, + preFilter: { + CLASS: function( match, curLoop, inplace, result, not, isXML ) { + match = " " + match[1].replace( rBackslash, "" ) + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + + ID: function( match ) { + return match[1].replace( rBackslash, "" ); + }, + + TAG: function( match, curLoop ) { + return match[1].replace( rBackslash, "" ).toLowerCase(); + }, + + CHILD: function( match ) { + if ( match[1] === "nth" ) { + if ( !match[2] ) { + Sizzle.error( match[0] ); + } + + match[2] = match[2].replace(/^\+|\s*/g, ''); + + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + else if ( match[2] ) { + Sizzle.error( match[0] ); + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + + ATTR: function( match, curLoop, inplace, result, not, isXML ) { + var name = match[1] = match[1].replace( rBackslash, "" ); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + // Handle if an un-quoted value was used + match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + + PSEUDO: function( match, curLoop, inplace, result, not ) { + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + + if ( !inplace ) { + result.push.apply( result, ret ); + } + + return false; + } + + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + + POS: function( match ) { + match.unshift( true ); + + return match; + } + }, + + filters: { + enabled: function( elem ) { + return elem.disabled === false && elem.type !== "hidden"; + }, + + disabled: function( elem ) { + return elem.disabled === true; + }, + + checked: function( elem ) { + return elem.checked === true; + }, + + selected: function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + parent: function( elem ) { + return !!elem.firstChild; + }, + + empty: function( elem ) { + return !elem.firstChild; + }, + + has: function( elem, i, match ) { + return !!Sizzle( match[3], elem ).length; + }, + + header: function( elem ) { + return (/h\d/i).test( elem.nodeName ); + }, + + text: function( elem ) { + var attr = elem.getAttribute( "type" ), type = elem.type; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); + }, + + radio: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; + }, + + checkbox: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; + }, + + file: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; + }, + + password: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; + }, + + submit: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "submit" === elem.type; + }, + + image: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; + }, + + reset: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "reset" === elem.type; + }, + + button: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && "button" === elem.type || name === "button"; + }, + + input: function( elem ) { + return (/input|select|textarea|button/i).test( elem.nodeName ); + }, + + focus: function( elem ) { + return elem === elem.ownerDocument.activeElement; + } + }, + setFilters: { + first: function( elem, i ) { + return i === 0; + }, + + last: function( elem, i, match, array ) { + return i === array.length - 1; + }, + + even: function( elem, i ) { + return i % 2 === 0; + }, + + odd: function( elem, i ) { + return i % 2 === 1; + }, + + lt: function( elem, i, match ) { + return i < match[3] - 0; + }, + + gt: function( elem, i, match ) { + return i > match[3] - 0; + }, + + nth: function( elem, i, match ) { + return match[3] - 0 === i; + }, + + eq: function( elem, i, match ) { + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function( elem, match, i, array ) { + var name = match[1], + filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; + + } else if ( name === "not" ) { + var not = match[3]; + + for ( var j = 0, l = not.length; j < l; j++ ) { + if ( not[j] === elem ) { + return false; + } + } + + return true; + + } else { + Sizzle.error( name ); + } + }, + + CHILD: function( elem, match ) { + var type = match[1], + node = elem; + + switch ( type ) { + case "only": + case "first": + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + if ( type === "first" ) { + return true; + } + + node = elem; + + case "last": + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + return true; + + case "nth": + var first = match[2], + last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + var doneName = match[0], + parent = elem.parentNode; + + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { + var count = 0; + + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + + parent.sizcache = doneName; + } + + var diff = elem.nodeIndex - last; + + if ( first === 0 ) { + return diff === 0; + + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + + ID: function( elem, match ) { + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + + TAG: function( elem, match ) { + return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; + }, + + CLASS: function( elem, match ) { + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + + ATTR: function( elem, match ) { + var name = match[1], + result = Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + + POS: function( elem, match, i, array ) { + var name = match[2], + filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS, + fescape = function(all, num){ + return "\\" + (num - 0 + 1); + }; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); +} + +var makeArray = function( array, results ) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; + +// Provide a fallback method if it does not work +} catch( e ) { + makeArray = function( array, results ) { + var i = 0, + ret = results || []; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + + } else { + if ( typeof array.length === "number" ) { + for ( var l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + + } else { + for ( ; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder, siblingCheck; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + return a.compareDocumentPosition ? -1 : 1; + } + + return a.compareDocumentPosition(b) & 4 ? -1 : 1; + }; + +} else { + sortOrder = function( a, b ) { + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Fallback to using sourceIndex (in IE) if it's available on both nodes + } else if ( a.sourceIndex && b.sourceIndex ) { + return a.sourceIndex - b.sourceIndex; + } + + var al, bl, + ap = [], + bp = [], + aup = a.parentNode, + bup = b.parentNode, + cur = aup; + + // If the nodes are siblings (or identical) we can do a quick check + if ( aup === bup ) { + return siblingCheck( a, b ); + + // If no parents were found then the nodes are disconnected + } else if ( !aup ) { + return -1; + + } else if ( !bup ) { + return 1; + } + + // Otherwise they're somewhere else in the tree so we need + // to build up a full list of the parentNodes for comparison + while ( cur ) { + ap.unshift( cur ); + cur = cur.parentNode; + } + + cur = bup; + + while ( cur ) { + bp.unshift( cur ); + cur = cur.parentNode; + } + + al = ap.length; + bl = bp.length; + + // Start walking down the tree looking for a discrepancy + for ( var i = 0; i < al && i < bl; i++ ) { + if ( ap[i] !== bp[i] ) { + return siblingCheck( ap[i], bp[i] ); + } + } + + // We ended someplace up the tree so do a sibling check + return i === al ? + siblingCheck( a, bp[i], -1 ) : + siblingCheck( ap[i], b, 1 ); + }; + + siblingCheck = function( a, b, ret ) { + if ( a === b ) { + return ret; + } + + var cur = a.nextSibling; + + while ( cur ) { + if ( cur === b ) { + return -1; + } + + cur = cur.nextSibling; + } + + return 1; + }; +} + +// Utility function for retreiving the text value of an array of DOM nodes +Sizzle.getText = function( elems ) { + var ret = "", elem; + + for ( var i = 0; elems[i]; i++ ) { + elem = elems[i]; + + // Get the text from text nodes and CDATA nodes + if ( elem.nodeType === 3 || elem.nodeType === 4 ) { + ret += elem.nodeValue; + + // Traverse everything else, except comment nodes + } else if ( elem.nodeType !== 8 ) { + ret += Sizzle.getText( elem.childNodes ); + } + } + + return ret; +}; + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date()).getTime(), + root = document.documentElement; + + form.innerHTML = ""; + + // Inject it into the root element, check its status, and remove it quickly + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + + return m ? + m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? + [m] : + undefined : + []; + } + }; + + Expr.filter.ID = function( elem, match ) { + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + + // release memory in IE + root = form = null; +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function( match, context ) { + var results = context.getElementsByTagName( match[1] ); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = ""; + + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + + Expr.attrHandle.href = function( elem ) { + return elem.getAttribute( "href", 2 ); + }; + } + + // release memory in IE + div = null; +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, + div = document.createElement("div"), + id = "__sizzle__"; + + div.innerHTML = "

"; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function( query, context, extra, seed ) { + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && !Sizzle.isXML(context) ) { + // See if we find a selector to speed up + var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); + + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { + // Speed-up: Sizzle("TAG") + if ( match[1] ) { + return makeArray( context.getElementsByTagName( query ), extra ); + + // Speed-up: Sizzle(".CLASS") + } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { + return makeArray( context.getElementsByClassName( match[2] ), extra ); + } + } + + if ( context.nodeType === 9 ) { + // Speed-up: Sizzle("body") + // The body element only exists once, optimize finding it + if ( query === "body" && context.body ) { + return makeArray( [ context.body ], extra ); + + // Speed-up: Sizzle("#ID") + } else if ( match && match[3] ) { + var elem = context.getElementById( match[3] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id === match[3] ) { + return makeArray( [ elem ], extra ); + } + + } else { + return makeArray( [], extra ); + } + } + + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(qsaError) {} + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + var oldContext = context, + old = context.getAttribute( "id" ), + nid = old || id, + hasParent = context.parentNode, + relativeHierarchySelector = /^\s*[+~]/.test( query ); + + if ( !old ) { + context.setAttribute( "id", nid ); + } else { + nid = nid.replace( /'/g, "\\$&" ); + } + if ( relativeHierarchySelector && hasParent ) { + context = context.parentNode; + } + + try { + if ( !relativeHierarchySelector || hasParent ) { + return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); + } + + } catch(pseudoError) { + } finally { + if ( !old ) { + oldContext.removeAttribute( "id" ); + } + } + } + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + // release memory in IE + div = null; + })(); +} + +(function(){ + var html = document.documentElement, + matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; + + if ( matches ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9 fails this) + var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), + pseudoWorks = false; + + try { + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( document.documentElement, "[test!='']:sizzle" ); + + } catch( pseudoError ) { + pseudoWorks = true; + } + + Sizzle.matchesSelector = function( node, expr ) { + // Make sure that attribute selectors are quoted + expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); + + if ( !Sizzle.isXML( node ) ) { + try { + if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { + var ret = matches.call( node, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || !disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9, so check for that + node.document && node.document.nodeType !== 11 ) { + return ret; + } + } + } catch(e) {} + } + + return Sizzle(expr, null, null, [node]).length > 0; + }; + } +})(); + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "
"; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function( match, context, isXML ) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + // release memory in IE + div = null; +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +if ( document.documentElement.contains ) { + Sizzle.contains = function( a, b ) { + return a !== b && (a.contains ? a.contains(b) : true); + }; + +} else if ( document.documentElement.compareDocumentPosition ) { + Sizzle.contains = function( a, b ) { + return !!(a.compareDocumentPosition(b) & 16); + }; + +} else { + Sizzle.contains = function() { + return false; + }; +} + +Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function( selector, context ) { + var match, + tmpSet = [], + later = "", + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.filters; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})(); + + +var runtil = /Until$/, + rparentsprev = /^(?:parents|prevUntil|prevAll)/, + // Note: This RegExp should be improved, or likely pulled from Sizzle + rmultiselector = /,/, + isSimple = /^.[^:#\[\.,]*$/, + slice = Array.prototype.slice, + POS = jQuery.expr.match.POS, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var self = this, + i, l; + + if ( typeof selector !== "string" ) { + return jQuery( selector ).filter(function() { + for ( i = 0, l = self.length; i < l; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }); + } + + var ret = this.pushStack( "", "find", selector ), + length, n, r; + + for ( i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( n = length; n < ret.length; n++ ) { + for ( r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + has: function( target ) { + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false), "not", selector); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && ( typeof selector === "string" ? + jQuery.filter( selector, this ).length > 0 : + this.filter( selector ).length > 0 ); + }, + + closest: function( selectors, context ) { + var ret = [], i, l, cur = this[0]; + + // Array + if ( jQuery.isArray( selectors ) ) { + var match, selector, + matches = {}, + level = 1; + + if ( cur && selectors.length ) { + for ( i = 0, l = selectors.length; i < l; i++ ) { + selector = selectors[i]; + + if ( !matches[ selector ] ) { + matches[ selector ] = POS.test( selector ) ? + jQuery( selector, context || this.context ) : + selector; + } + } + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( selector in matches ) { + match = matches[ selector ]; + + if ( match.jquery ? match.index( cur ) > -1 : jQuery( cur ).is( match ) ) { + ret.push({ selector: selector, elem: cur, level: level }); + } + } + + cur = cur.parentNode; + level++; + } + } + + return ret; + } + + // String + var pos = POS.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( i = 0, l = this.length; i < l; i++ ) { + cur = this[i]; + + while ( cur ) { + if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + + } else { + cur = cur.parentNode; + if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { + break; + } + } + } + } + + ret = ret.length > 1 ? jQuery.unique( ret ) : ret; + + return this.pushStack( ret, "closest", selectors ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + andSelf: function() { + return this.add( this.prevObject ); + } +}); + +// A painfully simple check to see if an element is disconnected +// from a document (should be improved, where feasible). +function isDisconnected( node ) { + return !node || !node.parentNode || node.parentNode.nodeType === 11; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return jQuery.nth( elem, 2, "nextSibling" ); + }, + prev: function( elem ) { + return jQuery.nth( elem, 2, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( elem.parentNode.firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.makeArray( elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ), + // The variable 'args' was introduced in + // https://github.com/jquery/jquery/commit/52a0238 + // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. + // http://code.google.com/p/v8/issues/detail?id=1050 + args = slice.call(arguments); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, args.join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + nth: function( cur, result, dir, elem ) { + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, keep ) { + + // Can't pass null or undefined to indexOf in Firefox 4 + // Set to 0 to skip string check + qualifier = qualifier || 0; + + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + var retVal = !!qualifier.call( elem, i, elem ); + return retVal === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return (elem === qualifier) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return (jQuery.inArray( elem, qualifier ) >= 0) === keep; + }); +} + + + + +var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, + rtagName = /<([\w:]+)/, + rtbody = /", "" ], + legend: [ 1, "
", "
" ], + thead: [ 1, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + col: [ 2, "", "
" ], + area: [ 1, "", "" ], + _default: [ 0, "", "" ] + }; + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize and \ No newline at end of file diff --git a/Azure/WebSite_WindowsAzure/Views/Admin/Certificates.cshtml b/Azure/WebSite_WindowsAzure/Views/Admin/Certificates.cshtml new file mode 100644 index 0000000..e6e446f --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Views/Admin/Certificates.cshtml @@ -0,0 +1,85 @@ +@model Thinktecture.IdentityServer.Web.ViewModels.Administration.EditCertificatesModel + +@{ + ViewBag.Title = "Certificates Configuration"; +} + +

+ Certificates Configuration + (help) +

+ + + + +@using (Html.BeginForm()) { + @Html.ValidationSummary(true) + @Html.AntiForgeryToken() + +
+ Configuration + +
+ @Html.LabelFor(model => model.SslCertificate) +
+
+ @Model.SslCertificate + @Html.ValidationMessageFor(model => model.SslCertificate) +
+ +
+ @Html.EditorFor(model => model.UpdateSslCertificate) + @Html.LabelFor(model => model.UpdateSslCertificate) + @Html.ValidationMessageFor(model => model.UpdateSslCertificate) + + @Html.DropDownList("UpdatedSslCertificate", Model.AvailableCertificatesList) +
+ +
+ @Html.LabelFor(model => model.SigningCertificate) +
+
+ @Model.SigningCertificate + @Html.ValidationMessageFor(model => model.SigningCertificate) +
+ +
+ @Html.EditorFor(model => model.UpdateSigningCertificate) + @Html.LabelFor(model => model.UpdateSigningCertificate) + @Html.ValidationMessageFor(model => model.UpdateSigningCertificate) + + @Html.DropDownList("UpdatedSigningCertificate", Model.AvailableCertificatesList) +
+ + @if (ViewBag.SaveEnabled) + { +

+ +

+ } +
+} + +
+ @Html.ActionLink("Back", "Index") +
+ +@if (false) +{ + \ No newline at end of file diff --git a/Azure/WebSite_WindowsAzure/Views/Admin/Configuration.cshtml b/Azure/WebSite_WindowsAzure/Views/Admin/Configuration.cshtml new file mode 100644 index 0000000..ef63ef5 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Views/Admin/Configuration.cshtml @@ -0,0 +1,37 @@ +@model Thinktecture.IdentityServer.Web.ViewModels.Administration.GlobalConfigurationModel + +@{ + ViewBag.Title = "Global Token Service Configuration"; +} + +

+ Global Token Service Configuration + (help) +

+ + + + +@using (Html.BeginForm()) +{ + @Html.ValidationSummary(true) + @Html.AntiForgeryToken() + +
+ Configuration + + @Html.EditorForModel() + + @if (ViewBag.SaveEnabled) + { +

+ +

+ } +
+} + +
+ @Html.ActionLink("Back", "Index") +
+ diff --git a/Azure/WebSite_WindowsAzure/Views/Admin/Endpoints.cshtml b/Azure/WebSite_WindowsAzure/Views/Admin/Endpoints.cshtml new file mode 100644 index 0000000..ff19298 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Views/Admin/Endpoints.cshtml @@ -0,0 +1,37 @@ +@model Thinktecture.IdentityServer.Web.ViewModels.Administration.EndpointConfigurationModel + +@{ + ViewBag.Title = "Endpoint Configuration"; +} + +

+ Endpoint Configuration + (help) +

+ + + + +@using (Html.BeginForm()) +{ + @Html.ValidationSummary(true) + @Html.AntiForgeryToken() + +
+ Configuration + + @Html.EditorForModel() + + @if (ViewBag.SaveEnabled) + { +

+ +

+ } +
+} + +
+ @Html.ActionLink("Back", "Index") +
+ diff --git a/Azure/WebSite_WindowsAzure/Views/Admin/Index.cshtml b/Azure/WebSite_WindowsAzure/Views/Admin/Index.cshtml new file mode 100644 index 0000000..ee527d1 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Views/Admin/Index.cshtml @@ -0,0 +1,41 @@ +@{ + ViewBag.Title = "Administration"; +} + +

Administration

+ +

+ @Html.ActionLink("My Claims", "myclaims") +

+ +

+ @Html.ActionLink("My Token", "mytoken") +

+ +

+ @Html.ActionLink("Global Configuration", "configuration") +

+ +

+ @Html.ActionLink("Endpoint Configuration", "endpoints") +

+ +

+ @Html.ActionLink("Service Certificates", "certificates") +

+ +

+ @Html.ActionLink("Relying Parties", "index", "RelyingPartiesAdmin") +

+ +

+ @Html.ActionLink("Client Certificates", "index", "ClientCertificatesAdmin") +

+ +

+ @Html.ActionLink("Delegation", "index", "DelegationAdmin") +

+ +

+ @Html.ActionLink("Recycle IdentityServer", "restart") +

diff --git a/Azure/WebSite_WindowsAzure/Views/Admin/MyClaims.cshtml b/Azure/WebSite_WindowsAzure/Views/Admin/MyClaims.cshtml new file mode 100644 index 0000000..a3a2dab --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Views/Admin/MyClaims.cshtml @@ -0,0 +1,16 @@ +@model Thinktecture.IdentityServer.Web.ViewModels.Administration.MyModel + +@{ + ViewBag.Title = "My Claims"; +} + +

My Claims

+ +@foreach (var claim in Model.Claims) +{ +

+ @claim.ClaimType +
+ @claim.Value +

+} diff --git a/Azure/WebSite_WindowsAzure/Views/ClientCertificatesAdmin/Add.cshtml b/Azure/WebSite_WindowsAzure/Views/ClientCertificatesAdmin/Add.cshtml new file mode 100644 index 0000000..fee399f --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Views/ClientCertificatesAdmin/Add.cshtml @@ -0,0 +1,60 @@ +@model Thinktecture.IdentityServer.Web.ViewModels.Administration.AddClientCertificateModel + +@{ + ViewBag.Title = "Add"; +} + +

+ Add + (help) +

+ + + + +@using (Html.BeginForm("add", "ClientCertificatesAdmin", FormMethod.Post, new { enctype = "multipart/form-data" })) +{ + @Html.AntiForgeryToken() + @Html.ValidationSummary(true) + +
+ Client Certificate + +
+ @Html.LabelFor(model => model.UserName) +
+
+ @Html.EditorFor(model => model.UserName) + @Html.ValidationMessageFor(model => model.UserName) +
+ +
+ @Html.LabelFor(model => model.Description) +
+
+ @Html.EditorFor(model => model.Description) + @Html.ValidationMessageFor(model => model.Description) +
+ +
+ @Html.LabelFor(model => model.Thumbprint) +
+
+ @Html.EditorFor(model => model.Thumbprint) + @Html.ValidationMessageFor(model => model.Thumbprint) +
+ +
+ +
+ +

+ +

+
+} + +
+ @Html.ActionLink("Back", "Index") +
+ diff --git a/Azure/WebSite_WindowsAzure/Views/ClientCertificatesAdmin/Delete.cshtml b/Azure/WebSite_WindowsAzure/Views/ClientCertificatesAdmin/Delete.cshtml new file mode 100644 index 0000000..a4497ad --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Views/ClientCertificatesAdmin/Delete.cshtml @@ -0,0 +1,16 @@ +@{ + ViewBag.Title = "Delete"; +} + +

Delete

+ +@using (Html.BeginForm()) +{ + @Html.AntiForgeryToken() + @Html.ValidationSummary() + + +
+
+ +} diff --git a/Azure/WebSite_WindowsAzure/Views/ClientCertificatesAdmin/Edit.cshtml b/Azure/WebSite_WindowsAzure/Views/ClientCertificatesAdmin/Edit.cshtml new file mode 100644 index 0000000..8afff9b --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Views/ClientCertificatesAdmin/Edit.cshtml @@ -0,0 +1,32 @@ +@model Thinktecture.IdentityServer.Web.ViewModels.Administration.EditClientCertificatesModel + +@{ + ViewBag.Title = "Edit"; +} + +

+ Edit Client Certificates for @Model.UserName + (help) +

+ +

+ @Html.ActionLink("Add New", "Add") +

+ +
    + @foreach (var cert in Model.ClientCertificates) + { +
  • + @cert.Description +
    + @cert.Thumbprint + @Html.ActionLink("(delete)", "delete", new { userName = Model.UserName, thumbprint = cert.Thumbprint }) +
    +
    +
  • + } +
+ +

+ @Html.ActionLink("Back", "Index") +

diff --git a/Azure/WebSite_WindowsAzure/Views/ClientCertificatesAdmin/Index.cshtml b/Azure/WebSite_WindowsAzure/Views/ClientCertificatesAdmin/Index.cshtml new file mode 100644 index 0000000..1eddd39 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Views/ClientCertificatesAdmin/Index.cshtml @@ -0,0 +1,28 @@ +@model List + +@{ + ViewBag.Title = "Client Certificates"; +} + +

Client Certificates

+ +

+ @Html.ActionLink("Add New", "add") +

+ +
    + @foreach (var user in Model) + { +
  • + @user + @Html.ActionLink("(edit)", "edit", new { username = user }) + @Html.ActionLink("(delete)", "deleteall", new { username = user }) +
  • + } +
+ +

+ @Html.ActionLink("Back", "index", "admin") +

+ + diff --git a/Azure/WebSite_WindowsAzure/Views/DelegationAdmin/Add.cshtml b/Azure/WebSite_WindowsAzure/Views/DelegationAdmin/Add.cshtml new file mode 100644 index 0000000..6a93fbb --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Views/DelegationAdmin/Add.cshtml @@ -0,0 +1,56 @@ +@model Thinktecture.IdentityServer.Web.ViewModels.Administration.AddDelegationModel + +@{ + ViewBag.Title = "Add"; +} + +

+ Add + (help) +

+ + + + +@using (Html.BeginForm()) +{ + @Html.AntiForgeryToken() + @Html.ValidationSummary(true) + +
+ Delegation + +
+ @Html.LabelFor(model => model.UserName) +
+
+ @Html.EditorFor(model => model.UserName) + @Html.ValidationMessageFor(model => model.UserName) +
+ +
+ @Html.LabelFor(model => model.Description) +
+
+ @Html.EditorFor(model => model.Description) + @Html.ValidationMessageFor(model => model.Description) +
+ +
+ @Html.LabelFor(model => model.Realm) +
+
+ @Html.EditorFor(model => model.Realm) + @Html.ValidationMessageFor(model => model.Realm) +
+ +

+ +

+
+} + +
+ @Html.ActionLink("Back", "Index") +
+ diff --git a/Azure/WebSite_WindowsAzure/Views/DelegationAdmin/Delete.cshtml b/Azure/WebSite_WindowsAzure/Views/DelegationAdmin/Delete.cshtml new file mode 100644 index 0000000..a4497ad --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Views/DelegationAdmin/Delete.cshtml @@ -0,0 +1,16 @@ +@{ + ViewBag.Title = "Delete"; +} + +

Delete

+ +@using (Html.BeginForm()) +{ + @Html.AntiForgeryToken() + @Html.ValidationSummary() + + +
+
+ +} diff --git a/Azure/WebSite_WindowsAzure/Views/DelegationAdmin/Edit.cshtml b/Azure/WebSite_WindowsAzure/Views/DelegationAdmin/Edit.cshtml new file mode 100644 index 0000000..983ecab --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Views/DelegationAdmin/Edit.cshtml @@ -0,0 +1,32 @@ +@model Thinktecture.IdentityServer.Web.ViewModels.Administration.EditDelegationModel + +@{ + ViewBag.Title = "Edit"; +} + +

+ Edit Delegation Settings for @Model.UserName + (help) +

+ +

+ @Html.ActionLink("Add New", "Add") +

+ +
    + @foreach (var setting in Model.Settings) + { +
  • + @setting.Description +
    + @setting.Realm.AbsoluteUri + @Html.ActionLink("(delete)", "delete", new { userName = Model.UserName, realm = setting.Realm.AbsoluteUri }) +
    +
    +
  • + } +
+ +

+ @Html.ActionLink("Back", "Index") +

diff --git a/Azure/WebSite_WindowsAzure/Views/DelegationAdmin/Index.cshtml b/Azure/WebSite_WindowsAzure/Views/DelegationAdmin/Index.cshtml new file mode 100644 index 0000000..c669315 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Views/DelegationAdmin/Index.cshtml @@ -0,0 +1,28 @@ +@model IEnumerable + +@{ + ViewBag.Title = "Delegation"; +} + +

Delegation

+ +

+ @Html.ActionLink("Add New", "add") +

+ +
    + @foreach (var user in Model) + { +
  • + @user + @Html.ActionLink("(edit)", "edit", new { username = user }) + @Html.ActionLink("(delete)", "deleteall", new { username = user }) +
  • + } +
+ +

+ @Html.ActionLink("Back", "index", "admin") +

+ + diff --git a/Azure/WebSite_WindowsAzure/Views/Home/AppIntegration.cshtml b/Azure/WebSite_WindowsAzure/Views/Home/AppIntegration.cshtml new file mode 100644 index 0000000..3123dfe --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Views/Home/AppIntegration.cshtml @@ -0,0 +1,16 @@ +@model Dictionary + +@{ + ViewBag.Title = "Application Integration"; +} + +

Application Integration

+ +@foreach (var pair in Model) +{ +

+ @pair.Key +
+ @pair.Value +

+} \ No newline at end of file diff --git a/Azure/WebSite_WindowsAzure/Views/Home/Index.cshtml b/Azure/WebSite_WindowsAzure/Views/Home/Index.cshtml new file mode 100644 index 0000000..44a2992 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Views/Home/Index.cshtml @@ -0,0 +1,13 @@ +@{ + ViewBag.Title = ViewBag.SiteName; +} + +

Welcome to thinktecture Identity Server

+ +

+ @Html.ActionLink("View WS-Federation Metadata", "Generate", "FederationMetadata") +

+ +

+ @Html.ActionLink("Application integration", "appintegration", "home") +

\ No newline at end of file diff --git a/Azure/WebSite_WindowsAzure/Views/InitialConfiguration/Index.cshtml b/Azure/WebSite_WindowsAzure/Views/InitialConfiguration/Index.cshtml new file mode 100644 index 0000000..e22fed0 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Views/InitialConfiguration/Index.cshtml @@ -0,0 +1,49 @@ +@model Thinktecture.IdentityServer.Web.ViewModels.InitialConfigurationModel + +@{ + ViewBag.Title = "Initial Configuration"; +} + +

+ Initial Configuration + (help) +

+ + +@using (Html.BeginForm()) +{ + @Html.ValidationSummary(true) + +
+ Settings + +
+ @Html.LabelFor(model => model.SiteName) +
+
+ @Html.EditorFor(model => model.SiteName) + @Html.ValidationMessageFor(model => model.SiteName) +
+ +
+ @Html.LabelFor(model => model.IssuerUri) +
+
+ @Html.EditorFor(model => model.IssuerUri) + @Html.ValidationMessageFor(model => model.IssuerUri) +
+ +
+ @Html.LabelFor(model => model.SigningCertificate) +
+ +
+ @Html.DropDownList("SigningCertificate", Model.AvailableCertificatesList) +
+ +

+ +

+
+ +} \ No newline at end of file diff --git a/Azure/WebSite_WindowsAzure/Views/RelyingPartiesAdmin/Add.cshtml b/Azure/WebSite_WindowsAzure/Views/RelyingPartiesAdmin/Add.cshtml new file mode 100644 index 0000000..36748c1 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Views/RelyingPartiesAdmin/Add.cshtml @@ -0,0 +1,116 @@ +@model Thinktecture.IdentityServer.Web.ViewModels.Administration.RelyingPartyModel + +@{ + ViewBag.Title = "Add new Relying Party"; +} + +

+ Add new Relying Party + (help) +

+ + + + +@using (Html.BeginForm("Add", "RelyingPartiesAdmin", FormMethod.Post, new { enctype = "multipart/form-data" })) +{ + @Html.AntiForgeryToken() + @Html.ValidationSummary(true) + +
+ Relying Party Details + +
+ @Html.LabelFor(model => model.Name) +
+
+ @Html.EditorFor(model => model.Name) + @Html.ValidationMessageFor(model => model.Name) +
+ +
+ @Html.LabelFor(model => model.Realm) +
+
+ @Html.EditorFor(model => model.Realm) + @Html.ValidationMessageFor(model => model.Realm) +
+ +
+ @Html.LabelFor(model => model.ReplyTo) +
+
+ @Html.EditorFor(model => model.ReplyTo) + @Html.ValidationMessageFor(model => model.ReplyTo) +
+ +
+ @Html.LabelFor(model => model.ExtraData1) +
+
+ @Html.EditorFor(model => model.ExtraData1) + @Html.ValidationMessageFor(model => model.ExtraData1) +
+ +
+ @Html.LabelFor(model => model.ExtraData2) +
+
+ @Html.EditorFor(model => model.ExtraData2) + @Html.ValidationMessageFor(model => model.ExtraData2) +
+ +
+ @Html.LabelFor(model => model.ExtraData3) +
+
+ @Html.EditorFor(model => model.ExtraData3) + @Html.ValidationMessageFor(model => model.ExtraData3) +
+ +
+ @Html.LabelFor(model => model.EncryptingCertificate) +
+
+ @Html.EditorFor(model => model.EncryptingCertificate) + @Html.ValidationMessageFor(model => model.EncryptingCertificate) +
+ +
+ +
+ @Html.LabelFor(model => model.SymmetricSigningKey) +
+
+ @Html.EditorFor(model => model.SymmetricSigningKey) + @Html.ValidationMessageFor(model => model.SymmetricSigningKey) + +
+ +
+ +

+ +

+
+} + +
+ @Html.ActionLink("Back", "Index") +
+ +@if (false) +{ + \ No newline at end of file diff --git a/Azure/WebSite_WindowsAzure/Views/RelyingPartiesAdmin/Delete.cshtml b/Azure/WebSite_WindowsAzure/Views/RelyingPartiesAdmin/Delete.cshtml new file mode 100644 index 0000000..4e61782 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Views/RelyingPartiesAdmin/Delete.cshtml @@ -0,0 +1,19 @@ +@{ + ViewBag.Title = "Delete"; +} + +

Delete

+ +@using (Html.BeginForm()) +{ + @Html.AntiForgeryToken() + @Html.ValidationSummary() + + +
+
+ +} + + + diff --git a/Azure/WebSite_WindowsAzure/Views/RelyingPartiesAdmin/Edit.cshtml b/Azure/WebSite_WindowsAzure/Views/RelyingPartiesAdmin/Edit.cshtml new file mode 100644 index 0000000..7648bff --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Views/RelyingPartiesAdmin/Edit.cshtml @@ -0,0 +1,123 @@ +@model Thinktecture.IdentityServer.Web.ViewModels.Administration.RelyingPartyModel + +@{ + ViewBag.Title = "Edit " + Model.Name; +} + +

+ Edit @Model.Name + (help) +

+ + + + +@using (Html.BeginForm("Edit", "RelyingPartiesAdmin", FormMethod.Post, new { enctype = "multipart/form-data" })) +{ + @Html.AntiForgeryToken() + @Html.ValidationSummary(true) + @Html.HiddenFor(model => model.Id) + +
+ Relying Party + +
+ @Html.LabelFor(model => model.Name) +
+
+ @Html.EditorFor(model => model.Name) + @Html.ValidationMessageFor(model => model.Name) +
+ +
+ @Html.LabelFor(model => model.Realm) +
+
+ @Html.EditorFor(model => model.Realm) + @Html.ValidationMessageFor(model => model.Realm) +
+ +
+ @Html.LabelFor(model => model.ReplyTo) +
+
+ @Html.EditorFor(model => model.ReplyTo) + @Html.ValidationMessageFor(model => model.ReplyTo) +
+ +
+ @Html.LabelFor(model => model.ExtraData1) +
+
+ @Html.EditorFor(model => model.ExtraData1) + @Html.ValidationMessageFor(model => model.ExtraData1) +
+ +
+ @Html.LabelFor(model => model.ExtraData2) +
+
+ @Html.EditorFor(model => model.ExtraData2) + @Html.ValidationMessageFor(model => model.ExtraData2) +
+ +
+ @Html.LabelFor(model => model.ExtraData3) +
+
+ @Html.EditorFor(model => model.ExtraData3) + @Html.ValidationMessageFor(model => model.ExtraData3) +
+ +
+ @Html.LabelFor(model => model.EncryptingCertificate) +
+
+ @Html.EditorFor(model => model.EncryptingCertificate) + @Html.ValidationMessageFor(model => model.EncryptingCertificate) +
+ (@Model.EncryptingCertificateName) + +
+
+ +
+ + +
+ +
+ @Html.LabelFor(model => model.SymmetricSigningKey) +
+
+ @Html.EditorFor(model => model.SymmetricSigningKey) + @Html.ValidationMessageFor(model => model.SymmetricSigningKey) +
+ +
+ +

+ +

+
+} + +
+ @Html.ActionLink("Back", "Index") +
+ +@if (false) +{ + \ No newline at end of file diff --git a/Azure/WebSite_WindowsAzure/Views/RelyingPartiesAdmin/Index.cshtml b/Azure/WebSite_WindowsAzure/Views/RelyingPartiesAdmin/Index.cshtml new file mode 100644 index 0000000..300b8d4 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Views/RelyingPartiesAdmin/Index.cshtml @@ -0,0 +1,22 @@ +@model Thinktecture.IdentityServer.Web.ViewModels.Administration.RelyingPartiesModel +@{ + ViewBag.Title = "Relying Parties"; +} +

Relying Parties

+ +

+ @Html.ActionLink("Add New", "add") +

+ +
    + @foreach (var item in Model.RelyingParties) + { +
  • + @item.Name + @Html.ActionLink("(edit)", "edit", new { id = item.Id }) + @Html.ActionLink("(delete)", "delete", new { id = item.Id }) +
    + (@item.Realm) +
  • + } +
\ No newline at end of file diff --git a/Azure/WebSite_WindowsAzure/Views/Shared/Confirm.cshtml b/Azure/WebSite_WindowsAzure/Views/Shared/Confirm.cshtml new file mode 100644 index 0000000..e9d96c2 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Views/Shared/Confirm.cshtml @@ -0,0 +1,16 @@ +@{ + ViewBag.Title = "Confirm"; +} + +

Confirm

+ +@using (Html.BeginForm()) +{ + @Html.AntiForgeryToken() + @Html.ValidationSummary() + + +
+
+ +} diff --git a/Azure/WebSite_WindowsAzure/Views/Shared/Error.cshtml b/Azure/WebSite_WindowsAzure/Views/Shared/Error.cshtml new file mode 100644 index 0000000..7618dc4 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Views/Shared/Error.cshtml @@ -0,0 +1,15 @@ +@{ + Layout = null; +} + + + + + Error + + +

+ Sorry, an error occurred while processing your request. +

+ + \ No newline at end of file diff --git a/Azure/WebSite_WindowsAzure/Views/Shared/SignedOut.cshtml b/Azure/WebSite_WindowsAzure/Views/Shared/SignedOut.cshtml new file mode 100644 index 0000000..bf38dce --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Views/Shared/SignedOut.cshtml @@ -0,0 +1,15 @@ +@{ + Layout = null; +} + + + + + Error + + +

+ You have been signed out of Identity Server. It might be possible that you still have active sessions with other applications. +

+ + \ No newline at end of file diff --git a/Azure/WebSite_WindowsAzure/Views/Shared/_Layout.cshtml b/Azure/WebSite_WindowsAzure/Views/Shared/_Layout.cshtml new file mode 100644 index 0000000..6450548 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Views/Shared/_Layout.cshtml @@ -0,0 +1,48 @@ + + + + @ViewBag.Title + + + @Html.Raw(ViewBag.Meta) + + + + +
+
+ Logo + +

@ViewBag.SiteName

+
+ + + +
+ + @RenderBody() + + diff --git a/Azure/WebSite_WindowsAzure/Views/WSFederation/SignOut.cshtml b/Azure/WebSite_WindowsAzure/Views/WSFederation/SignOut.cshtml new file mode 100644 index 0000000..baa5a2a --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Views/WSFederation/SignOut.cshtml @@ -0,0 +1,24 @@ +@model IEnumerable + +@{ + ViewBag.Title = "Federated Sign Out"; +} + +

Federated Sign Out

+ +@foreach (var link in Model) +{ +

+ @link +   + Signout Request +

+} + + +@if (!string.IsNullOrWhiteSpace(ViewBag.ReturnUrl)) +{ +

+ Return to application +

+} \ No newline at end of file diff --git a/Azure/WebSite_WindowsAzure/Views/Web.config b/Azure/WebSite_WindowsAzure/Views/Web.config new file mode 100644 index 0000000..41c7be1 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Views/Web.config @@ -0,0 +1,60 @@ + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Azure/WebSite_WindowsAzure/Views/_ViewStart.cshtml b/Azure/WebSite_WindowsAzure/Views/_ViewStart.cshtml new file mode 100644 index 0000000..efda124 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Views/_ViewStart.cshtml @@ -0,0 +1,3 @@ +@{ + Layout = "~/Views/Shared/_Layout.cshtml"; +} \ No newline at end of file diff --git a/Azure/WebSite_WindowsAzure/Web.Debug.config b/Azure/WebSite_WindowsAzure/Web.Debug.config new file mode 100644 index 0000000..2c6dd51 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Web.Debug.config @@ -0,0 +1,30 @@ + + + + + + + + + + \ No newline at end of file diff --git a/Azure/WebSite_WindowsAzure/Web.Release.config b/Azure/WebSite_WindowsAzure/Web.Release.config new file mode 100644 index 0000000..4122d79 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Web.Release.config @@ -0,0 +1,31 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Azure/WebSite_WindowsAzure/Web.config b/Azure/WebSite_WindowsAzure/Web.config new file mode 100644 index 0000000..b46ec5a --- /dev/null +++ b/Azure/WebSite_WindowsAzure/Web.config @@ -0,0 +1,164 @@ + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Azure/WebSite_WindowsAzure/WebSite (WindowsAzure).csproj b/Azure/WebSite_WindowsAzure/WebSite (WindowsAzure).csproj new file mode 100644 index 0000000..45fb32c --- /dev/null +++ b/Azure/WebSite_WindowsAzure/WebSite (WindowsAzure).csproj @@ -0,0 +1,406 @@ + + + + Debug + AnyCPU + + + 2.0 + {B9C90A36-86C0-4974-B0B4-3524F508D847} + {E53F8FEA-EAE0-44A6-8774-FFD645390401};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + Thinktecture.IdentityServer.Web + Thinktecture.IdentityServer.Web + v4.0 + false + false + + + + + + + + + ..\ + true + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + true + + + pdbonly + true + bin\ + TRACE + prompt + 4 + + + + False + ..\packages\AutoMapper.2.0.0\lib\net40-client\AutoMapper.dll + + + False + ..\packages\EntityFramework.4.2.0.0\lib\net40\EntityFramework.dll + + + True + + + True + ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll + + + False + ..\packages\routedebugger.2.1.1\lib\net40\RouteDebugger.dll + + + + + True + ..\packages\SqlServerCompact.4.0.8482.1\lib\System.Data.SqlServerCe.dll + + + True + ..\packages\EntityFramework.SqlServerCompact.4.1.8482.2\lib\System.Data.SqlServerCe.Entity.dll + + + + + + + + + True + + + ..\packages\System.Web.Providers.1.0.1\lib\Net40\System.Web.Providers.dll + + + True + + + True + + + True + + + + + + + + + + + + + True + + + True + + + + + + + + + + + + False + ..\packages\Thinktecture.IdentityModel.1.3.0.0\lib\Thinktecture.IdentityModel.dll + + + False + ..\packages\WebActivator.1.5\lib\net40\WebActivator.dll + + + + + Controllers\AccountController.cs + + + Controllers\Admin\AdminController.cs + + + Controllers\Admin\ClientCertificatesAdminController.cs + + + Controllers\Admin\DelegationAdminController.cs + + + Controllers\Admin\RelyingPartiesAdminController.cs + + + Controllers\FederationMetadataController.cs + + + Controllers\HomeController.cs + + + Controllers\Issue\JSNotifyController.cs + + + Controllers\Issue\OAuth2Controller.cs + + + Controllers\Issue\SimpleHttpController.cs + + + Controllers\Issue\WrapController.cs + + + Controllers\Issue\WSFederationController.cs + + + ViewModels\Administration\AddClientCertificateModel.cs + + + ViewModels\Administration\AddDelegationModel.cs + + + ViewModels\Administration\EditCertificatesModel.cs + + + ViewModels\Administration\EditClientCertificatesModel.cs + + + ViewModels\Administration\EditDelegationModel.cs + + + ViewModels\Administration\EndpointConfigurationModel.cs + + + ViewModels\Administration\Extensions.cs + + + ViewModels\Administration\GlobalConfigurationModel.cs + + + ViewModels\Administration\MyModel.cs + + + ViewModels\Administration\RelyingPartiesModel.cs + + + ViewModels\Administration\RelyingPartyModel.cs + + + ViewModels\SignInModel.cs + + + Global.asax + + + + + + + + + + + + + + + + + + + + + + + + + + + + Designer + + + Web.config + + + Web.config + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Always + + + Always + + + + + {9658F86F-3059-4731-9EB0-5F67A4FF1A8A} + Thinktecture.IdentityServer.Core.Repositories + + + {38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A} + Thinktecture.IdentityServer.Core + + + {FC2D7E2A-65A2-480F-AAE8-855FD026AF85} + Thinktecture.IdentityServer.Web.Library + + + {36D5F61F-F4BA-41F8-AA13-1F32DDB970A4} + Thinktecture.IdentityServer.WindowsAzure + + + + + + + + + + + + + True + + + + + + +if not exist "$(TargetDir)x86" md "$(TargetDir)x86" +xcopy /s /y "$(SolutionDir)packages\SqlServerCompact.4.0.8482.1\NativeBinaries\x86\*.*" "$(TargetDir)x86" +if not exist "$(TargetDir)amd64" md "$(TargetDir)amd64" +xcopy /s /y "$(SolutionDir)packages\SqlServerCompact.4.0.8482.1\NativeBinaries\amd64\*.*" "$(TargetDir)amd64" + + + \ No newline at end of file diff --git a/Azure/WebSite_WindowsAzure/WebSite.csproj.vspscc b/Azure/WebSite_WindowsAzure/WebSite.csproj.vspscc new file mode 100644 index 0000000..b6d3289 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/WebSite.csproj.vspscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "" +"NUMBER_OF_EXCLUDED_FILES" = "0" +"ORIGINAL_PROJECT_FILE_PATH" = "" +"NUMBER_OF_NESTED_PROJECTS" = "0" +"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER" +} diff --git a/Azure/WebSite_WindowsAzure/license.txt b/Azure/WebSite_WindowsAzure/license.txt new file mode 100644 index 0000000..f7700e0 --- /dev/null +++ b/Azure/WebSite_WindowsAzure/license.txt @@ -0,0 +1,24 @@ +Copyright 2011 - Dominick Baier + +Microsoft Public License (Ms-PL) + +This license governs use of the accompanying software. If you use the software, you +accept this license. If you do not accept the license, do not use the software. + +1. Definitions +The terms "reproduce," "reproduction," "derivative works," and "distribution" have the +same meaning here as under U.S. copyright law. +A "contribution" is the original software, or any additions or changes to the software. +A "contributor" is any person that distributes its contribution under this license. +"Licensed patents" are a contributor's patent claims that read directly on its contribution. + +2. Grant of Rights +(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. +(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. + +3. Conditions and Limitations +(A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. +(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. +(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. +(D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license. +(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. \ No newline at end of file diff --git a/Azure/WebSite_WindowsAzure/packages.config b/Azure/WebSite_WindowsAzure/packages.config new file mode 100644 index 0000000..854459a --- /dev/null +++ b/Azure/WebSite_WindowsAzure/packages.config @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Core.Repositories/App.config b/Libraries/Thinktecture.IdentityServer.Core.Repositories/App.config new file mode 100644 index 0000000..4dcf670 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core.Repositories/App.config @@ -0,0 +1,14 @@ + + + + +
+ + + + + + + + + \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Core.Repositories/ClientCertificatesRepository.cs b/Libraries/Thinktecture.IdentityServer.Core.Repositories/ClientCertificatesRepository.cs new file mode 100644 index 0000000..cdc67cf --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core.Repositories/ClientCertificatesRepository.cs @@ -0,0 +1,110 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography.X509Certificates; +using Thinktecture.IdentityServer.Models; + +namespace Thinktecture.IdentityServer.Repositories.Sql +{ + /// + /// TODO: Update summary. + /// + public class ClientCertificatesRepository : IClientCertificatesRepository + { + #region Runtime + public bool TryGetUserNameFromThumbprint(X509Certificate2 certificate, out string userName) + { + userName = null; + + using (var entities = IdentityServerConfigurationContext.Get()) + { + userName = (from mapping in entities.ClientCertificates + where mapping.Thumbprint.Equals(certificate.Thumbprint, StringComparison.OrdinalIgnoreCase) + select mapping.UserName).FirstOrDefault(); + + return (userName != null); + } + } + #endregion + + #region Management + public bool SupportsWriteAccess + { + get { return true; } + } + + public IEnumerable List(int pageIndex, int pageSize) + { + using (var entities = IdentityServerConfigurationContext.Get()) + { + var users = + (from user in entities.ClientCertificates + orderby user.UserName + select user.UserName) + .Distinct(); + + if (pageIndex != -1 && pageSize != -1) + { + users = users.Skip(pageIndex * pageSize).Take(pageSize); + } + + return users.ToList(); + } + } + + public IEnumerable GetClientCertificatesForUser(string userName) + { + using (var entities = IdentityServerConfigurationContext.Get()) + { + var certs = + from record in entities.ClientCertificates + where record.UserName.Equals(userName, StringComparison.OrdinalIgnoreCase) + select record; + + return certs.ToList().ToDomainModel(); + } + } + + public void Add(ClientCertificate certificate) + { + using (var entities = IdentityServerConfigurationContext.Get()) + { + var entity = new ClientCertificates + { + UserName = certificate.UserName, + Thumbprint = certificate.Thumbprint, + Description = certificate.Description + }; + + entities.ClientCertificates.Add(entity); + entities.SaveChanges(); + } + } + + public void Delete(ClientCertificate certificate) + { + using (var entities = IdentityServerConfigurationContext.Get()) + { + var record = + (from entry in entities.ClientCertificates + where entry.UserName.Equals(certificate.UserName, StringComparison.OrdinalIgnoreCase) && + entry.Thumbprint.Equals(certificate.Thumbprint, StringComparison.OrdinalIgnoreCase) + select entry) + .Single(); + + entities.ClientCertificates.Remove(record); + entities.SaveChanges(); + } + } + #endregion + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core.Repositories/ConfigurationRepository.cs b/Libraries/Thinktecture.IdentityServer.Core.Repositories/ConfigurationRepository.cs new file mode 100644 index 0000000..0cb819c --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core.Repositories/ConfigurationRepository.cs @@ -0,0 +1,253 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.ComponentModel.Composition; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Security.Cryptography.X509Certificates; +using AutoMapper; +using Thinktecture.IdentityServer.Helper; +using Thinktecture.IdentityServer.Models; + +namespace Thinktecture.IdentityServer.Repositories.Sql +{ + public class ConfigurationRepository : IConfigurationRepository + { + private const string StandardConfigurationName = "Standard"; + private const string SslCertificateName = "SSL"; + private const string SigningCertificateName = "SigningCertificate"; + + private const string EndpointConfigurationCacheKey = "Cache_EndpointConfiguration"; + private const string GlobalConfigurationCacheKey = "Cache_GlobalConfiguration"; + private const string SslCertificateCachekey = "Cache_SslCertificate"; + private const string SigningCertificateCacheKey = "Cache_SigningCertificate"; + + [Import] + public ICacheRepository CacheRepository { get; set; } + + static ConfigurationRepository() + { + Mapper.CreateMap() + .ForMember(m => m.Name, opt => opt.Ignore()); + + Mapper.CreateMap(); + + Mapper.CreateMap() + .ForMember(m => m.Name, opt => opt.Ignore()); + + Mapper.CreateMap(); + + Mapper.AssertConfigurationIsValid(); + } + + public ConfigurationRepository() + { + Container.Current.SatisfyImportsOnce(this); + } + + public ConfigurationRepository(ICacheRepository cacheRepository) + { + CacheRepository = cacheRepository; + } + + #region Runtime + public GlobalConfiguration Configuration + { + get + { + return Cache.ReturnFromCache(CacheRepository, GlobalConfigurationCacheKey, 1, () => + { + using (var entities = IdentityServerConfigurationContext.Get()) + { + var global = (from c in entities.Global where c.Name == StandardConfigurationName select c).FirstOrDefault(); + if (global == null) + { + throw new ConfigurationErrorsException("No standard global configuration found"); + } + + return Mapper.Map(global); + } + }); + } + } + + public EndpointConfiguration Endpoints + { + get + { + return Cache.ReturnFromCache(CacheRepository, EndpointConfigurationCacheKey, 1, () => + { + using (var entities = IdentityServerConfigurationContext.Get()) + { + var eps = (from c in entities.Endpoints where c.Name == StandardConfigurationName select c).FirstOrDefault(); + if (eps == null) + { + throw new ConfigurationErrorsException("No standard endpoint configuration found in database"); + } + + return Mapper.Map(eps); + } + }); + } + } + + public CertificateConfiguration SslCertificate + { + get + { + return Cache.ReturnFromCache(CacheRepository, SslCertificateCachekey, 1, () => + { + using (var entities = IdentityServerConfigurationContext.Get()) + { + var cert = (from c in entities.Certificates where c.Name == SslCertificateName select c).FirstOrDefault(); + if (cert == null) + { + throw new ConfigurationErrorsException("No SSL certificate found in database"); + } + + return LoadCertificateConfiguration(cert); + } + }); + } + } + + public CertificateConfiguration SigningCertificate + { + get + { + return Cache.ReturnFromCache(CacheRepository, SigningCertificateCacheKey, 1, () => + { + using (var entities = IdentityServerConfigurationContext.Get()) + { + var cert = (from c in entities.Certificates where c.Name == SigningCertificateName select c).FirstOrDefault(); + if (cert == null) + { + throw new ConfigurationErrorsException("No signing certificate found in database"); + } + + return LoadCertificateConfiguration(cert); + } + }); + } + } + + protected virtual CertificateConfiguration LoadCertificateConfiguration(Certificates cert) + { + object findValue; + X509FindType findType; + + var certConfig = new CertificateConfiguration + { + SubjectDistinguishedName = cert.SubjectDistinguishedName, + }; + + if (!string.IsNullOrWhiteSpace(cert.SubjectDistinguishedName)) + { + findValue = cert.SubjectDistinguishedName; + findType = X509FindType.FindBySubjectDistinguishedName; + } + else + { + Tracing.Error("No distinguished name or thumbprint for certificate: " + cert.Name); + return certConfig; + } + + try + { + certConfig.Certificate = X509Certificates.GetCertificateFromStore(StoreLocation.LocalMachine, StoreName.My, findType, findValue); + } + catch + { + Tracing.Error("No certificate found for: " + findValue); + throw new ConfigurationErrorsException("No certificate found for: " + findValue); + } + + return certConfig; + } + #endregion + + #region Management + public bool SupportsWriteAccess + { + get { return true; } + } + + public void UpdateConfiguration(GlobalConfiguration configuration) + { + using (var entities = IdentityServerConfigurationContext.Get()) + { + var entity = Mapper.Map(configuration); + entity.Name = StandardConfigurationName; + + entities.Global.Attach(entity); + entities.Entry(entity).State = EntityState.Modified; + + entities.SaveChanges(); + CacheRepository.Invalidate(GlobalConfigurationCacheKey); + CacheRepository.Invalidate(Constants.CacheKeys.WSFedMetadata); + } + } + + public void UpdateEndpoints(EndpointConfiguration endpoints) + { + using (var entities = IdentityServerConfigurationContext.Get()) + { + var entity = Mapper.Map(endpoints); + entity.Name = StandardConfigurationName; + + entities.Endpoints.Attach(entity); + entities.Entry(entity).State = System.Data.EntityState.Modified; + + entities.SaveChanges(); + CacheRepository.Invalidate(EndpointConfigurationCacheKey); + CacheRepository.Invalidate(Constants.CacheKeys.WSFedMetadata); + } + } + + public void UpdateCertificates(string sslSubjectName, string signingSubjectName) + { + using (var entities = IdentityServerConfigurationContext.Get()) + { + var certs = entities.Certificates; + + if (!string.IsNullOrWhiteSpace(sslSubjectName)) + { + var ssl = new Certificates + { + Name = SslCertificateName, + SubjectDistinguishedName = sslSubjectName + }; + + certs.Attach(ssl); + entities.Entry(ssl).State = EntityState.Modified; + } + + if (!string.IsNullOrWhiteSpace(signingSubjectName)) + { + var signing = new Certificates + { + Name = SigningCertificateName, + SubjectDistinguishedName = signingSubjectName + }; + + certs.Attach(signing); + entities.Entry(signing).State = EntityState.Modified; + } + + entities.SaveChanges(); + + CacheRepository.Invalidate(SigningCertificateCacheKey); + CacheRepository.Invalidate(SslCertificateCachekey); + CacheRepository.Invalidate(Constants.CacheKeys.WSFedMetadata); + } + } + #endregion + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core.Repositories/DelegationRepository.cs b/Libraries/Thinktecture.IdentityServer.Core.Repositories/DelegationRepository.cs new file mode 100644 index 0000000..2034e56 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core.Repositories/DelegationRepository.cs @@ -0,0 +1,108 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using Thinktecture.IdentityServer.Models; + +namespace Thinktecture.IdentityServer.Repositories.Sql +{ + /// + /// TODO: Update summary. + /// + public class DelegationRepository : IDelegationRepository + { + #region Runtime + public bool IsDelegationAllowed(string userName, string realm) + { + using (var entities = IdentityServerConfigurationContext.Get()) + { + var record = (from entry in entities.Delegation + where entry.UserName.Equals(userName, StringComparison.OrdinalIgnoreCase) && + entry.Realm.Equals(realm, StringComparison.OrdinalIgnoreCase) + select entry).FirstOrDefault(); + + return (record != null); + } + } + #endregion + + #region Management + public bool SupportsWriteAccess + { + get { return true; } + } + + public IEnumerable GetAllUsers(int pageIndex, int pageSize) + { + using (var entities = IdentityServerConfigurationContext.Get()) + { + var users = + (from user in entities.Delegation + orderby user.UserName + select user.UserName) + .Distinct(); + + if (pageIndex != -1 && pageSize != -1) + { + users = users.Skip(pageIndex * pageSize).Take(pageSize); + } + + return users.ToList(); + } + } + + public IEnumerable GetDelegationSettingsForUser(string userName) + { + using (var entities = IdentityServerConfigurationContext.Get()) + { + var settings = + from record in entities.Delegation + where record.UserName.Equals(userName, StringComparison.OrdinalIgnoreCase) + select record; + + return settings.ToList().ToDomainModel(); + } + } + + public void Add(DelegationSetting setting) + { + using (var entities = IdentityServerConfigurationContext.Get()) + { + var entity = new Delegation + { + UserName = setting.UserName, + Realm = setting.Realm.AbsoluteUri, + Description = setting.Description + }; + + entities.Delegation.Add(entity); + entities.SaveChanges(); + } + } + + public void Delete(DelegationSetting setting) + { + using (var entities = IdentityServerConfigurationContext.Get()) + { + var record = + (from entry in entities.Delegation + where entry.UserName.Equals(setting.UserName, StringComparison.OrdinalIgnoreCase) && + entry.Realm.Equals(setting.Realm.AbsoluteUri, StringComparison.OrdinalIgnoreCase) + select entry) + .Single(); + + entities.Delegation.Remove(record); + entities.SaveChanges(); + } + } + #endregion + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core.Repositories/EntityModel/Certificates.cs b/Libraries/Thinktecture.IdentityServer.Core.Repositories/EntityModel/Certificates.cs new file mode 100644 index 0000000..2961fbd --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core.Repositories/EntityModel/Certificates.cs @@ -0,0 +1,21 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.ComponentModel.DataAnnotations; + +namespace Thinktecture.IdentityServer.Repositories.Sql +{ + public class Certificates + { + [Key] + public string Name { get; set; } + + public string SubjectDistinguishedName { get; set; } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core.Repositories/EntityModel/ClientCertificates.cs b/Libraries/Thinktecture.IdentityServer.Core.Repositories/EntityModel/ClientCertificates.cs new file mode 100644 index 0000000..bfe4395 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core.Repositories/EntityModel/ClientCertificates.cs @@ -0,0 +1,28 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.ComponentModel.DataAnnotations; + +namespace Thinktecture.IdentityServer.Repositories.Sql +{ + public class ClientCertificates + { + [Key] + public int Id { get; set; } + + [Required] + public string UserName { get; set; } + + [Required] + public string Thumbprint { get; set; } + + [Required] + public string Description { get; set; } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core.Repositories/EntityModel/Delegation.cs b/Libraries/Thinktecture.IdentityServer.Core.Repositories/EntityModel/Delegation.cs new file mode 100644 index 0000000..501a703 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core.Repositories/EntityModel/Delegation.cs @@ -0,0 +1,24 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.ComponentModel.DataAnnotations; + +namespace Thinktecture.IdentityServer.Repositories.Sql +{ + public class Delegation + { + [Key] + public int Id { get; set; } + [Required] + public string UserName { get; set; } + [Required] + public string Realm { get; set; } + public string Description { get; set; } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core.Repositories/EntityModel/Endpoints.cs b/Libraries/Thinktecture.IdentityServer.Core.Repositories/EntityModel/Endpoints.cs new file mode 100644 index 0000000..38b6daf --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core.Repositories/EntityModel/Endpoints.cs @@ -0,0 +1,50 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.ComponentModel.DataAnnotations; + +namespace Thinktecture.IdentityServer.Repositories.Sql +{ + public class Endpoints + { + [Key] + public string Name { get; set; } + + [Required] + public Boolean WSFederation { get; set; } + + [Required] + public Boolean WSTrustMessage { get; set; } + + [Required] + public Boolean WSTrustMixed { get; set; } + + [Required] + public Boolean SimpleHttp { get; set; } + + [Required] + public Boolean FederationMetadata { get; set; } + + [Required] + public Boolean OAuthWRAP { get; set; } + + [Required] + public Boolean OAuth2 { get; set; } + + [Required] + public Boolean JSNotify { get; set; } + + [Required] + public int HttpPort { get; set; } + + [Required] + public int HttpsPort { get; set; } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core.Repositories/EntityModel/Global.cs b/Libraries/Thinktecture.IdentityServer.Core.Repositories/EntityModel/Global.cs new file mode 100644 index 0000000..cb8544c --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core.Repositories/EntityModel/Global.cs @@ -0,0 +1,74 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.ComponentModel.DataAnnotations; + +namespace Thinktecture.IdentityServer.Repositories.Sql +{ + public class Global + { + [Key] + public string Name { get; set; } + + [Required] + public String SiteName { get; set; } + + [Required] + public String IssuerUri { get; set; } + + [Required] + public String IssuerContactEmail { get; set; } + + [Required] + public string DefaultTokenType { get; set; } + + [Required] + public int DefaultTokenLifetime { get; set; } + + [Required] + public int MaximumTokenLifetime { get; set; } + + [Required] + public int SsoCookieLifetime { get; set; } + + [Required] + public Boolean RequireSsl { get; set; } + + [Required] + public Boolean RequireEncryption { get; set; } + + [Required] + public Boolean RequireSignInConfirmation { get; set; } + + [Required] + public Boolean RequireReplyToWithinRealm { get; set; } + + [Required] + public Boolean AllowKnownRealmsOnly { get; set; } + + [Required] + public Boolean AllowReplyTo { get; set; } + + [Required] + public Boolean EnableClientCertificates { get; set; } + + [Required] + public Boolean EnableDelegation { get; set; } + + [Required] + public Boolean EnableStrongEpiForSsl { get; set; } + + [Required] + public Boolean EnableFederationMessageTracing { get; set; } + + [Required] + public Boolean EnforceUsersGroupMembership { get; set; } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core.Repositories/EntityModel/RelyingParties.cs b/Libraries/Thinktecture.IdentityServer.Core.Repositories/EntityModel/RelyingParties.cs new file mode 100644 index 0000000..4acac5f --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core.Repositories/EntityModel/RelyingParties.cs @@ -0,0 +1,37 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.ComponentModel.DataAnnotations; + +namespace Thinktecture.IdentityServer.Repositories.Sql +{ + public class RelyingParties + { + [Key] + public int Id { get; set; } + + [Required] + public string Name { get; set; } + + [Required] + public string Realm { get; set; } + + public string ReplyTo { get; set; } + + public string EncryptingCertificate { get; set; } + + public string SymmetricSigningKey { get; set; } + + public string ExtraData1 { get; set; } + + public string ExtraData2 { get; set; } + + public string ExtraData3 { get; set; } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core.Repositories/Extensions.cs b/Libraries/Thinktecture.IdentityServer.Core.Repositories/Extensions.cs new file mode 100644 index 0000000..cbbf347 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core.Repositories/Extensions.cs @@ -0,0 +1,137 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography.X509Certificates; +using Thinktecture.IdentityServer.Models; + +namespace Thinktecture.IdentityServer.Repositories.Sql +{ + internal static class Extensions + { + #region Relying Party + public static RelyingParty ToDomainModel(this RelyingParties rpEntity) + { + var rp = new RelyingParty + { + Id = rpEntity.Id.ToString(), + Name = rpEntity.Name, + Realm = new Uri("http://" + rpEntity.Realm), + ExtraData1 = rpEntity.ExtraData1, + ExtraData2 = rpEntity.ExtraData2, + ExtraData3 = rpEntity.ExtraData3 + }; + + if (!string.IsNullOrWhiteSpace(rpEntity.ReplyTo)) + { + rp.ReplyTo = new Uri(rpEntity.ReplyTo); + } + + if (!string.IsNullOrWhiteSpace(rpEntity.EncryptingCertificate)) + { + rp.EncryptingCertificate = new X509Certificate2(Convert.FromBase64String(rpEntity.EncryptingCertificate)); + } + + if (!string.IsNullOrWhiteSpace(rpEntity.SymmetricSigningKey)) + { + rp.SymmetricSigningKey = Convert.FromBase64String(rpEntity.SymmetricSigningKey); + } + + return rp; + } + + public static RelyingParties ToEntity(this RelyingParty relyingParty) + { + var rpEntity = new RelyingParties + { + Name = relyingParty.Name, + Realm = relyingParty.Realm.AbsoluteUri.StripProtocolMoniker(), + ExtraData1 = relyingParty.ExtraData1, + ExtraData2 = relyingParty.ExtraData2, + ExtraData3 = relyingParty.ExtraData3, + }; + + if (!string.IsNullOrEmpty(relyingParty.Id)) + { + rpEntity.Id = int.Parse(relyingParty.Id); + } + + if (relyingParty.ReplyTo != null) + { + rpEntity.ReplyTo = relyingParty.ReplyTo.AbsoluteUri; + } + + if (relyingParty.EncryptingCertificate != null) + { + rpEntity.EncryptingCertificate = Convert.ToBase64String(relyingParty.EncryptingCertificate.RawData); + } + + if (relyingParty.SymmetricSigningKey != null && relyingParty.SymmetricSigningKey.Length != 0) + { + rpEntity.SymmetricSigningKey = Convert.ToBase64String(relyingParty.SymmetricSigningKey); + } + + return rpEntity; + } + + public static IEnumerable ToDomainModel(this List relyingParties) + { + return + (from rp in relyingParties + select new RelyingParty + { + Id = rp.Id.ToString(), + Name = rp.Name, + Realm = new Uri("http://" + rp.Realm) + }).ToList(); + } + #endregion + + #region Client Certificates + public static List ToDomainModel(this List entities) + { + return + (from entity in entities + select new ClientCertificate + { + UserName = entity.UserName, + Thumbprint = entity.Thumbprint, + Description = entity.Description + } + ).ToList(); + } + #endregion + + #region Delegation + public static List ToDomainModel(this List entities) + { + return + (from entity in entities + select new DelegationSetting + { + UserName = entity.UserName, + Realm = new Uri(entity.Realm), + Description = entity.Description + } + ).ToList(); + } + #endregion + + #region Misc + public static string StripProtocolMoniker(this string uriString) + { + var uri = new Uri(uriString); + string stripped = uri.AbsoluteUri.Substring(uri.Scheme.Length + 3); + return stripped.ToLowerInvariant(); + } + #endregion + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core.Repositories/IdentityServerConfigurationContext.cs b/Libraries/Thinktecture.IdentityServer.Core.Repositories/IdentityServerConfigurationContext.cs new file mode 100644 index 0000000..f7b3574 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core.Repositories/IdentityServerConfigurationContext.cs @@ -0,0 +1,62 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Configuration; +using System.Data.Common; +using System.Data.Entity; +using System.Data.Entity.ModelConfiguration.Conventions; + +namespace Thinktecture.IdentityServer.Repositories.Sql +{ + public class IdentityServerConfigurationContext : DbContext + { + public DbSet Global { get; set; } + + public DbSet Certificates { get; set; } + + public DbSet ClientCertificates { get; set; } + + public DbSet Delegation { get; set; } + + public DbSet RelyingParties { get; set; } + + public DbSet Endpoints { get; set; } + + public static Func FactoryMethod { get; set; } + + public IdentityServerConfigurationContext() + { + } + + public IdentityServerConfigurationContext(DbConnection conn) : base(conn, true) + { + } + + public IdentityServerConfigurationContext(IDatabaseInitializer initializer) + { + Database.SetInitializer(initializer); + } + + public static IdentityServerConfigurationContext Get() + { + if (FactoryMethod != null) return FactoryMethod(); + + var cs = ConfigurationManager.ConnectionStrings["IdentityServerConfiguration"].ConnectionString; + var conn = Database.DefaultConnectionFactory.CreateConnection(cs); + return new IdentityServerConfigurationContext(conn); + } + + protected override void OnModelCreating(DbModelBuilder modelBuilder) + { + modelBuilder.Conventions.Remove(); + base.OnModelCreating(modelBuilder); + } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core.Repositories/MemoryCacheRepository.cs b/Libraries/Thinktecture.IdentityServer.Core.Repositories/MemoryCacheRepository.cs new file mode 100644 index 0000000..9e0a1a9 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core.Repositories/MemoryCacheRepository.cs @@ -0,0 +1,39 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Runtime.Caching; + +namespace Thinktecture.IdentityServer.Repositories +{ + public class MemoryCacheRepository : ICacheRepository + { + static MemoryCache _cache = new MemoryCache("Thinktecture.IdentityServer.Caching"); + + public void Put(string name, object value, int ttl) + { + Tracing.Verbose(String.Format("Adding {0} to cache", name)); + _cache.Add(name, value, DateTimeOffset.Now.AddHours(ttl)); + } + + public object Get(string name) + { + var item = _cache.Get(name); + Tracing.Verbose(String.Format("Fetching {0} from cache: {1}", name, item == null ? "miss" : "hit")); + + return item; + } + + public void Invalidate(string name) + { + Tracing.Verbose(String.Format("Invalidating {0} in cache", name)); + _cache.Remove(name); + } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core.Repositories/NullCacheRepository.cs b/Libraries/Thinktecture.IdentityServer.Core.Repositories/NullCacheRepository.cs new file mode 100644 index 0000000..87fbbab --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core.Repositories/NullCacheRepository.cs @@ -0,0 +1,25 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +namespace Thinktecture.IdentityServer.Repositories +{ + public class NullCacheRepository : ICacheRepository + { + public void Put(string name, object value, int ttl) + { } + + public object Get(string name) + { + return null; + } + + public void Invalidate(string name) + { } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core.Repositories/Properties/AssemblyInfo.cs b/Libraries/Thinktecture.IdentityServer.Core.Repositories/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..8e3bec6 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core.Repositories/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +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("Thinktecture.IdentityServer.Core.Repositories")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("Thinktecture.IdentityServer.Core.Repositories")] +[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("b0e84943-0c77-41d9-b4ec-5a015a01aacf")] + +// 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 Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Libraries/Thinktecture.IdentityServer.Core.Repositories/ProviderUserRepository.cs b/Libraries/Thinktecture.IdentityServer.Core.Repositories/ProviderUserRepository.cs new file mode 100644 index 0000000..9a6607d --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core.Repositories/ProviderUserRepository.cs @@ -0,0 +1,125 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Configuration; +using System.Linq; +using System.Security.Cryptography.X509Certificates; +using System.Web.Profile; +using System.Web.Security; +using Microsoft.IdentityModel.Claims; +using Thinktecture.IdentityServer.TokenService; + +namespace Thinktecture.IdentityServer.Repositories +{ + public class ProviderUserRepository : IUserRepository + { + private const string ProfileClaimPrefix = "http://identityserver.thinktecture.com/claims/profileclaims/"; + + [Import] + public IClientCertificatesRepository Repository { get; set; } + + public ProviderUserRepository() + { + Container.Current.SatisfyImportsOnce(this); + } + + public bool ValidateUser(string userName, string password) + { + return Membership.ValidateUser(userName, password); + } + + public bool ValidateUser(X509Certificate2 clientCertificate, out string userName) + { + return Repository.TryGetUserNameFromThumbprint(clientCertificate, out userName); + } + + public IEnumerable GetRoles(string userName, RoleTypes roleType) + { + var returnedRoles = new List(); + + if (Roles.Enabled) + { + var roles = Roles.GetRolesForUser(userName); + + if (roleType == RoleTypes.All) + { + returnedRoles = roles.ToList(); + } + else if (roleType == RoleTypes.IdentityServer) + { + returnedRoles = roles.Where(role => role.StartsWith(Constants.Roles.InternalRolesPrefix)).ToList(); + } + else if (roleType == RoleTypes.Client) + { + returnedRoles = roles.Where(role => !(role.StartsWith(Constants.Roles.InternalRolesPrefix))).ToList(); + } + } + + return returnedRoles; + } + + public IEnumerable GetClaims(IClaimsPrincipal principal, RequestDetails requestDetails) + { + var userName = principal.Identity.Name; + var claims = new List(); + + // email address + string email = Membership.FindUsersByName(userName)[userName].Email; + if (!String.IsNullOrEmpty(email)) + { + claims.Add(new Claim(ClaimTypes.Email, email)); + } + + // roles + GetRoles(userName, RoleTypes.Client).ToList().ForEach(role => claims.Add(new Claim(ClaimTypes.Role, role))); + + // profile claims + if (ProfileManager.Enabled) + { + var profile = ProfileBase.Create(userName, true); + if (profile != null) + { + foreach (SettingsProperty prop in ProfileBase.Properties) + { + string value = profile.GetPropertyValue(prop.Name).ToString(); + if (!String.IsNullOrWhiteSpace(value)) + { + claims.Add(new Claim(ProfileClaimPrefix + prop.Name.ToLowerInvariant(), value)); + } + } + } + } + + return claims; + } + + public IEnumerable GetSupportedClaimTypes() + { + var claimTypes = new List + { + ClaimTypes.Name, + ClaimTypes.Email, + ClaimTypes.Role + }; + + if (ProfileManager.Enabled) + { + foreach (SettingsProperty prop in ProfileBase.Properties) + { + claimTypes.Add(ProfileClaimPrefix + prop.Name.ToLowerInvariant()); + } + } + + return claimTypes; + } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Core.Repositories/RelyingPartyRepository.cs b/Libraries/Thinktecture.IdentityServer.Core.Repositories/RelyingPartyRepository.cs new file mode 100644 index 0000000..1146428 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core.Repositories/RelyingPartyRepository.cs @@ -0,0 +1,114 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.Collections.Generic; +using System.Data; +using System.Linq; +using Thinktecture.IdentityServer.Models; + +namespace Thinktecture.IdentityServer.Repositories.Sql +{ + public class RelyingPartyRepository : IRelyingPartyRepository + { + public bool TryGet(string realm, out RelyingParty relyingParty) + { + relyingParty = null; + + using (var entities = IdentityServerConfigurationContext.Get()) + { + var strippedRealm = realm.StripProtocolMoniker(); + + var bestMatch = (from rp in entities.RelyingParties + where strippedRealm.Contains(rp.Realm) + orderby rp.Realm descending + select rp) + .FirstOrDefault(); + + if (bestMatch != null) + { + relyingParty = bestMatch.ToDomainModel(); + return true; + } + } + + return false; + } + + #region Management + public bool SupportsWriteAccess + { + get { return true; } + } + + public IEnumerable List(int pageIndex, int pageSize) + { + using (var entities = IdentityServerConfigurationContext.Get()) + { + var rps = from e in entities.RelyingParties + orderby e.Name + select e; + + if (pageIndex != -1 && pageSize != -1) + { + rps = rps.Skip(pageIndex * pageSize).Take(pageSize).OrderBy(rp => rp.Name); + } + + return rps.ToList().ToDomainModel(); + } + } + + public RelyingParty Get(string id) + { + var uniqueId = int.Parse(id); + + using (var entities = IdentityServerConfigurationContext.Get()) + { + return + (from rp in entities.RelyingParties + where rp.Id == uniqueId + select rp) + .First() + .ToDomainModel(); + } + } + + public void Add(RelyingParty relyingParty) + { + using (var entities = IdentityServerConfigurationContext.Get()) + { + entities.RelyingParties.Add(relyingParty.ToEntity()); + entities.SaveChanges(); + } + } + + public void Update(RelyingParty relyingParty) + { + var rpEntity = relyingParty.ToEntity(); + + using (var entities = IdentityServerConfigurationContext.Get()) + { + entities.RelyingParties.Attach(rpEntity); + entities.Entry(rpEntity).State = EntityState.Modified; + entities.SaveChanges(); + } + } + + public void Delete(string id) + { + using (var entities = IdentityServerConfigurationContext.Get()) + { + var rpEntity = new RelyingParties { Id = int.Parse(id) }; + entities.RelyingParties.Attach(rpEntity); + entities.Entry(rpEntity).State = EntityState.Deleted; + entities.SaveChanges(); + } + } + #endregion + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core.Repositories/Thinktecture.IdentityServer.Core.Repositories.csproj b/Libraries/Thinktecture.IdentityServer.Core.Repositories/Thinktecture.IdentityServer.Core.Repositories.csproj new file mode 100644 index 0000000..2c46a50 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core.Repositories/Thinktecture.IdentityServer.Core.Repositories.csproj @@ -0,0 +1,99 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {9658F86F-3059-4731-9EB0-5F67A4FF1A8A} + Library + Properties + Thinktecture.IdentityServer.Core.Repositories + Thinktecture.IdentityServer.Core.Repositories + v4.0 + 512 + ..\ + true + + + true + full + false + ..\build\Common\ + DEBUG;TRACE + prompt + 4 + false + SecurityRules.ruleset + + + pdbonly + true + ..\build\Common\ + TRACE + prompt + 4 + + + + ..\..\OnPremise\packages\AutoMapper.2.1.265\lib\net40\AutoMapper.dll + + + False + ..\..\OnPremise\packages\EntityFramework.4.3.1\lib\net40\EntityFramework.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A} + Thinktecture.IdentityServer.Core + + + + + + + + + + \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Core.Repositories/packages.config b/Libraries/Thinktecture.IdentityServer.Core.Repositories/packages.config new file mode 100644 index 0000000..e5ea947 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core.Repositories/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Core/Configuration/RepositoryConfigurationSection.cs b/Libraries/Thinktecture.IdentityServer.Core/Configuration/RepositoryConfigurationSection.cs new file mode 100644 index 0000000..f66078f --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/Configuration/RepositoryConfigurationSection.cs @@ -0,0 +1,195 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +namespace Thinktecture.IdentityServer.Configuration +{ + /// + /// The StarterTokenServiceSection Configuration Section. + /// + public partial class RepositoryConfigurationSection : global::System.Configuration.ConfigurationSection + { + public const string SectionName = "thinktecture.identityServer.repositories"; + + #region TokenServiceConfiguration Property + + /// + /// The XML name of the property. + /// + internal const global::System.String TokenServiceConfigurationPropertyName = "tokenServiceConfiguration"; + + /// + /// Gets or sets type of the class that provides encryption certificates + /// + [global::System.Configuration.ConfigurationProperty(TokenServiceConfigurationPropertyName, IsRequired = false, IsKey = false, IsDefaultCollection = false, DefaultValue = "Thinktecture.IdentityServer.Repositories.SqlCompactConfigurationRepository, Thinktecture.IdentityServer")] + public global::System.String TokenServiceConfiguration + { + get + { + return (global::System.String)base[TokenServiceConfigurationPropertyName]; + } + set + { + base[TokenServiceConfigurationPropertyName] = value; + } + } + + #endregion + + #region UserManagement Property + + /// + /// The XML name of the property. + /// + internal const global::System.String UserManagementPropertyName = "userManagement"; + + /// + /// Gets or sets type of the class that provides encryption certificates + /// + [global::System.Configuration.ConfigurationProperty(UserManagementPropertyName, IsRequired = false, IsKey = false, IsDefaultCollection = false, DefaultValue = "Thinktecture.IdentityServer.Repositories.ProviderUserRepository, Thinktecture.IdentityServer")] + public global::System.String UserManagement + { + get + { + return (global::System.String)base[UserManagementPropertyName]; + } + set + { + base[UserManagementPropertyName] = value; + } + } + + #endregion + + #region RelyingParties Property + + /// + /// The XML name of the property. + /// + internal const global::System.String RelyingPartiesPropertyName = "relyingParties"; + + /// + /// Gets or sets type of the class that provides encryption certificates + /// + [global::System.Configuration.ConfigurationProperty(RelyingPartiesPropertyName, IsRequired = false, IsKey = false, IsDefaultCollection = false, DefaultValue = "Thinktecture.IdentityServer.Repositories.SqlCompactRelyingPartyRepository, Thinktecture.IdentityServer")] + public global::System.String RelyingParties + { + get + { + return (global::System.String)base[RelyingPartiesPropertyName]; + } + set + { + base[RelyingPartiesPropertyName] = value; + } + } + + #endregion + + #region ClientCertificates Property + + /// + /// The XML name of the property. + /// + internal const global::System.String ClientCertificatesPropertyName = "clientCertificates"; + + /// + /// Gets or sets type of the class that provides encryption certificates + /// + [global::System.Configuration.ConfigurationProperty(ClientCertificatesPropertyName, IsRequired = false, IsKey = false, IsDefaultCollection = false, DefaultValue = "Thinktecture.IdentityServer.Repositories.SqlCompactUserMappingsRepository, Thinktecture.IdentityServer")] + public global::System.String ClientCertificates + { + get + { + return (global::System.String)base[ClientCertificatesPropertyName]; + } + set + { + base[ClientCertificatesPropertyName] = value; + } + } + + #endregion + + #region Delegation Property + + /// + /// The XML name of the property. + /// + internal const global::System.String DelegationPropertyName = "delegation"; + + /// + /// Gets or sets type of the class that provides encryption certificates + /// + [global::System.Configuration.ConfigurationProperty(DelegationPropertyName, IsRequired = false, IsKey = false, IsDefaultCollection = false, DefaultValue = "Thinktecture.IdentityServer.Repositories.SqlCompactUserMappingsRepository, Thinktecture.IdentityServer")] + public global::System.String Delegation + { + get + { + return (global::System.String)base[DelegationPropertyName]; + } + set + { + base[DelegationPropertyName] = value; + } + } + + #endregion + + #region Caching Property + + /// + /// The XML name of the property. + /// + internal const global::System.String CachingPropertyName = "caching"; + + /// + /// Gets or sets type of the class that provides encryption certificates + /// + [global::System.Configuration.ConfigurationProperty(CachingPropertyName, IsRequired = false, IsKey = false, IsDefaultCollection = false, DefaultValue = "Thinktecture.IdentityServer.Repositories.MemoryCacheRepository, Thinktecture.IdentityServer")] + public global::System.String Caching + { + get + { + return (global::System.String)base[CachingPropertyName]; + } + set + { + base[CachingPropertyName] = value; + } + } + + #endregion + + #region Xmlns Property + + /// + /// The XML name of the property. + /// + internal const global::System.String XmlnsPropertyName = "xmlns"; + + /// + /// Gets the XML namespace of this Configuration Section. + /// + /// + /// This property makes sure that if the configuration file contains the XML namespace, + /// the parser doesn't throw an exception because it encounters the unknown "xmlns" attribute. + /// + [global::System.Configuration.ConfigurationProperty(XmlnsPropertyName, IsRequired = false, IsKey = false, IsDefaultCollection = false)] + public global::System.String Xmlns + { + get + { + return (global::System.String)base[XmlnsPropertyName]; + } + } + + #endregion + } +} + diff --git a/Libraries/Thinktecture.IdentityServer.Core/Constants.cs b/Libraries/Thinktecture.IdentityServer.Core/Constants.cs new file mode 100644 index 0000000..6b3f104 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/Constants.cs @@ -0,0 +1,55 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +namespace Thinktecture.IdentityServer +{ + public static class Constants + { + public static class Actions + { + public const string Issue = "Issue"; + public const string Administration = "Administration"; + } + + public static class Resources + { + // issue actions + public const string WSFederation = "WSFederation"; + public const string SimpleHttp = "SimpleHttp"; + public const string OAuth2 = "OAuth2"; + public const string WRAP = "WRAP"; + public const string WSTrust = "WSTrust"; + public const string JSNotify = "JSNotify"; + + // administration actions + public const string General = "General"; + public const string Configuration = "Configuration"; + public const string RelyingParty = "RelyingParty"; + public const string ServiceCertificates = "ServiceCertificates"; + public const string ClientCertificates = "ClientCertificates"; + public const string Delegation = "Delegation"; + public const string UI = "UI"; + } + + public static class Roles + { + public const string InternalRolesPrefix = "IdentityServer"; + public const string Users = "Users"; + public const string Administrators = "Administrators"; + + public const string IdentityServerUsers = InternalRolesPrefix + Users; + public const string IdentityServerAdministrators = InternalRolesPrefix + Administrators; + } + + public static class CacheKeys + { + public const string WSFedMetadata = "Cache_WSFedMetadata"; + } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core/DateTimeEpochExtensions.cs b/Libraries/Thinktecture.IdentityServer.Core/DateTimeEpochExtensions.cs new file mode 100644 index 0000000..cfc4a75 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/DateTimeEpochExtensions.cs @@ -0,0 +1,61 @@ +#region BSD License +/* +Copyright (c) 2010, NETFx +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +* Neither the name of Clarius Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#endregion + +using System; +namespace Thinktecture.IdentityServer.Core +{ + internal static class DateTimeEpochExtensions + { + /// + /// Converts the given date value to epoch time. + /// + public static ulong ToEpochTime(this DateTime dateTime) + { + var date = dateTime.ToUniversalTime(); + var ts = date - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + + return Convert.ToUInt64(ts.TotalSeconds); + } + + /// + /// Converts the given date value to epoch time. + /// + public static ulong ToEpochTime(this DateTimeOffset dateTime) + { + var date = dateTime.ToUniversalTime(); + var ts = date - new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero); + + return Convert.ToUInt64(ts.TotalSeconds); + } + + /// + /// Converts the given epoch time to a with kind. + /// + public static DateTime ToDateTimeFromEpoch(this ulong secondsSince1970) + { + return new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddSeconds(secondsSince1970); + } + + /// + /// Converts the given epoch time to a UTC . + /// + public static DateTimeOffset ToDateTimeOffsetFromEpoch(this ulong secondsSince1970) + { + return new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero).AddSeconds(secondsSince1970); + } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Core/Endpoints.cs b/Libraries/Thinktecture.IdentityServer.Core/Endpoints.cs new file mode 100644 index 0000000..e2608a5 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/Endpoints.cs @@ -0,0 +1,139 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; + +namespace Thinktecture.IdentityServer +{ + /// + /// Creates endpoint URIs for the various STS endpoints + /// + public class Endpoints + { + public Uri WSFederation { get; set; } + public Uri WSFederationMetadata { get; set; } + public Uri WSTrustMex { get; set; } + public Uri PrivacyNotice { get; set; } + + public Uri WSTrustMessageUserName { get; set; } + public Uri WSTrustMixedUserName { get; set; } + public Uri WSTrustMessageCertificate { get; set; } + public Uri WSTrustMixedCertificate { get; set; } + + public Uri SimpleHttp { get; set; } + public Uri Wrap { get; set; } + public Uri OAuth2 { get; set; } + public Uri JSNotify { get; set; } + + public static class Paths + { + public const string WSFedIssuePage = "/issue/wsfed"; + public const string WSFedMetadata = "/FederationMetadata/2007-06/FederationMetadata.xml"; + public const string PrivacyNotice = "/privacyNotice.txt"; + public const string WSTrustBase = "/issue/wstrust"; + public const string SimpleHttp = "/issue/simple"; + public const string Wrap = "/issue/wrap"; + public const string OAuth2 = "/issue/oauth2"; + public const string JSNotify = "/issue/jsnotify"; + public const string Mex = "/mex"; + public const string WSTrustMessageUserName = "/message/username"; + public const string WSTrustMixedUserName = "/mixed/username"; + public const string WSTrustMessageCertificate = "/message/certificate"; + public const string WSTrustMixedCertificate = "/mixed/certificate"; + } + + /// + /// Creates the URIs based on the host header + /// + /// STS Endpoints + public static Endpoints Create(string host, string applicationPath, int httpPort, int httpsPort) + { + return Create("https://" + host + applicationPath, httpPort, httpsPort); + } + + /// + /// Creates the URIs based on the baseUri. + /// + /// The base URI. + /// STS Endpoints + public static Endpoints Create(string baseUriString, int httpPort, int httpsPort) + { + var ep = new Endpoints(); + if (baseUriString.EndsWith("/")) + { + baseUriString = baseUriString.Substring(0, baseUriString.Length - 1); + } + + // construct various http and https URIs + var passive = new Uri(baseUriString + Paths.WSFedIssuePage); + var builder = new UriBuilder(passive); + builder.Scheme = Uri.UriSchemeHttps; + builder.Port = httpsPort; + ep.WSFederation = builder.Uri; + + // construct various http and https URIs + var privacy = new Uri(baseUriString + Paths.PrivacyNotice); + builder = new UriBuilder(privacy); + builder.Scheme = Uri.UriSchemeHttps; + builder.Port = httpsPort; + ep.PrivacyNotice = builder.Uri; + + var simpleHttp = new Uri(baseUriString + Paths.SimpleHttp); + builder = new UriBuilder(simpleHttp); + builder.Scheme = Uri.UriSchemeHttps; + builder.Port = httpsPort; + ep.SimpleHttp = builder.Uri; + + var wrap = new Uri(baseUriString + Paths.Wrap); + builder = new UriBuilder(wrap); + builder.Scheme = Uri.UriSchemeHttps; + builder.Port = httpsPort; + ep.Wrap = builder.Uri; + + var oauth2 = new Uri(baseUriString + Paths.OAuth2); + builder = new UriBuilder(oauth2); + builder.Scheme = Uri.UriSchemeHttps; + builder.Port = httpsPort; + ep.OAuth2 = builder.Uri; + + var jsnotify = new Uri(baseUriString + Paths.JSNotify); + builder = new UriBuilder(jsnotify); + builder.Scheme = Uri.UriSchemeHttps; + builder.Port = httpsPort; + ep.JSNotify = builder.Uri; + + var wsfedmd = new Uri(baseUriString + Paths.WSFedMetadata); + builder = new UriBuilder(wsfedmd); + builder.Scheme = Uri.UriSchemeHttps; + builder.Port = httpsPort; + ep.WSFederationMetadata = builder.Uri; + + var activeClear = new Uri(baseUriString + Paths.WSTrustBase); + builder = new UriBuilder(activeClear); + builder.Scheme = Uri.UriSchemeHttp; + builder.Port = httpPort; + activeClear = builder.Uri; + + builder = new UriBuilder(activeClear); + builder.Scheme = Uri.UriSchemeHttps; + builder.Port = httpsPort; + var activeSsl = builder.Uri; + + ep.WSTrustMessageUserName = new Uri(activeClear + Paths.WSTrustMessageUserName); + ep.WSTrustMixedUserName = new Uri(activeSsl + Paths.WSTrustMixedUserName); + + ep.WSTrustMessageCertificate = new Uri(activeClear + Paths.WSTrustMessageCertificate); + ep.WSTrustMixedCertificate = new Uri(activeSsl + Paths.WSTrustMixedCertificate); + + ep.WSTrustMex = new Uri(activeSsl + Paths.Mex); + + return ep; + } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Core/Helper/Cache.cs b/Libraries/Thinktecture.IdentityServer.Core/Helper/Cache.cs new file mode 100644 index 0000000..f703461 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/Helper/Cache.cs @@ -0,0 +1,30 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using Thinktecture.IdentityServer.Repositories; + +namespace Thinktecture.IdentityServer.Helper +{ + public static class Cache + { + public static T ReturnFromCache(ICacheRepository cacheRepository, string name, int ttl, Func action) + where T: class + { + var item = cacheRepository.Get(name) as T; + if (item == null) + { + item = action(); + cacheRepository.Put(name, item, ttl); + } + + return item; + } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core/Helper/X509Certificates.cs b/Libraries/Thinktecture.IdentityServer.Core/Helper/X509Certificates.cs new file mode 100644 index 0000000..c9a128d --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/Helper/X509Certificates.cs @@ -0,0 +1,100 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Security.Cryptography.X509Certificates; + +namespace Thinktecture.IdentityServer.Helper +{ + /// + /// Helper class to retrieve certificates from configuration + /// + public static class X509Certificates + { + + /// + /// Retrieves a certificate from the certificate store. + /// + /// The location. + /// The name. + /// Type of the find. + /// The value. + /// A X509Certificate2 + public static X509Certificate2 GetCertificateFromStore(StoreLocation location, StoreName name, X509FindType findType, object value) + { + X509Store store = new X509Store(name, location); + + try + { + store.Open(OpenFlags.ReadOnly); + + // work around possible bug in framework + if (findType == X509FindType.FindByThumbprint) + { + var thumbprint = value.ToString(); + thumbprint = thumbprint.Trim(); + thumbprint = thumbprint.Replace(" ", ""); + + foreach (var cert in store.Certificates) + { + if (string.Equals(cert.Thumbprint, thumbprint, StringComparison.OrdinalIgnoreCase) || + string.Equals(cert.Thumbprint, thumbprint, StringComparison.InvariantCultureIgnoreCase)) + { + return cert; + } + } + } + if (findType == X509FindType.FindBySerialNumber) + { + var serial = value.ToString(); + serial = serial.Trim(); + serial = serial.Replace(" ", ""); + + foreach (var cert in store.Certificates) + { + if (string.Equals(cert.SerialNumber, serial, StringComparison.OrdinalIgnoreCase) || + string.Equals(cert.SerialNumber, serial, StringComparison.InvariantCultureIgnoreCase)) + { + return cert; + } + } + } + + var certs = store.Certificates.Find(findType, value, false); + + if (certs.Count != 1) + { + throw new InvalidOperationException(String.Format("Certificate not found: {0}", value)); + } + + return certs[0]; + } + finally + { + store.Close(); + } + } + + + + /// + /// Retrieves a certificate from the local machine / personal certificate store. + /// + /// The subject distinguished name of the certificate. + /// A X509Certificate2 + public static X509Certificate2 GetCertificateFromStore(string subjectDistinguishedName) + { + return GetCertificateFromStore( + StoreLocation.LocalMachine, + StoreName.My, + X509FindType.FindBySubjectDistinguishedName, + subjectDistinguishedName); + } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core/Models/CertificateConfiguration.cs b/Libraries/Thinktecture.IdentityServer.Core/Models/CertificateConfiguration.cs new file mode 100644 index 0000000..4771703 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/Models/CertificateConfiguration.cs @@ -0,0 +1,19 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.Security.Cryptography.X509Certificates; + +namespace Thinktecture.IdentityServer.Models +{ + public class CertificateConfiguration + { + public string SubjectDistinguishedName { get; set; } + public X509Certificate2 Certificate { get; set; } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core/Models/ClientCertificate.cs b/Libraries/Thinktecture.IdentityServer.Core/Models/ClientCertificate.cs new file mode 100644 index 0000000..2a85391 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/Models/ClientCertificate.cs @@ -0,0 +1,18 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +namespace Thinktecture.IdentityServer.Models +{ + public class ClientCertificate + { + public string UserName { get; set; } + public string Thumbprint { get; set; } + public string Description { get; set; } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core/Models/DelegationSetting.cs b/Libraries/Thinktecture.IdentityServer.Core/Models/DelegationSetting.cs new file mode 100644 index 0000000..1d6210c --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/Models/DelegationSetting.cs @@ -0,0 +1,20 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; + +namespace Thinktecture.IdentityServer.Models +{ + public class DelegationSetting + { + public string UserName { get; set; } + public Uri Realm { get; set; } + public string Description { get; set; } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core/Models/EndpointConfiguration.cs b/Libraries/Thinktecture.IdentityServer.Core/Models/EndpointConfiguration.cs new file mode 100644 index 0000000..3ba81f9 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/Models/EndpointConfiguration.cs @@ -0,0 +1,26 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + + +namespace Thinktecture.IdentityServer.Models +{ + public class EndpointConfiguration + { + public bool WSFederation { get; set; } + public bool WSTrustMessage { get; set; } + public bool WSTrustMixed { get; set; } + public bool SimpleHttp { get; set; } + public bool FederationMetadata { get; set; } + public bool OAuthWRAP { get; set; } + public bool OAuth2 { get; set; } + public bool JSNotify { get; set; } + public int HttpPort { get; set; } + public int HttpsPort { get; set; } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core/Models/GlobalConfiguration.cs b/Libraries/Thinktecture.IdentityServer.Core/Models/GlobalConfiguration.cs new file mode 100644 index 0000000..d636d29 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/Models/GlobalConfiguration.cs @@ -0,0 +1,37 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; + +namespace Thinktecture.IdentityServer.Models +{ + public class GlobalConfiguration + { + public String SiteName { get; set; } + public String IssuerUri { get; set; } + public String IssuerContactEmail { get; set; } + public string DefaultTokenType { get; set; } + public int DefaultTokenLifetime { get; set; } + public int MaximumTokenLifetime { get; set; } + public int SsoCookieLifetime { get; set; } + public Boolean RequireSsl { get; set; } + public Boolean RequireEncryption { get; set; } + public Boolean RequireSignInConfirmation { get; set; } + public Boolean RequireReplyToWithinRealm { get; set; } + public Boolean AllowKnownRealmsOnly { get; set; } + public Boolean AllowReplyTo { get; set; } + public Boolean EnableClientCertificates { get; set; } + public Boolean EnableDelegation { get; set; } + public Boolean EnableStrongEpiForSsl { get; set; } + public Boolean EnableFederationMessageTracing { get; set; } + public Boolean EnforceUsersGroupMembership { get; set; } + } +} + + diff --git a/Libraries/Thinktecture.IdentityServer.Core/Models/RelyingParty.cs b/Libraries/Thinktecture.IdentityServer.Core/Models/RelyingParty.cs new file mode 100644 index 0000000..4b80165 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/Models/RelyingParty.cs @@ -0,0 +1,27 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Security.Cryptography.X509Certificates; + +namespace Thinktecture.IdentityServer.Models +{ + public class RelyingParty + { + public string Id { get; set; } + public string Name { get; set; } + public Uri Realm { get; set; } + public Uri ReplyTo { get; set; } + public X509Certificate2 EncryptingCertificate { get; set; } + public byte[] SymmetricSigningKey { get; set; } + public string ExtraData1 { get; set; } + public string ExtraData2 { get; set; } + public string ExtraData3 { get; set; } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Core/Properties/AssemblyInfo.cs b/Libraries/Thinktecture.IdentityServer.Core/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..e5fedc1 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +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("Thinktecture.IdentityServer.Core")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("Thinktecture.IdentityServer.Core")] +[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("ee4ae22d-7664-4089-864e-ac340a137c31")] + +// 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 Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Libraries/Thinktecture.IdentityServer.Core/Repositories/Container.cs b/Libraries/Thinktecture.IdentityServer.Core/Repositories/Container.cs new file mode 100644 index 0000000..efa6e55 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/Repositories/Container.cs @@ -0,0 +1,18 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.ComponentModel.Composition.Hosting; + +namespace Thinktecture.IdentityServer.Repositories +{ + public static class Container + { + public static CompositionContainer Current { get; set; } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Core/Repositories/ICacheRepository.cs b/Libraries/Thinktecture.IdentityServer.Core/Repositories/ICacheRepository.cs new file mode 100644 index 0000000..5777ab0 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/Repositories/ICacheRepository.cs @@ -0,0 +1,18 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +namespace Thinktecture.IdentityServer.Repositories +{ + public interface ICacheRepository + { + void Put(string name, object value, int ttl); + object Get(string name); + void Invalidate(string name); + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core/Repositories/IClientCertificatesRepository.cs b/Libraries/Thinktecture.IdentityServer.Core/Repositories/IClientCertificatesRepository.cs new file mode 100644 index 0000000..9c0eb96 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/Repositories/IClientCertificatesRepository.cs @@ -0,0 +1,28 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.Collections.Generic; +using System.Security.Cryptography.X509Certificates; +using Thinktecture.IdentityServer.Models; + +namespace Thinktecture.IdentityServer.Repositories +{ + public interface IClientCertificatesRepository + { + // run time + bool TryGetUserNameFromThumbprint(X509Certificate2 certificate, out string userName); + + // management + bool SupportsWriteAccess { get; } + IEnumerable List(int pageIndex, int pageSize); + IEnumerable GetClientCertificatesForUser(string userName); + void Add(ClientCertificate certificate); + void Delete(ClientCertificate certificate); + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core/Repositories/IConfigurationRepository.cs b/Libraries/Thinktecture.IdentityServer.Core/Repositories/IConfigurationRepository.cs new file mode 100644 index 0000000..708f2e8 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/Repositories/IConfigurationRepository.cs @@ -0,0 +1,26 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using Thinktecture.IdentityServer.Models; + +namespace Thinktecture.IdentityServer.Repositories +{ + public interface IConfigurationRepository + { + GlobalConfiguration Configuration { get; } + EndpointConfiguration Endpoints { get; } + CertificateConfiguration SslCertificate { get; } + CertificateConfiguration SigningCertificate { get; } + + bool SupportsWriteAccess { get; } + void UpdateConfiguration(GlobalConfiguration configuration); + void UpdateEndpoints(EndpointConfiguration endpoints); + void UpdateCertificates(string sslSubjectName, string signingSubjectName); + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Core/Repositories/IDelegationRepository.cs b/Libraries/Thinktecture.IdentityServer.Core/Repositories/IDelegationRepository.cs new file mode 100644 index 0000000..095e7b3 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/Repositories/IDelegationRepository.cs @@ -0,0 +1,27 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.Collections.Generic; +using Thinktecture.IdentityServer.Models; + +namespace Thinktecture.IdentityServer.Repositories +{ + public interface IDelegationRepository + { + // run time + bool IsDelegationAllowed(string userName, string realm); + + // management + bool SupportsWriteAccess { get; } + IEnumerable GetAllUsers(int pageIndex, int pageSize); + IEnumerable GetDelegationSettingsForUser(string userName); + void Add(DelegationSetting setting); + void Delete(DelegationSetting setting); + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core/Repositories/IRelyingPartyRepository.cs b/Libraries/Thinktecture.IdentityServer.Core/Repositories/IRelyingPartyRepository.cs new file mode 100644 index 0000000..48a733a --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/Repositories/IRelyingPartyRepository.cs @@ -0,0 +1,27 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.Collections.Generic; +using Thinktecture.IdentityServer.Models; + +namespace Thinktecture.IdentityServer.Repositories +{ + public interface IRelyingPartyRepository + { + bool TryGet(string realm, out RelyingParty relyingParty); + + // management + bool SupportsWriteAccess { get; } + IEnumerable List(int pageIndex, int pageSize); + RelyingParty Get(string id); + void Add(RelyingParty relyingParty); + void Update(RelyingParty relyingParty); + void Delete(string id); + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core/Repositories/IUserRepository.cs b/Libraries/Thinktecture.IdentityServer.Core/Repositories/IUserRepository.cs new file mode 100644 index 0000000..96834c0 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/Repositories/IUserRepository.cs @@ -0,0 +1,32 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.Collections.Generic; +using System.Security.Cryptography.X509Certificates; +using Microsoft.IdentityModel.Claims; +using Thinktecture.IdentityServer.TokenService; + +namespace Thinktecture.IdentityServer.Repositories +{ + public interface IUserRepository + { + bool ValidateUser(string userName, string password); + bool ValidateUser(X509Certificate2 clientCertificate, out string userName); + IEnumerable GetRoles(string userName, RoleTypes roleType); + IEnumerable GetClaims(IClaimsPrincipal principal, RequestDetails requestDetails); + IEnumerable GetSupportedClaimTypes(); + } + + public enum RoleTypes + { + All, + IdentityServer, + Client + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Core/Repositories/RepositoryExportProvider.cs b/Libraries/Thinktecture.IdentityServer.Core/Repositories/RepositoryExportProvider.cs new file mode 100644 index 0000000..9bd8825 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/Repositories/RepositoryExportProvider.cs @@ -0,0 +1,61 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition.Hosting; +using System.ComponentModel.Composition.Primitives; +using System.Configuration; +using Thinktecture.IdentityServer.Configuration; + +namespace Thinktecture.IdentityServer.Repositories +{ + public class RepositoryExportProvider : ExportProvider + { + private Dictionary _mappings; + + public RepositoryExportProvider() + { + var section = ConfigurationManager.GetSection(RepositoryConfigurationSection.SectionName) as RepositoryConfigurationSection; + + _mappings = new Dictionary + { + { typeof(IConfigurationRepository).FullName, section.TokenServiceConfiguration }, + { typeof(IUserRepository).FullName, section.UserManagement }, + { typeof(IRelyingPartyRepository).FullName, section.RelyingParties }, + { typeof(IClientCertificatesRepository).FullName, section.ClientCertificates}, + { typeof(IDelegationRepository).FullName, section.Delegation}, + { typeof(ICacheRepository).FullName, section.Caching } + }; + } + + protected override IEnumerable GetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition) + { + var exports = new List(); + + string implementingType; + if (_mappings.TryGetValue(definition.ContractName, out implementingType)) + { + var t = Type.GetType(implementingType); + if (t == null) + { + throw new InvalidOperationException("Type not found for interface: " + definition.ContractName); + } + + var instance = t.GetConstructor(Type.EmptyTypes).Invoke(null); + var exportDefintion = new ExportDefinition(definition.ContractName, new Dictionary()); + var toAdd = new Export(exportDefintion, () => instance); + + exports.Add(toAdd); + } + + return exports; + } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Core/SWT/SimpleWebToken.cs b/Libraries/Thinktecture.IdentityServer.Core/SWT/SimpleWebToken.cs new file mode 100644 index 0000000..308fd9a --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/SWT/SimpleWebToken.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.IdentityModel.Tokens; +using System.Linq; +using System.Web; +using Microsoft.IdentityModel.Claims; +using Microsoft.IdentityModel.Tokens; + +namespace Thinktecture.IdentityServer.Core.Swt +{ + /// + /// Parses an SWT token. See http://groups.google.com/group/oauth-wrap-wg. + /// + public class SimpleWebToken : SecurityToken + { + public const string OasisTokenProfile = "http://schemas.xmlsoap.org/ws/2009/11/swt-token-profile-1.0"; + + private DateTime validFrom = DateTime.UtcNow; + + public string Audience { get; private set; } + public NameValueCollection Claims { get; private set; } + public DateTime ExpiresOn { get; private set; } + public string Issuer { get; private set; } + public string RawToken { get; private set; } + + public SimpleWebToken(string rawToken) + { + this.RawToken = rawToken; + this.Parse(); + } + + public bool IsExpired + { + get + { + var expiresOn = this.ExpiresOn.ToEpochTime(); + var currentTime = DateTime.UtcNow.ToEpochTime(); + + return currentTime > expiresOn; + } + } + + /// + /// Converts the SimpleWebToken to a ClaimsIdentity + /// + public ClaimsIdentity ToClaimsIdentity(string nameClaimType = null, string roleClaimType = null) + { + var claims = this.Claims + .AllKeys + .SelectMany(key => this.Claims.GetValues(key) + .Select(value => new { Key = key, Value = value })) + .Select(keyValue => new Claim(keyValue.Key, keyValue.Value)); + + return new ClaimsIdentity(claims, "OAUTH-SWT", + nameClaimType ?? ClaimTypes.Name, roleClaimType ?? ClaimTypes.Role); + } + + public override string ToString() + { + return this.RawToken; + } + + private void Parse() + { + this.Claims = new NameValueCollection(); + + foreach (var rawNameValue in this.RawToken.Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries)) + { + if (rawNameValue.StartsWith(SwtConstants.HmacSha256 + "=")) + continue; + + var nameValue = rawNameValue.Split('='); + + if (nameValue.Length != 2) + throw new InvalidSecurityTokenException(string.Format( + "Invalid token contains a name/value pair missing an = character: '{0}'", rawNameValue)); + + var key = HttpUtility.UrlDecode(nameValue[0]); + + if (this.Claims.AllKeys.Contains(key)) + throw new InvalidSecurityTokenException("Duplicated name token."); + + var values = HttpUtility.UrlDecode(nameValue[1]); + + switch (key) + { + case SwtConstants.Audience: + this.Audience = values; + break; + case SwtConstants.ExpiresOn: + this.ExpiresOn = ulong.Parse(values).ToDateTimeFromEpoch(); + break; + case SwtConstants.Issuer: + this.Issuer = values; + break; + default: + foreach (var value in values.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) + { + this.Claims.Add(key, value); + } + break; + } + } + } + + /* SecurityToken */ + public override DateTime ValidFrom { get { return this.validFrom; } } + public override DateTime ValidTo { get { return this.ExpiresOn; } } + public override string Id { get { throw new NotImplementedException(); } } + public override ReadOnlyCollection SecurityKeys { get { return new List().AsReadOnly(); } } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Core/SWT/SwtConstants.cs b/Libraries/Thinktecture.IdentityServer.Core/SWT/SwtConstants.cs new file mode 100644 index 0000000..9b977ac --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/SWT/SwtConstants.cs @@ -0,0 +1,12 @@ +using Microsoft.IdentityModel.Tokens.Saml2; + +namespace Thinktecture.IdentityServer.Core.Swt +{ + internal class SwtConstants + { + public const string Audience = Saml2Constants.Elements.Audience; + public const string Issuer = Saml2Constants.Elements.Issuer; + public const string ExpiresOn = "ExpiresOn"; + public const string HmacSha256 = "HMACSHA256"; + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Core/SWT/SwtSecurityKeyClause.cs b/Libraries/Thinktecture.IdentityServer.Core/SWT/SwtSecurityKeyClause.cs new file mode 100644 index 0000000..2ee15df --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/SWT/SwtSecurityKeyClause.cs @@ -0,0 +1,22 @@ +using System.IdentityModel.Tokens; + +namespace Thinktecture.IdentityServer.Core.Swt +{ + /// + /// The passes an instance of this clause to + /// the so that it knows it's an SWT that has + /// already been verified against the trusted + /// issuers list. + /// + /// + /// Because we only support one symmetric + /// for SWT, we don't need to differentiate between issuers. + /// + internal class SwtSecurityKeyClause : SecurityKeyIdentifierClause + { + public SwtSecurityKeyClause() + : base("SWT") + { + } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core/SWT/SwtSecurityTokenHandler.cs b/Libraries/Thinktecture.IdentityServer.Core/SWT/SwtSecurityTokenHandler.cs new file mode 100644 index 0000000..c1ea625 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/SWT/SwtSecurityTokenHandler.cs @@ -0,0 +1,217 @@ +/* + * Credits: http://zamd.net/2011/02/08/using-simple-web-token-swt-with-wif/ + * kzu: simplified impl. for netfx + * + */ + +using System; +using System.Collections.Generic; +using System.IdentityModel.Tokens; +using System.Linq; +using System.Security.Cryptography; +using System.ServiceModel.Security; +using System.ServiceModel.Web; +using System.Text; +using System.Web; +using System.Xml; +using Microsoft.IdentityModel; +using Microsoft.IdentityModel.Claims; +using Microsoft.IdentityModel.Tokens; + +namespace Thinktecture.IdentityServer.Core.Swt +{ + /// + /// Handles SWT tokens. + /// + public class SwtSecurityTokenHandler : SecurityTokenHandler + { + public override string[] GetTokenTypeIdentifiers() + { + return new[] { "http://schemas.microsoft.com/ws/2010/07/identitymodel/tokens/SWT", + "http://schemas.xmlsoap.org/ws/2009/11/swt-token-profile-1.0" }; + } + + public override Type TokenType + { + get { return typeof(SimpleWebToken); } + } + + public override bool CanReadToken(XmlReader reader) + { + // since this STS does not accept incoming SWT token, the code path is short circuited + return false; + + return + reader.IsStartElement(WSSecurity10Constants.Elements.BinarySecurityToken, WSSecurity10Constants.Namespace) && + reader.GetAttribute(WSSecurity10Constants.Attributes.ValueType) == "http://schemas.xmlsoap.org/ws/2009/11/swt-token-profile-1.0"; + } + + public override SecurityToken ReadToken(XmlReader reader) + { + if (!this.CanReadToken(reader)) + throw new WebFaultException(System.Net.HttpStatusCode.Unauthorized); + + var swtBuffer = Convert.FromBase64String(reader.ReadElementContentAsString()); + var swt = Encoding.Default.GetString(swtBuffer); + + try + { + return new SimpleWebToken(swt); + } + catch (InvalidSecurityTokenException) + { + throw new WebFaultException(System.Net.HttpStatusCode.Unauthorized); + } + } + + public override bool CanValidateToken + { + get { return true; } + } + + public override bool CanWriteToken + { + get { return true; } + } + + public override void WriteToken(XmlWriter writer, SecurityToken token) + { + var swt = token as SimpleWebToken; + + if (swt == null) + throw new InvalidSecurityTokenException(); + + // Wrap the token into a binary token for XML transport. + writer.WriteStartElement(WSSecurity10Constants.Elements.BinarySecurityToken, WSSecurity10Constants.Namespace); + writer.WriteAttributeString(WSSecurity10Constants.Attributes.ValueType, "http://schemas.xmlsoap.org/ws/2009/11/swt-token-profile-1.0"); + writer.WriteAttributeString(WSSecurity10Constants.Attributes.EncodingType, WSSecurity10Constants.EncodingTypes.Base64); + writer.WriteValue(Convert.ToBase64String(Encoding.Default.GetBytes(swt.RawToken))); + writer.WriteEndElement(); + } + + public override ClaimsIdentityCollection ValidateToken(SecurityToken token) + { + var swt = token as SimpleWebToken; + if (swt == null) + throw new WebFaultException(System.Net.HttpStatusCode.Unauthorized); + + if (base.Configuration.IssuerNameRegistry != null) + { + var resolvedIssuer = base.Configuration.IssuerNameRegistry.GetIssuerName(token); + if (resolvedIssuer != swt.Issuer) + throw new WebFaultException(System.Net.HttpStatusCode.Unauthorized); + } + + // If we get this far, it's because the issuer is a trusted one, or we don't + // care as we didn't setup an issuerNameRegistry at all. To the resolver + // always returns the key. + var securityKey = base.Configuration.IssuerTokenResolver.ResolveSecurityKey( + new SwtSecurityKeyClause()) as InMemorySymmetricSecurityKey; + + if (securityKey == null) + throw new WebFaultException(System.Net.HttpStatusCode.Unauthorized); + + if (!IsHMACValid(swt.RawToken, securityKey.GetSymmetricKey())) + throw new WebFaultException(System.Net.HttpStatusCode.Unauthorized); + + if (swt.IsExpired) + throw new WebFaultException(System.Net.HttpStatusCode.Unauthorized); + + if (base.Configuration.AudienceRestriction.AudienceMode != System.IdentityModel.Selectors.AudienceUriMode.Never) + { + var allowedAudiences = base.Configuration.AudienceRestriction.AllowedAudienceUris; + var swtAudienceUri = default(Uri); + if (!Uri.TryCreate(swt.Audience, UriKind.RelativeOrAbsolute, out swtAudienceUri)) + throw new WebFaultException(System.Net.HttpStatusCode.Unauthorized); + + if (!allowedAudiences.Any(uri => uri == swtAudienceUri)) + throw new WebFaultException(System.Net.HttpStatusCode.Unauthorized); + } + + var incomingIdentity = swt.ToClaimsIdentity(); + + if (base.Configuration.SaveBootstrapTokens) + { + incomingIdentity.BootstrapToken = token; + } + + return new ClaimsIdentityCollection(new IClaimsIdentity[] { incomingIdentity }); + } + + public override SecurityToken CreateToken(SecurityTokenDescriptor tokenDescriptor) + { + var sb = new StringBuilder(); + + CreateClaims(tokenDescriptor, sb); + + sb.AppendFormat("Issuer={0}&", HttpUtility.UrlEncode(tokenDescriptor.TokenIssuerName)); + sb.AppendFormat("Audience={0}&", HttpUtility.UrlEncode(tokenDescriptor.AppliesToAddress)); + + var seconds = (tokenDescriptor.Lifetime.Expires - tokenDescriptor.Lifetime.Created); + double lifeTimeInSeconds = 3600; + if (seconds.HasValue) + lifeTimeInSeconds = seconds.Value.TotalSeconds; + + sb.AppendFormat("ExpiresOn={0:0}", DateTime.UtcNow.ToEpochTime() + lifeTimeInSeconds); + + var unsignedToken = sb.ToString(); + + var key = (InMemorySymmetricSecurityKey)tokenDescriptor.SigningCredentials.SigningKey; + var hmac = new HMACSHA256(key.GetSymmetricKey()); + var sig = hmac.ComputeHash(Encoding.ASCII.GetBytes(unsignedToken)); + + var signedToken = String.Format("{0}&HMACSHA256={1}", + unsignedToken, + HttpUtility.UrlEncode(Convert.ToBase64String(sig))); + + return new SimpleWebToken(signedToken); + } + + private static void CreateClaims(SecurityTokenDescriptor tokenDescriptor, StringBuilder sb) + { + var claims = new Dictionary(); + + foreach (var claim in tokenDescriptor.Subject.Claims) + { + string value; + if (claims.TryGetValue(claim.ClaimType, out value)) + { + claims[claim.ClaimType] = claims[claim.ClaimType] + "," + claim.Value; + } + else + { + claims.Add(claim.ClaimType, claim.Value); + } + } + + foreach (var kv in claims) + { + sb.AppendFormat("{0}={1}&", HttpUtility.UrlEncode(kv.Key), HttpUtility.UrlEncode(kv.Value)); + } + } + + public override SecurityKeyIdentifierClause CreateSecurityTokenReference(SecurityToken token, bool attached) + { + var swt = token as SimpleWebToken; + if (swt == null) + throw new InvalidSecurityTokenException("Expected SWT token."); + + return new KeyNameIdentifierClause(swt.Issuer); + } + + private static bool IsHMACValid(string swt, byte[] sha256HMACKey) + { + var swtWithSignature = swt.Split(new string[] { String.Format("&{0}=", SwtConstants.HmacSha256) }, StringSplitOptions.None); + if (swtWithSignature.Length != 2) + return false; + + using (var hmac = new HMACSHA256(sha256HMACKey)) + { + var locallyGeneratedSignatureInBytes = hmac.ComputeHash(Encoding.ASCII.GetBytes(swtWithSignature[0])); + var locallyGeneratedSignature = HttpUtility.UrlEncode(Convert.ToBase64String(locallyGeneratedSignatureInBytes)); + + return String.Equals(locallyGeneratedSignature, swtWithSignature[1], StringComparison.InvariantCulture); + } + } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Core/SWT/SymmetricSigningCredentials.cs b/Libraries/Thinktecture.IdentityServer.Core/SWT/SymmetricSigningCredentials.cs new file mode 100644 index 0000000..cbca3db --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/SWT/SymmetricSigningCredentials.cs @@ -0,0 +1,18 @@ +using System; +using System.IdentityModel.Tokens; + +namespace Thinktecture.IdentityServer.Core.Swt +{ + public class SymmetricSigningCredentials : SigningCredentials + { + public SymmetricSigningCredentials(string base64EncodedKey) + : this(Convert.FromBase64String(base64EncodedKey)) + { } + + public SymmetricSigningCredentials(byte[] key) + : base(new InMemorySymmetricSecurityKey(key), + SecurityAlgorithms.HmacSha256Signature, SecurityAlgorithms.Sha256Digest) + { } + } +} + diff --git a/Libraries/Thinktecture.IdentityServer.Core/Thinktecture.IdentityServer.Core.csproj b/Libraries/Thinktecture.IdentityServer.Core/Thinktecture.IdentityServer.Core.csproj new file mode 100644 index 0000000..ba4a937 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/Thinktecture.IdentityServer.Core.csproj @@ -0,0 +1,149 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A} + Library + Properties + Thinktecture.IdentityServer + Thinktecture.IdentityServer.Core + v4.0 + 512 + + + + + + + + + 1 + ..\ + true + + + true + full + false + ..\build\Common\ + DEBUG;TRACE + prompt + 4 + False + False + True + False + False + False + False + False + False + False + False + True + False + False + False + + + + + + + False + Full + %28none%29 + 0 + + + pdbonly + true + ..\build\Common\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + + ..\..\OnPremise\packages\Thinktecture.IdentityModel.1.3.0.0\lib\Thinktecture.IdentityModel.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Core/Thinktecture.IdentityServer.csproj.vspscc b/Libraries/Thinktecture.IdentityServer.Core/Thinktecture.IdentityServer.csproj.vspscc new file mode 100644 index 0000000..b6d3289 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/Thinktecture.IdentityServer.csproj.vspscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "" +"NUMBER_OF_EXCLUDED_FILES" = "0" +"ORIGINAL_PROJECT_FILE_PATH" = "" +"NUMBER_OF_NESTED_PROJECTS" = "0" +"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER" +} diff --git a/Libraries/Thinktecture.IdentityServer.Core/TokenService/ClientCertificateIssuerNameRegistry.cs b/Libraries/Thinktecture.IdentityServer.Core/TokenService/ClientCertificateIssuerNameRegistry.cs new file mode 100644 index 0000000..03986f1 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/TokenService/ClientCertificateIssuerNameRegistry.cs @@ -0,0 +1,37 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.IdentityModel.Tokens; +using Microsoft.IdentityModel.Tokens; + +namespace Thinktecture.IdentityServer.TokenService +{ + class ClientCertificateIssuerNameRegistry : IssuerNameRegistry + { + public override string GetIssuerName(SecurityToken securityToken) + { + if (securityToken == null) + { + Tracing.Error("ClientCertificateIssuerNameRegistry: securityToken is null"); + throw new ArgumentNullException("securityToken"); + } + + X509SecurityToken token = securityToken as X509SecurityToken; + if (token != null) + { + Tracing.Verbose("ClientCertificateIssuerNameRegistry: X509 SubjectName: " + token.Certificate.SubjectName.Name); + Tracing.Verbose("ClientCertificateIssuerNameRegistry: X509 Thumbprint : " + token.Certificate.Thumbprint); + return token.Certificate.Thumbprint; + } + + return null; + } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core/TokenService/GenericUserNameSecurityTokenHandler.cs b/Libraries/Thinktecture.IdentityServer.Core/TokenService/GenericUserNameSecurityTokenHandler.cs new file mode 100644 index 0000000..12c94cf --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/TokenService/GenericUserNameSecurityTokenHandler.cs @@ -0,0 +1,142 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Collections.Generic; +using System.IdentityModel.Tokens; +using Microsoft.IdentityModel.Claims; +using Microsoft.IdentityModel.Tokens; +using Thinktecture.IdentityModel.Claims; + +namespace Thinktecture.IdentityServer.TokenService +{ + /// + /// Generic security token handler for username/password type credentials + /// + public class GenericUserNameSecurityTokenHandler : UserNameSecurityTokenHandler + { + /// + /// Callback type for validating the credential + /// + /// The username. + /// The password. + /// True when the credential could be validated succesfully. Otherwise false. + public delegate bool ValidateUserNameCredentialDelegate(string username, string password); + + /// + /// Gets or sets the credential validation callback + /// + /// + /// The credential validation callback. + /// + public ValidateUserNameCredentialDelegate ValidateUserNameCredential { get; set; } + + /// + /// Initializes a new instance of the class. + /// + public GenericUserNameSecurityTokenHandler() + { } + + /// + /// Initializes a new instance of the class. + /// + /// The credential validation callback. + public GenericUserNameSecurityTokenHandler(ValidateUserNameCredentialDelegate validateUserNameCredential) + { + if (validateUserNameCredential == null) + { + throw new ArgumentNullException("ValidateUserNameCredential"); + } + + ValidateUserNameCredential = validateUserNameCredential; + } + + /// + /// Validates the user name credential core. + /// + /// Name of the user. + /// The password. + /// + protected virtual bool ValidateUserNameCredentialCore(string userName, string password) + { + if (ValidateUserNameCredential == null) + { + throw new InvalidOperationException("ValidateUserNameCredentialDelegate not set"); + } + + return ValidateUserNameCredential(userName, password); + } + + /// + /// Validates the username and password. + /// + /// The token. + /// A ClaimsIdentityCollection representing the identity in the token + public override ClaimsIdentityCollection ValidateToken(SecurityToken token) + { + if (token == null) + { + throw new ArgumentNullException("token"); + } + + if (base.Configuration == null) + { + throw new InvalidOperationException("No Configuration set"); + } + + UserNameSecurityToken unToken = token as UserNameSecurityToken; + if (unToken == null) + { + throw new ArgumentException("SecurityToken is no UserNameSecurityToken"); + } + + if (!ValidateUserNameCredentialCore(unToken.UserName, unToken.Password)) + { + throw new SecurityTokenValidationException(unToken.UserName); + } + + var claims = new List + { + new Claim(ClaimTypes.Name, unToken.UserName), + new Claim(ClaimTypes.AuthenticationMethod, AuthenticationMethods.Password), + AuthenticationInstantClaim.Now + }; + + var identity = new ClaimsIdentity(claims); + + if (base.Configuration.SaveBootstrapTokens) + { + if (this.RetainPassword) + { + identity.BootstrapToken = unToken; + } + else + { + identity.BootstrapToken = new UserNameSecurityToken(unToken.UserName, null); + } + } + + return new ClaimsIdentityCollection(new IClaimsIdentity[] { identity }); + } + + /// + /// Gets a value indicating whether this instance can validate a token. + /// + /// + /// true if this instance can validate a token; otherwise, false. + /// + public override bool CanValidateToken + { + get + { + return true; + } + } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core/TokenService/RepositoryUserNameSecurityTokenHandler.cs b/Libraries/Thinktecture.IdentityServer.Core/TokenService/RepositoryUserNameSecurityTokenHandler.cs new file mode 100644 index 0000000..679a731 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/TokenService/RepositoryUserNameSecurityTokenHandler.cs @@ -0,0 +1,26 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.ComponentModel.Composition; +using Thinktecture.IdentityServer.Repositories; + +namespace Thinktecture.IdentityServer.TokenService +{ + public class RepositoryUserNameSecurityTokenHandler : GenericUserNameSecurityTokenHandler + { + [Import] + public IUserRepository UserRepository { get; set; } + + protected override bool ValidateUserNameCredentialCore(string userName, string password) + { + Container.Current.SatisfyImportsOnce(this); + return UserRepository.ValidateUser(userName, password); + } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core/TokenService/RepositoryX509SecurityTokenHandler.cs b/Libraries/Thinktecture.IdentityServer.Core/TokenService/RepositoryX509SecurityTokenHandler.cs new file mode 100644 index 0000000..7f21b59 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/TokenService/RepositoryX509SecurityTokenHandler.cs @@ -0,0 +1,65 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.IdentityModel.Tokens; +using System.Linq; +using Microsoft.IdentityModel.Claims; +using Microsoft.IdentityModel.Protocols.WSIdentity; +using Microsoft.IdentityModel.Tokens; +using Thinktecture.IdentityServer.Repositories; + +namespace Thinktecture.IdentityServer.TokenService +{ + public class RepositoryX509SecurityTokenHandler : X509SecurityTokenHandler + { + [Import] + public IUserRepository UserRepository { get; set; } + + public override ClaimsIdentityCollection ValidateToken(SecurityToken token) + { + Tracing.Information("Beginning client certificate token validation and authentication for SOAP"); + Container.Current.SatisfyImportsOnce(this); + + // call base class implementation for validation and claims generation + var identity = base.ValidateToken(token).First(); + + // retrieve thumbprint + var clientCert = ((X509SecurityToken)token).Certificate; + Tracing.Information(String.Format("Client certificate thumbprint: {0}", clientCert.Thumbprint)); + + // check if mapped user exists + string userName; + if (!UserRepository.ValidateUser(clientCert, out userName)) + { + var message = String.Format("No mapped user exists for thumbprint {0}", clientCert.Thumbprint); + Tracing.Error(message); + throw new SecurityTokenValidationException(message); + } + + Tracing.Information(String.Format("Mapped user found: {0}", userName)); + + // retrieve issuer name + var issuer = identity.Claims.First().Issuer; + Tracing.Information(String.Format("Certificate issuer: {0}", issuer)); + + // create new ClaimsIdentity for the STS issuance logic + var claims = new List + { + new Claim(WSIdentityConstants.ClaimTypes.Name, userName), + new Claim(ClaimTypes.AuthenticationMethod, AuthenticationMethods.X509) + }; + + var id = new ClaimsIdentity(claims); + return new ClaimsIdentityCollection(new IClaimsIdentity[] { id }); + } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Core/TokenService/Request.cs b/Libraries/Thinktecture.IdentityServer.Core/TokenService/Request.cs new file mode 100644 index 0000000..870205b --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/TokenService/Request.cs @@ -0,0 +1,450 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.ComponentModel.Composition; +using System.Linq; +using System.Security.Cryptography.X509Certificates; +using System.ServiceModel; +using System.Text; +using Microsoft.IdentityModel.Claims; +using Microsoft.IdentityModel.Protocols.WSTrust; +using Microsoft.IdentityModel.SecurityTokenService; +using Thinktecture.IdentityModel.Extensions; +using Thinktecture.IdentityServer.Core.Swt; +using Thinktecture.IdentityServer.Models; +using Thinktecture.IdentityServer.Repositories; + +namespace Thinktecture.IdentityServer.TokenService +{ + /// + /// This class analyzes the token request so the STS can inspect the information later + /// + public class Request + { + GlobalConfiguration _configuration; + RequestDetails _details; + + [Import] + public IRelyingPartyRepository RelyingPartyRepository { get; set; } + + [Import] + public IDelegationRepository DelegationRepository { get; set; } + + public Request(GlobalConfiguration configuration) + { + _configuration = configuration; + Container.Current.SatisfyImportsOnce(this); + } + + public Request(GlobalConfiguration configuration, IRelyingPartyRepository relyingPartyRepository, IDelegationRepository delegationRepository) + { + _configuration = configuration; + RelyingPartyRepository = relyingPartyRepository; + DelegationRepository = delegationRepository; + } + + public RequestDetails Analyze(RequestSecurityToken rst, IClaimsPrincipal principal) + { + if (rst == null) + { + throw new ArgumentNullException("rst"); + } + + if (principal == null) + { + throw new ArgumentNullException("principal"); + } + + Tracing.Information("Starting PolicyOptions creation"); + + var clientIdentity = AnalyzeClientIdentity(principal); + + var details = new RequestDetails + { + ClientIdentity = clientIdentity, + IsActive = false, + Realm = null, + IsKnownRealm = false, + UsesSsl = false, + UsesEncryption = false, + ReplyToAddress = null, + ReplyToAddressIsWithinRealm = false, + IsReplyToFromConfiguration = false, + EncryptingCertificate = null, + ClaimsRequested = false, + RequestClaims = null, + Request = null, + IsActAsRequest = false, + RelyingPartyRegistration = null + }; + + AnalyzeRst(rst, details); + AnalyzeTokenType(rst, details); + AnalyzeKeyType(rst); + AnalyzeRealm(rst, details); + AnalyzeOperationContext(details); + AnalyzeDelegation(rst, details); + AnalyzeRelyingParty(details); + AnalyzeEncryption(details); + AnalyzeReplyTo(details); + AnalyzeSsl(details); + AnalyzeRequestClaims(details); + + Tracing.Information("PolicyOptions creation done."); + + _details = details; + return details; + } + + public void Validate() + { + Validate(_details); + } + + public void Validate(RequestDetails details) + { + if (details == null) + { + throw new ArgumentNullException("details"); + } + + Tracing.Information("Starting policy validation"); + + ValidateKnownRealm(details); + ValidateTokenType(details); + ValidateReplyTo(details); + ValidateEncryption(details); + ValidateSsl(details); + ValidateDelegation(details); + + Tracing.Information("Policy Validation succeeded"); + } + + #region Analyze + protected virtual void AnalyzeRequestClaims(RequestDetails details) + { + // check if specific claims are requested + if (details.Request.Claims != null && details.Request.Claims.Count > 0) + { + details.ClaimsRequested = true; + details.RequestClaims = details.Request.Claims; + + var requestClaims = new StringBuilder(20); + details.RequestClaims.ToList().ForEach(rq => requestClaims.AppendFormat("{0}\n", rq.ClaimType)); + Tracing.Information("Specific claims requested"); + Tracing.Information(String.Format("Request claims: {0}", requestClaims)); + } + else + { + Tracing.Information("No request claims"); + } + } + + protected virtual void AnalyzeSsl(RequestDetails details) + { + // determine if reply to is via SSL + details.UsesSsl = (details.ReplyToAddress.Scheme == Uri.UriSchemeHttps); + Tracing.Information(String.Format("SSL used:{0}", details.UsesSsl)); + } + + protected virtual void AnalyzeReplyTo(RequestDetails details) + { + var rp = details.RelyingPartyRegistration; + + // determine the reply to address (only relevant for passive requests) + if (rp != null && rp.ReplyTo != null) + { + details.ReplyToAddress = rp.ReplyTo; + details.IsReplyToFromConfiguration = true; + + // check if reply to is a sub-address of the realm address + if (details.ReplyToAddress.AbsoluteUri.StartsWith(details.Realm.Uri.AbsoluteUri, StringComparison.OrdinalIgnoreCase)) + { + details.ReplyToAddressIsWithinRealm = true; + } + + Tracing.Information(String.Format("ReplyTo Address set from configuration: {0}", details.ReplyToAddress.AbsoluteUri)); + } + else + { + if (!String.IsNullOrEmpty(details.Request.ReplyTo)) + { + if (_configuration.AllowReplyTo) + { + // explicit address + details.ReplyToAddress = new Uri(details.Request.ReplyTo); + Tracing.Information(String.Format("Explicit ReplyTo address set: {0}", details.ReplyToAddress.AbsoluteUri)); + + // check if reply to is a sub-address of the realm address + if (details.ReplyToAddress.AbsoluteUri.StartsWith(details.Realm.Uri.AbsoluteUri, StringComparison.OrdinalIgnoreCase)) + { + details.ReplyToAddressIsWithinRealm = true; + } + + Tracing.Information(String.Format("ReplyTo Address is within Realm: {0}", details.ReplyToAddressIsWithinRealm)); + } + else + { + // same as realm + details.ReplyToAddress = details.Realm.Uri; + details.ReplyToAddressIsWithinRealm = true; + Tracing.Warning(string.Format("ReplyTo address of ({0}) was supplied, but since configuration does not allow ReplyTo, the realm address is used", details.Request.ReplyTo)); + } + } + else + { + // same as realm + details.ReplyToAddress = details.Realm.Uri; + details.ReplyToAddressIsWithinRealm = true; + Tracing.Information("ReplyTo address set to realm address"); + } + } + } + + protected virtual void AnalyzeTokenType(RequestSecurityToken rst, RequestDetails details) + { + if (string.IsNullOrWhiteSpace(rst.TokenType)) + { + details.TokenType = _configuration.DefaultTokenType; + Tracing.Information("Token Type: not specified, falling back to default token type"); + } + else + { + Tracing.Information("Token Type: " + rst.TokenType); + details.TokenType = rst.TokenType; + } + } + + protected virtual void AnalyzeEncryption(RequestDetails details) + { + if (details.EncryptingCertificate == null) + { + X509Certificate2 requestCertificate; + if (TryGetEncryptionCertificateFromRequest(details.Realm, out requestCertificate)) + { + details.EncryptingCertificate = requestCertificate; + Tracing.Information("Encrypting certificate set from RST"); + } + } + + details.UsesEncryption = (details.EncryptingCertificate != null); + Tracing.Information("Token encryption: " + details.UsesEncryption); + } + + protected virtual RelyingParty AnalyzeRelyingParty(RequestDetails details) + { + // check if the relying party is registered + RelyingParty rp = null; + if (RelyingPartyRepository.TryGet(details.Realm.Uri.AbsoluteUri, out rp)) + { + details.RelyingPartyRegistration = rp; + details.IsKnownRealm = true; + + var traceString = String.Format("Relying Party found in registry - Realm: {0}", rp.Realm.AbsoluteUri); + + if (!string.IsNullOrEmpty(rp.Name)) + { + traceString += String.Format(" ({0})", rp.Name); + } + + Tracing.Information(traceString); + + if (rp.EncryptingCertificate != null) + { + details.EncryptingCertificate = rp.EncryptingCertificate; + Tracing.Information("Encrypting certificate set from registry"); + } + } + else + { + Tracing.Information("Relying party is not registered."); + } + return rp; + } + + protected virtual void AnalyzeDelegation(RequestSecurityToken rst, RequestDetails details) + { + // check for identity delegation request + if (rst.ActAs != null) + { + details.IsActAsRequest = true; + Tracing.Information("Request is ActAs request"); + } + } + + protected virtual void AnalyzeKeyType(RequestSecurityToken rst) + { + if (!string.IsNullOrEmpty(rst.KeyType)) + { + Tracing.Information(String.Format("Requested KeyType: {0}", rst.KeyType)); + } + } + + protected virtual void AnalyzeOperationContext(RequestDetails details) + { + // determine if this is a WCF call + if (OperationContext.Current != null) + { + details.IsActive = true; + Tracing.Information("Active request"); + } + else + { + Tracing.Information("Passive request"); + } + } + + protected virtual IClaimsIdentity AnalyzeClientIdentity(IClaimsPrincipal principal) + { + if (principal == null) + { + throw new ArgumentNullException("principal"); + } + + if (principal.Identity == null) + { + throw new ArgumentNullException("identity"); + } + + var clientIdentity = principal.Identity as IClaimsIdentity; + + if (!clientIdentity.IsAuthenticated) + { + Tracing.Error("Client Identity is anonymous"); + throw new ArgumentException("client identity"); + } + + return clientIdentity; + } + + protected virtual void AnalyzeRst(RequestSecurityToken rst, RequestDetails options) + { + if (rst == null) + { + throw new ArgumentNullException("request"); + } + + options.Request = rst; + } + + protected virtual void AnalyzeRealm(RequestSecurityToken rst, RequestDetails options) + { + // check realm + if (rst.AppliesTo == null || rst.AppliesTo.Uri == null) + { + throw new MissingAppliesToException("AppliesTo is missing"); + } + + options.Realm = rst.AppliesTo; + } + #endregion + + #region Validate + protected virtual void ValidateDelegation(RequestDetails details) + { + // check for ActAs request + if (details.IsActAsRequest) + { + if (!_configuration.EnableDelegation) + { + Tracing.Error("Request is ActAs request - but ActAs is not enabled"); + throw new InvalidRequestException("Request is ActAs request - but ActAs is not enabled"); + } + + if (!DelegationRepository.IsDelegationAllowed(details.ClientIdentity.Name, details.Realm.Uri.AbsoluteUri)) + { + Tracing.Error(String.Format("ActAs mapping not found.")); + throw new InvalidRequestException("ActAs mapping not found."); + } + } + } + + protected virtual void ValidateSsl(RequestDetails details) + { + // check if SSL is used (for passive only) + if (_configuration.RequireSsl && !details.UsesSsl) + { + if (!details.IsActive) + { + Tracing.Error("Configuration requires SSL - but clear text reply address used"); + throw new InvalidRequestException("SSL is required"); + } + } + } + + private void ValidateTokenType(RequestDetails details) + { + if (details.TokenType == SimpleWebToken.OasisTokenProfile) + { + if (details.RelyingPartyRegistration == null || + details.RelyingPartyRegistration.SymmetricSigningKey == null || + details.RelyingPartyRegistration.SymmetricSigningKey.Length == 0) + { + Tracing.Error("SWT token requested, but no symmetric signing key found"); + throw new InvalidRequestException("SWT token requested, but no symmetric signing key found"); + } + } + } + + protected virtual void ValidateEncryption(RequestDetails details) + { + // check if token must be encrypted + if (_configuration.RequireEncryption && (!details.UsesEncryption)) + { + Tracing.Error("Configuration requires encryption - but no key available"); + throw new InvalidRequestException("No encryption key available"); + } + } + + protected virtual void ValidateReplyTo(RequestDetails details) + { + // check if replyto is part of a registered realm (when not explicitly registered in config) + if (!details.IsReplyToFromConfiguration) + { + if (_configuration.RequireReplyToWithinRealm && (!details.ReplyToAddressIsWithinRealm)) + { + Tracing.Error("Configuration requires that ReplyTo is a sub-address of the realm - this is not the case"); + throw new InvalidRequestException("Invalid ReplyTo"); + } + } + } + + protected virtual void ValidateKnownRealm(RequestDetails details) + { + // check if realm is allowed + if (_configuration.AllowKnownRealmsOnly && (!details.IsKnownRealm)) + { + Tracing.Error("Configuration requires a known realm - but realm is not registered"); + throw new InvalidScopeException(details.Realm.Uri.AbsoluteUri); + } + } + #endregion + + protected virtual bool TryGetEncryptionCertificateFromRequest(EndpointAddress appliesTo, out X509Certificate2 certificate) + { + if (appliesTo == null) + { + throw new ArgumentNullException("appliesTo"); + } + + certificate = null; + + var epi = appliesTo.Identity as X509CertificateEndpointIdentity; + if (epi != null && epi.Certificates.Count > 0) + { + certificate = epi.GetEndCertificate(); + return true; + } + + // no cert found + return false; + } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Core/TokenService/RequestDetails.cs b/Libraries/Thinktecture.IdentityServer.Core/TokenService/RequestDetails.cs new file mode 100644 index 0000000..aa32372 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/TokenService/RequestDetails.cs @@ -0,0 +1,38 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Security.Cryptography.X509Certificates; +using System.ServiceModel; +using Microsoft.IdentityModel.Claims; +using Microsoft.IdentityModel.Protocols.WSTrust; +using Thinktecture.IdentityServer.Models; + +namespace Thinktecture.IdentityServer.TokenService +{ + public class RequestDetails + { + public IClaimsIdentity ClientIdentity { get; set; } + public string TokenType { get; set; } + public bool IsActive { get; set; } + public bool IsKnownRealm { get; set; } + public EndpointAddress Realm { get; set; } + public bool UsesSsl { get; set; } + public bool UsesEncryption { get; set; } + public X509Certificate2 EncryptingCertificate { get; set; } + public Uri ReplyToAddress { get; set; } + public bool IsReplyToFromConfiguration { get; set; } + public bool ReplyToAddressIsWithinRealm { get; set; } + public RequestSecurityToken Request { get; set; } + public bool ClaimsRequested { get; set; } + public RequestClaimCollection RequestClaims { get; set; } + public bool IsActAsRequest { get; set; } + public RelyingParty RelyingPartyRegistration { get; set; } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core/TokenService/RequestDetailsScope.cs b/Libraries/Thinktecture.IdentityServer.Core/TokenService/RequestDetailsScope.cs new file mode 100644 index 0000000..6073b9f --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/TokenService/RequestDetailsScope.cs @@ -0,0 +1,42 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.IdentityModel.Tokens; +using Microsoft.IdentityModel.SecurityTokenService; +using Thinktecture.IdentityServer.Core.Swt; + +namespace Thinktecture.IdentityServer.TokenService +{ + /// + /// Summary description for PolicyScope + /// + public class RequestDetailsScope : Scope + { + public RequestDetails RequestDetails { get; protected set; } + + public RequestDetailsScope(RequestDetails details, SigningCredentials signingCredentials, bool requireEncryption) + : base(details.Realm.Uri.AbsoluteUri, signingCredentials) + { + RequestDetails = details; + + if (RequestDetails.UsesEncryption) + { + EncryptingCredentials = new X509EncryptingCredentials(details.EncryptingCertificate); + } + + if (RequestDetails.TokenType == SimpleWebToken.OasisTokenProfile) + { + SigningCredentials = new SymmetricSigningCredentials(details.RelyingPartyRegistration.SymmetricSigningKey); + } + + ReplyToAddress = RequestDetails.ReplyToAddress.AbsoluteUri; + TokenEncryptionRequired = requireEncryption; + } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Core/TokenService/SignInSessionsManager.cs b/Libraries/Thinktecture.IdentityServer.Core/TokenService/SignInSessionsManager.cs new file mode 100644 index 0000000..b932eae --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/TokenService/SignInSessionsManager.cs @@ -0,0 +1,89 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; + +namespace Thinktecture.IdentityServer.TokenService +{ + public class SignInSessionsManager + { + private const string COOKIENAME = ".idsrvsso"; + + HttpContextBase _context; + int _maximumCookieLifetime; + + public SignInSessionsManager(HttpContextBase context) : this(context, 24) + { } + + public SignInSessionsManager(HttpContextBase context, int maximumCookieLifetime) + { + _context = context; + _maximumCookieLifetime = maximumCookieLifetime; + } + + public void AddRealm(string realm) + { + var realms = ReadCookie(); + if (!realms.Contains(realm.ToLowerInvariant())) + { + realms.Add(realm.ToLowerInvariant()); + WriteCookie(realms); + } + } + + public List GetRealms() + { + return ReadCookie(); + } + + public void ClearRealms() + { + var cookie = _context.Request.Cookies[COOKIENAME]; + if (cookie != null) + { + cookie.Value = ""; + cookie.Expires = new DateTime(2000, 1, 1); + _context.Response.SetCookie(cookie); + } + } + + private List ReadCookie() + { + var cookie = _context.Request.Cookies[COOKIENAME]; + if (cookie == null) + { + return new List(); + } + + return cookie.Value.Split('|').ToList(); + } + + private void WriteCookie(List realms) + { + if (realms.Count == 0) + { + ClearRealms(); + return; + } + + var realmString = string.Join("|", realms).ToLowerInvariant(); + + var cookie = new HttpCookie(COOKIENAME, realmString) + { + Expires = DateTime.Now.AddHours(_maximumCookieLifetime), + HttpOnly = true, + }; + + _context.Response.Cookies.Add(cookie); + } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core/TokenService/TokenService.cs b/Libraries/Thinktecture.IdentityServer.Core/TokenService/TokenService.cs new file mode 100644 index 0000000..ea2cb3d --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/TokenService/TokenService.cs @@ -0,0 +1,228 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.IdentityModel.Tokens; +using System.IO; +using System.Linq; +using System.Text; +using System.Xml; +using Microsoft.IdentityModel.Claims; +using Microsoft.IdentityModel.Configuration; +using Microsoft.IdentityModel.Protocols.WSTrust; +using Microsoft.IdentityModel.SecurityTokenService; +using Microsoft.IdentityModel.Tokens; +using Microsoft.IdentityModel.Web; +using Thinktecture.IdentityModel.Claims; +using Thinktecture.IdentityModel.Extensions; +using Thinktecture.IdentityServer.Models; +using Thinktecture.IdentityServer.Repositories; + +namespace Thinktecture.IdentityServer.TokenService +{ + /// + /// This class contains the token issuance logic + /// + public class TokenService : SecurityTokenService + { + [Import] + public IUserRepository UserRepository { get; set; } + + public TokenService(SecurityTokenServiceConfiguration configuration) + : base(configuration) + { + Container.Current.SatisfyImportsOnce(this); + } + + public TokenService(SecurityTokenServiceConfiguration configuration, IUserRepository userRepository) + : base(configuration) + { + UserRepository = userRepository; + } + + protected GlobalConfiguration GlobalConfiguration + { + get + { + var config = SecurityTokenServiceConfiguration as TokenServiceConfiguration; + return config.GlobalConfiguration; + } + } + + /// + /// Analyzes the token request + /// + /// The principal. + /// The request. + /// A PolicyScope that describes the relying party and policy options + protected override Scope GetScope(IClaimsPrincipal principal, RequestSecurityToken rst) + { + if (rst.AppliesTo == null) + { + Tracing.Error(string.Format("token request from {0} - but no realm specified.", + principal.Identity.Name)); + + throw new MissingAppliesToException(); + } + + Tracing.Information(string.Format("Starting token request from {0} for {1}", + principal.Identity.Name, + rst.AppliesTo.Uri.AbsoluteUri)); + + Tracing.Information("Authentication method: " + principal.Identities.First().GetClaimValue(ClaimTypes.AuthenticationMethod)); + + // analyze request + var request = new Request(GlobalConfiguration); + var details = request.Analyze(rst, principal); + + // validate against policy + request.Validate(details); + + // create scope + var scope = new RequestDetailsScope( + details, + SecurityTokenServiceConfiguration.SigningCredentials, + GlobalConfiguration.RequireEncryption); + + return scope; + } + + /// + /// Produces the output identity that gets transformed into a token + /// + /// The principal. + /// The request. + /// The scope. + /// An IClaimsIdentity describing the subject + protected override IClaimsIdentity GetOutputClaimsIdentity(IClaimsPrincipal principal, RequestSecurityToken request, Scope scope) + { + var requestDetails = (scope as RequestDetailsScope).RequestDetails; + + var userClaims = GetOutputClaims(principal, requestDetails, UserRepository); + var outputIdentity = new ClaimsIdentity(userClaims); + + if (requestDetails.IsActAsRequest) + { + Tracing.Information("Issuing act as token"); + return GetActAsClaimsIdentity(outputIdentity, requestDetails); + } + else + { + Tracing.Information("Issuing identity token"); + return outputIdentity; + } + } + + public static List GetOutputClaims(IClaimsPrincipal principal, RequestDetails requestDetails, IUserRepository userRepository) + { + var name = principal.FindClaims(ClaimTypes.Name).First().Value; + var nameId = new Claim(ClaimTypes.NameIdentifier, name); + + var userClaims = new List + { + new Claim(ClaimTypes.Name, name), + nameId, + new Claim(ClaimTypes.AuthenticationMethod, principal.FindClaims(ClaimTypes.AuthenticationMethod).First().Value), + AuthenticationInstantClaim.Now + }; + + userClaims.AddRange(userRepository.GetClaims(principal, requestDetails)); + + return userClaims; + } + + protected virtual IClaimsIdentity GetActAsClaimsIdentity(IClaimsIdentity clientIdentity, RequestDetails requestDetails) + { + var actAsSubject = requestDetails.Request.ActAs.GetSubject()[0]; + var actAsIdentity = actAsSubject.Copy(); + + // find the last actor in the actAs identity + IClaimsIdentity lastActor = actAsIdentity; + while (lastActor.Actor != null) + { + lastActor = lastActor.Actor; + } + + // set the caller's identity as the last actor in the delegation chain + lastActor.Actor = clientIdentity; + + Tracing.Information("ActAs client identity: " + actAsIdentity.Name); + Tracing.Information("ActAs actor identity : " + actAsIdentity.Actor.Name); + + // return the actAsIdentity instead of the caller's identity in this case + return actAsIdentity; + } + + #region FederationMessageTracing + protected override RequestSecurityTokenResponse GetResponse(RequestSecurityToken request, SecurityTokenDescriptor tokenDescriptor) + { + var response = base.GetResponse(request, tokenDescriptor); + + if (GlobalConfiguration.EnableFederationMessageTracing) + { + Tracing.Information(SerializeRequest(request)); + Tracing.Information(SerializeResponse(response)); + Tracing.Information(SerializeToken(tokenDescriptor)); + } + + return response; + } + + private string SerializeRequest(RequestSecurityToken request) + { + var serializer = new WSTrust13RequestSerializer(); + var context = new WSTrustSerializationContext(); + var sb = new StringBuilder(128); + + using (var writer = XmlWriter.Create(new StringWriter(sb))) + { + serializer.WriteXml(request, writer, context); + return sb.ToString(); + } + } + + private string SerializeResponse(RequestSecurityTokenResponse response) + { + var serializer = new WSTrust13ResponseSerializer(); + var context = new WSTrustSerializationContext(FederatedAuthentication.ServiceConfiguration.SecurityTokenHandlerCollectionManager); + var sb = new StringBuilder(128); + + using (var writer = XmlWriter.Create(new StringWriter(sb))) + { + serializer.WriteXml(response, writer, context); + return sb.ToString(); + } + } + + private string SerializeToken(SecurityTokenDescriptor tokenDescriptor) + { + // see if token is encrypted + var encryptedToken = tokenDescriptor.Token as EncryptedSecurityToken; + SecurityToken token; + + if (encryptedToken != null) + { + // use inner token + token = encryptedToken.Token; + } + else + { + // if not, use the token directly + token = tokenDescriptor.Token; + } + + var sb = new StringBuilder(128); + FederatedAuthentication.ServiceConfiguration.SecurityTokenHandlers.WriteToken(XmlWriter.Create(new StringWriter(sb)), token); + + return sb.ToString(); + } + #endregion + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Core/TokenService/TokenServiceConfiguration.cs b/Libraries/Thinktecture.IdentityServer.Core/TokenService/TokenServiceConfiguration.cs new file mode 100644 index 0000000..6c74621 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/TokenService/TokenServiceConfiguration.cs @@ -0,0 +1,78 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.ComponentModel.Composition; +using System.IdentityModel.Selectors; +using Microsoft.IdentityModel.Configuration; +using Microsoft.IdentityModel.SecurityTokenService; +using Microsoft.IdentityModel.Tokens; +using Thinktecture.IdentityServer.Models; +using Thinktecture.IdentityServer.Repositories; + +namespace Thinktecture.IdentityServer.TokenService +{ + /// + /// Configuration information for the token service + /// + public class TokenServiceConfiguration : SecurityTokenServiceConfiguration + { + private static readonly object _syncRoot = new object(); + private static Lazy _configuration = new Lazy(); + + [Import] + public IConfigurationRepository ConfigurationRepository { get; set; } + + public GlobalConfiguration GlobalConfiguration { get; protected set; } + + public TokenServiceConfiguration() : base() + { + Tracing.Information("Configuring token service"); + Container.Current.SatisfyImportsOnce(this); + GlobalConfiguration = ConfigurationRepository.Configuration; + + SecurityTokenService = typeof(TokenService); + DefaultTokenLifetime = TimeSpan.FromHours(GlobalConfiguration.DefaultTokenLifetime); + MaximumTokenLifetime = TimeSpan.FromDays(GlobalConfiguration.MaximumTokenLifetime); + DefaultTokenType = GlobalConfiguration.DefaultTokenType; + + TokenIssuerName = GlobalConfiguration.IssuerUri; + SigningCredentials = new X509SigningCredentials(ConfigurationRepository.SigningCertificate.Certificate); + + if (GlobalConfiguration.EnableDelegation) + { + Tracing.Information("Configuring identity delegation support"); + + try + { + var actAsRegistry = new ConfigurationBasedIssuerNameRegistry(); + actAsRegistry.AddTrustedIssuer(ConfigurationRepository.SigningCertificate.Certificate.Thumbprint, GlobalConfiguration.IssuerUri); + + var actAsHandlers = SecurityTokenHandlerCollectionManager["ActAs"]; + actAsHandlers.Configuration.IssuerNameRegistry = actAsRegistry; + actAsHandlers.Configuration.AudienceRestriction.AudienceMode = AudienceUriMode.Never; + } + catch (Exception ex) + { + Tracing.Error("Error configuring identity delegation"); + Tracing.Error(ex.ToString()); + throw; + } + } + } + + public static TokenServiceConfiguration Current + { + get + { + return _configuration.Value; + } + } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Core/TokenService/TokenServiceHostFactory.cs b/Libraries/Thinktecture.IdentityServer.Core/TokenService/TokenServiceHostFactory.cs new file mode 100644 index 0000000..bad7010 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/TokenService/TokenServiceHostFactory.cs @@ -0,0 +1,133 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.ComponentModel.Composition; +using System.Reflection; +using System.ServiceModel; +using System.ServiceModel.Activation; +using System.ServiceModel.Description; +using Microsoft.IdentityModel.Configuration; +using Microsoft.IdentityModel.Protocols.WSTrust; +using Microsoft.IdentityModel.Protocols.WSTrust.Bindings; +using Thinktecture.IdentityServer.Repositories; + +namespace Thinktecture.IdentityServer.TokenService +{ + /// + /// Abstracts away the details of the WS-Trust ServiceHost creation and configuration + /// + public class TokenServiceHostFactory : ServiceHostFactory + { + [Import] + public IConfigurationRepository ConfigurationRepository { get; set; } + + public TokenServiceHostFactory() : base() + { + Container.Current.SatisfyImportsOnce(this); + } + + /// + /// Creates a service host to process WS-Trust 1.3 requests + /// + /// The constructor string. + /// The base addresses. + /// A WS-Trust ServiceHost + public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses) + { + var globalConfiguration = ConfigurationRepository.Configuration; + var config = CreateSecurityTokenServiceConfiguration(constructorString); + var host = new WSTrustServiceHost(config, baseAddresses); + + // add behavior for load balancing support + host.Description.Behaviors.Add(new UseRequestHeadersForMetadataAddressBehavior()); + + // modify address filter mode for load balancing + var serviceBehavior = host.Description.Behaviors.Find(); + serviceBehavior.AddressFilterMode = AddressFilterMode.Any; + + // add and configure a mixed mode security endpoint + if (ConfigurationRepository.Endpoints.WSTrustMixed) + { + EndpointIdentity epi = null; + if (ConfigurationRepository.Configuration.EnableStrongEpiForSsl) + { + if (ConfigurationRepository.SslCertificate.Certificate == null) + { + throw new ServiceActivationException("No SSL certificate configured for strong endpoint identity."); + } + + epi = EndpointIdentity.CreateX509CertificateIdentity(ConfigurationRepository.SslCertificate.Certificate); + } + + if (globalConfiguration.EnableClientCertificates) + { + var sep2 = host.AddServiceEndpoint( + typeof(IWSTrust13SyncContract), + new CertificateWSTrustBinding(SecurityMode.TransportWithMessageCredential), + Endpoints.Paths.WSTrustMixedCertificate); + + if (epi != null) + { + sep2.Address = new EndpointAddress(sep2.Address.Uri, epi); + } + } + + var sep = host.AddServiceEndpoint( + typeof(IWSTrust13SyncContract), + new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential), + Endpoints.Paths.WSTrustMixedUserName); + + if (epi != null) + { + sep.Address = new EndpointAddress(sep.Address.Uri, epi); + } + } + + // add and configure a message security endpoint + if (ConfigurationRepository.Endpoints.WSTrustMessage) + { + var credential = new ServiceCredentials(); + credential.ServiceCertificate.Certificate = ConfigurationRepository.SigningCertificate.Certificate; + host.Description.Behaviors.Add(credential); + + if (globalConfiguration.EnableClientCertificates) + { + host.AddServiceEndpoint( + typeof(IWSTrust13SyncContract), + new CertificateWSTrustBinding(SecurityMode.Message), + Endpoints.Paths.WSTrustMessageCertificate); + } + + host.AddServiceEndpoint( + typeof(IWSTrust13SyncContract), + new UserNameWSTrustBinding(SecurityMode.Message), + Endpoints.Paths.WSTrustMessageUserName); + } + + return host; + } + + protected virtual SecurityTokenServiceConfiguration CreateSecurityTokenServiceConfiguration(string constructorString) + { + Type type = Type.GetType(constructorString, true); + if (!type.IsSubclassOf(typeof(SecurityTokenServiceConfiguration))) + { + throw new InvalidOperationException("SecurityTokenServiceConfiguration"); + } + + return (Activator.CreateInstance( + type, + BindingFlags.CreateInstance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, + null, + null, + null) as SecurityTokenServiceConfiguration); + } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Core/TokenService/WSFederationMetadataGenerator.cs b/Libraries/Thinktecture.IdentityServer.Core/TokenService/WSFederationMetadataGenerator.cs new file mode 100644 index 0000000..787130d --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/TokenService/WSFederationMetadataGenerator.cs @@ -0,0 +1,139 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.ComponentModel.Composition; +using System.Globalization; +using System.IdentityModel.Tokens; +using System.IO; +using System.Linq; +using System.ServiceModel; +using System.ServiceModel.Channels; +using System.ServiceModel.Description; +using System.Text; +using System.Xml; +using Microsoft.IdentityModel.Claims; +using Microsoft.IdentityModel.Protocols.WSFederation.Metadata; +using Microsoft.IdentityModel.Protocols.WSIdentity; +using Microsoft.IdentityModel.SecurityTokenService; +using Thinktecture.IdentityServer.Core.Swt; +using Thinktecture.IdentityServer.Repositories; + +namespace Thinktecture.IdentityServer.TokenService +{ + /// + /// Handler for dynamic generation of the WS-Federation metadata document + /// + public class WSFederationMetadataGenerator + { + Endpoints _endpoints; + + [Import] + public IConfigurationRepository ConfigurationRepository { get; set; } + + [Import] + public IUserRepository UserRepository { get; set; } + + public WSFederationMetadataGenerator(Endpoints endpoints) + { + _endpoints = endpoints; + Container.Current.SatisfyImportsOnce(this); + } + + public string Generate() + { + var tokenServiceDescriptor = GetTokenServiceDescriptor(); + var id = new EntityId(ConfigurationRepository.Configuration.IssuerUri); + var entity = new EntityDescriptor(id); + entity.SigningCredentials = new X509SigningCredentials(ConfigurationRepository.SigningCertificate.Certificate); + entity.RoleDescriptors.Add(tokenServiceDescriptor); + + var ser = new MetadataSerializer(); + var sb = new StringBuilder(512); + + ser.WriteMetadata(XmlWriter.Create(new StringWriter(sb), new XmlWriterSettings { OmitXmlDeclaration = true }), entity); + return sb.ToString(); + } + + private SecurityTokenServiceDescriptor GetTokenServiceDescriptor() + { + var tokenService = new SecurityTokenServiceDescriptor(); + tokenService.ServiceDescription = ConfigurationRepository.Configuration.SiteName; + tokenService.Keys.Add(GetSigningKeyDescriptor()); + + tokenService.PassiveRequestorEndpoints.Add(new EndpointAddress(_endpoints.WSFederation)); + + tokenService.TokenTypesOffered.Add(new Uri(Microsoft.IdentityModel.Tokens.SecurityTokenTypes.OasisWssSaml11TokenProfile11)); + tokenService.TokenTypesOffered.Add(new Uri(Microsoft.IdentityModel.Tokens.SecurityTokenTypes.OasisWssSaml2TokenProfile11)); + tokenService.TokenTypesOffered.Add(new Uri(SimpleWebToken.OasisTokenProfile)); + + UserRepository.GetSupportedClaimTypes().ToList().ForEach(claimType => tokenService.ClaimTypesOffered.Add(new DisplayClaim(claimType))); + tokenService.ProtocolsSupported.Add(new Uri("http://docs.oasis-open.org/wsfed/federation/200706")); + + if (ConfigurationRepository.Endpoints.WSTrustMessage) + { + var addressMessageUserName = new EndpointAddress(_endpoints.WSTrustMessageUserName, null, null, CreateMetadataReader(_endpoints.WSTrustMex), null); + tokenService.SecurityTokenServiceEndpoints.Add(addressMessageUserName); + + if (ConfigurationRepository.Configuration.EnableClientCertificates) + { + var addressMessageCertificate = new EndpointAddress(_endpoints.WSTrustMessageCertificate, null, null, CreateMetadataReader(_endpoints.WSTrustMex), null); + tokenService.SecurityTokenServiceEndpoints.Add(addressMessageCertificate); + } + } + if (ConfigurationRepository.Endpoints.WSTrustMixed) + { + var addressMixedUserName = new EndpointAddress(_endpoints.WSTrustMixedUserName, null, null, CreateMetadataReader(_endpoints.WSTrustMex), null); + tokenService.SecurityTokenServiceEndpoints.Add(addressMixedUserName); + + if (ConfigurationRepository.Configuration.EnableClientCertificates) + { + var addressMixedCertificate = new EndpointAddress(_endpoints.WSTrustMixedCertificate, null, null, CreateMetadataReader(_endpoints.WSTrustMex), null); + tokenService.SecurityTokenServiceEndpoints.Add(addressMixedCertificate); + } + } + + if (tokenService.SecurityTokenServiceEndpoints.Count == 0) + tokenService.SecurityTokenServiceEndpoints.Add(new EndpointAddress(_endpoints.WSFederation)); + + return tokenService; + } + + private KeyDescriptor GetSigningKeyDescriptor() + { + var certificate = ConfigurationRepository.SigningCertificate.Certificate; + + var clause = new X509SecurityToken(certificate).CreateKeyIdentifierClause(); + var key = new KeyDescriptor(new SecurityKeyIdentifier(clause)); + key.Use = KeyType.Signing; + + return key; + } + + private XmlDictionaryReader CreateMetadataReader(Uri mexAddress) + { + var metadataSet = new MetadataSet(); + var metadataReference = new MetadataReference(new EndpointAddress(mexAddress), AddressingVersion.WSAddressing10); + var metadataSection = new MetadataSection(MetadataSection.MetadataExchangeDialect, null, metadataReference); + metadataSet.MetadataSections.Add(metadataSection); + + var sb = new StringBuilder(); + var w = new StringWriter(sb, CultureInfo.InvariantCulture); + var writer = XmlWriter.Create(w); + + metadataSet.WriteTo(writer); + writer.Flush(); + w.Flush(); + + var input = new StringReader(sb.ToString()); + var reader = new XmlTextReader(input); + return XmlDictionaryReader.CreateDictionaryReader(reader); + } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Core/TokenService/X509CertificateSessionSecurityTokenHandler.cs b/Libraries/Thinktecture.IdentityServer.Core/TokenService/X509CertificateSessionSecurityTokenHandler.cs new file mode 100644 index 0000000..0c03505 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/TokenService/X509CertificateSessionSecurityTokenHandler.cs @@ -0,0 +1,36 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Security.Cryptography.X509Certificates; +using Microsoft.IdentityModel.Tokens; +using Microsoft.IdentityModel.Web; + +namespace Thinktecture.IdentityServer.TokenService +{ + public class X509CertificateSessionSecurityTokenHandler : SessionSecurityTokenHandler + { + public X509CertificateSessionSecurityTokenHandler(X509Certificate2 protectionCertificate) + : base(CreateTransforms(protectionCertificate)) + { } + + private static ReadOnlyCollection CreateTransforms(X509Certificate2 protectionCertificate) + { + var transforms = new List() + { + new DeflateCookieTransform(), + new RsaEncryptionCookieTransform(protectionCertificate), + new RsaSignatureCookieTransform(protectionCertificate), + }; + + return transforms.AsReadOnly(); + } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Core/Tracing/Tracing.cs b/Libraries/Thinktecture.IdentityServer.Core/Tracing/Tracing.cs new file mode 100644 index 0000000..338e530 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/Tracing/Tracing.cs @@ -0,0 +1,72 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Diagnostics; + +namespace Thinktecture.IdentityServer +{ + /// + /// Helper class for Tracing + /// + public static class Tracing + { + [DebuggerStepThrough] + public static void Start(string message) + { + TraceEvent(TraceEventType.Start, message, false); + } + + [DebuggerStepThrough] + public static void Stop(string message) + { + TraceEvent(TraceEventType.Stop, message, false); + } + + [DebuggerStepThrough] + public static void Information(string message) + { + TraceEvent(TraceEventType.Information, message, false); + } + + [DebuggerStepThrough] + public static void Warning(string message) + { + TraceEvent(TraceEventType.Warning, message, false); + } + + [DebuggerStepThrough] + public static void Error(string message) + { + TraceEvent(TraceEventType.Error, message, false); + } + + [DebuggerStepThrough] + public static void Verbose(string message) + { + TraceEvent(TraceEventType.Verbose, message, false); + } + + [DebuggerStepThrough] + public static void TraceEvent(TraceEventType type, string message, bool suppressTraceService) + { + TraceSource ts = new TraceSource("Thinktecture.IdentityServer"); + + if (Trace.CorrelationManager.ActivityId == Guid.Empty) + { + if (type != TraceEventType.Verbose) + { + Trace.CorrelationManager.ActivityId = Guid.NewGuid(); + } + } + + ts.TraceEvent(type, 0, message); + } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Core/packages.config b/Libraries/Thinktecture.IdentityServer.Core/packages.config new file mode 100644 index 0000000..531e1e1 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Core/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Web.Library/ActionResults/AccessTokenResponse.cs b/Libraries/Thinktecture.IdentityServer.Web.Library/ActionResults/AccessTokenResponse.cs new file mode 100644 index 0000000..54088f3 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Web.Library/ActionResults/AccessTokenResponse.cs @@ -0,0 +1,29 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.Runtime.Serialization; + +namespace Thinktecture.IdentityServer.Web.ActionResults +{ + [DataContract] + public class AccessTokenResponse + { + [DataMember(Order = 1, Name = "access_token")] + public string AccessToken { get; set; } + + [DataMember(Order = 2, Name = "token_type")] + public string TokenType { get; set; } + + [DataMember(Order = 3, Name = "expires_in")] + public int ExpiresIn { get; set; } + + [DataMember(Order = 4, Name = "refresh_token")] + public string RefreshToken { get; set; } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Web.Library/ActionResults/JSNotifyResult.cs b/Libraries/Thinktecture.IdentityServer.Web.Library/ActionResults/JSNotifyResult.cs new file mode 100644 index 0000000..abae554 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Web.Library/ActionResults/JSNotifyResult.cs @@ -0,0 +1,47 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.IO; +using System.Reflection; +using System.Runtime.Serialization.Json; +using System.Web; +using System.Web.Mvc; + +namespace Thinktecture.IdentityServer.Web.ActionResults +{ + public class JSNotifyResult : ActionResult + { + AccessTokenResponse _response; + + public JSNotifyResult(AccessTokenResponse response) + { + _response = response; + } + + public override void ExecuteResult(ControllerContext context) + { + var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Thinktecture.IdentityServer.Web.Resources.jsnotify.htm"); + var html = new StreamReader(stream).ReadToEnd(); + + var ser = new DataContractJsonSerializer(typeof(AccessTokenResponse)); + var ms = new MemoryStream(); + ser.WriteObject(ms, _response); + ms.Seek(0, SeekOrigin.Begin); + + var dtoString = new StreamReader(ms).ReadToEnd(); + var responseString = string.Format(html, dtoString); + + context.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache); + context.HttpContext.Response.Cache.SetNoStore(); + + context.HttpContext.Response.Write(responseString); + context.HttpContext.Response.Flush(); + } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Web.Library/ActionResults/OAuth2AccessTokenResult.cs b/Libraries/Thinktecture.IdentityServer.Web.Library/ActionResults/OAuth2AccessTokenResult.cs new file mode 100644 index 0000000..6ce8a35 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Web.Library/ActionResults/OAuth2AccessTokenResult.cs @@ -0,0 +1,39 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.Runtime.Serialization.Json; +using System.Web; +using System.Web.Mvc; + +namespace Thinktecture.IdentityServer.Web.ActionResults +{ + public class OAuth2AccessTokenResult : ActionResult + { + AccessTokenResponse _response; + + public OAuth2AccessTokenResult(AccessTokenResponse response) + { + _response = response; + } + + public override void ExecuteResult(ControllerContext context) + { + context.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache); + context.HttpContext.Response.Cache.SetNoStore(); + context.HttpContext.Response.ContentType = "application/json"; + + context.HttpContext.Response.Headers.Add("Access-Control-Allow-Origin", "*"); + context.HttpContext.Response.Headers.Add("Access-Control-Allow-Methods", "POST"); + context.HttpContext.Response.Headers.Add("Access-Control-Max-Age", "86400"); + + var ser = new DataContractJsonSerializer(typeof(AccessTokenResponse)); + ser.WriteObject(context.HttpContext.Response.OutputStream, _response); + } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Web.Library/ActionResults/SimpleHttpResult.cs b/Libraries/Thinktecture.IdentityServer.Web.Library/ActionResults/SimpleHttpResult.cs new file mode 100644 index 0000000..4d0583c --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Web.Library/ActionResults/SimpleHttpResult.cs @@ -0,0 +1,45 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.Web; +using System.Web.Mvc; +using WIF = Microsoft.IdentityModel; + +namespace Thinktecture.IdentityServer.Web.ActionResults +{ + public class SimpleHttpResult : ContentResult + { + public SimpleHttpResult(string token, string tokenType) + { + Content = token; + + if (tokenType == WIF.Tokens.SecurityTokenTypes.OasisWssSaml11TokenProfile11 || + tokenType == WIF.Tokens.SecurityTokenTypes.Saml11TokenProfile11 || + tokenType == WIF.Tokens.SecurityTokenTypes.OasisWssSaml2TokenProfile11 || + tokenType == WIF.Tokens.SecurityTokenTypes.Saml2TokenProfile11) + { + ContentType = "text/xml"; + } + else + { + ContentType = "text/plain"; + } + } + + protected virtual void WriteToken(ControllerContext context) + { + var response = context.HttpContext.Response; + + response.Cache.SetCacheability(HttpCacheability.NoCache); + response.Cache.SetNoStore(); + + base.ExecuteResult(context); + } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Web.Library/ActionResults/UnauthorizedResult.cs b/Libraries/Thinktecture.IdentityServer.Web.Library/ActionResults/UnauthorizedResult.cs new file mode 100644 index 0000000..dbb690c --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Web.Library/ActionResults/UnauthorizedResult.cs @@ -0,0 +1,57 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Web.Mvc; + +namespace Thinktecture.IdentityServer.Web.ActionResults +{ + public class UnauthorizedResult : ActionResult + { + int _statusCode = 401; + string _scheme; + ResponseAction _responseAction = ResponseAction.Send401; + + public enum ResponseAction + { + Send401, + RedirectToLoginPage + } + + public UnauthorizedResult(string scheme) + : this (scheme, ResponseAction.Send401) + { } + + public UnauthorizedResult(string scheme, ResponseAction responseAction) + { + _scheme = scheme; + _responseAction = responseAction; + } + + public override void ExecuteResult(ControllerContext context) + { + if (context == null) + { + throw new ArgumentNullException("context"); + } + + context.HttpContext.Response.StatusCode = _statusCode; + + if (!string.IsNullOrWhiteSpace(_scheme)) + { + context.HttpContext.Response.Headers.Add("WWW-Authenticate", _scheme); + } + + if (_responseAction == ResponseAction.Send401) + { + context.HttpContext.Items["NoRedirect"] = true; + } + } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Web.Library/ActionResults/WSFederationResult.cs b/Libraries/Thinktecture.IdentityServer.Web.Library/ActionResults/WSFederationResult.cs new file mode 100644 index 0000000..bb4cedc --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Web.Library/ActionResults/WSFederationResult.cs @@ -0,0 +1,22 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.Web.Mvc; +using Microsoft.IdentityModel.Protocols.WSFederation; + +namespace Thinktecture.IdentityServer.Web.ActionResults +{ + public class WSFederationResult : ContentResult + { + public WSFederationResult(SignInResponseMessage message) + { + Content = message.WriteFormPost(); + } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Web.Library/ActionResults/WrapResult.cs b/Libraries/Thinktecture.IdentityServer.Web.Library/ActionResults/WrapResult.cs new file mode 100644 index 0000000..32d915f --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Web.Library/ActionResults/WrapResult.cs @@ -0,0 +1,55 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Web; +using System.Web.Mvc; +using Thinktecture.IdentityServer.Web.Security; + +namespace Thinktecture.IdentityServer.Web.ActionResults +{ + public class WrapResult : ActionResult + { + public TokenResponse TokenResponse { get; set; } + + protected string _contentType = "text/plain"; + protected string _content; + + public WrapResult() + { } + + public WrapResult(TokenResponse response) + { + TokenResponse = response; + } + + public override void ExecuteResult(ControllerContext context) + { + if (context == null) + { + throw new ArgumentNullException("context"); + } + + _content = "wrap_access_token=" + Uri.EscapeDataString(TokenResponse.TokenString); + + WriteToken(context); + } + + protected virtual void WriteToken(ControllerContext context) + { + var response = context.HttpContext.Response; + + response.Cache.SetCacheability(HttpCacheability.NoCache); + response.Cache.SetNoStore(); + + response.ContentType = _contentType; + response.Write(_content); + } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.Web.Library/GlobalFilter/GlobalViewModelFilter.cs b/Libraries/Thinktecture.IdentityServer.Web.Library/GlobalFilter/GlobalViewModelFilter.cs new file mode 100644 index 0000000..7c09cac --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Web.Library/GlobalFilter/GlobalViewModelFilter.cs @@ -0,0 +1,33 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.ComponentModel.Composition; +using System.Web.Mvc; +using Thinktecture.IdentityServer.Repositories; +using Thinktecture.IdentityServer.Web.Security; + +namespace Thinktecture.IdentityServer.Web.GlobalFilter +{ + public class GlobalViewModelFilter : ActionFilterAttribute + { + [Import] + public IConfigurationRepository ConfigurationRepository { get; set; } + + public override void OnActionExecuting(ActionExecutingContext filterContext) + { + Container.Current.SatisfyImportsOnce(this); + + filterContext.Controller.ViewBag.SiteName = ConfigurationRepository.Configuration.SiteName; + filterContext.Controller.ViewBag.IsAdministrator = ClaimsAuthorize.CheckAccess(Constants.Actions.Administration, Constants.Resources.UI); + filterContext.Controller.ViewBag.IsSignedIn = filterContext.HttpContext.User.Identity.IsAuthenticated; + + base.OnActionExecuting(filterContext); + } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Web.Library/GlobalFilter/InitialConfigurationFilter.cs b/Libraries/Thinktecture.IdentityServer.Web.Library/GlobalFilter/InitialConfigurationFilter.cs new file mode 100644 index 0000000..6a26397 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Web.Library/GlobalFilter/InitialConfigurationFilter.cs @@ -0,0 +1,43 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Web.Mvc; +using System.Web.Routing; +using Thinktecture.IdentityServer.Repositories; + +namespace Thinktecture.IdentityServer.Web.GlobalFilter +{ + public class InitialConfigurationFilter : ActionFilterAttribute + { + [Import] + public IConfigurationRepository ConfigurationRepository { get; set; } + + public override void OnActionExecuting(ActionExecutingContext filterContext) + { + Container.Current.SatisfyImportsOnce(this); + + if (!filterContext.ActionDescriptor.ControllerDescriptor.ControllerName.Equals("InitialConfiguration")) + { + if (string.IsNullOrWhiteSpace(ConfigurationRepository.SigningCertificate.SubjectDistinguishedName)) + { + var route = new RouteValueDictionary(new Dictionary + { + { "Controller", "InitialConfiguration" }, + }); + + filterContext.Result = new RedirectToRouteResult(route); + } + } + + base.OnActionExecuting(filterContext); + } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Web.Library/GlobalFilter/SslRedirectFilter.cs b/Libraries/Thinktecture.IdentityServer.Web.Library/GlobalFilter/SslRedirectFilter.cs new file mode 100644 index 0000000..7ecf06b --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Web.Library/GlobalFilter/SslRedirectFilter.cs @@ -0,0 +1,45 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Web.Mvc; + +namespace Thinktecture.IdentityServer.Web.GlobalFilter +{ + public class SslRedirectFilter : ActionFilterAttribute + { + public override void OnActionExecuting(ActionExecutingContext filterContext) + { + if (!filterContext.HttpContext.Request.IsSecureConnection) + { + filterContext.Result = new RedirectResult( + GetAbsoluteUri(filterContext.HttpContext.Request.Url).AbsoluteUri, + true); + } + } + + private Uri GetAbsoluteUri(Uri uriFromCaller) + { + UriBuilder builder = new UriBuilder(Uri.UriSchemeHttps, uriFromCaller.Host); + builder.Path = uriFromCaller.GetComponents(UriComponents.Path, UriFormat.Unescaped); + + string query = uriFromCaller.GetComponents(UriComponents.Query, UriFormat.UriEscaped); + if (query.Length > 0) + { + string uriWithoutQuery = builder.Uri.AbsoluteUri; + string absoluteUri = string.Format("{0}?{1}", uriWithoutQuery, query); + return new Uri(absoluteUri, UriKind.Absolute); + } + else + { + return builder.Uri; + } + } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Web.Library/Properties/AssemblyInfo.cs b/Libraries/Thinktecture.IdentityServer.Web.Library/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..33b5b37 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Web.Library/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +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("Thinktecture.IdentityServer.Web.Library")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Thinktecture.IdentityServer.Web.Library")] +[assembly: AssemblyCopyright("Copyright © 2012")] +[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("39c8af91-04b5-41db-84b9-20d6b3862a12")] + +// 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 Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Libraries/Thinktecture.IdentityServer.Web.Library/Resources/jsnotify.htm b/Libraries/Thinktecture.IdentityServer.Web.Library/Resources/jsnotify.htm new file mode 100644 index 0000000..59fa3d5 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Web.Library/Resources/jsnotify.htm @@ -0,0 +1,17 @@ + + + + + Loading... + + + + + \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Web.Library/Security/AuthenticationHelper b/Libraries/Thinktecture.IdentityServer.Web.Library/Security/AuthenticationHelper new file mode 100644 index 0000000..9e6cd3e --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Web.Library/Security/AuthenticationHelper @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using Microsoft.IdentityModel.Claims; +using System.Security.Cryptography.X509Certificates; +using Thinktecture.IdentityServer.Repositories; +using System.ComponentModel.Composition; + +namespace Thinktecture.IdentityServer.Web.Security +{ + internal class AuthenticationHelper + { + [Import] + public IUserRepository UserRepository { get; set; } + + public AuthenticationHelper() + { + Container.Current.SatisfyImportsOnce(this); + } + + public bool TryExtractCredentialFromRequest(HttpRequestBase Request, out IClaimsPrincipal principal) + { + // first check for client certificate + if (Request.ClientCertificate.IsPresent && Request.ClientCertificate.IsValid) + { + var clientCert = new X509Certificate2(Request.ClientCertificate.Certificate); + + } + + return false; + } + + private IClaimsPrincipal CreatePrincipal(string username, string authenticationMethod) + { + var claims = new List + { + new Claim(ClaimTypes.Name, username), + new Claim(ClaimTypes.AuthenticationMethod, authenticationMethod), + AuthenticationInstantClaim.Now + }; + + var principal = ClaimsPrincipal.CreateFromIdentity(new ClaimsIdentity(claims)); + return principal; + } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Web.Library/Security/AuthenticationHelper.cs b/Libraries/Thinktecture.IdentityServer.Web.Library/Security/AuthenticationHelper.cs new file mode 100644 index 0000000..085932d --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Web.Library/Security/AuthenticationHelper.cs @@ -0,0 +1,317 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.IdentityModel.Tokens; +using System.IO; +using System.Net; +using System.Security.Cryptography.X509Certificates; +using System.ServiceModel; +using System.Text; +using System.Web; +using System.Xml; +using Microsoft.IdentityModel.Claims; +using Microsoft.IdentityModel.Protocols.WSFederation; +using Microsoft.IdentityModel.Protocols.WSTrust; +using Microsoft.IdentityModel.SecurityTokenService; +using Microsoft.IdentityModel.Tokens; +using Microsoft.IdentityModel.Web; +using Thinktecture.IdentityModel.Claims; +using Thinktecture.IdentityServer.Core.Swt; +using Thinktecture.IdentityServer.Models; +using Thinktecture.IdentityServer.Repositories; +using Thinktecture.IdentityServer.TokenService; +using Thinktecture.IdentityServer.Web.ViewModels.OAuth2; + +namespace Thinktecture.IdentityServer.Web.Security +{ + public class AuthenticationHelper + { + [Import] + public IUserRepository UserRepository { get; set; } + + [Import] + public IRelyingPartyRepository RelyingPartyRepository { get; set; } + + public AuthenticationHelper() + { + Container.Current.SatisfyImportsOnce(this); + } + + public AuthenticationHelper(IUserRepository userRepository, IRelyingPartyRepository relyingPartyRepository) + { + UserRepository = userRepository; + RelyingPartyRepository = relyingPartyRepository; + } + + public bool TryGetPrincipalFromHttpRequest(HttpRequestBase request, out IClaimsPrincipal principal) + { + principal = null; + + // first check for client certificate + if (TryGetClientCertificatePrinciaplFromRequest(request, out principal)) + { + return true; + } + + // then basic authentication + if (TryGetBasicAuthenticationPrincipalFromRequest(request, out principal)) + { + return true; + } + + return false; + } + + public bool TryGetPrincipalFromOAuth2Request(HttpRequestBase request, ResourceOwnerCredentialRequest tokenRequest, out IClaimsPrincipal principal) + { + principal = null; + + // first check for client certificate + if (TryGetClientCertificatePrinciaplFromRequest(request, out principal)) + { + return true; + } + + // then OAuth2 userName credential + if (UserRepository.ValidateUser(tokenRequest.UserName ?? "", tokenRequest.Password ?? "")) + { + principal = CreatePrincipal(tokenRequest.UserName, AuthenticationMethods.Password); + return true; + } + + return false; + } + + public bool TryGetPrincipalFromWrapRequest(HttpRequestBase request, out IClaimsPrincipal principal) + { + HttpListenerBasicIdentity userNameId; + principal = null; + + // first check for client certificate + if (TryGetClientCertificatePrinciaplFromRequest(request, out principal)) + { + return true; + } + + // then WRAP userName credential + if (TryGetUserNameCredentialsFromWrapRequest(request, out userNameId)) + { + if (UserRepository.ValidateUser(userNameId.Name, userNameId.Password)) + { + principal = CreatePrincipal(userNameId.Name, AuthenticationMethods.Password); + return true; + } + } + + return false; + } + + public bool TryGetClientCertificatePrinciaplFromRequest(HttpRequestBase request, out IClaimsPrincipal principal) + { + X509Certificate2 clientCertificate = null; + principal = null; + + if (TryGetClientCertificateFromRequest(request, out clientCertificate)) + { + string userName; + if (UserRepository.ValidateUser(clientCertificate, out userName)) + { + principal = CreatePrincipal(userName, AuthenticationMethods.X509); + return true; + } + } + + return false; + } + + public bool TryGetClientCertificateFromRequest(HttpRequestBase request, out X509Certificate2 clientCertificate) + { + clientCertificate = null; + + if (request.ClientCertificate.IsPresent && request.ClientCertificate.IsValid) + { + clientCertificate = new X509Certificate2(request.ClientCertificate.Certificate); + return true; + } + + return false; + } + + public bool TryGetBasicAuthenticationPrincipalFromRequest(HttpRequestBase request, out IClaimsPrincipal principal) + { + principal = null; + HttpListenerBasicIdentity identity = null; + + if (TryGetBasicAuthenticationCredentialsFromRequest(request, out identity)) + { + if (UserRepository.ValidateUser(identity.Name, identity.Password)) + { + principal = CreatePrincipal(identity.Name, AuthenticationMethods.Password); + return true; + } + } + + return false; + } + + public bool TryGetBasicAuthenticationCredentialsFromRequest(HttpRequestBase request, out HttpListenerBasicIdentity identity) + { + identity = null; + + string header = request.Headers["Authorization"] ?? request.Headers["X-Authorization"]; + if (header != null && header.StartsWith("Basic")) + { + string encodedUserPass = header.Substring(6).Trim(); + + Encoding encoding = Encoding.GetEncoding("iso-8859-1"); + string userPass = encoding.GetString(Convert.FromBase64String(encodedUserPass)); + int separator = userPass.IndexOf(':'); + + string[] credentials = new string[2]; + credentials[0] = userPass.Substring(0, separator); + credentials[1] = userPass.Substring(separator + 1); + + identity = new HttpListenerBasicIdentity(credentials[0], credentials[1]); + return true; + } + + return false; + } + + public bool TryGetUserNameCredentialsFromWrapRequest(HttpRequestBase request, out HttpListenerBasicIdentity identity) + { + identity = null; + var userName = request.Form["wrap_name"]; + var password = request.Form["wrap_password"]; + + if (string.IsNullOrWhiteSpace(userName) || + string.IsNullOrWhiteSpace(password)) + { + return false; + } + + identity = new HttpListenerBasicIdentity(userName, password); + return true; + } + + public IClaimsPrincipal CreatePrincipal(string username, string authenticationMethod) + { + var claims = new List + { + new Claim(ClaimTypes.Name, username), + new Claim(ClaimTypes.AuthenticationMethod, authenticationMethod), + AuthenticationInstantClaim.Now + }; + + var principal = ClaimsPrincipal.CreateFromIdentity(new ClaimsIdentity(claims)); + return FederatedAuthentication.ServiceConfiguration.ClaimsAuthenticationManager.Authenticate(string.Empty, principal); + } + + public bool TryIssueToken(EndpointAddress appliesTo, IClaimsPrincipal principal, string tokenType, out SecurityToken token) + { + token = null; + + var rst = new RequestSecurityToken + { + RequestType = RequestTypes.Issue, + AppliesTo = appliesTo, + KeyType = KeyTypes.Bearer, + TokenType = tokenType + }; + + var sts = TokenServiceConfiguration.Current.CreateSecurityTokenService(); + + try + { + var rstr = sts.Issue(principal, rst); + token = rstr.RequestedSecurityToken.SecurityToken; + return true; + } + catch + { + return false; + } + } + + public bool TryIssueToken(EndpointAddress appliesTo, IClaimsPrincipal principal, string tokenType, out TokenResponse response) + { + SecurityToken token = null; + response = new TokenResponse { TokenType = tokenType }; + + var result = TryIssueToken(appliesTo, principal, tokenType, out token); + if (result == false) + { + return false; + } + + var swt = token as SimpleWebToken; + if (swt != null) + { + response.TokenString = swt.RawToken; + response.ContentType = "text"; + } + else + { + var handler = FederatedAuthentication.ServiceConfiguration.SecurityTokenHandlers; + var sb = new StringBuilder(128); + handler.WriteToken(new XmlTextWriter(new StringWriter(sb)), token); + + response.ContentType = "text/xml"; + response.TokenString = sb.ToString(); + } + + return result; + } + + public void SetSessionToken(string userName, string authenticationMethod, bool isPersistent, int ttl, string resourceName) + { + var principal = CreatePrincipal(userName, authenticationMethod); + var transformedPrincipal = FederatedAuthentication.ServiceConfiguration.ClaimsAuthenticationManager.Authenticate(resourceName, principal); + var sessionToken = new SessionSecurityToken(transformedPrincipal, TimeSpan.FromHours(ttl)) + { + IsPersistent = isPersistent + }; + + FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(sessionToken); + } + + public RelyingParty GetRelyingPartyDetails(string realm) + { + RelyingParty rp = null; + + if (RelyingPartyRepository.TryGet(realm, out rp)) + { + return rp; + } + + return null; + } + + public RelyingParty GetRelyingPartyDetailsFromReturnUrl(string returnUrl) + { + if (string.IsNullOrWhiteSpace(returnUrl)) + { + return null; + } + + var url = HttpUtility.UrlDecode(returnUrl); + var message = WSFederationMessage.CreateFromUri(new Uri("http://foo.com" + url, UriKind.Absolute)) as SignInRequestMessage; + + if (message != null) + { + return GetRelyingPartyDetails(message.Realm); + } + + return null; + } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Web.Library/Security/AuthorizationManager.cs b/Libraries/Thinktecture.IdentityServer.Web.Library/Security/AuthorizationManager.cs new file mode 100644 index 0000000..db7dbac --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Web.Library/Security/AuthorizationManager.cs @@ -0,0 +1,104 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.Collections.ObjectModel; +using System.ComponentModel.Composition; +using System.Linq; +using Microsoft.IdentityModel.Claims; +using Microsoft.IdentityModel.Protocols.WSTrust; +using Thinktecture.IdentityModel.Extensions; +using Thinktecture.IdentityServer.Repositories; + +namespace Thinktecture.IdentityServer.Web.Security +{ + public class AuthorizationManager : ClaimsAuthorizationManager + { + [Import] + public IConfigurationRepository ConfigurationRepository { get; set; } + + public AuthorizationManager() + { + Container.Current.SatisfyImportsOnce(this); + } + + public AuthorizationManager(IConfigurationRepository configuration) + { + ConfigurationRepository = configuration; + } + + public override bool CheckAccess(AuthorizationContext context) + { + var action = context.Action.First(); + var id = context.Principal.Identities.First(); + + // if application authorization request + if (action.ClaimType.Equals(ClaimsAuthorize.ActionType)) + { + return AuthorizeCore(action, context.Resource, context.Principal.Identity as IClaimsIdentity); + } + + // if ws-trust issue request + if (action.Value.Equals(WSTrust13Constants.Actions.Issue)) + { + return AuthorizeTokenIssuance(new Collection { new Claim(ClaimsAuthorize.ResourceType, Constants.Resources.WSTrust) }, id); + } + + return base.CheckAccess(context); + } + + protected virtual bool AuthorizeCore(Claim action, Collection resource, IClaimsIdentity id) + { + switch (action.Value) + { + case Constants.Actions.Issue: + return AuthorizeTokenIssuance(resource, id); + case Constants.Actions.Administration: + return AuthorizeAdministration(resource, id); + } + + return false; + } + + protected virtual bool AuthorizeTokenIssuance(Collection resource, IClaimsIdentity id) + { + if (!ConfigurationRepository.Configuration.EnforceUsersGroupMembership) + { + var authResult = id.IsAuthenticated; + if (!authResult) + { + Tracing.Error("Authorization for token issuance failed because the user is anonymous"); + } + + return authResult; + } + + var roleResult = id.ClaimExists(ClaimTypes.Role, Constants.Roles.IdentityServerUsers); + if (!roleResult) + { + Tracing.Error(string.Format("Authorization for token issuance failed because user {0} is not in the {1} role", id.Name, Constants.Roles.IdentityServerUsers)); + } + + return roleResult; + } + + protected virtual bool AuthorizeAdministration(Collection resource, IClaimsIdentity id) + { + var roleResult = id.ClaimExists(ClaimTypes.Role, Constants.Roles.IdentityServerAdministrators); + if (!roleResult) + { + if (resource[0].Value != Constants.Resources.UI) + { + Tracing.Error(string.Format("Administration authorization failed because user {0} is not in the {1} role", id.Name, Constants.Roles.IdentityServerAdministrators)); + } + } + + return roleResult; + } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Web.Library/Security/ClaimsAuthorizeAttribute.cs b/Libraries/Thinktecture.IdentityServer.Web.Library/Security/ClaimsAuthorizeAttribute.cs new file mode 100644 index 0000000..42168ac --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Web.Library/Security/ClaimsAuthorizeAttribute.cs @@ -0,0 +1,97 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.Collections.ObjectModel; +using System.Linq; +using System.Threading; +using System.Web; +using System.Web.Mvc; +using Microsoft.IdentityModel.Claims; +using Thinktecture.IdentityModel.Claims; +using WIF = Microsoft.IdentityModel.Claims; + +namespace Thinktecture.IdentityServer.Web.Security +{ + public class ClaimsAuthorize : AuthorizeAttribute + { + private string _resource; + private string _action; + private string[] _additionalResources; + + /// + /// Default action claim type. + /// + public const string ActionType = "http://application/claims/authorization/action"; + + /// + /// Default resource claim type + /// + public const string ResourceType = "http://application/claims/authorization/resource"; + + /// + /// Additional resource claim type + /// + public const string AdditionalResourceType = "http://application/claims/authorization/additionalresource"; + + public ClaimsAuthorize(string action, string resource, params string[] additionalResources) + { + _action = action; + _resource = resource; + _additionalResources = additionalResources; + } + + public static bool CheckAccess(string action, string resource, params string[] additionalResources) + { + return CheckAccess( + Thread.CurrentPrincipal as IClaimsPrincipal, + action, + resource, + additionalResources); + } + + public static bool CheckAccess(IClaimsPrincipal principal, string action, string resource, params string[] additionalResources) + { + var context = CreateAuthorizationContext( + principal, + action, + resource, + additionalResources); + + return ClaimsAuthorization.CheckAccess(context); + } + + protected override bool AuthorizeCore(HttpContextBase httpContext) + { + return CheckAccess(_action, _resource, _additionalResources); + } + + private static WIF.AuthorizationContext CreateAuthorizationContext(IClaimsPrincipal principal, string action, string resource, params string[] additionalResources) + { + var actionClaims = new Collection + { + new Claim(ActionType, action) + }; + + var resourceClaims = new Collection + { + new Claim(ResourceType, resource) + }; + + if (additionalResources != null && additionalResources.Length > 0) + { + additionalResources.ToList().ForEach(ar => resourceClaims.Add(new Claim(AdditionalResourceType, ar))); + } + + return new WIF.AuthorizationContext( + principal, + resourceClaims, + actionClaims); + } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Web.Library/Security/ClaimsTransformer.cs b/Libraries/Thinktecture.IdentityServer.Web.Library/Security/ClaimsTransformer.cs new file mode 100644 index 0000000..4fc1aba --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Web.Library/Security/ClaimsTransformer.cs @@ -0,0 +1,40 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.ComponentModel.Composition; +using System.Linq; +using Microsoft.IdentityModel.Claims; +using Thinktecture.IdentityServer.Repositories; + +namespace Thinktecture.IdentityServer.Web.Security +{ + public class ClaimsTransformer : ClaimsAuthenticationManager + { + [Import] + public IUserRepository UserRepository { get; set; } + + public ClaimsTransformer() + { + Container.Current.SatisfyImportsOnce(this); + } + + public override IClaimsPrincipal Authenticate(string resourceName, IClaimsPrincipal incomingPrincipal) + { + if (!incomingPrincipal.Identity.IsAuthenticated) + { + return base.Authenticate(resourceName, incomingPrincipal); + } + + UserRepository.GetRoles(incomingPrincipal.Identity.Name, RoleTypes.IdentityServer).ToList().ForEach(role => + incomingPrincipal.Identities[0].Claims.Add(new Claim(ClaimTypes.Role, role))); + + return incomingPrincipal; + } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Web.Library/Security/OAuth2/ResourceOwnerCredentialRequest.cs b/Libraries/Thinktecture.IdentityServer.Web.Library/Security/OAuth2/ResourceOwnerCredentialRequest.cs new file mode 100644 index 0000000..a7b2cfb --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Web.Library/Security/OAuth2/ResourceOwnerCredentialRequest.cs @@ -0,0 +1,17 @@ +using System.ComponentModel.DataAnnotations; + +namespace Thinktecture.IdentityServer.Web.ViewModels.OAuth2 +{ + public class ResourceOwnerCredentialRequest + { + [Required] + public string Grant_Type { get; set; } + + [Required] + public string Scope { get; set; } + + public string UserName { get; set; } + + public string Password { get; set; } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Web.Library/Security/TokenResponse.cs b/Libraries/Thinktecture.IdentityServer.Web.Library/Security/TokenResponse.cs new file mode 100644 index 0000000..658d97c --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Web.Library/Security/TokenResponse.cs @@ -0,0 +1,10 @@ + +namespace Thinktecture.IdentityServer.Web.Security +{ + public class TokenResponse + { + public string TokenString { get; set; } + public string TokenType { get; set; } + public string ContentType { get; set; } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Web.Library/Thinktecture.IdentityServer.Web.Library.csproj b/Libraries/Thinktecture.IdentityServer.Web.Library/Thinktecture.IdentityServer.Web.Library.csproj new file mode 100644 index 0000000..c04b62b --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Web.Library/Thinktecture.IdentityServer.Web.Library.csproj @@ -0,0 +1,95 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {FC2D7E2A-65A2-480F-AAE8-855FD026AF85} + Library + Properties + Thinktecture.IdentityServer.Web + Thinktecture.IdentityServer.Web.Library + v4.0 + 512 + ..\ + true + + + true + full + false + ..\build\Common\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\build\Common\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + ..\packages\Thinktecture.IdentityModel.1.3.0.0\lib\Thinktecture.IdentityModel.dll + + + + + + + + + + + + + + + + + + + + + + + + {38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A} + Thinktecture.IdentityServer.Core + + + + + + + + + + + + \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.Web.Library/packages.config b/Libraries/Thinktecture.IdentityServer.Web.Library/packages.config new file mode 100644 index 0000000..531e1e1 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.Web.Library/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.WindowsAzure/EntryPoint.cs b/Libraries/Thinktecture.IdentityServer.WindowsAzure/EntryPoint.cs new file mode 100644 index 0000000..6f3b853 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.WindowsAzure/EntryPoint.cs @@ -0,0 +1,101 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using Microsoft.WindowsAzure; +using Microsoft.WindowsAzure.Diagnostics; +using Microsoft.WindowsAzure.ServiceRuntime; +using Microsoft.WindowsAzure.StorageClient; +using Thinktecture.IdentityServer.Repositories.WindowsAzure; +using System.Linq; + +namespace Thinktecture.IdentityServer.Web +{ + public class EntryPoint : RoleEntryPoint + { + private const string DiagnosticStorage = "Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString"; + private const string StorageConnectionString = "StorageConnectionString"; + + public override bool OnStart() + { + try + { + RoleEnvironment.Changing += RoleEnvironment_Changing; + ConfigureDiagnosticMonitoring(); + + return base.OnStart(); + } + catch (Exception ex) + { + WriteExceptionToBlobStorage(ex); + return false; + } + } + + void RoleEnvironment_Changing(object sender, RoleEnvironmentChangingEventArgs e) + { + if (e.Changes.Any(c => c is RoleEnvironmentConfigurationSettingChange)) + { + e.Cancel = true; + } + } + + // adjust these settings to your needs + private void ConfigureDiagnosticMonitoring() + { + var standardTransfer = TimeSpan.FromMinutes(60); + var pollInterval = TimeSpan.FromMinutes(10); + + // retrieve standard config + var config = DiagnosticMonitor.GetDefaultInitialConfiguration(); + + // check for config changes + config.ConfigurationChangePollInterval = pollInterval; + + // traces transfer + config.Logs.ScheduledTransferLogLevelFilter = LogLevel.Verbose; + config.Logs.ScheduledTransferPeriod = standardTransfer; + + // infrastructure traces + config.DiagnosticInfrastructureLogs.ScheduledTransferLogLevelFilter = LogLevel.Error; + config.DiagnosticInfrastructureLogs.ScheduledTransferPeriod = standardTransfer; + + // automatic transfer of application event log + config.WindowsEventLog.DataSources.Add("Application!*"); + config.WindowsEventLog.DataSources.Add("System!*"); + config.WindowsEventLog.ScheduledTransferLogLevelFilter = LogLevel.Warning; + config.WindowsEventLog.ScheduledTransferPeriod = standardTransfer; + + // automatic transfer of CPU load + var procTime = new PerformanceCounterConfiguration + { + CounterSpecifier = @"\Processor(*)\% Processor Time", + SampleRate = TimeSpan.FromMinutes(1) + }; + + config.PerformanceCounters.DataSources.Add(procTime); + config.PerformanceCounters.ScheduledTransferPeriod = standardTransfer; + + // send config to monitor + DiagnosticMonitor.Start(DiagnosticStorage, config); + } + + private void WriteExceptionToBlobStorage(Exception ex) + { + var storageAccount = CloudStorageAccount.Parse( + RoleEnvironment.GetConfigurationSettingValue(DiagnosticStorage)); + + var container = storageAccount.CreateCloudBlobClient().GetContainerReference("exceptions"); + container.CreateIfNotExist(); + + var blob = container.GetBlobReference(string.Format("exception-{0}-{1}.log", RoleEnvironment.CurrentRoleInstance.Id, DateTime.UtcNow.Ticks)); + blob.UploadText(ex.ToString()); + } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.WindowsAzure/Properties/AssemblyInfo.cs b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..ccd093f --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +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("Thinktecture.IdentityServer.WindowsAzure")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Thinktecture.IdentityServer.WindowsAzure")] +[assembly: AssemblyCopyright("Copyright © 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("1c12020f-ed99-4e1d-8ad8-bbce09d138d5")] + +// 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 Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Configuration/ClientCertificateEntity.cs b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Configuration/ClientCertificateEntity.cs new file mode 100644 index 0000000..b444e67 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Configuration/ClientCertificateEntity.cs @@ -0,0 +1,34 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using Microsoft.WindowsAzure.StorageClient; + +namespace Thinktecture.IdentityServer.Repositories.WindowsAzure +{ + public class ClientCertificateEntity : TableServiceEntity + { + // partition key: default + // rowkey: thumbprint + + public string UserName { get; set; } + public string Description { get; set; } + + public ClientCertificateEntity() + { } + + public ClientCertificateEntity(string thumbprint, string userName, string description) + { + PartitionKey = RelyingPartyRepository.DefaultPartitionKey; + RowKey = thumbprint.ToLowerInvariant(); + + UserName = userName.ToLowerInvariant(); + Description = description; + } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Configuration/ClientCertificatesRepository.cs b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Configuration/ClientCertificatesRepository.cs new file mode 100644 index 0000000..3b232f8 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Configuration/ClientCertificatesRepository.cs @@ -0,0 +1,109 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography.X509Certificates; +using Microsoft.WindowsAzure; +using Microsoft.WindowsAzure.ServiceRuntime; +using Thinktecture.IdentityServer.Models; + +namespace Thinktecture.IdentityServer.Repositories.WindowsAzure +{ + public class ClientCertificatesRepository : IClientCertificatesRepository + { + CloudStorageAccount _account; + internal const string DefaultPartitionKey = "default"; + + public ClientCertificatesRepository() + : this(TableStorageContext.StorageConnectionString) + { } + + public ClientCertificatesRepository(CloudStorageAccount account) + { + _account = account; + } + + public ClientCertificatesRepository(string storageConnectionString) + { + _account = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue(storageConnectionString)); + } + + #region Runtime + public bool TryGetUserNameFromThumbprint(X509Certificate2 certificate, out string userName) + { + userName = null; + var thumbprint = certificate.Thumbprint.ToLowerInvariant(); + var context = NewContext; + context.IgnoreResourceNotFoundException = true; + + var entity = (from cc in context.ClientCertificates + where cc.PartitionKey == DefaultPartitionKey && + cc.RowKey == thumbprint + select cc) + .SingleOrDefault(); + + if (entity != null && !string.IsNullOrEmpty(entity.UserName)) + { + userName = entity.UserName; + return true; + } + + return false; + } + #endregion + + #region Management + public bool SupportsWriteAccess + { + get { return true; } + } + + public IEnumerable List(int pageIndex, int pageSize) + { + var all = NewContext.AllClientCertificates(DefaultPartitionKey); + + return (from cc in all + select cc.UserName) + .Distinct().ToList(); + } + + public IEnumerable GetClientCertificatesForUser(string userName) + { + var user = userName.ToLowerInvariant(); + + var certs = from e in NewContext.ClientCertificates + where e.PartitionKey == DefaultPartitionKey && + e.UserName == user + select e; + + return certs.ToList().ToDomainModel(); + } + + public void Add(ClientCertificate certificate) + { + NewContext.AddClientCertificate(certificate.ToEntity()); + } + + public void Delete(ClientCertificate certificate) + { + NewContext.DeleteClientCertificate(certificate.ToEntity()); + } + #endregion + + private TableStorageContext NewContext + { + get + { + var context = new TableStorageContext(_account.TableEndpoint.AbsoluteUri, _account.Credentials); + return context; + } + } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Configuration/ConfigurationRepository.cs b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Configuration/ConfigurationRepository.cs new file mode 100644 index 0000000..200689d --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Configuration/ConfigurationRepository.cs @@ -0,0 +1,192 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Configuration; +using System.Diagnostics; +using System.Security.Cryptography.X509Certificates; +using Microsoft.WindowsAzure.ServiceRuntime; +using Thinktecture.IdentityServer.Helper; +using Thinktecture.IdentityServer.Models; + +namespace Thinktecture.IdentityServer.Repositories.WindowsAzure +{ + public class ConfigurationRepository : IConfigurationRepository + { + #region Runtime + public GlobalConfiguration Configuration + { + get + { + return new GlobalConfiguration + { + SiteName = GetConfigurationString("SiteName"), + IssuerUri = GetConfigurationString("IssuerUri"), + IssuerContactEmail = GetConfigurationString("IssuerContactEmail"), + + DefaultTokenType = GetConfigurationString("DefaultTokenType"), + DefaultTokenLifetime = GetConfigurationInteger("DefaultTokenLifetime"), + MaximumTokenLifetime = GetConfigurationInteger("MaximumTokenLifetime"), + SsoCookieLifetime = GetConfigurationInteger("SsoCookieLifetime"), + + RequireSsl = GetConfigurationBoolean("RequireSsl"), + RequireEncryption = GetConfigurationBoolean("RequireEncryption"), + + EnableClientCertificates = GetConfigurationBoolean("EnableClientCertificates"), + EnableDelegation = GetConfigurationBoolean("EnableDelegation"), + + AllowKnownRealmsOnly = GetConfigurationBoolean("AllowKnownRealmsOnly"), + AllowReplyTo = GetConfigurationBoolean("AllowReplyTo"), + RequireReplyToWithinRealm = GetConfigurationBoolean("RequireReplyToWithinRealm"), + + EnableStrongEpiForSsl = GetConfigurationBoolean("EnableStrongEpiForSsl"), + EnableFederationMessageTracing = GetConfigurationBoolean("EnableFederationMessageTracing"), + EnforceUsersGroupMembership = GetConfigurationBoolean("EnforceUsersGroupMembership"), + + RequireSignInConfirmation = GetConfigurationBoolean("RequireSignInConfirmation"), + }; + } + } + + public EndpointConfiguration Endpoints + { + get + { + return new EndpointConfiguration + { + WSFederation = GetConfigurationBoolean("Endpoints__WSFederation"), + FederationMetadata = GetConfigurationBoolean("Endpoints__FederationMetadata"), + + WSTrustMessage = GetConfigurationBoolean("Endpoints__WSTrustMessage"), + WSTrustMixed = GetConfigurationBoolean("Endpoints__WSTrustMixed"), + + SimpleHttp = GetConfigurationBoolean("Endpoints__SimpleHttp"), + OAuth2 = GetConfigurationBoolean("Endpoints__OAuth2"), + OAuthWRAP = GetConfigurationBoolean("Endpoints__WRAP"), + JSNotify = GetConfigurationBoolean("Endpoints__JSNotify"), + + HttpPort = GetConfigurationInteger("HttpPort"), + HttpsPort = GetConfigurationInteger("HttpsPort") + }; + } + } + + public CertificateConfiguration SslCertificate + { + get + { + var dn = GetConfigurationString("SslCertificateDistinguishedName"); + + var cert = new CertificateConfiguration + { + SubjectDistinguishedName = dn, + }; + + if (!string.IsNullOrWhiteSpace(dn)) + { + cert.Certificate = GetCertificateFromStore(dn); + } + + return cert; + } + } + + public CertificateConfiguration SigningCertificate + { + get + { + var dn = GetConfigurationString("SigningCertificateDistinguishedName"); + + var cert = new CertificateConfiguration + { + SubjectDistinguishedName = dn, + }; + + if (!string.IsNullOrWhiteSpace(dn)) + { + cert.Certificate = GetCertificateFromStore(dn); + } + + return cert; + } + } + + private X509Certificate2 GetCertificateFromStore(string distinguishedName) + { + return X509Certificates.GetCertificateFromStore(distinguishedName); + } + + + private bool GetConfigurationBoolean(string name) + { + var value = GetConfigurationString(name); + + bool valueBool = false; + if (bool.TryParse(value, out valueBool)) + { + return valueBool; + } + + Tracing.TraceEvent(TraceEventType.Error, "Error converting configuration value to boolean: " + name, true); + throw new ConfigurationErrorsException(name); + } + + private int GetConfigurationInteger(string name) + { + var value = GetConfigurationString(name); + + int valueInt = 0; + if (int.TryParse(value, out valueInt)) + { + return valueInt; + } + + Tracing.TraceEvent(TraceEventType.Error, "Error converting configuration value to integer: " + name, true); + throw new ConfigurationErrorsException(name); + } + + private string GetConfigurationString(string name) + { + Tracing.Verbose("Retrieving configuration value for: " + name); + + try + { + return RoleEnvironment.GetConfigurationSettingValue(name); + } + catch (Exception ex) + { + Tracing.TraceEvent(TraceEventType.Error, "Error retrieving configuration value: " + ex.ToString(), true); + throw; + } + } + #endregion + + #region Management + public bool SupportsWriteAccess + { + get { return false; } + } + + public void UpdateConfiguration(GlobalConfiguration configuration) + { + throw new NotImplementedException(); + } + + public void UpdateEndpoints(EndpointConfiguration endpoints) + { + throw new NotImplementedException(); + } + + public void UpdateCertificates(string sslSubjectName, string signingSubjectName) + { + throw new NotImplementedException(); + } + #endregion + } +} diff --git a/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Configuration/DelegationEntity.cs b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Configuration/DelegationEntity.cs new file mode 100644 index 0000000..625b021 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Configuration/DelegationEntity.cs @@ -0,0 +1,23 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using Microsoft.WindowsAzure.StorageClient; + +namespace Thinktecture.IdentityServer.Repositories.WindowsAzure +{ + public class DelegationEntity : TableServiceEntity + { + // partition key: default + // rowkey: unique id + + public string UserName { get; set; } + public string Realm { get; set; } + public string Description { get; set; } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Configuration/DelegationRepository.cs b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Configuration/DelegationRepository.cs new file mode 100644 index 0000000..3c404f1 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Configuration/DelegationRepository.cs @@ -0,0 +1,108 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.WindowsAzure; +using Microsoft.WindowsAzure.ServiceRuntime; +using Thinktecture.IdentityServer.Models; + +namespace Thinktecture.IdentityServer.Repositories.WindowsAzure +{ + public class DelegationRepository : IDelegationRepository + { + CloudStorageAccount _account; + internal const string DefaultPartitionKey = "default"; + + public DelegationRepository() + : this(TableStorageContext.StorageConnectionString) + { } + + public DelegationRepository(CloudStorageAccount account) + { + _account = account; + } + + public DelegationRepository(string storageConnectionString) + { + _account = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue(storageConnectionString)); + } + + #region Runtime + public bool IsDelegationAllowed(string userName, string realm) + { + var context = NewContext; + + context.IgnoreResourceNotFoundException = true; + + var result = (from d in context.Delegation + where d.PartitionKey == DefaultPartitionKey && + d.UserName.Equals(userName, StringComparison.OrdinalIgnoreCase) && + d.Realm.Equals(realm, StringComparison.OrdinalIgnoreCase) + select d) + .FirstOrDefault(); + + if (result != null) + { + return true; + } + + return false; + } + #endregion + + #region Management + public void Add(DelegationSetting setting) + { + NewContext.AddDelegation(setting.ToEntity()); + } + + public void Delete(DelegationSetting setting) + { + var entity = (from e in NewContext.Delegation + where e.PartitionKey == DefaultPartitionKey && + e.UserName.Equals(setting.UserName, StringComparison.OrdinalIgnoreCase) && + e.Realm.Equals(setting.Realm.AbsoluteUri, StringComparison.OrdinalIgnoreCase) + select e) + .Single(); + + NewContext.DeleteDelegation(entity.PartitionKey, entity.RowKey); + } + + public IEnumerable GetAllUsers(int pageIndex, int pageSize) + { + var all = (from e in NewContext.AllDelegations(DefaultPartitionKey) + select e.UserName); + + return all.Distinct().ToList(); + } + + public IEnumerable GetDelegationSettingsForUser(string userName) + { + return NewContext.AllDelegations(DefaultPartitionKey, userName).ToDomainModel(); + } + + public bool SupportsWriteAccess + { + get { return true; } + } + + #endregion + + private TableStorageContext NewContext + { + get + { + var context = new TableStorageContext(_account.TableEndpoint.AbsoluteUri, _account.Credentials); + return context; + } + } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Configuration/RelyingPartyEntity.cs b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Configuration/RelyingPartyEntity.cs new file mode 100644 index 0000000..369b1d9 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Configuration/RelyingPartyEntity.cs @@ -0,0 +1,29 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using Microsoft.WindowsAzure.StorageClient; + +namespace Thinktecture.IdentityServer.Repositories.WindowsAzure +{ + public class RelyingPartyEntity : TableServiceEntity + { + // partition key = default + // rowkey = unique id + + public string RealmHost { get; set; } + public string RealmPath { get; set; } + public string Description { get; set; } + public string ReplyToAddress { get; set; } + public string EncryptingCertificate { get; set; } + public string SymmetricSigningKey { get; set; } + public string ExtraData1 { get; set; } + public string ExtraData2 { get; set; } + public string ExtraData3 { get; set; } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Configuration/RelyingPartyRepository.cs b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Configuration/RelyingPartyRepository.cs new file mode 100644 index 0000000..9caba38 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Configuration/RelyingPartyRepository.cs @@ -0,0 +1,148 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.WindowsAzure; +using Microsoft.WindowsAzure.ServiceRuntime; +using Thinktecture.IdentityServer.Models; + +namespace Thinktecture.IdentityServer.Repositories.WindowsAzure +{ + public class RelyingPartyRepository : IRelyingPartyRepository + { + CloudStorageAccount _account; + internal const string DefaultPartitionKey = "default"; + + public RelyingPartyRepository() + : this(TableStorageContext.StorageConnectionString) + { } + + public RelyingPartyRepository(CloudStorageAccount account) + { + _account = account; + } + + public RelyingPartyRepository(string storageConnectionString) + { + _account = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue(storageConnectionString)); + } + + #region Runtime + public bool TryGet(string realm, out RelyingParty relyingParty) + { + relyingParty = null; + + var rps = GetRelyingPartiesForServer(realm); + var strippedRealm = realm.ToLowerInvariant().StripProtocolMoniker(); + + var bestMatch = + (from rp in rps + let strippedConfig = rp.Realm.AbsoluteUri.ToLowerInvariant().StripProtocolMoniker() + where strippedRealm.Contains(strippedConfig) + orderby rp.Realm.AbsoluteUri.Length descending + select rp) + .FirstOrDefault(); + + if (bestMatch != null) + { + relyingParty = bestMatch; + return true; + } + + return false; + } + + private List GetRelyingPartiesForServer(string realm) + { + var rps = new List(); + var realmUri = new Uri(realm); + + var result = from rp in NewContext.RelyingParties + where rp.PartitionKey == DefaultPartitionKey && + rp.RealmHost.Equals(realmUri.DnsSafeHost, StringComparison.OrdinalIgnoreCase) + select rp; + + foreach (var rp in result) + { + rps.Add(rp.ToDomainModel()); + } + + return rps; + } + #endregion + + #region Management + public bool SupportsWriteAccess + { + get { return true; } + } + + public IEnumerable List(int pageIndex, int pageSize) + { + if (pageIndex != -1 && pageSize != -1) + { + return All().Skip(pageIndex * pageSize).Take(pageSize).ToList().ToDomainModel(); + } + + return All().ToDomainModel(); + } + + public RelyingParty Get(string id) + { + var entity = (from rp in NewContext.RelyingParties + where rp.PartitionKey == DefaultPartitionKey && + rp.RowKey == id + select rp) + .Single(); + + return entity.ToDomainModel(); + } + + public void Add(RelyingParty relyingParty) + { + NewContext.AddRelyingParty(relyingParty.ToEntity()); + } + + public void Update(RelyingParty relyingParty) + { + NewContext.UpdateRelyingParty(relyingParty.ToEntity(relyingParty.Id)); + } + + public void Delete(string id) + { + NewContext.DeleteRelyingParty(DefaultPartitionKey, id); + } + + private List All() + { + var rpEntities = from rp in NewContext.RelyingParties + where rp.PartitionKey == DefaultPartitionKey + select rp; + + return rpEntities.ToList().OrderBy(rp => rp.PartitionKey).ToList(); + } + #endregion + + private TableStorageContext NewContext + { + get + { + var context = new TableStorageContext(_account.TableEndpoint.AbsoluteUri, _account.Credentials); + return context; + } + } + + + + + + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Extensions.cs b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Extensions.cs new file mode 100644 index 0000000..6e2df5a --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Extensions.cs @@ -0,0 +1,189 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography.X509Certificates; +using Thinktecture.IdentityServer.Models; + +namespace Thinktecture.IdentityServer.Repositories.WindowsAzure +{ + public static class Extensions + { + #region Relying Party + public static RelyingPartyEntity ToEntity(this RelyingParty model) + { + return model.ToEntity(Guid.NewGuid().ToString()); + } + + public static RelyingPartyEntity ToEntity(this RelyingParty model, string id) + { + return model.ToEntity(id, RelyingPartyRepository.DefaultPartitionKey); + } + + public static RelyingPartyEntity ToEntity(this RelyingParty model, string id, string partitionKey) + { + var entity = new RelyingPartyEntity + { + PartitionKey = partitionKey, + RowKey = id, + RealmHost = model.Realm.DnsSafeHost.ToLowerInvariant(), + RealmPath = model.Realm.PathAndQuery.ToLowerInvariant(), + Description = model.Name, + ExtraData1 = model.ExtraData1 ?? "", + ExtraData2 = model.ExtraData2 ?? "", + ExtraData3 = model.ExtraData3 ?? "", + }; + + if (model.ReplyTo != null) + { + entity.ReplyToAddress = model.ReplyTo.AbsoluteUri; + } + else + { + entity.ReplyToAddress = ""; + } + + if (model.EncryptingCertificate != null) + { + entity.EncryptingCertificate = Convert.ToBase64String(model.EncryptingCertificate.RawData); + } + + if (model.SymmetricSigningKey != null && model.SymmetricSigningKey.Length != 0) + { + entity.SymmetricSigningKey = Convert.ToBase64String(model.SymmetricSigningKey); + } + else + { + entity.SymmetricSigningKey = ""; + } + + return entity; + } + + public static RelyingParty ToDomainModel(this RelyingPartyEntity entity) + { + var model = new RelyingParty + { + Id = entity.RowKey, + Realm = new Uri("http://" + entity.RealmHost + entity.RealmPath), + Name = entity.Description, + ExtraData1 = entity.ExtraData1, + ExtraData2 = entity.ExtraData2, + ExtraData3 = entity.ExtraData3 + }; + + if (entity.EncryptingCertificate != null) + { + model.EncryptingCertificate = new X509Certificate2(Convert.FromBase64String(entity.EncryptingCertificate)); + } + + if (!string.IsNullOrWhiteSpace(entity.ReplyToAddress)) + { + model.ReplyTo = new Uri(entity.ReplyToAddress); + } + + if (!string.IsNullOrWhiteSpace(entity.SymmetricSigningKey)) + { + model.SymmetricSigningKey = Convert.FromBase64String(entity.SymmetricSigningKey); + } + + return model; + } + + public static List ToDomainModel(this List entities) + { + return (from e in entities + select e.ToDomainModel()) + .ToList(); + } + + public static string StripProtocolMoniker(this string uriString) + { + var uri = new Uri(uriString); + string stripped = uri.AbsoluteUri.Substring(uri.Scheme.Length + 3); + return stripped; + } + #endregion + + #region Client Certificates + public static List ToDomainModel(this List entities) + { + return (from e in entities + select e.ToDomainModel()) + .ToList(); + } + + public static ClientCertificate ToDomainModel(this ClientCertificateEntity entity) + { + var cc = new ClientCertificate + { + UserName = entity.UserName, + Thumbprint = entity.RowKey, + Description = entity.Description + }; + + return cc; + } + + public static ClientCertificateEntity ToEntity(this ClientCertificate model) + { + return model.ToEntity(ClientCertificatesRepository.DefaultPartitionKey); + } + + public static ClientCertificateEntity ToEntity(this ClientCertificate model, string partitionKey) + { + return new ClientCertificateEntity(model.Thumbprint, model.UserName, model.Description) + { + PartitionKey = partitionKey + }; + } + #endregion + + #region Delegation + public static DelegationEntity ToEntity(this DelegationSetting model) + { + return model.ToEntity(DelegationRepository.DefaultPartitionKey); + } + + public static DelegationEntity ToEntity(this DelegationSetting model, string partitionKey) + { + var entity = new DelegationEntity + { + PartitionKey = partitionKey, + RowKey = Guid.NewGuid().ToString(), + + UserName = model.UserName.ToLowerInvariant(), + Realm = model.Realm.AbsoluteUri.ToLowerInvariant(), + Description = model.Description + }; + + return entity; + } + + public static List ToDomainModel(this List entities) + { + return (from e in entities + select e.ToDomainModel()) + .ToList(); + } + + public static DelegationSetting ToDomainModel(this DelegationEntity entity) + { + return new DelegationSetting + { + UserName = entity.UserName, + Realm = new Uri(entity.Realm), + Description = entity.Description + }; + } + #endregion + } +} diff --git a/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/TableStorageContext.cs b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/TableStorageContext.cs new file mode 100644 index 0000000..f783688 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/TableStorageContext.cs @@ -0,0 +1,323 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Collections.Generic; +using System.Data.Services.Client; +using System.Linq; +using Microsoft.IdentityModel.Claims; +using Microsoft.WindowsAzure; +using Microsoft.WindowsAzure.StorageClient; +using Microsoft.WindowsAzure.ServiceRuntime; + +namespace Thinktecture.IdentityServer.Repositories.WindowsAzure +{ + public class TableStorageContext : TableServiceContext + { + internal const string RelyingPartiesTable = "RelyingParties"; + internal const string ClientCertificatesTable = "ClientCertificates"; + internal const string DelegationTable = "Delegation"; + internal const string UsersTable = "Users"; + internal const string StorageConnectionString = "StorageConnectionString"; + + #region Structural + static TableStorageContext() + { + try + { + SetupTables(); + } + catch { } + } + + public static void SetupTables() + { + var account = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue(StorageConnectionString)); + SetupTables(account); + } + + public static void SetupTables(string connectionString) + { + var account = CloudStorageAccount.Parse(connectionString); + SetupTables(account); + } + + public static void SetupTables(CloudStorageAccount account) + { + var client = account.CreateCloudTableClient(); + + client.CreateTableIfNotExist(RelyingPartiesTable); + client.CreateTableIfNotExist(ClientCertificatesTable); + client.CreateTableIfNotExist(DelegationTable); + client.CreateTableIfNotExist(UsersTable); + } + + public TableStorageContext(string baseAddress, StorageCredentials credentials) + : base(baseAddress, credentials) + { } + + public TableStorageContext(string connectionString) + : base(GetBaseAddress(connectionString), GetCredentials(connectionString)) + { } + + private static string GetBaseAddress(string connectionString) + { + var account = CloudStorageAccount.Parse(connectionString); + return account.TableEndpoint.AbsoluteUri; + } + + private static StorageCredentials GetCredentials(string connectionString) + { + var account = CloudStorageAccount.Parse(connectionString); + return account.Credentials; + } + #endregion + + #region Users + public IQueryable UserAccounts + { + get + { + return CreateQuery(UsersTable).Where(t => t.RowKey == UserAccountEntity.EntityKind).AsTableServiceQuery(); + } + } + + public IQueryable UserClaims + { + get + { + return CreateQuery(UsersTable).Where(t => t.Kind == UserClaimEntity.EntityKind).AsTableServiceQuery(); + } + } + + public IEnumerable GetUsers() + { + var users = (from u in UserAccounts + select u) + .ToList(); + + return (from item in users + select item.PartitionKey) + .ToList(); + } + + public IEnumerable GetUserClaims(string userName) + { + var userClaims = (from u in UserClaims + where u.PartitionKey == userName.ToLowerInvariant() + select new Claim(u.ClaimType, u.Value)) + .ToList(); + + return userClaims; + } + + public void AddUserAccount(string userName, string password, bool isAdministrator) + { + string hash; + string salt; + new PasswordCrypto().HashPassword(password, out hash, out salt); + + var internalRoles = Constants.Roles.IdentityServerUsers; + if (isAdministrator) + { + internalRoles += "," + Constants.Roles.IdentityServerAdministrators; + } + + AddUserAccount(userName, hash, salt, internalRoles); + } + + public void AddUserAccount(string userName, string passwordHash, string salt, string internalRoles) + { + var entity = new UserAccountEntity + { + PartitionKey = userName.ToLowerInvariant(), + RowKey = UserAccountEntity.EntityKind, + Kind = UserAccountEntity.EntityKind, + PasswordHash = passwordHash, + Salt = salt, + InternalRoles = internalRoles + }; + + AddEntity(entity, UsersTable); + } + + public void DeleteUserAccount(string userName) + { + var user = (from u in UserAccounts + where u.PartitionKey == userName.ToLowerInvariant() + select u) + .Single(); + + DeleteObject(user); + SaveChangesWithRetries(); + + DeleteUserClaims(userName); + } + + public void DeleteUserClaims(string userName) + { + var userClaims = from u in UserClaims + where u.PartitionKey == userName.ToLowerInvariant() + select u; + + userClaims.ToList().ForEach(u => DeleteObject(u)); + SaveChangesWithRetries(SaveChangesOptions.Batch); + } + + public void AddUserClaims(string userName, IEnumerable> claimsStrings) + { + var claims = (from c in claimsStrings.ToList() + select new Claim(c.Item1, c.Item2)) + .ToList(); + + AddUserClaims(userName, claims); + } + + public void AddUserClaims(string userName, IEnumerable claims) + { + var userClaims = new List( + from c in claims.ToList() + select new UserClaimEntity + { + PartitionKey = userName.ToLowerInvariant(), + RowKey = Guid.NewGuid().ToString(), + Kind = UserClaimEntity.EntityKind, + ClaimType = c.ClaimType, + Value = c.Value + }); + + userClaims.ForEach(c => AddObject(UsersTable, c)); + SaveChangesWithRetries(SaveChangesOptions.Batch); + } + #endregion + + #region Relying Parties + public IQueryable RelyingParties + { + get + { + return CreateQuery(RelyingPartiesTable).AsTableServiceQuery(); + } + } + + public void AddRelyingParty(RelyingPartyEntity entity) + { + AddEntity(entity, RelyingPartiesTable); + } + + public void DeleteRelyingParty(string partitionKey, string id) + { + var entity = new RelyingPartyEntity + { + PartitionKey = partitionKey, + RowKey = id + }; + + AttachTo(RelyingPartiesTable, entity, "*"); + DeleteObject(entity); + SaveChangesWithRetries(); + } + + public void UpdateRelyingParty(RelyingPartyEntity entity) + { + AttachTo(RelyingPartiesTable, entity, "*"); + UpdateObject(entity); + SaveChangesWithRetries(); + } + #endregion + + #region Client Certificates + public IQueryable ClientCertificates + { + get + { + return CreateQuery(ClientCertificatesTable).AsTableServiceQuery(); + } + } + + public List AllClientCertificates(string partitionKey) + { + var entities = (from e in ClientCertificates + where e.PartitionKey == partitionKey + select e) + .ToList(); + + return entities.ToList(); + } + + + public void AddClientCertificate(ClientCertificateEntity entity) + { + AddEntity(entity, ClientCertificatesTable); + } + + public void DeleteClientCertificate(ClientCertificateEntity entity) + { + AttachTo(ClientCertificatesTable, entity, "*"); + DeleteObject(entity); + SaveChangesWithRetries(); + } + #endregion + + #region Delegation + public IQueryable Delegation + { + get + { + return CreateQuery(DelegationTable).AsTableServiceQuery(); + } + } + + public List AllDelegations(string partitionKey) + { + var entities = (from e in Delegation + where e.PartitionKey == partitionKey + select e) + .ToList(); + + return entities.ToList(); + } + + public List AllDelegations(string partitionKey, string userName) + { + var entities = (from e in Delegation + where e.PartitionKey == partitionKey && + e.UserName.Equals(userName, System.StringComparison.OrdinalIgnoreCase) + select e) + .ToList(); + + return entities.ToList(); + } + + public void AddDelegation(DelegationEntity entity) + { + AddEntity(entity, DelegationTable); + } + + public void DeleteDelegation(string partitionKey, string id) + { + var entity = new DelegationEntity + { + PartitionKey = partitionKey, + RowKey = id + }; + + AttachTo(DelegationTable, entity, "*"); + DeleteObject(entity); + SaveChangesWithRetries(); + } + #endregion + + private void AddEntity(object entity, string table) + { + AddObject(table, entity); + SaveChangesWithRetries(); + } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Users/PasswordCrypto.cs b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Users/PasswordCrypto.cs new file mode 100644 index 0000000..e157c7a --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Users/PasswordCrypto.cs @@ -0,0 +1,32 @@ +using System; +using System.Security.Cryptography; +using Thinktecture.IdentityModel; + +namespace Thinktecture.IdentityServer.Repositories.WindowsAzure +{ + internal class PasswordCrypto + { + internal const int IterationCount = 5000; + internal const int HashSize = 16; + internal const int SaltSize = 16; + + public void HashPassword(string password, out string hash, out string salt) + { + var rfc = new Rfc2898DeriveBytes(password, SaltSize, IterationCount); + hash = Convert.ToBase64String(rfc.GetBytes(HashSize)); + salt = Convert.ToBase64String(rfc.Salt); + } + + public string HashPasswordWithSalt(string password, string salt) + { + var rfc = new Rfc2898DeriveBytes(password, Convert.FromBase64String(salt), IterationCount); + return Convert.ToBase64String(rfc.GetBytes(HashSize)); + } + + public bool ValidatePassword(string password, string hash, string salt) + { + var calculatedHash = HashPasswordWithSalt(password, salt); + return ObfuscatingComparer.IsEqual(hash, calculatedHash); + } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Users/TableStorageUserRepository.cs b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Users/TableStorageUserRepository.cs new file mode 100644 index 0000000..d9495de --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Users/TableStorageUserRepository.cs @@ -0,0 +1,128 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography.X509Certificates; +using Microsoft.IdentityModel.Claims; +using Microsoft.WindowsAzure; +using Microsoft.WindowsAzure.ServiceRuntime; +using Thinktecture.IdentityServer.TokenService; +using System.ComponentModel.Composition; + +namespace Thinktecture.IdentityServer.Repositories.WindowsAzure +{ + public class TableStorageUserRepository : IUserRepository + { + CloudStorageAccount _account; + + [Import] + public IClientCertificatesRepository ClientCertificateRepository { get; set; } + + public TableStorageUserRepository() + : this(TableStorageContext.StorageConnectionString) + { + Container.Current.SatisfyImportsOnce(this); + } + + public TableStorageUserRepository(string storageConnectionString) + { + _account = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue(storageConnectionString)); + } + + public TableStorageUserRepository(string storageConnectionString, IClientCertificatesRepository repository) + : this(storageConnectionString) + { + ClientCertificateRepository = repository; + } + + public bool ValidateUser(string userName, string password) + { + var context = NewContext; + + // check if user exists + var user = (from c in context.UserAccounts + where c.PartitionKey == userName.ToLowerInvariant() && + c.RowKey == UserAccountEntity.EntityKind + select c).FirstOrDefault(); + + if (user == null) + { + Tracing.Error("User not found in Table Storage: " + userName); + return false; + } + + // check password + var result = new PasswordCrypto().ValidatePassword(password, user.PasswordHash, user.Salt); + if (result) + { + Tracing.Information("Successful sign-in: " + userName); + } + else + { + Tracing.Error("Invalid password for: " + userName); + } + + return result; + } + + public bool ValidateUser(X509Certificate2 clientCertificate, out string userName) + { + return ClientCertificateRepository.TryGetUserNameFromThumbprint(clientCertificate, out userName); + } + + public IEnumerable GetRoles(string userName, RoleTypes roleType) + { + if (roleType == RoleTypes.IdentityServer) + { + UserAccountEntity account = null; + if (TryGetUserAccount(userName, out account)) + { + if (!string.IsNullOrWhiteSpace(account.InternalRoles)) + { + var roles = account.InternalRoles.Split(','); + return new List(from r in roles select r); + } + + } + } + + return new string[] { }; + } + + public IEnumerable GetClaims(IClaimsPrincipal principal, RequestDetails requestDetails) + { + var claims = from c in NewContext.UserClaims + where c.PartitionKey == principal.Identity.Name.ToLower() && + c.Kind == UserClaimEntity.EntityKind + select new Claim(c.ClaimType, c.Value); + + return claims.ToList(); + } + + public IEnumerable GetSupportedClaimTypes() + { + return new string[] { ClaimTypes.Name, ClaimTypes.Role, ClaimTypes.Email }; + } + + private bool TryGetUserAccount(string userName, out UserAccountEntity account) + { + var context = NewContext; + + // check if user exists + account = (from c in context.UserAccounts + where c.PartitionKey == userName.ToLowerInvariant() && + c.RowKey == UserAccountEntity.EntityKind + select c).FirstOrDefault(); + + return (account != null); + } + + private TableStorageContext NewContext + { + get + { + var context = new TableStorageContext(_account.TableEndpoint.AbsoluteUri, _account.Credentials); + return context; + } + } + } +} \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Users/UserAccountEntity.cs b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Users/UserAccountEntity.cs new file mode 100644 index 0000000..9dabe44 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Users/UserAccountEntity.cs @@ -0,0 +1,14 @@ +using Microsoft.WindowsAzure.StorageClient; + +namespace Thinktecture.IdentityServer.Repositories.WindowsAzure +{ + public class UserAccountEntity : TableServiceEntity + { + public const string EntityKind = "Account"; + + public string Kind { get; set; } + public string PasswordHash { get; set; } + public string Salt { get; set; } + public string InternalRoles { get; set; } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Users/UserClaimEntity.cs b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Users/UserClaimEntity.cs new file mode 100644 index 0000000..5b763b6 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Repositories/Users/UserClaimEntity.cs @@ -0,0 +1,13 @@ +using Microsoft.WindowsAzure.StorageClient; + +namespace Thinktecture.IdentityServer.Repositories.WindowsAzure +{ + public class UserClaimEntity : TableServiceEntity + { + public const string EntityKind = "Claim"; + + public string Kind { get; set; } + public string ClaimType { get; set; } + public string Value { get; set; } + } +} diff --git a/Libraries/Thinktecture.IdentityServer.WindowsAzure/Thinktecture.IdentityServer.WindowsAzure.csproj b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Thinktecture.IdentityServer.WindowsAzure.csproj new file mode 100644 index 0000000..aeb118a --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.WindowsAzure/Thinktecture.IdentityServer.WindowsAzure.csproj @@ -0,0 +1,91 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {36D5F61F-F4BA-41F8-AA13-1F32DDB970A4} + Library + Properties + Thinktecture.IdentityServer.WindowsAzure + Thinktecture.IdentityServer.WindowsAzure + v4.0 + 512 + ..\ + true + + + true + full + false + ..\build\Azure\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\build\Azure\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + ..\packages\Thinktecture.IdentityModel.1.3.0.0\lib\Thinktecture.IdentityModel.dll + + + + + + + + + + + + + + + + + + + + + + {38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A} + Thinktecture.IdentityServer.Core + + + + + + + + + \ No newline at end of file diff --git a/Libraries/Thinktecture.IdentityServer.WindowsAzure/packages.config b/Libraries/Thinktecture.IdentityServer.WindowsAzure/packages.config new file mode 100644 index 0000000..531e1e1 --- /dev/null +++ b/Libraries/Thinktecture.IdentityServer.WindowsAzure/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/OnPremise/.nuget/NuGet.Config b/OnPremise/.nuget/NuGet.Config new file mode 100644 index 0000000..67f8ea0 --- /dev/null +++ b/OnPremise/.nuget/NuGet.Config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/OnPremise/.nuget/NuGet.exe b/OnPremise/.nuget/NuGet.exe new file mode 100644 index 0000000000000000000000000000000000000000..34ad49b494dd855dabf1b1cee5d3a8d51525d3b9 GIT binary patch literal 558080 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%0A|w=%&@u7j7;}<-)k0>bYB`T-B(A&wRHbW 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

Ekj^+5jehgt4{Op!7wB|J;~=-=l2?c3i{CT#0( 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 z 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 G=zjnx2wiCa literal 0 HcmV?d00001 diff --git a/OnPremise/.nuget/NuGet.targets b/OnPremise/.nuget/NuGet.targets new file mode 100644 index 0000000..25380fe --- /dev/null +++ b/OnPremise/.nuget/NuGet.targets @@ -0,0 +1,52 @@ + + + + $(MSBuildProjectDirectory)\..\ + $([System.IO.Path]::Combine($(SolutionDir), ".nuget")) + $(NuGetToolsPath)\nuget.exe + $([System.IO.Path]::Combine($(ProjectDir), "packages.config")) + $([System.IO.Path]::Combine($(SolutionDir), "packages")) + $(TargetDir.Trim('\\')) + + + "" + + + false + + + false + + + "$(NuGetExePath)" install "$(PackagesConfig)" -source $(PackageSources) -o "$(PackagesDir)" + "$(NuGetExePath)" pack "$(ProjectPath)" -p Configuration=$(Configuration) -o "$(PackageOutputDir)" -symbols + + + + RestorePackages; + $(BuildDependsOn); + + + + + $(BuildDependsOn); + BuildPackage; + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OnPremise/Local.testsettings b/OnPremise/Local.testsettings new file mode 100644 index 0000000..9f4b3af --- /dev/null +++ b/OnPremise/Local.testsettings @@ -0,0 +1,10 @@ + + + These are default test settings for a local test run. + + + + + + + \ No newline at end of file diff --git a/OnPremise/Thinktecture.IdentityServer.sln b/OnPremise/Thinktecture.IdentityServer.sln new file mode 100644 index 0000000..9992979 --- /dev/null +++ b/OnPremise/Thinktecture.IdentityServer.sln @@ -0,0 +1,98 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebSite", "WebSite\WebSite.csproj", "{B9C90A36-86C0-4974-B0B4-3524F508D847}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Thinktecture.IdentityServer.Core", "..\Libraries\Thinktecture.IdentityServer.Core\Thinktecture.IdentityServer.Core.csproj", "{38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{052789EB-BFB0-48B7-A5D2-F890FF3608CA}" + ProjectSection(SolutionItems) = preProject + Local.testsettings = Local.testsettings + Thinktecture.IdentityServer.vsmdi = Thinktecture.IdentityServer.vsmdi + TraceAndTestImpact.testsettings = TraceAndTestImpact.testsettings + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Thinktecture.IdentityServer.Core.Repositories", "..\Libraries\Thinktecture.IdentityServer.Core.Repositories\Thinktecture.IdentityServer.Core.Repositories.csproj", "{9658F86F-3059-4731-9EB0-5F67A4FF1A8A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Thinktecture.IdentityServer.Web.Library", "..\Libraries\Thinktecture.IdentityServer.Web.Library\Thinktecture.IdentityServer.Web.Library.csproj", "{FC2D7E2A-65A2-480F-AAE8-855FD026AF85}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libaries", "Libaries", "{2C19FF9A-AD66-4483-A787-05F22BB8B5EA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "..\Tests\Tests.csproj", "{7392F6F9-9723-4E1F-A0C4-7F6340E5CAAF}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{37144EFB-AB32-4CCA-B6B4-F0494D00681B}" +EndProject +Global + GlobalSection(TestCaseManagementSettings) = postSolution + CategoryFile = Thinktecture.IdentityServer.vsmdi + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|Mixed Platforms = Release|Mixed Platforms + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B9C90A36-86C0-4974-B0B4-3524F508D847}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B9C90A36-86C0-4974-B0B4-3524F508D847}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B9C90A36-86C0-4974-B0B4-3524F508D847}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {B9C90A36-86C0-4974-B0B4-3524F508D847}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {B9C90A36-86C0-4974-B0B4-3524F508D847}.Debug|x86.ActiveCfg = Debug|Any CPU + {B9C90A36-86C0-4974-B0B4-3524F508D847}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B9C90A36-86C0-4974-B0B4-3524F508D847}.Release|Any CPU.Build.0 = Release|Any CPU + {B9C90A36-86C0-4974-B0B4-3524F508D847}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {B9C90A36-86C0-4974-B0B4-3524F508D847}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {B9C90A36-86C0-4974-B0B4-3524F508D847}.Release|x86.ActiveCfg = Release|Any CPU + {38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A}.Debug|x86.ActiveCfg = Debug|Any CPU + {38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A}.Release|Any CPU.Build.0 = Release|Any CPU + {38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A}.Release|x86.ActiveCfg = Release|Any CPU + {9658F86F-3059-4731-9EB0-5F67A4FF1A8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9658F86F-3059-4731-9EB0-5F67A4FF1A8A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9658F86F-3059-4731-9EB0-5F67A4FF1A8A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {9658F86F-3059-4731-9EB0-5F67A4FF1A8A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {9658F86F-3059-4731-9EB0-5F67A4FF1A8A}.Debug|x86.ActiveCfg = Debug|Any CPU + {9658F86F-3059-4731-9EB0-5F67A4FF1A8A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9658F86F-3059-4731-9EB0-5F67A4FF1A8A}.Release|Any CPU.Build.0 = Release|Any CPU + {9658F86F-3059-4731-9EB0-5F67A4FF1A8A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {9658F86F-3059-4731-9EB0-5F67A4FF1A8A}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {9658F86F-3059-4731-9EB0-5F67A4FF1A8A}.Release|x86.ActiveCfg = Release|Any CPU + {FC2D7E2A-65A2-480F-AAE8-855FD026AF85}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FC2D7E2A-65A2-480F-AAE8-855FD026AF85}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FC2D7E2A-65A2-480F-AAE8-855FD026AF85}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {FC2D7E2A-65A2-480F-AAE8-855FD026AF85}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {FC2D7E2A-65A2-480F-AAE8-855FD026AF85}.Debug|x86.ActiveCfg = Debug|Any CPU + {FC2D7E2A-65A2-480F-AAE8-855FD026AF85}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FC2D7E2A-65A2-480F-AAE8-855FD026AF85}.Release|Any CPU.Build.0 = Release|Any CPU + {FC2D7E2A-65A2-480F-AAE8-855FD026AF85}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {FC2D7E2A-65A2-480F-AAE8-855FD026AF85}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {FC2D7E2A-65A2-480F-AAE8-855FD026AF85}.Release|x86.ActiveCfg = Release|Any CPU + {7392F6F9-9723-4E1F-A0C4-7F6340E5CAAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7392F6F9-9723-4E1F-A0C4-7F6340E5CAAF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7392F6F9-9723-4E1F-A0C4-7F6340E5CAAF}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {7392F6F9-9723-4E1F-A0C4-7F6340E5CAAF}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {7392F6F9-9723-4E1F-A0C4-7F6340E5CAAF}.Debug|x86.ActiveCfg = Debug|Any CPU + {7392F6F9-9723-4E1F-A0C4-7F6340E5CAAF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7392F6F9-9723-4E1F-A0C4-7F6340E5CAAF}.Release|Any CPU.Build.0 = Release|Any CPU + {7392F6F9-9723-4E1F-A0C4-7F6340E5CAAF}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {7392F6F9-9723-4E1F-A0C4-7F6340E5CAAF}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {7392F6F9-9723-4E1F-A0C4-7F6340E5CAAF}.Release|x86.ActiveCfg = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {9658F86F-3059-4731-9EB0-5F67A4FF1A8A} = {2C19FF9A-AD66-4483-A787-05F22BB8B5EA} + {FC2D7E2A-65A2-480F-AAE8-855FD026AF85} = {2C19FF9A-AD66-4483-A787-05F22BB8B5EA} + {38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A} = {2C19FF9A-AD66-4483-A787-05F22BB8B5EA} + {7392F6F9-9723-4E1F-A0C4-7F6340E5CAAF} = {37144EFB-AB32-4CCA-B6B4-F0494D00681B} + EndGlobalSection +EndGlobal diff --git a/OnPremise/Thinktecture.IdentityServer.vsmdi b/OnPremise/Thinktecture.IdentityServer.vsmdi new file mode 100644 index 0000000..2985023 --- /dev/null +++ b/OnPremise/Thinktecture.IdentityServer.vsmdi @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/OnPremise/TraceAndTestImpact.testsettings b/OnPremise/TraceAndTestImpact.testsettings new file mode 100644 index 0000000..c3d0e15 --- /dev/null +++ b/OnPremise/TraceAndTestImpact.testsettings @@ -0,0 +1,21 @@ + + + These are test settings for Trace and Test Impact. + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OnPremise/WebSite/App_Data/IdentityServerConfiguration.sdf b/OnPremise/WebSite/App_Data/IdentityServerConfiguration.sdf new file mode 100644 index 0000000000000000000000000000000000000000..2fedd8bb1cb355cb888fd257f7a8d45a7669dc64 GIT binary patch literal 172032 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 T5 + + + \ No newline at end of file diff --git a/OnPremise/WebSite/Configuration/profile.config b/OnPremise/WebSite/Configuration/profile.config new file mode 100644 index 0000000..8dab4a5 --- /dev/null +++ b/OnPremise/WebSite/Configuration/profile.config @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OnPremise/WebSite/Configuration/repositories.config b/OnPremise/WebSite/Configuration/repositories.config new file mode 100644 index 0000000..5725a34 --- /dev/null +++ b/OnPremise/WebSite/Configuration/repositories.config @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/OnPremise/WebSite/Configuration/tracing.azure.config b/OnPremise/WebSite/Configuration/tracing.azure.config new file mode 100644 index 0000000..dd5507a --- /dev/null +++ b/OnPremise/WebSite/Configuration/tracing.azure.config @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OnPremise/WebSite/Configuration/tracing.config b/OnPremise/WebSite/Configuration/tracing.config new file mode 100644 index 0000000..32d68ee --- /dev/null +++ b/OnPremise/WebSite/Configuration/tracing.config @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OnPremise/WebSite/Configuration/wif.config b/OnPremise/WebSite/Configuration/wif.config new file mode 100644 index 0000000..f2d65cd --- /dev/null +++ b/OnPremise/WebSite/Configuration/wif.config @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OnPremise/WebSite/Content/Site.css b/OnPremise/WebSite/Content/Site.css new file mode 100644 index 0000000..ce5197f --- /dev/null +++ b/OnPremise/WebSite/Content/Site.css @@ -0,0 +1,175 @@ +body +{ + font-family: Calibri, Verdana, Tahoma, Arial, "Helvetica Neue", Helvetica, Sans-Serif; + color: #232323; + background-color: #fff; +} + +/* Styles for basic forms +-----------------------------------------------------------*/ + +fieldset +{ + border:1px solid #ddd; + padding:0 1.4em 1.4em 1.4em; + margin:0 0 1.5em 0; +} + +legend +{ + font-size:1.2em; + font-weight: bold; +} + +textarea +{ + min-height: 75px; +} + +.editor-label +{ + margin: 1em 0 0 0; +} + +.editor-field +{ + margin:0.5em 0 0 0; +} + +.editor-field-slim +{ + margin:0.5em 0 0 0; +} + +.editor-field input[type=text] +{ + width:400px +} + +.editor-field input[type=file] +{ + width:400px +} + +/* 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 the web frontent +-----------------------------------------------------------*/ + + +a:link +{ + color: Black; + text-decoration: none; +} + +a:visited +{ + color: Black; + text-decoration: none; +} +a:hover +{ + color: Black; + text-decoration: overline underline; +} +a:active +{ + color: Black; + text-decoration: none; +} + +.masterHeader +{ + background-color: #606060; + padding-top: 5px; + padding-bottom: 5px; +} + +.masterHeaderText +{ + padding-left: 15px; + font-weight: bold; + color: White; +} + +.menu +{ + background-color: #7285a3; + padding-top: 5px; + padding-bottom: 5px; + color: #000000; + padding-left: 15px; +} + +.menu a:link +{ + color: #FFFFFF; + text-decoration: none; +} + +.menu a:visited +{ + color: #FFFFFF; + text-decoration: none; +} +.menu a:hover +{ + color: #FFFFFF; + text-decoration: overline underline; +} +.menu a:active +{ + color: #FFFFFF; + text-decoration: none; +} + +a.bodyLink:link +{ + color: #7285a3; + text-decoration: none; +} +a.bodyLink:visited +{ + color: #7285a3; + text-decoration: none; +} + +a.bodyLink:hover +{ + color: #7285a3; + text-decoration: overline underline; +} +a.bodyLink:active +{ + color: #7285a3; + text-decoration: none; +} + diff --git a/OnPremise/WebSite/Content/images/logo.jpg b/OnPremise/WebSite/Content/images/logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7ea7b8b5db728e0488513f1b00d79428c72e15e4 GIT binary patch literal 4766 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 bKWmfUD(bFmXg1D%J*s>ni@Uo&M4$c-Sr;Ki literal 0 HcmV?d00001 diff --git a/OnPremise/WebSite/Content/resources/jsnotify.htm b/OnPremise/WebSite/Content/resources/jsnotify.htm new file mode 100644 index 0000000..59fa3d5 --- /dev/null +++ b/OnPremise/WebSite/Content/resources/jsnotify.htm @@ -0,0 +1,17 @@ + + + + + Loading... + + + + + \ No newline at end of file diff --git a/OnPremise/WebSite/Content/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png b/OnPremise/WebSite/Content/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..5b5dab2ab7b1c50dea9cfe73dc5a269a92d2d4b4 GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FscKIb$B>N1x91EQ4=4yQ7#`R^ z$vje}bP0l+XkK DSH>_4 literal 0 HcmV?d00001 diff --git a/OnPremise/WebSite/Content/themes/base/images/ui-bg_flat_75_ffffff_40x100.png b/OnPremise/WebSite/Content/themes/base/images/ui-bg_flat_75_ffffff_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..ac8b229af950c29356abf64a6c4aa894575445f0 GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FsY*{5$B>N1x91EQ4=4yQYz+E8 zPo9&<{J;c_6SHRil>2s{Zw^OT)6@jj2u|u!(plXsM>LJD`vD!n;OXk;vd$@?2>^GI BH@yG= literal 0 HcmV?d00001 diff --git a/OnPremise/WebSite/Content/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png b/OnPremise/WebSite/Content/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..ad3d6346e00f246102f72f2e026ed0491988b394 GIT binary patch literal 120 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnour0hLi978O6-<~(*I$*%ybaDOn z{W;e!B}_MSUQoPXhYd^Y6RUoS1yepnPx`2Kz)7OXQG!!=-jY=F+d2OOy?#DnJ32>z UEim$g7SJdLPgg&ebxsLQ09~*s;{X5v literal 0 HcmV?d00001 diff --git a/OnPremise/WebSite/Content/themes/base/images/ui-bg_glass_65_ffffff_1x400.png b/OnPremise/WebSite/Content/themes/base/images/ui-bg_glass_65_ffffff_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..42ccba269b6e91bef12ad0fa18be651b5ef0ee68 GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouqzpV=978O6-=0?FV^9z|eBtf= z|7WztIJ;WT>{+tN>ySr~=F{k$>;_x^_y?afmf9pRKH0)6?eSP?3s5hEr>mdKI;Vst E0O;M1& literal 0 HcmV?d00001 diff --git a/OnPremise/WebSite/Content/themes/base/images/ui-bg_glass_75_dadada_1x400.png b/OnPremise/WebSite/Content/themes/base/images/ui-bg_glass_75_dadada_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..5a46b47cb16631068aee9e0bd61269fc4e95e5cd GIT binary patch literal 111 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouq|7{B978O6lPf+wIa#m9#>Unb zm^4K~wN3Zq+uP{vDV26o)#~38k_!`W=^oo1w6ixmPC4R1b Tyd6G3lNdZ*{an^LB{Ts5`idse literal 0 HcmV?d00001 diff --git a/OnPremise/WebSite/Content/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/OnPremise/WebSite/Content/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png new file mode 100644 index 0000000000000000000000000000000000000000..7c9fa6c6edcfcdd3e5b77e6f547b719e6fc66e30 GIT binary patch literal 101 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 literal 0 HcmV?d00001 diff --git a/OnPremise/WebSite/Content/themes/base/images/ui-icons_2e83ff_256x240.png b/OnPremise/WebSite/Content/themes/base/images/ui-icons_2e83ff_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..45e8928e5284adacea3f9ec07b9b50667d2ac65f GIT binary patch literal 4369 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 literal 0 HcmV?d00001 diff --git a/OnPremise/WebSite/Content/themes/base/images/ui-icons_454545_256x240.png b/OnPremise/WebSite/Content/themes/base/images/ui-icons_454545_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..7ec70d11bfb2f77374dfd00ef61ba0c3647b5a0c GIT binary patch literal 4369 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 k*Kv;w;*%(i9W@fAqs5i2wiq literal 0 HcmV?d00001 diff --git a/OnPremise/WebSite/Content/themes/base/images/ui-icons_888888_256x240.png b/OnPremise/WebSite/Content/themes/base/images/ui-icons_888888_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..5ba708c39172a69e069136bd1309c4322c61f571 GIT binary patch literal 4369 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 literal 0 HcmV?d00001 diff --git a/OnPremise/WebSite/Content/themes/base/jquery-ui.css b/OnPremise/WebSite/Content/themes/base/jquery-ui.css new file mode 100644 index 0000000..30f0ed1 --- /dev/null +++ b/OnPremise/WebSite/Content/themes/base/jquery-ui.css @@ -0,0 +1,635 @@ +/* + * 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 UI CSS Framework 1.8.7 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * + * http://docs.jquery.com/UI/Theming/API + */ + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { display: none; } +.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); } +.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } +.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } +.ui-helper-clearfix { display: inline-block; } +/* required comment for clearfix to work in Opera \*/ +* html .ui-helper-clearfix { height:1%; } +.ui-helper-clearfix { display:block; } +/* end clearfix */ +.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { cursor: default !important; } + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } + + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } +/* + * 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 UI Accordion 1.8.7 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * + * http://docs.jquery.com/UI/Accordion#theming + */ +/* IE/Win - Fix animation bug - #4615 */ +.ui-accordion { width: 100%; } +.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; } +.ui-accordion .ui-accordion-li-fix { display: inline; } +.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; } +.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; } +.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; } +.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } +.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; } +.ui-accordion .ui-accordion-content-active { display: block; }/* + * 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 UI Autocomplete 1.8.7 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * + * http://docs.jquery.com/UI/Autocomplete#theming + */ +.ui-autocomplete { position: absolute; cursor: default; } + +/* workarounds */ +* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */ + +/* + * 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 UI Menu 1.8.7 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * + * http://docs.jquery.com/UI/Menu#theming + */ +.ui-menu { + list-style:none; + padding: 2px; + margin: 0; + display:block; + float: left; +} +.ui-menu .ui-menu { + margin-top: -3px; +} +.ui-menu .ui-menu-item { + margin:0; + padding: 0; + zoom: 1; + float: left; + clear: left; + width: 100%; +} +.ui-menu .ui-menu-item a { + text-decoration:none; + display:block; + padding:.2em .4em; + line-height:1.5; + zoom:1; +} +.ui-menu .ui-menu-item a.ui-state-hover, +.ui-menu .ui-menu-item a.ui-state-active { + font-weight: normal; + margin: -1px; +} +/* + * 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 UI Button 1.8.7 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * + * http://docs.jquery.com/UI/Button#theming + */ +.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */ +.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */ +button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */ +.ui-button-icons-only { width: 3.4em; } +button.ui-button-icons-only { width: 3.7em; } + +/*button text element */ +.ui-button .ui-button-text { display: block; line-height: 1.4; } +.ui-button-text-only .ui-button-text { padding: .4em 1em; } +.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; } +.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; } +.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; } +.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; } +/* no icon support for input elements, provide padding by default */ +input.ui-button { padding: .4em 1em; } + +/*button icon element(s) */ +.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; } +.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; } +.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; } +.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } +.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } + +/*button sets*/ +.ui-buttonset { margin-right: 7px; } +.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; } + +/* workarounds */ +button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */ +/* + * 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 UI Datepicker 1.8.7 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * + * http://docs.jquery.com/UI/Datepicker#theming + */ +.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; } +.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } +.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } +.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } +.ui-datepicker .ui-datepicker-prev { left:2px; } +.ui-datepicker .ui-datepicker-next { right:2px; } +.ui-datepicker .ui-datepicker-prev-hover { left:1px; } +.ui-datepicker .ui-datepicker-next-hover { right:1px; } +.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } +.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } +.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; } +.ui-datepicker select.ui-datepicker-month-year {width: 100%;} +.ui-datepicker select.ui-datepicker-month, +.ui-datepicker select.ui-datepicker-year { width: 49%;} +.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } +.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } +.ui-datepicker td { border: 0; padding: 1px; } +.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } +.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } +.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } + +/* with multiple calendars */ +.ui-datepicker.ui-datepicker-multi { width:auto; } +.ui-datepicker-multi .ui-datepicker-group { float:left; } +.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } +.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } +.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } +.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } +.ui-datepicker-row-break { clear:both; width:100%; } + +/* RTL support */ +.ui-datepicker-rtl { direction: rtl; } +.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } +.ui-datepicker-rtl .ui-datepicker-group { float:right; } +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } + +/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ +.ui-datepicker-cover { + display: none; /*sorry for IE5*/ + display/**/: block; /*sorry for IE5*/ + position: absolute; /*must have*/ + z-index: -1; /*must have*/ + filter: mask(); /*must have*/ + top: -4px; /*must have*/ + left: -4px; /*must have*/ + width: 200px; /*must have*/ + height: 200px; /*must have*/ +}/* + * 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 UI Dialog 1.8.7 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * + * http://docs.jquery.com/UI/Dialog#theming + */ +.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; } +.ui-dialog .ui-dialog-titlebar { padding: .5em 1em .3em; position: relative; } +.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .2em 0; } +.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } +.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } +.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } +.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } +.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } +.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; } +.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; } +.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } +.ui-draggable .ui-dialog-titlebar { cursor: move; } +/* + * 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 UI Progressbar 1.8.7 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * + * http://docs.jquery.com/UI/Progressbar#theming + */ +.ui-progressbar { height:2em; text-align: left; } +.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }/* + * 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 UI Resizable 1.8.7 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * + * http://docs.jquery.com/UI/Resizable#theming + */ +.ui-resizable { position: relative;} +.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;} +.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } +.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; } +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; } +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; } +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; } +.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } +.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } +.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } +.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* + * 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 UI Selectable 1.8.7 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * + * http://docs.jquery.com/UI/Selectable#theming + */ +.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; } +/* + * 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 UI Slider 1.8.7 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * + * http://docs.jquery.com/UI/Slider#theming + */ +.ui-slider { position: relative; text-align: left; } +.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } +.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; } + +.ui-slider-horizontal { height: .8em; } +.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } +.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } +.ui-slider-horizontal .ui-slider-range-min { left: 0; } +.ui-slider-horizontal .ui-slider-range-max { right: 0; } + +.ui-slider-vertical { width: .8em; height: 100px; } +.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } +.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } +.ui-slider-vertical .ui-slider-range-min { bottom: 0; } +.ui-slider-vertical .ui-slider-range-max { top: 0; }/* + * 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 UI Tabs 1.8.7 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * + * http://docs.jquery.com/UI/Tabs#theming + */ +.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ +.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; } +.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; } +.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; } +.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ +.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; } +.ui-tabs .ui-tabs-hide { display: none !important; } +/* + * 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 UI CSS Framework 1.8.7 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * + * http://docs.jquery.com/UI/Theming/API + * + * To view and modify this theme, visit http://jqueryui.com/themeroller/ + */ + + +/* Component containers +----------------------------------*/ +.ui-widget { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1.1em/*{fsDefault}*/; } +.ui-widget .ui-widget { font-size: 1em; } +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1em; } +.ui-widget-content { border: 1px solid #aaaaaa/*{borderColorContent}*/; background: #ffffff/*{bgColorContent}*/ url(images/ui-bg_flat_75_ffffff_40x100.png)/*{bgImgUrlContent}*/ 50%/*{bgContentXPos}*/ 50%/*{bgContentYPos}*/ repeat-x/*{bgContentRepeat}*/; color: #222222/*{fcContent}*/; } +.ui-widget-content a { color: #222222/*{fcContent}*/; } +.ui-widget-header { border: 1px solid #aaaaaa/*{borderColorHeader}*/; background: #cccccc/*{bgColorHeader}*/ url(images/ui-bg_highlight-soft_75_cccccc_1x100.png)/*{bgImgUrlHeader}*/ 50%/*{bgHeaderXPos}*/ 50%/*{bgHeaderYPos}*/ repeat-x/*{bgHeaderRepeat}*/; color: #222222/*{fcHeader}*/; font-weight: bold; } +.ui-widget-header a { color: #222222/*{fcHeader}*/; } + +/* Interaction states +----------------------------------*/ +.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3/*{borderColorDefault}*/; background: #e6e6e6/*{bgColorDefault}*/ url(images/ui-bg_glass_75_e6e6e6_1x400.png)/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #555555/*{fcDefault}*/; } +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555/*{fcDefault}*/; text-decoration: none; } +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999/*{borderColorHover}*/; background: #dadada/*{bgColorHover}*/ url(images/ui-bg_glass_75_dadada_1x400.png)/*{bgImgUrlHover}*/ 50%/*{bgHoverXPos}*/ 50%/*{bgHoverYPos}*/ repeat-x/*{bgHoverRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcHover}*/; } +.ui-state-hover a, .ui-state-hover a:hover { color: #212121/*{fcHover}*/; text-decoration: none; } +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa/*{borderColorActive}*/; background: #ffffff/*{bgColorActive}*/ url(images/ui-bg_glass_65_ffffff_1x400.png)/*{bgImgUrlActive}*/ 50%/*{bgActiveXPos}*/ 50%/*{bgActiveYPos}*/ repeat-x/*{bgActiveRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcActive}*/; } +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121/*{fcActive}*/; text-decoration: none; } +.ui-widget :active { outline: none; } + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1/*{borderColorHighlight}*/; background: #fbf9ee/*{bgColorHighlight}*/ url(images/ui-bg_glass_55_fbf9ee_1x400.png)/*{bgImgUrlHighlight}*/ 50%/*{bgHighlightXPos}*/ 50%/*{bgHighlightYPos}*/ repeat-x/*{bgHighlightRepeat}*/; color: #363636/*{fcHighlight}*/; } +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636/*{fcHighlight}*/; } +.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a/*{borderColorError}*/; background: #fef1ec/*{bgColorError}*/ url(images/ui-bg_glass_95_fef1ec_1x400.png)/*{bgImgUrlError}*/ 50%/*{bgErrorXPos}*/ 50%/*{bgErrorYPos}*/ repeat-x/*{bgErrorRepeat}*/; color: #cd0a0a/*{fcError}*/; } +.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a/*{fcError}*/; } +.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a/*{fcError}*/; } +.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } +.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; } +.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; } +.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsHeader}*/; } +.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png)/*{iconsDefault}*/; } +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsHover}*/; } +.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsActive}*/; } +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png)/*{iconsHighlight}*/; } +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png)/*{iconsError}*/; } + +/* positioning */ +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-off { background-position: -96px -144px; } +.ui-icon-radio-on { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-start { background-position: -80px -160px; } +/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + + +/* Misc visuals +----------------------------------*/ + +/* Corner radius */ +.ui-corner-tl { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; } +.ui-corner-tr { -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; } +.ui-corner-bl { -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; } +.ui-corner-br { -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; } +.ui-corner-top { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; } +.ui-corner-bottom { -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; } +.ui-corner-right { -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; } +.ui-corner-left { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; } +.ui-corner-all { -moz-border-radius: 4px/*{cornerRadius}*/; -webkit-border-radius: 4px/*{cornerRadius}*/; border-radius: 4px/*{cornerRadius}*/; } + +/* Overlays */ +.ui-widget-overlay { background: #aaaaaa/*{bgColorOverlay}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlOverlay}*/ 50%/*{bgOverlayXPos}*/ 50%/*{bgOverlayYPos}*/ repeat-x/*{bgOverlayRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityOverlay}*/; } +.ui-widget-shadow { margin: -8px/*{offsetTopShadow}*/ 0 0 -8px/*{offsetLeftShadow}*/; padding: 8px/*{thicknessShadow}*/; background: #aaaaaa/*{bgColorShadow}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlShadow}*/ 50%/*{bgShadowXPos}*/ 50%/*{bgShadowYPos}*/ repeat-x/*{bgShadowRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityShadow}*/; -moz-border-radius: 8px/*{cornerRadiusShadow}*/; -webkit-border-radius: 8px/*{cornerRadiusShadow}*/; border-radius: 8px/*{cornerRadiusShadow}*/; } \ No newline at end of file diff --git a/OnPremise/WebSite/Controllers/AccountController.cs b/OnPremise/WebSite/Controllers/AccountController.cs new file mode 100644 index 0000000..2301fe1 --- /dev/null +++ b/OnPremise/WebSite/Controllers/AccountController.cs @@ -0,0 +1,116 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.ComponentModel.Composition; +using System.Security.Cryptography.X509Certificates; +using System.Web; +using System.Web.Mvc; +using Microsoft.IdentityModel.Claims; +using Microsoft.IdentityModel.Web; +using Thinktecture.IdentityServer.Repositories; +using Thinktecture.IdentityServer.TokenService; +using Thinktecture.IdentityServer.Web.Security; +using Thinktecture.IdentityServer.Web.ViewModels; + +namespace Thinktecture.IdentityServer.Web.Controllers +{ + public class AccountController : Controller + { + [Import] + public IUserRepository UserRepository { get; set; } + + [Import] + public IConfigurationRepository ConfigurationRepository { get; set; } + + public AccountController() + { + Container.Current.SatisfyImportsOnce(this); + } + + public AccountController(IUserRepository userRepository, IConfigurationRepository configurationRepository) + { + UserRepository = userRepository; + ConfigurationRepository = configurationRepository; + } + + public ActionResult SignIn(string returnUrl) + { + ViewBag.ReturnUrl = returnUrl; + ViewBag.ShowClientCertificateLink = ConfigurationRepository.Configuration.EnableClientCertificates; + + return View(); + } + + [HttpPost] + public ActionResult SignIn(SignInModel model, string returnUrl) + { + if (ModelState.IsValid) + { + if (UserRepository.ValidateUser(model.UserName, model.Password)) + { + return SetPrincipalAndRedirect(model.UserName, AuthenticationMethods.Password, returnUrl, model.EnableSSO, ConfigurationRepository.Configuration.SsoCookieLifetime); + } + } + + ModelState.AddModelError("", "Incorrect credentials or no authorization."); + + ViewBag.ShowClientCertificateLink = ConfigurationRepository.Configuration.EnableClientCertificates; + return View(model); + } + + public ActionResult CertificateSignIn(string returnUrl) + { + if (!ConfigurationRepository.Configuration.EnableClientCertificates) + { + return new HttpNotFoundResult(); + } + + var clientCert = HttpContext.Request.ClientCertificate; + + if (clientCert != null && clientCert.IsPresent && clientCert.IsValid) + { + string userName; + if (UserRepository.ValidateUser(new X509Certificate2(clientCert.Certificate), out userName)) + { + return SetPrincipalAndRedirect(userName, AuthenticationMethods.X509, returnUrl, false, ConfigurationRepository.Configuration.SsoCookieLifetime); + } + } + + return View(); + } + + public ActionResult SignOut() + { + if (Request.IsAuthenticated) + { + FederatedAuthentication.SessionAuthenticationModule.DeleteSessionTokenCookie(); + } + + return RedirectToAction("Index", "Home"); + } + + #region Private + private ActionResult SetPrincipalAndRedirect(string userName, string authenticationMethod, string returnUrl, bool isPersistent, int ttl) + { + new AuthenticationHelper().SetSessionToken(userName, authenticationMethod, isPersistent, ttl, HttpContext.Request.Url.AbsoluteUri); + + if (!string.IsNullOrWhiteSpace(returnUrl)) + { + returnUrl = HttpUtility.UrlDecode(returnUrl); + if (Url.IsLocalUrl(returnUrl)) + { + return Redirect(returnUrl); + } + } + + return RedirectToAction("Index", "Home"); + } + #endregion + } +} \ No newline at end of file diff --git a/OnPremise/WebSite/Controllers/Admin/AdminController.cs b/OnPremise/WebSite/Controllers/Admin/AdminController.cs new file mode 100644 index 0000000..3243f6f --- /dev/null +++ b/OnPremise/WebSite/Controllers/Admin/AdminController.cs @@ -0,0 +1,217 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.IO; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Web; +using System.Web.Mvc; +using System.Xml; +using Microsoft.IdentityModel.Claims; +using Microsoft.IdentityModel.Protocols.WSTrust; +using Microsoft.IdentityModel.SecurityTokenService; +using Microsoft.IdentityModel.Tokens; +using Thinktecture.IdentityServer.Repositories; +using Thinktecture.IdentityServer.Web.Security; +using Thinktecture.IdentityServer.Web.ViewModels.Administration; + +namespace Thinktecture.IdentityServer.Web.Controllers +{ + [ClaimsAuthorize(Constants.Actions.Administration, Constants.Resources.Configuration)] + public class AdminController : Controller + { + [Import] + public IUserRepository UserRepository { get; set; } + + [Import] + public IConfigurationRepository ConfigurationRepository { get; set; } + + public AdminController() + { + Container.Current.SatisfyImportsOnce(this); + } + + public AdminController(IUserRepository userRepository, IConfigurationRepository configurationRepository) + { + UserRepository = userRepository; + ConfigurationRepository = configurationRepository; + } + + public ActionResult Index() + { + return View(); + } + + public ActionResult MyClaims() + { + var myModel = new MyModel + { + Claims = GetClaims() + }; + + return View(myModel); + } + + public ActionResult MyToken() + { + var config = ConfigurationRepository.Configuration; + var samlHandler = SecurityTokenHandlerCollection.CreateDefaultSecurityTokenHandlerCollection()[config.DefaultTokenType]; + + var descriptor = new SecurityTokenDescriptor + { + AppliesToAddress = "http://self", + Lifetime = new Lifetime(DateTime.UtcNow, DateTime.UtcNow.AddHours(config.DefaultTokenLifetime)), + SigningCredentials = new X509SigningCredentials(ConfigurationRepository.SigningCertificate.Certificate), + TokenIssuerName = config.IssuerUri, + Subject = new ClaimsIdentity(GetClaims()) + }; + + var token = samlHandler.CreateToken(descriptor); + + var sb = new StringBuilder(1024); + samlHandler.WriteToken(XmlWriter.Create(new StringWriter(sb)), token); + + return new ContentResult + { + ContentType = "text/xml", + Content = sb.ToString() + }; + } + + public ActionResult Configuration() + { + ViewBag.SaveEnabled = ConfigurationRepository.SupportsWriteAccess; + return View(ConfigurationRepository.Configuration.ToViewModel()); + } + + [HttpPost] + [ValidateAntiForgeryToken] + public ActionResult Configuration(GlobalConfigurationModel configuration) + { + if (ModelState.IsValid) + { + if (ConfigurationRepository.SupportsWriteAccess) + { + ConfigurationRepository.UpdateConfiguration(configuration.ToDomainModel()); + } + + return RedirectToAction("Index"); + } + + return View(); + } + + public ActionResult Endpoints() + { + ViewBag.SaveEnabled = ConfigurationRepository.SupportsWriteAccess; + return View(ConfigurationRepository.Endpoints.ToViewModel()); + } + + [HttpPost] + [ValidateAntiForgeryToken] + public ActionResult Endpoints(EndpointConfigurationModel endpoints) + { + if (ModelState.IsValid) + { + if (ConfigurationRepository.SupportsWriteAccess) + { + ConfigurationRepository.UpdateEndpoints(endpoints.ToDomainModel()); + } + + return RedirectToAction("Index"); + } + + return View(); + } + + [ClaimsAuthorize(Constants.Actions.Administration, Constants.Resources.ServiceCertificates)] + public ActionResult Certificates() + { + var model = new EditCertificatesModel + { + AvailableCertificates = GetAvailableCertificatesFromStore(), + + SigningCertificate = ConfigurationRepository.SigningCertificate.SubjectDistinguishedName, + SslCertificate = ConfigurationRepository.SslCertificate.SubjectDistinguishedName + }; + + ViewBag.SaveEnabled = ConfigurationRepository.SupportsWriteAccess; + return View(model); + } + + [HttpPost] + [ValidateAntiForgeryToken] + [ClaimsAuthorize(Constants.Actions.Administration, Constants.Resources.ServiceCertificates)] + public ActionResult Certificates(EditCertificatesModel model) + { + string newSsl = null, newSigning = null; + + if (model.UpdateSslCertificate) + { + newSsl = model.UpdatedSslCertificate; + } + if (model.UpdateSigningCertificate) + { + newSigning = model.UpdatedSigningCertificate; + } + + if (ConfigurationRepository.SupportsWriteAccess) + { + ConfigurationRepository.UpdateCertificates(newSsl, newSigning); + } + + return RedirectToAction("Index"); + } + + public ActionResult Restart() + { + return View("Confirm"); + } + + [HttpPost] + [ValidateAntiForgeryToken] + public ActionResult Restart(FormCollection collection) + { + HttpRuntime.UnloadAppDomain(); + + return RedirectToAction("Index"); + } + + #region Helper + private List GetClaims() + { + return TokenService.TokenService.GetOutputClaims(HttpContext.User as IClaimsPrincipal, null, UserRepository); + } + + private List GetAvailableCertificatesFromStore() + { + var list = new List(); + var store = new X509Store(StoreName.My, StoreLocation.LocalMachine); + store.Open(OpenFlags.ReadOnly); + + try + { + foreach (var cert in store.Certificates) + { + list.Add(cert.Subject); + } + } + finally + { + store.Close(); + } + + return list; + } + #endregion + } +} diff --git a/OnPremise/WebSite/Controllers/Admin/ClientCertificatesAdminController.cs b/OnPremise/WebSite/Controllers/Admin/ClientCertificatesAdminController.cs new file mode 100644 index 0000000..4511c45 --- /dev/null +++ b/OnPremise/WebSite/Controllers/Admin/ClientCertificatesAdminController.cs @@ -0,0 +1,158 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.ComponentModel.Composition; +using System.Linq; +using System.Security.Cryptography.X509Certificates; +using System.Web.Mvc; +using Thinktecture.IdentityServer.Models; +using Thinktecture.IdentityServer.Repositories; +using Thinktecture.IdentityServer.Web.Security; +using Thinktecture.IdentityServer.Web.ViewModels.Administration; + +namespace Thinktecture.IdentityServer.Web.Controllers +{ + [ClaimsAuthorize(Constants.Actions.Administration, Constants.Resources.ClientCertificates)] + public class ClientCertificatesAdminController : Controller + { + [Import] + public IClientCertificatesRepository Repository { get; set; } + + public ClientCertificatesAdminController() + { + Container.Current.SatisfyImportsOnce(this); + } + + public ClientCertificatesAdminController(IClientCertificatesRepository repository) + { + Repository = repository; + } + + public ActionResult Index() + { + var users = Repository.List(-1, -1); + + return View(users); + } + + public ActionResult Add() + { + return View(); + } + + [HttpPost] + [ValidateAntiForgeryToken] + public ActionResult Add(AddClientCertificateModel model) + { + if (!ModelState.IsValid) + { + return View(); + } + + var clientCert = new ClientCertificate + { + UserName = model.UserName, + Description = model.Description + }; + + if (model.CertificateUpload != null && model.CertificateUpload.ContentLength > 0) + { + var bytes = new byte[model.CertificateUpload.InputStream.Length]; + model.CertificateUpload.InputStream.Read(bytes, 0, bytes.Length); + + clientCert.Thumbprint = new X509Certificate2(bytes).Thumbprint; + } + else + { + if (string.IsNullOrWhiteSpace(model.Thumbprint)) + { + ModelState.AddModelError("", "No certificate (or thumbprint) specified"); + return View(); + } + + clientCert.Thumbprint = model.Thumbprint; + } + + try + { + Repository.Add(clientCert); + } + catch (Exception ex) + { + ModelState.AddModelError("", ex.InnerException.Message); + return View("Add"); + } + + return RedirectToAction("Index"); + } + + public ActionResult Edit(string userName) + { + var model = new EditClientCertificatesModel + { + UserName = userName + }; + + model.ClientCertificates = Repository.GetClientCertificatesForUser(userName); + + if (model.ClientCertificates.ToList().Count == 0) + { + return RedirectToAction("Index"); + } + + return View(model); + } + + public ActionResult DeleteAll(string userName) + { + return View("Delete"); + } + + [HttpPost] + [ValidateAntiForgeryToken] + public ActionResult DeleteAll(string userName, FormCollection collection) + { + try + { + Repository.GetClientCertificatesForUser(userName).ToList().ForEach(cert => + Repository.Delete(new ClientCertificate { UserName = userName, Thumbprint = cert.Thumbprint })); + } + catch (Exception ex) + { + ModelState.AddModelError("", ex.InnerException.Message); + return View("Delete"); + } + + return RedirectToAction("Index"); + } + + public ActionResult Delete(string userName, string thumbprint) + { + return View("Delete"); + } + + [HttpPost] + [ValidateAntiForgeryToken] + public ActionResult Delete(string userName, string thumbprint, FormCollection collection) + { + try + { + Repository.Delete(new ClientCertificate { UserName = userName, Thumbprint = thumbprint }); + } + catch (Exception ex) + { + ModelState.AddModelError("", ex.InnerException.Message); + return View("Delete"); + } + + return RedirectToAction("Edit", new { userName = userName }); + } + } +} diff --git a/OnPremise/WebSite/Controllers/Admin/DelegationAdminController.cs b/OnPremise/WebSite/Controllers/Admin/DelegationAdminController.cs new file mode 100644 index 0000000..5ada689 --- /dev/null +++ b/OnPremise/WebSite/Controllers/Admin/DelegationAdminController.cs @@ -0,0 +1,140 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.ComponentModel.Composition; +using System.Linq; +using System.Web.Mvc; +using Thinktecture.IdentityServer.Models; +using Thinktecture.IdentityServer.Repositories; +using Thinktecture.IdentityServer.Web.Security; +using Thinktecture.IdentityServer.Web.ViewModels.Administration; + +namespace Thinktecture.IdentityServer.Web.Controllers +{ + [ClaimsAuthorize(Constants.Actions.Administration, Constants.Resources.Delegation)] + public class DelegationAdminController : Controller + { + [Import] + public IDelegationRepository Repository { get; set; } + + public DelegationAdminController() + { + Container.Current.SatisfyImportsOnce(this); + } + + public DelegationAdminController(IDelegationRepository repository) + { + Repository = repository; + } + + public ActionResult Index() + { + var users = Repository.GetAllUsers(-1, -1); + + return View(users); + } + + public ActionResult Add() + { + return View(); + } + + [HttpPost] + [ValidateAntiForgeryToken] + public ActionResult Add(AddDelegationModel model) + { + if (!ModelState.IsValid) + { + return View(); + } + + var setting = new DelegationSetting + { + UserName = model.UserName, + Realm = new Uri(model.Realm), + Description = model.Description + }; + + try + { + Repository.Add(setting); + } + catch (Exception ex) + { + ModelState.AddModelError("", ex.InnerException.Message); + return View("Add"); + } + + return RedirectToAction("Index"); + } + + public ActionResult Edit(string userName) + { + var model = new EditDelegationModel + { + UserName = userName + }; + + model.Settings = Repository.GetDelegationSettingsForUser(userName); + + if (model.Settings.ToList().Count == 0) + { + return RedirectToAction("Index"); + } + + return View(model); + } + + public ActionResult DeleteAll(string userName) + { + return View("Delete"); + } + + [HttpPost] + [ValidateAntiForgeryToken] + public ActionResult DeleteAll(string userName, FormCollection collection) + { + try + { + Repository.GetDelegationSettingsForUser(userName).ToList().ForEach(setting => + Repository.Delete(new DelegationSetting { UserName = userName, Realm = setting.Realm })); + } + catch (Exception ex) + { + ModelState.AddModelError("", ex.InnerException.Message); + return View("Delete"); + } + + return RedirectToAction("Index"); + } + + public ActionResult Delete(string userName, string thumbprint) + { + return View("Delete"); + } + + [HttpPost] + [ValidateAntiForgeryToken] + public ActionResult Delete(string userName, string realm, FormCollection collection) + { + try + { + Repository.Delete(new DelegationSetting { UserName = userName, Realm = new Uri(realm) }); + } + catch (Exception ex) + { + ModelState.AddModelError("", ex.InnerException.Message ?? ex.Message); + return View("Delete"); + } + + return RedirectToAction("Edit", new { userName = userName }); + } + } +} diff --git a/OnPremise/WebSite/Controllers/Admin/RelyingPartiesAdminController.cs b/OnPremise/WebSite/Controllers/Admin/RelyingPartiesAdminController.cs new file mode 100644 index 0000000..20b07bb --- /dev/null +++ b/OnPremise/WebSite/Controllers/Admin/RelyingPartiesAdminController.cs @@ -0,0 +1,149 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.ComponentModel.Composition; +using System.Security.Cryptography; +using System.Web.Mvc; +using Thinktecture.IdentityServer.Repositories; +using Thinktecture.IdentityServer.Web.Security; +using Thinktecture.IdentityServer.Web.ViewModels.Administration; + +namespace Thinktecture.IdentityServer.Web.Controllers +{ + [ClaimsAuthorize(Constants.Actions.Administration, Constants.Resources.RelyingParty)] + public class RelyingPartiesAdminController : Controller + { + [Import] + public IRelyingPartyRepository Repository { get; set; } + + public RelyingPartiesAdminController() + { + Container.Current.SatisfyImportsOnce(this); + } + + public RelyingPartiesAdminController(IRelyingPartyRepository repository) + { + Repository = repository; + } + + public ActionResult Index() + { + var rps = Repository.List(-1, -1); + return View(rps.ToViewModel()); + } + + public ActionResult Add() + { + return View(); + } + + [HttpPost] + [ValidateAntiForgeryToken] + public ActionResult Add(RelyingPartyModel relyingParty) + { + try + { + if (ModelState.IsValid) + { + TrySetCertificateFromUpload(relyingParty); + Repository.Add(relyingParty.ToDomainModel()); + + return RedirectToAction("Index"); + } + + return View(relyingParty); + } + catch (Exception ex) + { + ModelState.AddModelError("", ex.Message); + return View(relyingParty); + } + } + + public ActionResult Edit(string id) + { + var rp = Repository.Get(id); + return View(rp.ToViewModel()); + } + + [HttpPost] + [ValidateAntiForgeryToken] + public ActionResult Edit(RelyingPartyModel relyingParty) + { + try + { + if (ModelState.IsValid) + { + TrySetCertificateFromUpload(relyingParty); + Repository.Update(relyingParty.ToDomainModel()); + + return RedirectToAction("Index"); + } + + return View(relyingParty); + } + catch (Exception ex) + { + if (ex.InnerException != null) + { + ModelState.AddModelError("", ex.InnerException.Message); + } + else + { + ModelState.AddModelError("", ex.Message); + } + + return View(relyingParty); + } + } + + public ActionResult Delete(string id) + { + return View(); + } + + [HttpPost] + [ValidateAntiForgeryToken] + public ActionResult Delete(string id, FormCollection collection) + { + try + { + Repository.Delete(id); + + return RedirectToAction("Index"); + } + catch (Exception ex) + { + ModelState.AddModelError("", ex.InnerException.Message); + return View(); + } + } + + [HttpPost] + public ActionResult GenerateSymmetricSigningKey() + { + var bytes = new byte[32]; + new RNGCryptoServiceProvider().GetBytes(bytes); + + return Json(Convert.ToBase64String(bytes)); + } + + private void TrySetCertificateFromUpload(RelyingPartyModel relyingParty) + { + if (relyingParty.CertificateUpload != null && relyingParty.CertificateUpload.ContentLength > 0) + { + byte[] bytes = new byte[relyingParty.CertificateUpload.InputStream.Length]; + relyingParty.CertificateUpload.InputStream.Read(bytes, 0, bytes.Length); + + relyingParty.EncryptingCertificate = Convert.ToBase64String(bytes); + } + } + } +} diff --git a/OnPremise/WebSite/Controllers/FederationMetadataController.cs b/OnPremise/WebSite/Controllers/FederationMetadataController.cs new file mode 100644 index 0000000..1fb8ab9 --- /dev/null +++ b/OnPremise/WebSite/Controllers/FederationMetadataController.cs @@ -0,0 +1,63 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.ComponentModel.Composition; +using System.Web; +using System.Web.Mvc; +using Thinktecture.IdentityServer.Helper; +using Thinktecture.IdentityServer.Repositories; +using Thinktecture.IdentityServer.TokenService; + +namespace Thinktecture.IdentityServer.Web.Controllers +{ + public class FederationMetadataController : Controller + { + [Import] + public IConfigurationRepository ConfigurationRepository { get; set; } + + [Import] + public ICacheRepository CacheRepository { get; set; } + + public FederationMetadataController() + { + Container.Current.SatisfyImportsOnce(this); + } + + public FederationMetadataController(IConfigurationRepository configurationRepository, ICacheRepository cacheRepository) + { + ConfigurationRepository = configurationRepository; + CacheRepository = cacheRepository; + } + + public ActionResult Generate() + { + if (ConfigurationRepository.Endpoints.FederationMetadata) + { + return Cache.ReturnFromCache(CacheRepository, Constants.CacheKeys.WSFedMetadata, 1, () => + { + var endpoints = Endpoints.Create( + HttpContext.Request.Headers["Host"], + HttpContext.Request.ApplicationPath, + ConfigurationRepository.Endpoints.HttpPort, + ConfigurationRepository.Endpoints.HttpsPort); + + return new ContentResult + { + Content = new WSFederationMetadataGenerator(endpoints).Generate(), + ContentType = "text/xml" + }; + }); + } + else + { + return new HttpNotFoundResult(); + } + } + } +} diff --git a/OnPremise/WebSite/Controllers/HomeController.cs b/OnPremise/WebSite/Controllers/HomeController.cs new file mode 100644 index 0000000..d57bf0d --- /dev/null +++ b/OnPremise/WebSite/Controllers/HomeController.cs @@ -0,0 +1,65 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Web.Mvc; +using Thinktecture.IdentityServer.Repositories; + +namespace Thinktecture.IdentityServer.Web.Controllers +{ + public class HomeController : Controller + { + [Import] + public IConfigurationRepository ConfigurationRepository { get; set; } + + public HomeController() + { + Container.Current.SatisfyImportsOnce(this); + } + + public HomeController(IConfigurationRepository configuration) + { + ConfigurationRepository = configuration; + } + + public ActionResult Index() + { + return View(); + } + + public ActionResult AppIntegration() + { + var endpoints = Endpoints.Create( + HttpContext.Request.Headers["Host"], + HttpContext.Request.ApplicationPath, + ConfigurationRepository.Endpoints.HttpPort, + ConfigurationRepository.Endpoints.HttpsPort); + + var list = new Dictionary + { + { "WS-Federation", endpoints.WSFederation.AbsoluteUri }, + { "WS-Federation metadata", endpoints.WSFederationMetadata.AbsoluteUri }, + + { "WS-Trust mixed (UserName)", endpoints.WSTrustMixedUserName.AbsoluteUri }, + { "WS-Trust mixed (Certificate)", endpoints.WSTrustMixedCertificate.AbsoluteUri }, + { "WS-Trust message (UserName)", endpoints.WSTrustMessageUserName.AbsoluteUri }, + { "WS-Trust message (Certificate)", endpoints.WSTrustMessageCertificate.AbsoluteUri }, + { "WS-Trust metadata", endpoints.WSTrustMex.AbsoluteUri }, + + { "WRAP", endpoints.Wrap.AbsoluteUri }, + { "OAuth2", endpoints.OAuth2.AbsoluteUri }, + { "JSNotify", endpoints.JSNotify.AbsoluteUri }, + { "Simple HTTP", endpoints.SimpleHttp.AbsoluteUri }, + }; + + return View(list); + } + } +} diff --git a/OnPremise/WebSite/Controllers/InitialConfigurationController.cs b/OnPremise/WebSite/Controllers/InitialConfigurationController.cs new file mode 100644 index 0000000..2a43778 --- /dev/null +++ b/OnPremise/WebSite/Controllers/InitialConfigurationController.cs @@ -0,0 +1,94 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Security.Cryptography.X509Certificates; +using System.Web.Mvc; +using Thinktecture.IdentityServer.Repositories; +using Thinktecture.IdentityServer.Web.ViewModels; + +namespace Thinktecture.IdentityServer.Web.Controllers +{ + public class InitialConfigurationController : Controller + { + [Import] + public IConfigurationRepository ConfigurationRepository { get; set; } + + public InitialConfigurationController() + { + Container.Current.SatisfyImportsOnce(this); + } + + public InitialConfigurationController(IConfigurationRepository configuration) + { + ConfigurationRepository = configuration; + } + + public ActionResult Index() + { + if (!string.IsNullOrWhiteSpace(ConfigurationRepository.SigningCertificate.SubjectDistinguishedName)) + { + return RedirectToAction("index", "home"); + } + + var model = new InitialConfigurationModel + { + AvailableCertificates = GetAvailableCertificatesFromStore(), + IssuerUri = ConfigurationRepository.Configuration.IssuerUri, + SiteName = ConfigurationRepository.Configuration.SiteName + }; + + return View(model); + } + + [HttpPost] + public ActionResult Index(InitialConfigurationModel model) + { + if (ModelState.IsValid) + { + var config = ConfigurationRepository.Configuration; + config.SiteName = model.SiteName; + config.IssuerUri = model.IssuerUri; + + ConfigurationRepository.UpdateConfiguration(config); + ConfigurationRepository.UpdateCertificates(null, model.SigningCertificate); + + return RedirectToAction("index", "home"); + } + + ModelState.AddModelError("", "Errors ocurred..."); + model.AvailableCertificates = GetAvailableCertificatesFromStore(); + return View(model); + } + + #region Helper + private List GetAvailableCertificatesFromStore() + { + var list = new List(); + var store = new X509Store(StoreName.My, StoreLocation.LocalMachine); + store.Open(OpenFlags.ReadOnly); + + try + { + foreach (var cert in store.Certificates) + { + list.Add(cert.Subject); + } + } + finally + { + store.Close(); + } + + return list; + } + #endregion + } +} diff --git a/OnPremise/WebSite/Controllers/Issue/JSNotifyController.cs b/OnPremise/WebSite/Controllers/Issue/JSNotifyController.cs new file mode 100644 index 0000000..d6c3602 --- /dev/null +++ b/OnPremise/WebSite/Controllers/Issue/JSNotifyController.cs @@ -0,0 +1,78 @@ +using System; +using System.ComponentModel.Composition; +using System.ServiceModel; +using System.Threading; +using System.Web.Mvc; +using Microsoft.IdentityModel.Claims; +using Thinktecture.IdentityServer.Core.Swt; +using Thinktecture.IdentityServer.Repositories; +using Thinktecture.IdentityServer.Web.ActionResults; +using Thinktecture.IdentityServer.Web.Security; + +namespace Thinktecture.IdentityServer.Web.Controllers.Issue +{ + [ClaimsAuthorize(Constants.Actions.Issue, Constants.Resources.JSNotify)] + public class JSNotifyController : Controller + { + [Import] + public IConfigurationRepository ConfigurationRepository { get; set; } + + public JSNotifyController() + { + Container.Current.SatisfyImportsOnce(this); + } + + public JSNotifyController(IConfigurationRepository configurationRepository) + { + ConfigurationRepository = configurationRepository; + } + + public ActionResult Issue(string realm, string tokenType) + { + Tracing.Verbose("JSNotify endpoint called."); + + if (!ConfigurationRepository.Endpoints.JSNotify) + { + Tracing.Warning("JSNotify endpoint called, but disabled in configuration"); + return new HttpNotFoundResult(); + } + + Tracing.Information("JSNotify endpoint called for realm: " + realm); + + if (tokenType == null) + { + tokenType = SimpleWebToken.OasisTokenProfile; + } + + Tracing.Information("Token type: " + tokenType); + + Uri uri; + if (!Uri.TryCreate(realm, UriKind.Absolute, out uri)) + { + Tracing.Error("Realm parameter is malformed."); + return new HttpStatusCodeResult(400); + } + + var endpoint = new EndpointAddress(uri); + var auth = new AuthenticationHelper(); + + TokenResponse response; + if (auth.TryIssueToken(endpoint, Thread.CurrentPrincipal as IClaimsPrincipal, tokenType, out response)) + { + var jsresponse = new AccessTokenResponse + { + AccessToken = response.TokenString, + TokenType = response.TokenType, + ExpiresIn = ConfigurationRepository.Configuration.DefaultTokenLifetime * 60 + }; + + Tracing.Information("JSNotify issue successful for user: " + User.Identity.Name); + return new JSNotifyResult(jsresponse); + } + else + { + return new HttpStatusCodeResult(400); + } + } + } +} diff --git a/OnPremise/WebSite/Controllers/Issue/OAuth2Controller.cs b/OnPremise/WebSite/Controllers/Issue/OAuth2Controller.cs new file mode 100644 index 0000000..058ed7d --- /dev/null +++ b/OnPremise/WebSite/Controllers/Issue/OAuth2Controller.cs @@ -0,0 +1,122 @@ +using System; +using System.ComponentModel.Composition; +using System.IdentityModel.Tokens; +using System.ServiceModel; +using System.Web.Mvc; +using Microsoft.IdentityModel.Claims; +using Thinktecture.IdentityServer.Core.Swt; +using Thinktecture.IdentityServer.Repositories; +using Thinktecture.IdentityServer.Web.ActionResults; +using Thinktecture.IdentityServer.Web.Security; +using Thinktecture.IdentityServer.Web.ViewModels.OAuth2; + +namespace Thinktecture.IdentityServer.Web.Controllers +{ + public class OAuth2Controller : Controller + { + [Import] + public IUserRepository UserRepository { get; set; } + + [Import] + public IConfigurationRepository ConfigurationRepository { get; set; } + + public OAuth2Controller() + { + Container.Current.SatisfyImportsOnce(this); + } + + public OAuth2Controller(IUserRepository userRepository, IConfigurationRepository configurationRepository) + { + UserRepository = userRepository; + ConfigurationRepository = configurationRepository; + } + + [HttpPost] + public ActionResult Token(ResourceOwnerCredentialRequest request) + { + Tracing.Verbose("OAuth2 endpoint called."); + + if (!ConfigurationRepository.Endpoints.OAuth2) + { + Tracing.Error("OAuth2 endpoint called, but disabled in configuration"); + return new HttpNotFoundResult(); + } + + if (!ModelState.IsValid) + { + Tracing.Error("OAuth2 called with malformed request"); + return new HttpStatusCodeResult(400); + } + + var auth = new AuthenticationHelper(); + + Uri uri; + if (!Uri.TryCreate(request.Scope, UriKind.Absolute, out uri)) + { + Tracing.Error("OAuth2 endpoint called with malformed realm: " + request.Scope); + return new HttpStatusCodeResult(400); + } + + IClaimsPrincipal principal = null; + if (auth.TryGetPrincipalFromOAuth2Request(Request, request, out principal)) + { + if (!ClaimsAuthorize.CheckAccess(principal, Constants.Actions.Issue, Constants.Resources.OAuth2)) + { + Tracing.Error("User not authorized"); + return new UnauthorizedResult("OAuth2", UnauthorizedResult.ResponseAction.Send401); + } + + SecurityToken token; + if (auth.TryIssueToken(new EndpointAddress(uri), principal, SimpleWebToken.OasisTokenProfile, out token)) + { + var swt = token as SimpleWebToken; + var response = new AccessTokenResponse + { + AccessToken = swt.RawToken, + TokenType = SimpleWebToken.OasisTokenProfile, + ExpiresIn = ConfigurationRepository.Configuration.DefaultTokenLifetime * 60, + }; + + Tracing.Information("OAuth2 issue successful for user: " + request.UserName); + return new OAuth2AccessTokenResult(response); + } + + return new HttpStatusCodeResult(400); + } + + Tracing.Error("OAuth2 endpoint authentication failed for user: " + request.UserName); + return new UnauthorizedResult("OAuth2", UnauthorizedResult.ResponseAction.Send401); + + //if (UserRepository.ValidateUser(request.UserName ?? "", request.Password ?? "")) + //{ + // var principal = auth.CreatePrincipal(request.UserName, AuthenticationMethods.Password); + + // if (!ClaimsAuthorize.CheckAccess(principal, Constants.Actions.Issue, Constants.Resources.OAuth2)) + // { + // Tracing.Error("User not authorized"); + // return new UnauthorizedResult("OAuth2", UnauthorizedResult.ResponseAction.Send401); + // } + + // SecurityToken token; + // if (auth.TryIssueToken(new EndpointAddress(uri), principal, SimpleWebToken.OasisTokenProfile, out token)) + // { + // var swt = token as SimpleWebToken; + // var response = new AccessTokenResponse + // { + // AccessToken = swt.RawToken, + // TokenType = SimpleWebToken.OasisTokenProfile, + // ExpiresIn = ConfigurationRepository.Configuration.DefaultTokenLifetime * 60, + // }; + + // Tracing.Information("OAuth2 issue successful for user: " + request.UserName); + // return new OAuth2AccessTokenResult(response); + // } + + // return new HttpStatusCodeResult(400); + //} + + //Tracing.Error("OAuth2 endpoint authentication failed for user: " + request.UserName); + //return new UnauthorizedResult("OAuth2", UnauthorizedResult.ResponseAction.Send401); + } + } +} diff --git a/OnPremise/WebSite/Controllers/Issue/SimpleHttpController.cs b/OnPremise/WebSite/Controllers/Issue/SimpleHttpController.cs new file mode 100644 index 0000000..6cc7671 --- /dev/null +++ b/OnPremise/WebSite/Controllers/Issue/SimpleHttpController.cs @@ -0,0 +1,89 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.ComponentModel.Composition; +using System.ServiceModel; +using System.Web.Mvc; +using Microsoft.IdentityModel.Claims; +using Thinktecture.IdentityServer.Repositories; +using Thinktecture.IdentityServer.Web.ActionResults; +using Thinktecture.IdentityServer.Web.Security; + +namespace Thinktecture.IdentityServer.Web.Controllers +{ + public class SimpleHttpController : Controller + { + [Import] + public IConfigurationRepository ConfigurationRepository { get; set; } + + public SimpleHttpController() + { + Container.Current.SatisfyImportsOnce(this); + } + + public SimpleHttpController(IConfigurationRepository configurationRepository) + { + ConfigurationRepository = configurationRepository; + } + + public ActionResult Issue(string realm, string tokenType) + { + Tracing.Verbose("Simple HTTP endpoint called."); + + if (!ConfigurationRepository.Endpoints.SimpleHttp) + { + Tracing.Warning("Simple HTTP endpoint is disabled in configuration"); + return new HttpNotFoundResult(); + } + + if (tokenType == null) + { + tokenType = ConfigurationRepository.Configuration.DefaultTokenType; + } + + Tracing.Information("Token type: " + tokenType); + + Uri uri; + if (!Uri.TryCreate(realm, UriKind.Absolute, out uri)) + { + Tracing.Error("Realm parameter is malformed."); + return new HttpStatusCodeResult(400); + } + + Tracing.Information("Simple HTTP endpoint called for realm: " + uri.AbsoluteUri); + + var endpoint = new EndpointAddress(uri); + var auth = new AuthenticationHelper(); + + IClaimsPrincipal principal; + if (!auth.TryGetPrincipalFromHttpRequest(Request, out principal)) + { + Tracing.Error("no or invalid credentials found."); + return new UnauthorizedResult("Basic", UnauthorizedResult.ResponseAction.Send401); + } + + if (!ClaimsAuthorize.CheckAccess(principal, Constants.Actions.Issue, Constants.Resources.SimpleHttp)) + { + Tracing.Error("User not authorized"); + return new UnauthorizedResult("Basic", UnauthorizedResult.ResponseAction.Send401); + } + + TokenResponse tokenResponse; + if (auth.TryIssueToken(endpoint, principal, tokenType, out tokenResponse)) + { + return new SimpleHttpResult(tokenResponse.TokenString, tokenType); + } + else + { + return new HttpStatusCodeResult(400); + } + } + } +} diff --git a/OnPremise/WebSite/Controllers/Issue/WSFederationController.cs b/OnPremise/WebSite/Controllers/Issue/WSFederationController.cs new file mode 100644 index 0000000..0b3d963 --- /dev/null +++ b/OnPremise/WebSite/Controllers/Issue/WSFederationController.cs @@ -0,0 +1,102 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.ComponentModel.Composition; +using System.Security.Principal; +using System.Web; +using System.Web.Mvc; +using Microsoft.IdentityModel.Protocols.WSFederation; +using Microsoft.IdentityModel.Web; +using Thinktecture.IdentityServer.Repositories; +using Thinktecture.IdentityServer.TokenService; +using Thinktecture.IdentityServer.Web.ActionResults; +using Thinktecture.IdentityServer.Web.Security; + +namespace Thinktecture.IdentityServer.Web.Controllers +{ + [ClaimsAuthorize(Constants.Actions.Issue, Constants.Resources.WSFederation)] + public class WSFederationController : Controller + { + [Import] + public IConfigurationRepository ConfigurationRepository { get; set; } + + public WSFederationController() + { + Container.Current.SatisfyImportsOnce(this); + } + + public WSFederationController(IConfigurationRepository configurationRepository) + { + ConfigurationRepository = configurationRepository; + } + + public ActionResult Issue() + { + Tracing.Verbose("WS-Federation endpoint called."); + + if (!ConfigurationRepository.Endpoints.WSFederation) + { + return new HttpNotFoundResult(); + } + + var message = WSFederationMessage.CreateFromUri(HttpContext.Request.Url); + + // sign in + var signinMessage = message as SignInRequestMessage; + if (signinMessage != null) + { + return ProcessWSFederationSignIn(signinMessage, HttpContext.User); + } + + // sign out + var signoutMessage = message as SignOutRequestMessage; + if (signoutMessage != null) + { + return ProcessWSFederationSignOut(signoutMessage); + } + + return View("Error"); + } + + #region Helper + private ActionResult ProcessWSFederationSignIn(SignInRequestMessage message, IPrincipal principal) + { + // issue token and create ws-fed response + var response = FederatedPassiveSecurityTokenServiceOperations.ProcessSignInRequest( + message, + principal, + TokenServiceConfiguration.Current.CreateSecurityTokenService()); + + // set cookie for single-sign-out + new SignInSessionsManager(HttpContext, ConfigurationRepository.Configuration.MaximumTokenLifetime) + .AddRealm(response.BaseUri.AbsoluteUri); + + return new WSFederationResult(response); + } + + private ActionResult ProcessWSFederationSignOut(SignOutRequestMessage message) + { + FederatedAuthentication.SessionAuthenticationModule.SignOut(); + + // check for return url + if (!string.IsNullOrWhiteSpace(message.Reply)) + { + ViewBag.ReturnUrl = message.Reply; + } + + // check for existing sign in sessions + var mgr = new SignInSessionsManager(HttpContext); + var realms = mgr.GetRealms(); + mgr.ClearRealms(); + + return View("Signout", realms); + } + #endregion + } +} diff --git a/OnPremise/WebSite/Controllers/Issue/WrapController.cs b/OnPremise/WebSite/Controllers/Issue/WrapController.cs new file mode 100644 index 0000000..9f8df0a --- /dev/null +++ b/OnPremise/WebSite/Controllers/Issue/WrapController.cs @@ -0,0 +1,92 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.ComponentModel.Composition; +using System.ServiceModel; +using System.Web.Mvc; +using Microsoft.IdentityModel.Claims; +using Thinktecture.IdentityServer.Core.Swt; +using Thinktecture.IdentityServer.Repositories; +using Thinktecture.IdentityServer.Web.ActionResults; +using Thinktecture.IdentityServer.Web.Security; + +namespace Thinktecture.IdentityServer.Web.Controllers.Issue +{ + public class WrapController : Controller + { + [Import] + public IConfigurationRepository ConfigurationRepository { get; set; } + + public WrapController() + { + Container.Current.SatisfyImportsOnce(this); + } + + public WrapController(IConfigurationRepository configurationRepository) + { + ConfigurationRepository = configurationRepository; + } + + [HttpPost] + public ActionResult Issue() + { + Tracing.Verbose("OAuth WRAP endpoint called."); + + if (!ConfigurationRepository.Endpoints.OAuthWRAP) + { + Tracing.Error("OAuth WRAP endpoint is disabled in configuration"); + return new HttpNotFoundResult(); + } + + var scope = Request.Form["wrap_scope"]; + + if (string.IsNullOrWhiteSpace(scope)) + { + Tracing.Error("OAuth WRAP endpoint called with empty realm."); + return new HttpStatusCodeResult(400); + } + + Uri uri; + if (!Uri.TryCreate(scope, UriKind.Absolute, out uri)) + { + Tracing.Error("OAuth WRAP endpoint called with malformed realm: " + scope); + return new HttpStatusCodeResult(400); + } + + Tracing.Information("OAuth WRAP endpoint called with realm: " + scope); + + var endpoint = new EndpointAddress(uri); + var auth = new AuthenticationHelper(); + + IClaimsPrincipal principal; + if (!auth.TryGetPrincipalFromWrapRequest(Request, out principal)) + { + Tracing.Error("Authentication failed"); + return new UnauthorizedResult("WRAP", UnauthorizedResult.ResponseAction.Send401); + } + + if (!ClaimsAuthorize.CheckAccess(principal, Constants.Actions.Issue, Constants.Resources.WRAP)) + { + Tracing.Error("User not authorized"); + return new UnauthorizedResult("WRAP", UnauthorizedResult.ResponseAction.Send401); + } + + TokenResponse response; + if (auth.TryIssueToken(endpoint, principal, SimpleWebToken.OasisTokenProfile, out response)) + { + return new WrapResult(response); + } + else + { + return new HttpStatusCodeResult(400); + } + } + } +} diff --git a/OnPremise/WebSite/Global.asax b/OnPremise/WebSite/Global.asax new file mode 100644 index 0000000..9098e78 --- /dev/null +++ b/OnPremise/WebSite/Global.asax @@ -0,0 +1 @@ +<%@ Application Codebehind="Global.asax.cs" Inherits="Thinktecture.IdentityServer.Web.MvcApplication" Language="C#" %> diff --git a/OnPremise/WebSite/Global.asax.cs b/OnPremise/WebSite/Global.asax.cs new file mode 100644 index 0000000..236f38f --- /dev/null +++ b/OnPremise/WebSite/Global.asax.cs @@ -0,0 +1,154 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.ComponentModel.Composition.Hosting; +using System.ServiceModel.Activation; +using System.Web; +using System.Web.Mvc; +using System.Web.Routing; +using Microsoft.IdentityModel.Web; +using Thinktecture.IdentityServer.Repositories; +using Thinktecture.IdentityServer.TokenService; +using Thinktecture.IdentityServer.Web.GlobalFilter; + +namespace Thinktecture.IdentityServer.Web +{ + public class MvcApplication : HttpApplication + { + private const string ConfigurationName = "WebSite"; + + [Import] + public IConfigurationRepository ConfigurationRepository { get; set; } + + protected void Application_Start() + { + SetupCompositionContainer(); + Container.Current.SatisfyImportsOnce(this); + + FederatedAuthentication.ServiceConfigurationCreated += (s, e) => + { + if (!string.IsNullOrWhiteSpace(ConfigurationRepository.SigningCertificate.SubjectDistinguishedName)) + { + e.ServiceConfiguration.SecurityTokenHandlers.AddOrReplace( + new X509CertificateSessionSecurityTokenHandler(ConfigurationRepository.SigningCertificate.Certificate)); + } + }; + + AreaRegistration.RegisterAllAreas(); + RegisterGlobalFilters(GlobalFilters.Filters); + RegisterRoutes(RouteTable.Routes); + } + + private void SetupCompositionContainer() + { + Container.Current = new CompositionContainer(new RepositoryExportProvider()); + } + + public static void RegisterGlobalFilters(GlobalFilterCollection filters) + { + filters.Add(new HandleErrorAttribute()); + filters.Add(new GlobalViewModelFilter()); + filters.Add(new SslRedirectFilter()); + filters.Add(new InitialConfigurationFilter()); + } + + public static void RegisterRoutes(RouteCollection routes) + { + routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); + + routes.MapRoute( + "FederationMetadata", + "FederationMetadata/2007-06/FederationMetadata.xml", + new { controller = "FederationMetadata", action = "Generate" } + ); + + routes.MapRoute( + "RelyingPartiesAdmin", + "admin/relyingparties/{action}/{id}", + new { controller = "RelyingPartiesAdmin", action = "Index", id = UrlParameter.Optional } + ); + + routes.MapRoute( + "ClientCertificatesAdmin", + "admin/clientcertificates/{action}/{userName}", + new { controller = "ClientCertificatesAdmin", action = "Index", userName = UrlParameter.Optional } + ); + + routes.MapRoute( + "DelegationAdmin", + "admin/delegation/{action}/{userName}", + new { controller = "DelegationAdmin", action = "Index", userName = UrlParameter.Optional } + ); + + routes.MapRoute( + "Default", + "{controller}/{action}/{id}", + new { controller = "Home", action = "Index", id = UrlParameter.Optional }, + new { controller = "^(?!issue).*" } + ); + + // ws-federation (mvc) + routes.MapRoute( + "wsfederation", + "issue/wsfed", + new { controller = "WSFederation", action = "issue" } + ); + + // jsnotify (mvc) + routes.MapRoute( + "jsnotify", + "issue/jsnotify", + new { controller = "JSNotify", action = "issue" } + ); + + // simple http (mvc) + routes.MapRoute( + "simplehttp", + "issue/simple", + new { controller = "SimpleHttp", action = "issue" } + ); + + // oauth wrap (mvc) + routes.MapRoute( + "wrap", + "issue/wrap", + new { controller = "Wrap", action = "issue" } + ); + + // oauth2 (mvc) + routes.MapRoute( + "oauth2", + "issue/oauth2/{action}", + new { controller = "OAuth2", action = "token" } + ); + + // ws-trust (wcf) + routes.Add(new ServiceRoute( + "issue/wstrust", + new TokenServiceHostFactory(), + typeof(TokenServiceConfiguration))); + } + + protected void Application_EndRequest(object sender, EventArgs e) + { + var context = (sender as HttpApplication).Context; + + if (context.Response.StatusCode == 401) + { + var noRedirect = context.Items["NoRedirect"]; + + if (noRedirect == null) + { + var route = new RouteValueDictionary(new Dictionary + { + { "Controller", "Account" }, + { "Action", "SignIn" }, + { "ReturnUrl", HttpUtility.UrlEncode(context.Request.RawUrl, context.Request.ContentEncoding) } + }); + + Response.RedirectToRoute(route); + } + } + } + } +} \ No newline at end of file diff --git a/OnPremise/WebSite/Properties/AssemblyInfo.cs b/OnPremise/WebSite/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..fa81676 --- /dev/null +++ b/OnPremise/WebSite/Properties/AssemblyInfo.cs @@ -0,0 +1,34 @@ +using System.Reflection; +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("IdentityServer2")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("IdentityServer2")] +[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("23de8f48-5bfb-481d-9bf4-8b9222efa4bd")] + +// 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")] diff --git a/OnPremise/WebSite/Scripts/MicrosoftAjax.debug.js b/OnPremise/WebSite/Scripts/MicrosoftAjax.debug.js new file mode 100644 index 0000000..a5f7942 --- /dev/null +++ b/OnPremise/WebSite/Scripts/MicrosoftAjax.debug.js @@ -0,0 +1,7117 @@ +// Name: MicrosoftAjax.debug.js +// Assembly: System.Web.Extensions +// Version: 4.0.0.0 +// FileVersion: 4.0.20526.0 +//----------------------------------------------------------------------- +// Copyright (C) Microsoft Corporation. All rights reserved. +//----------------------------------------------------------------------- +// MicrosoftAjax.js +// Microsoft AJAX Framework. + +Function.__typeName = 'Function'; +Function.__class = true; +Function.createCallback = function Function$createCallback(method, context) { + ///

+ /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "method", type: Function}, + {name: "context", mayBeNull: true} + ]); + if (e) throw e; + return function() { + var l = arguments.length; + if (l > 0) { + var args = []; + for (var i = 0; i < l; i++) { + args[i] = arguments[i]; + } + args[l] = context; + return method.apply(this, args); + } + return method.call(this, context); + } +} +Function.createDelegate = function Function$createDelegate(instance, method) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "instance", mayBeNull: true}, + {name: "method", type: Function} + ]); + if (e) throw e; + return function() { + return method.apply(instance, arguments); + } +} +Function.emptyFunction = Function.emptyMethod = function Function$emptyMethod() { + /// +} +Function.validateParameters = function Function$validateParameters(parameters, expectedParameters, validateParameterCount) { + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "parameters"}, + {name: "expectedParameters"}, + {name: "validateParameterCount", type: Boolean, optional: true} + ]); + if (e) throw e; + return Function._validateParams(parameters, expectedParameters, validateParameterCount); +} +Function._validateParams = function Function$_validateParams(params, expectedParams, validateParameterCount) { + var e, expectedLength = expectedParams.length; + validateParameterCount = validateParameterCount || (typeof(validateParameterCount) === "undefined"); + e = Function._validateParameterCount(params, expectedParams, validateParameterCount); + if (e) { + e.popStackFrame(); + return e; + } + for (var i = 0, l = params.length; i < l; i++) { + var expectedParam = expectedParams[Math.min(i, expectedLength - 1)], + paramName = expectedParam.name; + if (expectedParam.parameterArray) { + paramName += "[" + (i - expectedLength + 1) + "]"; + } + else if (!validateParameterCount && (i >= expectedLength)) { + break; + } + e = Function._validateParameter(params[i], expectedParam, paramName); + if (e) { + e.popStackFrame(); + return e; + } + } + return null; +} +Function._validateParameterCount = function Function$_validateParameterCount(params, expectedParams, validateParameterCount) { + var i, error, + expectedLen = expectedParams.length, + actualLen = params.length; + if (actualLen < expectedLen) { + var minParams = expectedLen; + for (i = 0; i < expectedLen; i++) { + var param = expectedParams[i]; + if (param.optional || param.parameterArray) { + minParams--; + } + } + if (actualLen < minParams) { + error = true; + } + } + else if (validateParameterCount && (actualLen > expectedLen)) { + error = true; + for (i = 0; i < expectedLen; i++) { + if (expectedParams[i].parameterArray) { + error = false; + break; + } + } + } + if (error) { + var e = Error.parameterCount(); + e.popStackFrame(); + return e; + } + return null; +} +Function._validateParameter = function Function$_validateParameter(param, expectedParam, paramName) { + var e, + expectedType = expectedParam.type, + expectedInteger = !!expectedParam.integer, + expectedDomElement = !!expectedParam.domElement, + mayBeNull = !!expectedParam.mayBeNull; + e = Function._validateParameterType(param, expectedType, expectedInteger, expectedDomElement, mayBeNull, paramName); + if (e) { + e.popStackFrame(); + return e; + } + var expectedElementType = expectedParam.elementType, + elementMayBeNull = !!expectedParam.elementMayBeNull; + if (expectedType === Array && typeof(param) !== "undefined" && param !== null && + (expectedElementType || !elementMayBeNull)) { + var expectedElementInteger = !!expectedParam.elementInteger, + expectedElementDomElement = !!expectedParam.elementDomElement; + for (var i=0; i < param.length; i++) { + var elem = param[i]; + e = Function._validateParameterType(elem, expectedElementType, + expectedElementInteger, expectedElementDomElement, elementMayBeNull, + paramName + "[" + i + "]"); + if (e) { + e.popStackFrame(); + return e; + } + } + } + return null; +} +Function._validateParameterType = function Function$_validateParameterType(param, expectedType, expectedInteger, expectedDomElement, mayBeNull, paramName) { + var e, i; + if (typeof(param) === "undefined") { + if (mayBeNull) { + return null; + } + else { + e = Error.argumentUndefined(paramName); + e.popStackFrame(); + return e; + } + } + if (param === null) { + if (mayBeNull) { + return null; + } + else { + e = Error.argumentNull(paramName); + e.popStackFrame(); + return e; + } + } + if (expectedType && expectedType.__enum) { + if (typeof(param) !== 'number') { + e = Error.argumentType(paramName, Object.getType(param), expectedType); + e.popStackFrame(); + return e; + } + if ((param % 1) === 0) { + var values = expectedType.prototype; + if (!expectedType.__flags || (param === 0)) { + for (i in values) { + if (values[i] === param) return null; + } + } + else { + var v = param; + for (i in values) { + var vali = values[i]; + if (vali === 0) continue; + if ((vali & param) === vali) { + v -= vali; + } + if (v === 0) return null; + } + } + } + e = Error.argumentOutOfRange(paramName, param, String.format(Sys.Res.enumInvalidValue, param, expectedType.getName())); + e.popStackFrame(); + return e; + } + if (expectedDomElement && (!Sys._isDomElement(param) || (param.nodeType === 3))) { + e = Error.argument(paramName, Sys.Res.argumentDomElement); + e.popStackFrame(); + return e; + } + if (expectedType && !Sys._isInstanceOfType(expectedType, param)) { + e = Error.argumentType(paramName, Object.getType(param), expectedType); + e.popStackFrame(); + return e; + } + if (expectedType === Number && expectedInteger) { + if ((param % 1) !== 0) { + e = Error.argumentOutOfRange(paramName, param, Sys.Res.argumentInteger); + e.popStackFrame(); + return e; + } + } + return null; +} + +Error.__typeName = 'Error'; +Error.__class = true; +Error.create = function Error$create(message, errorInfo) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "message", type: String, mayBeNull: true, optional: true}, + {name: "errorInfo", mayBeNull: true, optional: true} + ]); + if (e) throw e; + var err = new Error(message); + err.message = message; + if (errorInfo) { + for (var v in errorInfo) { + err[v] = errorInfo[v]; + } + } + err.popStackFrame(); + return err; +} +Error.argument = function Error$argument(paramName, message) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "paramName", type: String, mayBeNull: true, optional: true}, + {name: "message", type: String, mayBeNull: true, optional: true} + ]); + if (e) throw e; + var displayMessage = "Sys.ArgumentException: " + (message ? message : Sys.Res.argument); + if (paramName) { + displayMessage += "\n" + String.format(Sys.Res.paramName, paramName); + } + var err = Error.create(displayMessage, { name: "Sys.ArgumentException", paramName: paramName }); + err.popStackFrame(); + return err; +} +Error.argumentNull = function Error$argumentNull(paramName, message) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "paramName", type: String, mayBeNull: true, optional: true}, + {name: "message", type: String, mayBeNull: true, optional: true} + ]); + if (e) throw e; + var displayMessage = "Sys.ArgumentNullException: " + (message ? message : Sys.Res.argumentNull); + if (paramName) { + displayMessage += "\n" + String.format(Sys.Res.paramName, paramName); + } + var err = Error.create(displayMessage, { name: "Sys.ArgumentNullException", paramName: paramName }); + err.popStackFrame(); + return err; +} +Error.argumentOutOfRange = function Error$argumentOutOfRange(paramName, actualValue, message) { + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "paramName", type: String, mayBeNull: true, optional: true}, + {name: "actualValue", mayBeNull: true, optional: true}, + {name: "message", type: String, mayBeNull: true, optional: true} + ]); + if (e) throw e; + var displayMessage = "Sys.ArgumentOutOfRangeException: " + (message ? message : Sys.Res.argumentOutOfRange); + if (paramName) { + displayMessage += "\n" + String.format(Sys.Res.paramName, paramName); + } + if (typeof(actualValue) !== "undefined" && actualValue !== null) { + displayMessage += "\n" + String.format(Sys.Res.actualValue, actualValue); + } + var err = Error.create(displayMessage, { + name: "Sys.ArgumentOutOfRangeException", + paramName: paramName, + actualValue: actualValue + }); + err.popStackFrame(); + return err; +} +Error.argumentType = function Error$argumentType(paramName, actualType, expectedType, message) { + /// + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "paramName", type: String, mayBeNull: true, optional: true}, + {name: "actualType", type: Type, mayBeNull: true, optional: true}, + {name: "expectedType", type: Type, mayBeNull: true, optional: true}, + {name: "message", type: String, mayBeNull: true, optional: true} + ]); + if (e) throw e; + var displayMessage = "Sys.ArgumentTypeException: "; + if (message) { + displayMessage += message; + } + else if (actualType && expectedType) { + displayMessage += + String.format(Sys.Res.argumentTypeWithTypes, actualType.getName(), expectedType.getName()); + } + else { + displayMessage += Sys.Res.argumentType; + } + if (paramName) { + displayMessage += "\n" + String.format(Sys.Res.paramName, paramName); + } + var err = Error.create(displayMessage, { + name: "Sys.ArgumentTypeException", + paramName: paramName, + actualType: actualType, + expectedType: expectedType + }); + err.popStackFrame(); + return err; +} +Error.argumentUndefined = function Error$argumentUndefined(paramName, message) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "paramName", type: String, mayBeNull: true, optional: true}, + {name: "message", type: String, mayBeNull: true, optional: true} + ]); + if (e) throw e; + var displayMessage = "Sys.ArgumentUndefinedException: " + (message ? message : Sys.Res.argumentUndefined); + if (paramName) { + displayMessage += "\n" + String.format(Sys.Res.paramName, paramName); + } + var err = Error.create(displayMessage, { name: "Sys.ArgumentUndefinedException", paramName: paramName }); + err.popStackFrame(); + return err; +} +Error.format = function Error$format(message) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "message", type: String, mayBeNull: true, optional: true} + ]); + if (e) throw e; + var displayMessage = "Sys.FormatException: " + (message ? message : Sys.Res.format); + var err = Error.create(displayMessage, {name: 'Sys.FormatException'}); + err.popStackFrame(); + return err; +} +Error.invalidOperation = function Error$invalidOperation(message) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "message", type: String, mayBeNull: true, optional: true} + ]); + if (e) throw e; + var displayMessage = "Sys.InvalidOperationException: " + (message ? message : Sys.Res.invalidOperation); + var err = Error.create(displayMessage, {name: 'Sys.InvalidOperationException'}); + err.popStackFrame(); + return err; +} +Error.notImplemented = function Error$notImplemented(message) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "message", type: String, mayBeNull: true, optional: true} + ]); + if (e) throw e; + var displayMessage = "Sys.NotImplementedException: " + (message ? message : Sys.Res.notImplemented); + var err = Error.create(displayMessage, {name: 'Sys.NotImplementedException'}); + err.popStackFrame(); + return err; +} +Error.parameterCount = function Error$parameterCount(message) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "message", type: String, mayBeNull: true, optional: true} + ]); + if (e) throw e; + var displayMessage = "Sys.ParameterCountException: " + (message ? message : Sys.Res.parameterCount); + var err = Error.create(displayMessage, {name: 'Sys.ParameterCountException'}); + err.popStackFrame(); + return err; +} +Error.prototype.popStackFrame = function Error$popStackFrame() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (typeof(this.stack) === "undefined" || this.stack === null || + typeof(this.fileName) === "undefined" || this.fileName === null || + typeof(this.lineNumber) === "undefined" || this.lineNumber === null) { + return; + } + var stackFrames = this.stack.split("\n"); + var currentFrame = stackFrames[0]; + var pattern = this.fileName + ":" + this.lineNumber; + while(typeof(currentFrame) !== "undefined" && + currentFrame !== null && + currentFrame.indexOf(pattern) === -1) { + stackFrames.shift(); + currentFrame = stackFrames[0]; + } + var nextFrame = stackFrames[1]; + if (typeof(nextFrame) === "undefined" || nextFrame === null) { + return; + } + var nextFrameParts = nextFrame.match(/@(.*):(\d+)$/); + if (typeof(nextFrameParts) === "undefined" || nextFrameParts === null) { + return; + } + this.fileName = nextFrameParts[1]; + this.lineNumber = parseInt(nextFrameParts[2]); + stackFrames.shift(); + this.stack = stackFrames.join("\n"); +} + +Object.__typeName = 'Object'; +Object.__class = true; +Object.getType = function Object$getType(instance) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "instance"} + ]); + if (e) throw e; + var ctor = instance.constructor; + if (!ctor || (typeof(ctor) !== "function") || !ctor.__typeName || (ctor.__typeName === 'Object')) { + return Object; + } + return ctor; +} +Object.getTypeName = function Object$getTypeName(instance) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "instance"} + ]); + if (e) throw e; + return Object.getType(instance).getName(); +} + +String.__typeName = 'String'; +String.__class = true; +String.prototype.endsWith = function String$endsWith(suffix) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "suffix", type: String} + ]); + if (e) throw e; + return (this.substr(this.length - suffix.length) === suffix); +} +String.prototype.startsWith = function String$startsWith(prefix) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "prefix", type: String} + ]); + if (e) throw e; + return (this.substr(0, prefix.length) === prefix); +} +String.prototype.trim = function String$trim() { + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this.replace(/^\s+|\s+$/g, ''); +} +String.prototype.trimEnd = function String$trimEnd() { + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this.replace(/\s+$/, ''); +} +String.prototype.trimStart = function String$trimStart() { + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this.replace(/^\s+/, ''); +} +String.format = function String$format(format, args) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "format", type: String}, + {name: "args", mayBeNull: true, parameterArray: true} + ]); + if (e) throw e; + return String._toFormattedString(false, arguments); +} +String._toFormattedString = function String$_toFormattedString(useLocale, args) { + var result = ''; + var format = args[0]; + for (var i=0;;) { + var open = format.indexOf('{', i); + var close = format.indexOf('}', i); + if ((open < 0) && (close < 0)) { + result += format.slice(i); + break; + } + if ((close > 0) && ((close < open) || (open < 0))) { + if (format.charAt(close + 1) !== '}') { + throw Error.argument('format', Sys.Res.stringFormatBraceMismatch); + } + result += format.slice(i, close + 1); + i = close + 2; + continue; + } + result += format.slice(i, open); + i = open + 1; + if (format.charAt(i) === '{') { + result += '{'; + i++; + continue; + } + if (close < 0) throw Error.argument('format', Sys.Res.stringFormatBraceMismatch); + var brace = format.substring(i, close); + var colonIndex = brace.indexOf(':'); + var argNumber = parseInt((colonIndex < 0)? brace : brace.substring(0, colonIndex), 10) + 1; + if (isNaN(argNumber)) throw Error.argument('format', Sys.Res.stringFormatInvalid); + var argFormat = (colonIndex < 0)? '' : brace.substring(colonIndex + 1); + var arg = args[argNumber]; + if (typeof(arg) === "undefined" || arg === null) { + arg = ''; + } + if (arg.toFormattedString) { + result += arg.toFormattedString(argFormat); + } + else if (useLocale && arg.localeFormat) { + result += arg.localeFormat(argFormat); + } + else if (arg.format) { + result += arg.format(argFormat); + } + else + result += arg.toString(); + i = close + 1; + } + return result; +} + +Boolean.__typeName = 'Boolean'; +Boolean.__class = true; +Boolean.parse = function Boolean$parse(value) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "value", type: String} + ], false); + if (e) throw e; + var v = value.trim().toLowerCase(); + if (v === 'false') return false; + if (v === 'true') return true; + throw Error.argumentOutOfRange('value', value, Sys.Res.boolTrueOrFalse); +} + +Date.__typeName = 'Date'; +Date.__class = true; + +Number.__typeName = 'Number'; +Number.__class = true; + +RegExp.__typeName = 'RegExp'; +RegExp.__class = true; + +if (!window) this.window = this; +window.Type = Function; +Type.__fullyQualifiedIdentifierRegExp = new RegExp("^[^.0-9 \\s|,;:&*=+\\-()\\[\\]{}^%#@!~\\n\\r\\t\\f\\\\]([^ \\s|,;:&*=+\\-()\\[\\]{}^%#@!~\\n\\r\\t\\f\\\\]*[^. \\s|,;:&*=+\\-()\\[\\]{}^%#@!~\\n\\r\\t\\f\\\\])?$", "i"); +Type.__identifierRegExp = new RegExp("^[^.0-9 \\s|,;:&*=+\\-()\\[\\]{}^%#@!~\\n\\r\\t\\f\\\\][^. \\s|,;:&*=+\\-()\\[\\]{}^%#@!~\\n\\r\\t\\f\\\\]*$", "i"); +Type.prototype.callBaseMethod = function Type$callBaseMethod(instance, name, baseArguments) { + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "instance"}, + {name: "name", type: String}, + {name: "baseArguments", type: Array, mayBeNull: true, optional: true, elementMayBeNull: true} + ]); + if (e) throw e; + var baseMethod = Sys._getBaseMethod(this, instance, name); + if (!baseMethod) throw Error.invalidOperation(String.format(Sys.Res.methodNotFound, name)); + if (!baseArguments) { + return baseMethod.apply(instance); + } + else { + return baseMethod.apply(instance, baseArguments); + } +} +Type.prototype.getBaseMethod = function Type$getBaseMethod(instance, name) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "instance"}, + {name: "name", type: String} + ]); + if (e) throw e; + return Sys._getBaseMethod(this, instance, name); +} +Type.prototype.getBaseType = function Type$getBaseType() { + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return (typeof(this.__baseType) === "undefined") ? null : this.__baseType; +} +Type.prototype.getInterfaces = function Type$getInterfaces() { + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + var result = []; + var type = this; + while(type) { + var interfaces = type.__interfaces; + if (interfaces) { + for (var i = 0, l = interfaces.length; i < l; i++) { + var interfaceType = interfaces[i]; + if (!Array.contains(result, interfaceType)) { + result[result.length] = interfaceType; + } + } + } + type = type.__baseType; + } + return result; +} +Type.prototype.getName = function Type$getName() { + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return (typeof(this.__typeName) === "undefined") ? "" : this.__typeName; +} +Type.prototype.implementsInterface = function Type$implementsInterface(interfaceType) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "interfaceType", type: Type} + ]); + if (e) throw e; + this.resolveInheritance(); + var interfaceName = interfaceType.getName(); + var cache = this.__interfaceCache; + if (cache) { + var cacheEntry = cache[interfaceName]; + if (typeof(cacheEntry) !== 'undefined') return cacheEntry; + } + else { + cache = this.__interfaceCache = {}; + } + var baseType = this; + while (baseType) { + var interfaces = baseType.__interfaces; + if (interfaces) { + if (Array.indexOf(interfaces, interfaceType) !== -1) { + return cache[interfaceName] = true; + } + } + baseType = baseType.__baseType; + } + return cache[interfaceName] = false; +} +Type.prototype.inheritsFrom = function Type$inheritsFrom(parentType) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "parentType", type: Type} + ]); + if (e) throw e; + this.resolveInheritance(); + var baseType = this.__baseType; + while (baseType) { + if (baseType === parentType) { + return true; + } + baseType = baseType.__baseType; + } + return false; +} +Type.prototype.initializeBase = function Type$initializeBase(instance, baseArguments) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "instance"}, + {name: "baseArguments", type: Array, mayBeNull: true, optional: true, elementMayBeNull: true} + ]); + if (e) throw e; + if (!Sys._isInstanceOfType(this, instance)) throw Error.argumentType('instance', Object.getType(instance), this); + this.resolveInheritance(); + if (this.__baseType) { + if (!baseArguments) { + this.__baseType.apply(instance); + } + else { + this.__baseType.apply(instance, baseArguments); + } + } + return instance; +} +Type.prototype.isImplementedBy = function Type$isImplementedBy(instance) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "instance", mayBeNull: true} + ]); + if (e) throw e; + if (typeof(instance) === "undefined" || instance === null) return false; + var instanceType = Object.getType(instance); + return !!(instanceType.implementsInterface && instanceType.implementsInterface(this)); +} +Type.prototype.isInstanceOfType = function Type$isInstanceOfType(instance) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "instance", mayBeNull: true} + ]); + if (e) throw e; + return Sys._isInstanceOfType(this, instance); +} +Type.prototype.registerClass = function Type$registerClass(typeName, baseType, interfaceTypes) { + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "typeName", type: String}, + {name: "baseType", type: Type, mayBeNull: true, optional: true}, + {name: "interfaceTypes", type: Type, parameterArray: true} + ]); + if (e) throw e; + if (!Type.__fullyQualifiedIdentifierRegExp.test(typeName)) throw Error.argument('typeName', Sys.Res.notATypeName); + var parsedName; + try { + parsedName = eval(typeName); + } + catch(e) { + throw Error.argument('typeName', Sys.Res.argumentTypeName); + } + if (parsedName !== this) throw Error.argument('typeName', Sys.Res.badTypeName); + if (Sys.__registeredTypes[typeName]) throw Error.invalidOperation(String.format(Sys.Res.typeRegisteredTwice, typeName)); + if ((arguments.length > 1) && (typeof(baseType) === 'undefined')) throw Error.argumentUndefined('baseType'); + if (baseType && !baseType.__class) throw Error.argument('baseType', Sys.Res.baseNotAClass); + this.prototype.constructor = this; + this.__typeName = typeName; + this.__class = true; + if (baseType) { + this.__baseType = baseType; + this.__basePrototypePending = true; + } + Sys.__upperCaseTypes[typeName.toUpperCase()] = this; + if (interfaceTypes) { + this.__interfaces = []; + this.resolveInheritance(); + for (var i = 2, l = arguments.length; i < l; i++) { + var interfaceType = arguments[i]; + if (!interfaceType.__interface) throw Error.argument('interfaceTypes[' + (i - 2) + ']', Sys.Res.notAnInterface); + for (var methodName in interfaceType.prototype) { + var method = interfaceType.prototype[methodName]; + if (!this.prototype[methodName]) { + this.prototype[methodName] = method; + } + } + this.__interfaces.push(interfaceType); + } + } + Sys.__registeredTypes[typeName] = true; + return this; +} +Type.prototype.registerInterface = function Type$registerInterface(typeName) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "typeName", type: String} + ]); + if (e) throw e; + if (!Type.__fullyQualifiedIdentifierRegExp.test(typeName)) throw Error.argument('typeName', Sys.Res.notATypeName); + var parsedName; + try { + parsedName = eval(typeName); + } + catch(e) { + throw Error.argument('typeName', Sys.Res.argumentTypeName); + } + if (parsedName !== this) throw Error.argument('typeName', Sys.Res.badTypeName); + if (Sys.__registeredTypes[typeName]) throw Error.invalidOperation(String.format(Sys.Res.typeRegisteredTwice, typeName)); + Sys.__upperCaseTypes[typeName.toUpperCase()] = this; + this.prototype.constructor = this; + this.__typeName = typeName; + this.__interface = true; + Sys.__registeredTypes[typeName] = true; + return this; +} +Type.prototype.resolveInheritance = function Type$resolveInheritance() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (this.__basePrototypePending) { + var baseType = this.__baseType; + baseType.resolveInheritance(); + for (var memberName in baseType.prototype) { + var memberValue = baseType.prototype[memberName]; + if (!this.prototype[memberName]) { + this.prototype[memberName] = memberValue; + } + } + delete this.__basePrototypePending; + } +} +Type.getRootNamespaces = function Type$getRootNamespaces() { + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return Array.clone(Sys.__rootNamespaces); +} +Type.isClass = function Type$isClass(type) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "type", mayBeNull: true} + ]); + if (e) throw e; + if ((typeof(type) === 'undefined') || (type === null)) return false; + return !!type.__class; +} +Type.isInterface = function Type$isInterface(type) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "type", mayBeNull: true} + ]); + if (e) throw e; + if ((typeof(type) === 'undefined') || (type === null)) return false; + return !!type.__interface; +} +Type.isNamespace = function Type$isNamespace(object) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "object", mayBeNull: true} + ]); + if (e) throw e; + if ((typeof(object) === 'undefined') || (object === null)) return false; + return !!object.__namespace; +} +Type.parse = function Type$parse(typeName, ns) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "typeName", type: String, mayBeNull: true}, + {name: "ns", mayBeNull: true, optional: true} + ]); + if (e) throw e; + var fn; + if (ns) { + fn = Sys.__upperCaseTypes[ns.getName().toUpperCase() + '.' + typeName.toUpperCase()]; + return fn || null; + } + if (!typeName) return null; + if (!Type.__htClasses) { + Type.__htClasses = {}; + } + fn = Type.__htClasses[typeName]; + if (!fn) { + fn = eval(typeName); + if (typeof(fn) !== 'function') throw Error.argument('typeName', Sys.Res.notATypeName); + Type.__htClasses[typeName] = fn; + } + return fn; +} +Type.registerNamespace = function Type$registerNamespace(namespacePath) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "namespacePath", type: String} + ]); + if (e) throw e; + Type._registerNamespace(namespacePath); +} +Type._registerNamespace = function Type$_registerNamespace(namespacePath) { + if (!Type.__fullyQualifiedIdentifierRegExp.test(namespacePath)) throw Error.argument('namespacePath', Sys.Res.invalidNameSpace); + var rootObject = window; + var namespaceParts = namespacePath.split('.'); + for (var i = 0; i < namespaceParts.length; i++) { + var currentPart = namespaceParts[i]; + var ns = rootObject[currentPart]; + var nsType = typeof(ns); + if ((nsType !== "undefined") && (ns !== null)) { + if (nsType === "function") { + throw Error.invalidOperation(String.format(Sys.Res.namespaceContainsClass, namespaceParts.splice(0, i + 1).join('.'))); + } + if ((typeof(ns) !== "object") || (ns instanceof Array)) { + throw Error.invalidOperation(String.format(Sys.Res.namespaceContainsNonObject, namespaceParts.splice(0, i + 1).join('.'))); + } + } + if (!ns) { + ns = rootObject[currentPart] = {}; + } + if (!ns.__namespace) { + if ((i === 0) && (namespacePath !== "Sys")) { + Sys.__rootNamespaces[Sys.__rootNamespaces.length] = ns; + } + ns.__namespace = true; + ns.__typeName = namespaceParts.slice(0, i + 1).join('.'); + var parsedName; + try { + parsedName = eval(ns.__typeName); + } + catch(e) { + parsedName = null; + } + if (parsedName !== ns) { + delete rootObject[currentPart]; + throw Error.argument('namespacePath', Sys.Res.invalidNameSpace); + } + ns.getName = function ns$getName() {return this.__typeName;} + } + rootObject = ns; + } +} +Type._checkDependency = function Type$_checkDependency(dependency, featureName) { + var scripts = Type._registerScript._scripts, isDependent = (scripts ? (!!scripts[dependency]) : false); + if ((typeof(featureName) !== 'undefined') && !isDependent) { + throw Error.invalidOperation(String.format(Sys.Res.requiredScriptReferenceNotIncluded, + featureName, dependency)); + } + return isDependent; +} +Type._registerScript = function Type$_registerScript(scriptName, dependencies) { + var scripts = Type._registerScript._scripts; + if (!scripts) { + Type._registerScript._scripts = scripts = {}; + } + if (scripts[scriptName]) { + throw Error.invalidOperation(String.format(Sys.Res.scriptAlreadyLoaded, scriptName)); + } + scripts[scriptName] = true; + if (dependencies) { + for (var i = 0, l = dependencies.length; i < l; i++) { + var dependency = dependencies[i]; + if (!Type._checkDependency(dependency)) { + throw Error.invalidOperation(String.format(Sys.Res.scriptDependencyNotFound, scriptName, dependency)); + } + } + } +} +Type._registerNamespace("Sys"); +Sys.__upperCaseTypes = {}; +Sys.__rootNamespaces = [Sys]; +Sys.__registeredTypes = {}; +Sys._isInstanceOfType = function Sys$_isInstanceOfType(type, instance) { + if (typeof(instance) === "undefined" || instance === null) return false; + if (instance instanceof type) return true; + var instanceType = Object.getType(instance); + return !!(instanceType === type) || + (instanceType.inheritsFrom && instanceType.inheritsFrom(type)) || + (instanceType.implementsInterface && instanceType.implementsInterface(type)); +} +Sys._getBaseMethod = function Sys$_getBaseMethod(type, instance, name) { + if (!Sys._isInstanceOfType(type, instance)) throw Error.argumentType('instance', Object.getType(instance), type); + var baseType = type.getBaseType(); + if (baseType) { + var baseMethod = baseType.prototype[name]; + return (baseMethod instanceof Function) ? baseMethod : null; + } + return null; +} +Sys._isDomElement = function Sys$_isDomElement(obj) { + var val = false; + if (typeof (obj.nodeType) !== 'number') { + var doc = obj.ownerDocument || obj.document || obj; + if (doc != obj) { + var w = doc.defaultView || doc.parentWindow; + val = (w != obj); + } + else { + val = (typeof (doc.body) === 'undefined'); + } + } + return !val; +} + +Array.__typeName = 'Array'; +Array.__class = true; +Array.add = Array.enqueue = function Array$enqueue(array, item) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "array", type: Array, elementMayBeNull: true}, + {name: "item", mayBeNull: true} + ]); + if (e) throw e; + array[array.length] = item; +} +Array.addRange = function Array$addRange(array, items) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "array", type: Array, elementMayBeNull: true}, + {name: "items", type: Array, elementMayBeNull: true} + ]); + if (e) throw e; + array.push.apply(array, items); +} +Array.clear = function Array$clear(array) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "array", type: Array, elementMayBeNull: true} + ]); + if (e) throw e; + array.length = 0; +} +Array.clone = function Array$clone(array) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "array", type: Array, elementMayBeNull: true} + ]); + if (e) throw e; + if (array.length === 1) { + return [array[0]]; + } + else { + return Array.apply(null, array); + } +} +Array.contains = function Array$contains(array, item) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "array", type: Array, elementMayBeNull: true}, + {name: "item", mayBeNull: true} + ]); + if (e) throw e; + return (Sys._indexOf(array, item) >= 0); +} +Array.dequeue = function Array$dequeue(array) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "array", type: Array, elementMayBeNull: true} + ]); + if (e) throw e; + return array.shift(); +} +Array.forEach = function Array$forEach(array, method, instance) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "array", type: Array, elementMayBeNull: true}, + {name: "method", type: Function}, + {name: "instance", mayBeNull: true, optional: true} + ]); + if (e) throw e; + for (var i = 0, l = array.length; i < l; i++) { + var elt = array[i]; + if (typeof(elt) !== 'undefined') method.call(instance, elt, i, array); + } +} +Array.indexOf = function Array$indexOf(array, item, start) { + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "array", type: Array, elementMayBeNull: true}, + {name: "item", mayBeNull: true, optional: true}, + {name: "start", mayBeNull: true, optional: true} + ]); + if (e) throw e; + return Sys._indexOf(array, item, start); +} +Array.insert = function Array$insert(array, index, item) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "array", type: Array, elementMayBeNull: true}, + {name: "index", mayBeNull: true}, + {name: "item", mayBeNull: true} + ]); + if (e) throw e; + array.splice(index, 0, item); +} +Array.parse = function Array$parse(value) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "value", type: String, mayBeNull: true} + ]); + if (e) throw e; + if (!value) return []; + var v = eval(value); + if (!Array.isInstanceOfType(v)) throw Error.argument('value', Sys.Res.arrayParseBadFormat); + return v; +} +Array.remove = function Array$remove(array, item) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "array", type: Array, elementMayBeNull: true}, + {name: "item", mayBeNull: true} + ]); + if (e) throw e; + var index = Sys._indexOf(array, item); + if (index >= 0) { + array.splice(index, 1); + } + return (index >= 0); +} +Array.removeAt = function Array$removeAt(array, index) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "array", type: Array, elementMayBeNull: true}, + {name: "index", mayBeNull: true} + ]); + if (e) throw e; + array.splice(index, 1); +} +Sys._indexOf = function Sys$_indexOf(array, item, start) { + if (typeof(item) === "undefined") return -1; + var length = array.length; + if (length !== 0) { + start = start - 0; + if (isNaN(start)) { + start = 0; + } + else { + if (isFinite(start)) { + start = start - (start % 1); + } + if (start < 0) { + start = Math.max(0, length + start); + } + } + for (var i = start; i < length; i++) { + if ((typeof(array[i]) !== "undefined") && (array[i] === item)) { + return i; + } + } + } + return -1; +} +Type._registerScript._scripts = { + "MicrosoftAjaxCore.js": true, + "MicrosoftAjaxGlobalization.js": true, + "MicrosoftAjaxSerialization.js": true, + "MicrosoftAjaxComponentModel.js": true, + "MicrosoftAjaxHistory.js": true, + "MicrosoftAjaxNetwork.js" : true, + "MicrosoftAjaxWebServices.js": true }; + +Sys.IDisposable = function Sys$IDisposable() { + throw Error.notImplemented(); +} + function Sys$IDisposable$dispose() { + throw Error.notImplemented(); + } +Sys.IDisposable.prototype = { + dispose: Sys$IDisposable$dispose +} +Sys.IDisposable.registerInterface('Sys.IDisposable'); + +Sys.StringBuilder = function Sys$StringBuilder(initialText) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "initialText", mayBeNull: true, optional: true} + ]); + if (e) throw e; + this._parts = (typeof(initialText) !== 'undefined' && initialText !== null && initialText !== '') ? + [initialText.toString()] : []; + this._value = {}; + this._len = 0; +} + function Sys$StringBuilder$append(text) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "text", mayBeNull: true} + ]); + if (e) throw e; + this._parts[this._parts.length] = text; + } + function Sys$StringBuilder$appendLine(text) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "text", mayBeNull: true, optional: true} + ]); + if (e) throw e; + this._parts[this._parts.length] = + ((typeof(text) === 'undefined') || (text === null) || (text === '')) ? + '\r\n' : text + '\r\n'; + } + function Sys$StringBuilder$clear() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + this._parts = []; + this._value = {}; + this._len = 0; + } + function Sys$StringBuilder$isEmpty() { + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (this._parts.length === 0) return true; + return this.toString() === ''; + } + function Sys$StringBuilder$toString(separator) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "separator", type: String, mayBeNull: true, optional: true} + ]); + if (e) throw e; + separator = separator || ''; + var parts = this._parts; + if (this._len !== parts.length) { + this._value = {}; + this._len = parts.length; + } + var val = this._value; + if (typeof(val[separator]) === 'undefined') { + if (separator !== '') { + for (var i = 0; i < parts.length;) { + if ((typeof(parts[i]) === 'undefined') || (parts[i] === '') || (parts[i] === null)) { + parts.splice(i, 1); + } + else { + i++; + } + } + } + val[separator] = this._parts.join(separator); + } + return val[separator]; + } +Sys.StringBuilder.prototype = { + append: Sys$StringBuilder$append, + appendLine: Sys$StringBuilder$appendLine, + clear: Sys$StringBuilder$clear, + isEmpty: Sys$StringBuilder$isEmpty, + toString: Sys$StringBuilder$toString +} +Sys.StringBuilder.registerClass('Sys.StringBuilder'); + +Sys.Browser = {}; +Sys.Browser.InternetExplorer = {}; +Sys.Browser.Firefox = {}; +Sys.Browser.Safari = {}; +Sys.Browser.Opera = {}; +Sys.Browser.agent = null; +Sys.Browser.hasDebuggerStatement = false; +Sys.Browser.name = navigator.appName; +Sys.Browser.version = parseFloat(navigator.appVersion); +Sys.Browser.documentMode = 0; +if (navigator.userAgent.indexOf(' MSIE ') > -1) { + Sys.Browser.agent = Sys.Browser.InternetExplorer; + Sys.Browser.version = parseFloat(navigator.userAgent.match(/MSIE (\d+\.\d+)/)[1]); + if (Sys.Browser.version >= 8) { + if (document.documentMode >= 7) { + Sys.Browser.documentMode = document.documentMode; + } + } + Sys.Browser.hasDebuggerStatement = true; +} +else if (navigator.userAgent.indexOf(' Firefox/') > -1) { + Sys.Browser.agent = Sys.Browser.Firefox; + Sys.Browser.version = parseFloat(navigator.userAgent.match(/ Firefox\/(\d+\.\d+)/)[1]); + Sys.Browser.name = 'Firefox'; + Sys.Browser.hasDebuggerStatement = true; +} +else if (navigator.userAgent.indexOf(' AppleWebKit/') > -1) { + Sys.Browser.agent = Sys.Browser.Safari; + Sys.Browser.version = parseFloat(navigator.userAgent.match(/ AppleWebKit\/(\d+(\.\d+)?)/)[1]); + Sys.Browser.name = 'Safari'; +} +else if (navigator.userAgent.indexOf('Opera/') > -1) { + Sys.Browser.agent = Sys.Browser.Opera; +} + +Sys.EventArgs = function Sys$EventArgs() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); +} +Sys.EventArgs.registerClass('Sys.EventArgs'); +Sys.EventArgs.Empty = new Sys.EventArgs(); + +Sys.CancelEventArgs = function Sys$CancelEventArgs() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + Sys.CancelEventArgs.initializeBase(this); + this._cancel = false; +} + function Sys$CancelEventArgs$get_cancel() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._cancel; + } + function Sys$CancelEventArgs$set_cancel(value) { + var e = Function._validateParams(arguments, [{name: "value", type: Boolean}]); + if (e) throw e; + this._cancel = value; + } +Sys.CancelEventArgs.prototype = { + get_cancel: Sys$CancelEventArgs$get_cancel, + set_cancel: Sys$CancelEventArgs$set_cancel +} +Sys.CancelEventArgs.registerClass('Sys.CancelEventArgs', Sys.EventArgs); +Type.registerNamespace('Sys.UI'); + +Sys._Debug = function Sys$_Debug() { + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); +} + function Sys$_Debug$_appendConsole(text) { + if ((typeof(Debug) !== 'undefined') && Debug.writeln) { + Debug.writeln(text); + } + if (window.console && window.console.log) { + window.console.log(text); + } + if (window.opera) { + window.opera.postError(text); + } + if (window.debugService) { + window.debugService.trace(text); + } + } + function Sys$_Debug$_appendTrace(text) { + var traceElement = document.getElementById('TraceConsole'); + if (traceElement && (traceElement.tagName.toUpperCase() === 'TEXTAREA')) { + traceElement.value += text + '\n'; + } + } + function Sys$_Debug$assert(condition, message, displayCaller) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "condition", type: Boolean}, + {name: "message", type: String, mayBeNull: true, optional: true}, + {name: "displayCaller", type: Boolean, optional: true} + ]); + if (e) throw e; + if (!condition) { + message = (displayCaller && this.assert.caller) ? + String.format(Sys.Res.assertFailedCaller, message, this.assert.caller) : + String.format(Sys.Res.assertFailed, message); + if (confirm(String.format(Sys.Res.breakIntoDebugger, message))) { + this.fail(message); + } + } + } + function Sys$_Debug$clearTrace() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + var traceElement = document.getElementById('TraceConsole'); + if (traceElement && (traceElement.tagName.toUpperCase() === 'TEXTAREA')) { + traceElement.value = ''; + } + } + function Sys$_Debug$fail(message) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "message", type: String, mayBeNull: true} + ]); + if (e) throw e; + this._appendConsole(message); + if (Sys.Browser.hasDebuggerStatement) { + eval('debugger'); + } + } + function Sys$_Debug$trace(text) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "text"} + ]); + if (e) throw e; + this._appendConsole(text); + this._appendTrace(text); + } + function Sys$_Debug$traceDump(object, name) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "object", mayBeNull: true}, + {name: "name", type: String, mayBeNull: true, optional: true} + ]); + if (e) throw e; + var text = this._traceDump(object, name, true); + } + function Sys$_Debug$_traceDump(object, name, recursive, indentationPadding, loopArray) { + name = name? name : 'traceDump'; + indentationPadding = indentationPadding? indentationPadding : ''; + if (object === null) { + this.trace(indentationPadding + name + ': null'); + return; + } + switch(typeof(object)) { + case 'undefined': + this.trace(indentationPadding + name + ': Undefined'); + break; + case 'number': case 'string': case 'boolean': + this.trace(indentationPadding + name + ': ' + object); + break; + default: + if (Date.isInstanceOfType(object) || RegExp.isInstanceOfType(object)) { + this.trace(indentationPadding + name + ': ' + object.toString()); + break; + } + if (!loopArray) { + loopArray = []; + } + else if (Array.contains(loopArray, object)) { + this.trace(indentationPadding + name + ': ...'); + return; + } + Array.add(loopArray, object); + if ((object == window) || (object === document) || + (window.HTMLElement && (object instanceof HTMLElement)) || + (typeof(object.nodeName) === 'string')) { + var tag = object.tagName? object.tagName : 'DomElement'; + if (object.id) { + tag += ' - ' + object.id; + } + this.trace(indentationPadding + name + ' {' + tag + '}'); + } + else { + var typeName = Object.getTypeName(object); + this.trace(indentationPadding + name + (typeof(typeName) === 'string' ? ' {' + typeName + '}' : '')); + if ((indentationPadding === '') || recursive) { + indentationPadding += " "; + var i, length, properties, p, v; + if (Array.isInstanceOfType(object)) { + length = object.length; + for (i = 0; i < length; i++) { + this._traceDump(object[i], '[' + i + ']', recursive, indentationPadding, loopArray); + } + } + else { + for (p in object) { + v = object[p]; + if (!Function.isInstanceOfType(v)) { + this._traceDump(v, p, recursive, indentationPadding, loopArray); + } + } + } + } + } + Array.remove(loopArray, object); + } + } +Sys._Debug.prototype = { + _appendConsole: Sys$_Debug$_appendConsole, + _appendTrace: Sys$_Debug$_appendTrace, + assert: Sys$_Debug$assert, + clearTrace: Sys$_Debug$clearTrace, + fail: Sys$_Debug$fail, + trace: Sys$_Debug$trace, + traceDump: Sys$_Debug$traceDump, + _traceDump: Sys$_Debug$_traceDump +} +Sys._Debug.registerClass('Sys._Debug'); +Sys.Debug = new Sys._Debug(); + Sys.Debug.isDebug = true; + +function Sys$Enum$parse(value, ignoreCase) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "value", type: String}, + {name: "ignoreCase", type: Boolean, optional: true} + ]); + if (e) throw e; + var values, parsed, val; + if (ignoreCase) { + values = this.__lowerCaseValues; + if (!values) { + this.__lowerCaseValues = values = {}; + var prototype = this.prototype; + for (var name in prototype) { + values[name.toLowerCase()] = prototype[name]; + } + } + } + else { + values = this.prototype; + } + if (!this.__flags) { + val = (ignoreCase ? value.toLowerCase() : value); + parsed = values[val.trim()]; + if (typeof(parsed) !== 'number') throw Error.argument('value', String.format(Sys.Res.enumInvalidValue, value, this.__typeName)); + return parsed; + } + else { + var parts = (ignoreCase ? value.toLowerCase() : value).split(','); + var v = 0; + for (var i = parts.length - 1; i >= 0; i--) { + var part = parts[i].trim(); + parsed = values[part]; + if (typeof(parsed) !== 'number') throw Error.argument('value', String.format(Sys.Res.enumInvalidValue, value.split(',')[i].trim(), this.__typeName)); + v |= parsed; + } + return v; + } +} +function Sys$Enum$toString(value) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "value", mayBeNull: true, optional: true} + ]); + if (e) throw e; + if ((typeof(value) === 'undefined') || (value === null)) return this.__string; + if ((typeof(value) != 'number') || ((value % 1) !== 0)) throw Error.argumentType('value', Object.getType(value), this); + var values = this.prototype; + var i; + if (!this.__flags || (value === 0)) { + for (i in values) { + if (values[i] === value) { + return i; + } + } + } + else { + var sorted = this.__sortedValues; + if (!sorted) { + sorted = []; + for (i in values) { + sorted[sorted.length] = {key: i, value: values[i]}; + } + sorted.sort(function(a, b) { + return a.value - b.value; + }); + this.__sortedValues = sorted; + } + var parts = []; + var v = value; + for (i = sorted.length - 1; i >= 0; i--) { + var kvp = sorted[i]; + var vali = kvp.value; + if (vali === 0) continue; + if ((vali & value) === vali) { + parts[parts.length] = kvp.key; + v -= vali; + if (v === 0) break; + } + } + if (parts.length && v === 0) return parts.reverse().join(', '); + } + throw Error.argumentOutOfRange('value', value, String.format(Sys.Res.enumInvalidValue, value, this.__typeName)); +} +Type.prototype.registerEnum = function Type$registerEnum(name, flags) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "name", type: String}, + {name: "flags", type: Boolean, optional: true} + ]); + if (e) throw e; + if (!Type.__fullyQualifiedIdentifierRegExp.test(name)) throw Error.argument('name', Sys.Res.notATypeName); + var parsedName; + try { + parsedName = eval(name); + } + catch(e) { + throw Error.argument('name', Sys.Res.argumentTypeName); + } + if (parsedName !== this) throw Error.argument('name', Sys.Res.badTypeName); + if (Sys.__registeredTypes[name]) throw Error.invalidOperation(String.format(Sys.Res.typeRegisteredTwice, name)); + for (var j in this.prototype) { + var val = this.prototype[j]; + if (!Type.__identifierRegExp.test(j)) throw Error.invalidOperation(String.format(Sys.Res.enumInvalidValueName, j)); + if (typeof(val) !== 'number' || (val % 1) !== 0) throw Error.invalidOperation(Sys.Res.enumValueNotInteger); + if (typeof(this[j]) !== 'undefined') throw Error.invalidOperation(String.format(Sys.Res.enumReservedName, j)); + } + Sys.__upperCaseTypes[name.toUpperCase()] = this; + for (var i in this.prototype) { + this[i] = this.prototype[i]; + } + this.__typeName = name; + this.parse = Sys$Enum$parse; + this.__string = this.toString(); + this.toString = Sys$Enum$toString; + this.__flags = flags; + this.__enum = true; + Sys.__registeredTypes[name] = true; +} +Type.isEnum = function Type$isEnum(type) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "type", mayBeNull: true} + ]); + if (e) throw e; + if ((typeof(type) === 'undefined') || (type === null)) return false; + return !!type.__enum; +} +Type.isFlags = function Type$isFlags(type) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "type", mayBeNull: true} + ]); + if (e) throw e; + if ((typeof(type) === 'undefined') || (type === null)) return false; + return !!type.__flags; +} +Sys.CollectionChange = function Sys$CollectionChange(action, newItems, newStartingIndex, oldItems, oldStartingIndex) { + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "action", type: Sys.NotifyCollectionChangedAction}, + {name: "newItems", mayBeNull: true, optional: true}, + {name: "newStartingIndex", type: Number, mayBeNull: true, integer: true, optional: true}, + {name: "oldItems", mayBeNull: true, optional: true}, + {name: "oldStartingIndex", type: Number, mayBeNull: true, integer: true, optional: true} + ]); + if (e) throw e; + this.action = action; + if (newItems) { + if (!(newItems instanceof Array)) { + newItems = [newItems]; + } + } + this.newItems = newItems || null; + if (typeof newStartingIndex !== "number") { + newStartingIndex = -1; + } + this.newStartingIndex = newStartingIndex; + if (oldItems) { + if (!(oldItems instanceof Array)) { + oldItems = [oldItems]; + } + } + this.oldItems = oldItems || null; + if (typeof oldStartingIndex !== "number") { + oldStartingIndex = -1; + } + this.oldStartingIndex = oldStartingIndex; +} +Sys.CollectionChange.registerClass("Sys.CollectionChange"); +Sys.NotifyCollectionChangedAction = function Sys$NotifyCollectionChangedAction() { + /// + /// + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); +} +Sys.NotifyCollectionChangedAction.prototype = { + add: 0, + remove: 1, + reset: 2 +} +Sys.NotifyCollectionChangedAction.registerEnum('Sys.NotifyCollectionChangedAction'); +Sys.NotifyCollectionChangedEventArgs = function Sys$NotifyCollectionChangedEventArgs(changes) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "changes", type: Array, elementType: Sys.CollectionChange} + ]); + if (e) throw e; + this._changes = changes; + Sys.NotifyCollectionChangedEventArgs.initializeBase(this); +} + function Sys$NotifyCollectionChangedEventArgs$get_changes() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._changes || []; + } +Sys.NotifyCollectionChangedEventArgs.prototype = { + get_changes: Sys$NotifyCollectionChangedEventArgs$get_changes +} +Sys.NotifyCollectionChangedEventArgs.registerClass("Sys.NotifyCollectionChangedEventArgs", Sys.EventArgs); +Sys.Observer = function Sys$Observer() { + throw Error.invalidOperation(); +} +Sys.Observer.registerClass("Sys.Observer"); +Sys.Observer.makeObservable = function Sys$Observer$makeObservable(target) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target"} + ]); + if (e) throw e; + var isArray = target instanceof Array, + o = Sys.Observer; + Sys.Observer._ensureObservable(target); + if (target.setValue === o._observeMethods.setValue) return target; + o._addMethods(target, o._observeMethods); + if (isArray) { + o._addMethods(target, o._arrayMethods); + } + return target; +} +Sys.Observer._ensureObservable = function Sys$Observer$_ensureObservable(target) { + var type = typeof target; + if ((type === "string") || (type === "number") || (type === "boolean") || (type === "date")) { + throw Error.invalidOperation(String.format(Sys.Res.notObservable, type)); + } +} +Sys.Observer._addMethods = function Sys$Observer$_addMethods(target, methods) { + for (var m in methods) { + if (target[m] && (target[m] !== methods[m])) { + throw Error.invalidOperation(String.format(Sys.Res.observableConflict, m)); + } + target[m] = methods[m]; + } +} +Sys.Observer._addEventHandler = function Sys$Observer$_addEventHandler(target, eventName, handler) { + Sys.Observer._getContext(target, true).events._addHandler(eventName, handler); +} +Sys.Observer.addEventHandler = function Sys$Observer$addEventHandler(target, eventName, handler) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target"}, + {name: "eventName", type: String}, + {name: "handler", type: Function} + ]); + if (e) throw e; + Sys.Observer._ensureObservable(target); + Sys.Observer._addEventHandler(target, eventName, handler); +} +Sys.Observer._removeEventHandler = function Sys$Observer$_removeEventHandler(target, eventName, handler) { + Sys.Observer._getContext(target, true).events._removeHandler(eventName, handler); +} +Sys.Observer.removeEventHandler = function Sys$Observer$removeEventHandler(target, eventName, handler) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target"}, + {name: "eventName", type: String}, + {name: "handler", type: Function} + ]); + if (e) throw e; + Sys.Observer._ensureObservable(target); + Sys.Observer._removeEventHandler(target, eventName, handler); +} +Sys.Observer.raiseEvent = function Sys$Observer$raiseEvent(target, eventName, eventArgs) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target"}, + {name: "eventName", type: String}, + {name: "eventArgs", type: Sys.EventArgs} + ]); + if (e) throw e; + Sys.Observer._ensureObservable(target); + var ctx = Sys.Observer._getContext(target); + if (!ctx) return; + var handler = ctx.events.getHandler(eventName); + if (handler) { + handler(target, eventArgs); + } +} +Sys.Observer.addPropertyChanged = function Sys$Observer$addPropertyChanged(target, handler) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target"}, + {name: "handler", type: Function} + ]); + if (e) throw e; + Sys.Observer._ensureObservable(target); + Sys.Observer._addEventHandler(target, "propertyChanged", handler); +} +Sys.Observer.removePropertyChanged = function Sys$Observer$removePropertyChanged(target, handler) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target"}, + {name: "handler", type: Function} + ]); + if (e) throw e; + Sys.Observer._ensureObservable(target); + Sys.Observer._removeEventHandler(target, "propertyChanged", handler); +} +Sys.Observer.beginUpdate = function Sys$Observer$beginUpdate(target) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target"} + ]); + if (e) throw e; + Sys.Observer._ensureObservable(target); + Sys.Observer._getContext(target, true).updating = true; +} +Sys.Observer.endUpdate = function Sys$Observer$endUpdate(target) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target"} + ]); + if (e) throw e; + Sys.Observer._ensureObservable(target); + var ctx = Sys.Observer._getContext(target); + if (!ctx || !ctx.updating) return; + ctx.updating = false; + var dirty = ctx.dirty; + ctx.dirty = false; + if (dirty) { + if (target instanceof Array) { + var changes = ctx.changes; + ctx.changes = null; + Sys.Observer.raiseCollectionChanged(target, changes); + } + Sys.Observer.raisePropertyChanged(target, ""); + } +} +Sys.Observer.isUpdating = function Sys$Observer$isUpdating(target) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target"} + ]); + if (e) throw e; + Sys.Observer._ensureObservable(target); + var ctx = Sys.Observer._getContext(target); + return ctx ? ctx.updating : false; +} +Sys.Observer._setValue = function Sys$Observer$_setValue(target, propertyName, value) { + var getter, setter, mainTarget = target, path = propertyName.split('.'); + for (var i = 0, l = (path.length - 1); i < l ; i++) { + var name = path[i]; + getter = target["get_" + name]; + if (typeof (getter) === "function") { + target = getter.call(target); + } + else { + target = target[name]; + } + var type = typeof (target); + if ((target === null) || (type === "undefined")) { + throw Error.invalidOperation(String.format(Sys.Res.nullReferenceInPath, propertyName)); + } + } + var currentValue, lastPath = path[l]; + getter = target["get_" + lastPath]; + setter = target["set_" + lastPath]; + if (typeof(getter) === 'function') { + currentValue = getter.call(target); + } + else { + currentValue = target[lastPath]; + } + if (typeof(setter) === 'function') { + setter.call(target, value); + } + else { + target[lastPath] = value; + } + if (currentValue !== value) { + var ctx = Sys.Observer._getContext(mainTarget); + if (ctx && ctx.updating) { + ctx.dirty = true; + return; + }; + Sys.Observer.raisePropertyChanged(mainTarget, path[0]); + } +} +Sys.Observer.setValue = function Sys$Observer$setValue(target, propertyName, value) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target"}, + {name: "propertyName", type: String}, + {name: "value", mayBeNull: true} + ]); + if (e) throw e; + Sys.Observer._ensureObservable(target); + Sys.Observer._setValue(target, propertyName, value); +} +Sys.Observer.raisePropertyChanged = function Sys$Observer$raisePropertyChanged(target, propertyName) { + /// + /// + /// + Sys.Observer.raiseEvent(target, "propertyChanged", new Sys.PropertyChangedEventArgs(propertyName)); +} +Sys.Observer.addCollectionChanged = function Sys$Observer$addCollectionChanged(target, handler) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target", type: Array, elementMayBeNull: true}, + {name: "handler", type: Function} + ]); + if (e) throw e; + Sys.Observer._addEventHandler(target, "collectionChanged", handler); +} +Sys.Observer.removeCollectionChanged = function Sys$Observer$removeCollectionChanged(target, handler) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target", type: Array, elementMayBeNull: true}, + {name: "handler", type: Function} + ]); + if (e) throw e; + Sys.Observer._removeEventHandler(target, "collectionChanged", handler); +} +Sys.Observer._collectionChange = function Sys$Observer$_collectionChange(target, change) { + var ctx = Sys.Observer._getContext(target); + if (ctx && ctx.updating) { + ctx.dirty = true; + var changes = ctx.changes; + if (!changes) { + ctx.changes = changes = [change]; + } + else { + changes.push(change); + } + } + else { + Sys.Observer.raiseCollectionChanged(target, [change]); + Sys.Observer.raisePropertyChanged(target, 'length'); + } +} +Sys.Observer.add = function Sys$Observer$add(target, item) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target", type: Array, elementMayBeNull: true}, + {name: "item", mayBeNull: true} + ]); + if (e) throw e; + var change = new Sys.CollectionChange(Sys.NotifyCollectionChangedAction.add, [item], target.length); + Array.add(target, item); + Sys.Observer._collectionChange(target, change); +} +Sys.Observer.addRange = function Sys$Observer$addRange(target, items) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target", type: Array, elementMayBeNull: true}, + {name: "items", type: Array, elementMayBeNull: true} + ]); + if (e) throw e; + var change = new Sys.CollectionChange(Sys.NotifyCollectionChangedAction.add, items, target.length); + Array.addRange(target, items); + Sys.Observer._collectionChange(target, change); +} +Sys.Observer.clear = function Sys$Observer$clear(target) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target", type: Array, elementMayBeNull: true} + ]); + if (e) throw e; + var oldItems = Array.clone(target); + Array.clear(target); + Sys.Observer._collectionChange(target, new Sys.CollectionChange(Sys.NotifyCollectionChangedAction.reset, null, -1, oldItems, 0)); +} +Sys.Observer.insert = function Sys$Observer$insert(target, index, item) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target", type: Array, elementMayBeNull: true}, + {name: "index", type: Number, integer: true}, + {name: "item", mayBeNull: true} + ]); + if (e) throw e; + Array.insert(target, index, item); + Sys.Observer._collectionChange(target, new Sys.CollectionChange(Sys.NotifyCollectionChangedAction.add, [item], index)); +} +Sys.Observer.remove = function Sys$Observer$remove(target, item) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target", type: Array, elementMayBeNull: true}, + {name: "item", mayBeNull: true} + ]); + if (e) throw e; + var index = Array.indexOf(target, item); + if (index !== -1) { + Array.remove(target, item); + Sys.Observer._collectionChange(target, new Sys.CollectionChange(Sys.NotifyCollectionChangedAction.remove, null, -1, [item], index)); + return true; + } + return false; +} +Sys.Observer.removeAt = function Sys$Observer$removeAt(target, index) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target", type: Array, elementMayBeNull: true}, + {name: "index", type: Number, integer: true} + ]); + if (e) throw e; + if ((index > -1) && (index < target.length)) { + var item = target[index]; + Array.removeAt(target, index); + Sys.Observer._collectionChange(target, new Sys.CollectionChange(Sys.NotifyCollectionChangedAction.remove, null, -1, [item], index)); + } +} +Sys.Observer.raiseCollectionChanged = function Sys$Observer$raiseCollectionChanged(target, changes) { + /// + /// + /// + Sys.Observer.raiseEvent(target, "collectionChanged", new Sys.NotifyCollectionChangedEventArgs(changes)); +} +Sys.Observer._observeMethods = { + add_propertyChanged: function(handler) { + Sys.Observer._addEventHandler(this, "propertyChanged", handler); + }, + remove_propertyChanged: function(handler) { + Sys.Observer._removeEventHandler(this, "propertyChanged", handler); + }, + addEventHandler: function(eventName, handler) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "eventName", type: String}, + {name: "handler", type: Function} + ]); + if (e) throw e; + Sys.Observer._addEventHandler(this, eventName, handler); + }, + removeEventHandler: function(eventName, handler) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "eventName", type: String}, + {name: "handler", type: Function} + ]); + if (e) throw e; + Sys.Observer._removeEventHandler(this, eventName, handler); + }, + get_isUpdating: function() { + /// + /// + return Sys.Observer.isUpdating(this); + }, + beginUpdate: function() { + /// + Sys.Observer.beginUpdate(this); + }, + endUpdate: function() { + /// + Sys.Observer.endUpdate(this); + }, + setValue: function(name, value) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "name", type: String}, + {name: "value", mayBeNull: true} + ]); + if (e) throw e; + Sys.Observer._setValue(this, name, value); + }, + raiseEvent: function(eventName, eventArgs) { + /// + /// + /// + Sys.Observer.raiseEvent(this, eventName, eventArgs); + }, + raisePropertyChanged: function(name) { + /// + /// + Sys.Observer.raiseEvent(this, "propertyChanged", new Sys.PropertyChangedEventArgs(name)); + } +} +Sys.Observer._arrayMethods = { + add_collectionChanged: function(handler) { + Sys.Observer._addEventHandler(this, "collectionChanged", handler); + }, + remove_collectionChanged: function(handler) { + Sys.Observer._removeEventHandler(this, "collectionChanged", handler); + }, + add: function(item) { + /// + /// + Sys.Observer.add(this, item); + }, + addRange: function(items) { + /// + /// + Sys.Observer.addRange(this, items); + }, + clear: function() { + /// + Sys.Observer.clear(this); + }, + insert: function(index, item) { + /// + /// + /// + Sys.Observer.insert(this, index, item); + }, + remove: function(item) { + /// + /// + /// + return Sys.Observer.remove(this, item); + }, + removeAt: function(index) { + /// + /// + Sys.Observer.removeAt(this, index); + }, + raiseCollectionChanged: function(changes) { + /// + /// + Sys.Observer.raiseEvent(this, "collectionChanged", new Sys.NotifyCollectionChangedEventArgs(changes)); + } +} +Sys.Observer._getContext = function Sys$Observer$_getContext(obj, create) { + var ctx = obj._observerContext; + if (ctx) return ctx(); + if (create) { + return (obj._observerContext = Sys.Observer._createContext())(); + } + return null; +} +Sys.Observer._createContext = function Sys$Observer$_createContext() { + var ctx = { + events: new Sys.EventHandlerList() + }; + return function() { + return ctx; + } +} +Date._appendPreOrPostMatch = function Date$_appendPreOrPostMatch(preMatch, strBuilder) { + var quoteCount = 0; + var escaped = false; + for (var i = 0, il = preMatch.length; i < il; i++) { + var c = preMatch.charAt(i); + switch (c) { + case '\'': + if (escaped) strBuilder.append("'"); + else quoteCount++; + escaped = false; + break; + case '\\': + if (escaped) strBuilder.append("\\"); + escaped = !escaped; + break; + default: + strBuilder.append(c); + escaped = false; + break; + } + } + return quoteCount; +} +Date._expandFormat = function Date$_expandFormat(dtf, format) { + if (!format) { + format = "F"; + } + var len = format.length; + if (len === 1) { + switch (format) { + case "d": + return dtf.ShortDatePattern; + case "D": + return dtf.LongDatePattern; + case "t": + return dtf.ShortTimePattern; + case "T": + return dtf.LongTimePattern; + case "f": + return dtf.LongDatePattern + " " + dtf.ShortTimePattern; + case "F": + return dtf.FullDateTimePattern; + case "M": case "m": + return dtf.MonthDayPattern; + case "s": + return dtf.SortableDateTimePattern; + case "Y": case "y": + return dtf.YearMonthPattern; + default: + throw Error.format(Sys.Res.formatInvalidString); + } + } + else if ((len === 2) && (format.charAt(0) === "%")) { + format = format.charAt(1); + } + return format; +} +Date._expandYear = function Date$_expandYear(dtf, year) { + var now = new Date(), + era = Date._getEra(now); + if (year < 100) { + var curr = Date._getEraYear(now, dtf, era); + year += curr - (curr % 100); + if (year > dtf.Calendar.TwoDigitYearMax) { + year -= 100; + } + } + return year; +} +Date._getEra = function Date$_getEra(date, eras) { + if (!eras) return 0; + var start, ticks = date.getTime(); + for (var i = 0, l = eras.length; i < l; i += 4) { + start = eras[i+2]; + if ((start === null) || (ticks >= start)) { + return i; + } + } + return 0; +} +Date._getEraYear = function Date$_getEraYear(date, dtf, era, sortable) { + var year = date.getFullYear(); + if (!sortable && dtf.eras) { + year -= dtf.eras[era + 3]; + } + return year; +} +Date._getParseRegExp = function Date$_getParseRegExp(dtf, format) { + if (!dtf._parseRegExp) { + dtf._parseRegExp = {}; + } + else if (dtf._parseRegExp[format]) { + return dtf._parseRegExp[format]; + } + var expFormat = Date._expandFormat(dtf, format); + expFormat = expFormat.replace(/([\^\$\.\*\+\?\|\[\]\(\)\{\}])/g, "\\\\$1"); + var regexp = new Sys.StringBuilder("^"); + var groups = []; + var index = 0; + var quoteCount = 0; + var tokenRegExp = Date._getTokenRegExp(); + var match; + while ((match = tokenRegExp.exec(expFormat)) !== null) { + var preMatch = expFormat.slice(index, match.index); + index = tokenRegExp.lastIndex; + quoteCount += Date._appendPreOrPostMatch(preMatch, regexp); + if ((quoteCount%2) === 1) { + regexp.append(match[0]); + continue; + } + switch (match[0]) { + case 'dddd': case 'ddd': + case 'MMMM': case 'MMM': + case 'gg': case 'g': + regexp.append("(\\D+)"); + break; + case 'tt': case 't': + regexp.append("(\\D*)"); + break; + case 'yyyy': + regexp.append("(\\d{4})"); + break; + case 'fff': + regexp.append("(\\d{3})"); + break; + case 'ff': + regexp.append("(\\d{2})"); + break; + case 'f': + regexp.append("(\\d)"); + break; + case 'dd': case 'd': + case 'MM': case 'M': + case 'yy': case 'y': + case 'HH': case 'H': + case 'hh': case 'h': + case 'mm': case 'm': + case 'ss': case 's': + regexp.append("(\\d\\d?)"); + break; + case 'zzz': + regexp.append("([+-]?\\d\\d?:\\d{2})"); + break; + case 'zz': case 'z': + regexp.append("([+-]?\\d\\d?)"); + break; + case '/': + regexp.append("(\\" + dtf.DateSeparator + ")"); + break; + default: + Sys.Debug.fail("Invalid date format pattern"); + } + Array.add(groups, match[0]); + } + Date._appendPreOrPostMatch(expFormat.slice(index), regexp); + regexp.append("$"); + var regexpStr = regexp.toString().replace(/\s+/g, "\\s+"); + var parseRegExp = {'regExp': regexpStr, 'groups': groups}; + dtf._parseRegExp[format] = parseRegExp; + return parseRegExp; +} +Date._getTokenRegExp = function Date$_getTokenRegExp() { + return /\/|dddd|ddd|dd|d|MMMM|MMM|MM|M|yyyy|yy|y|hh|h|HH|H|mm|m|ss|s|tt|t|fff|ff|f|zzz|zz|z|gg|g/g; +} +Date.parseLocale = function Date$parseLocale(value, formats) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "value", type: String}, + {name: "formats", mayBeNull: true, optional: true, parameterArray: true} + ]); + if (e) throw e; + return Date._parse(value, Sys.CultureInfo.CurrentCulture, arguments); +} +Date.parseInvariant = function Date$parseInvariant(value, formats) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "value", type: String}, + {name: "formats", mayBeNull: true, optional: true, parameterArray: true} + ]); + if (e) throw e; + return Date._parse(value, Sys.CultureInfo.InvariantCulture, arguments); +} +Date._parse = function Date$_parse(value, cultureInfo, args) { + var i, l, date, format, formats, custom = false; + for (i = 1, l = args.length; i < l; i++) { + format = args[i]; + if (format) { + custom = true; + date = Date._parseExact(value, format, cultureInfo); + if (date) return date; + } + } + if (! custom) { + formats = cultureInfo._getDateTimeFormats(); + for (i = 0, l = formats.length; i < l; i++) { + date = Date._parseExact(value, formats[i], cultureInfo); + if (date) return date; + } + } + return null; +} +Date._parseExact = function Date$_parseExact(value, format, cultureInfo) { + value = value.trim(); + var dtf = cultureInfo.dateTimeFormat, + parseInfo = Date._getParseRegExp(dtf, format), + match = new RegExp(parseInfo.regExp).exec(value); + if (match === null) return null; + + var groups = parseInfo.groups, + era = null, year = null, month = null, date = null, weekDay = null, + hour = 0, hourOffset, min = 0, sec = 0, msec = 0, tzMinOffset = null, + pmHour = false; + for (var j = 0, jl = groups.length; j < jl; j++) { + var matchGroup = match[j+1]; + if (matchGroup) { + switch (groups[j]) { + case 'dd': case 'd': + date = parseInt(matchGroup, 10); + if ((date < 1) || (date > 31)) return null; + break; + case 'MMMM': + month = cultureInfo._getMonthIndex(matchGroup); + if ((month < 0) || (month > 11)) return null; + break; + case 'MMM': + month = cultureInfo._getAbbrMonthIndex(matchGroup); + if ((month < 0) || (month > 11)) return null; + break; + case 'M': case 'MM': + month = parseInt(matchGroup, 10) - 1; + if ((month < 0) || (month > 11)) return null; + break; + case 'y': case 'yy': + year = Date._expandYear(dtf,parseInt(matchGroup, 10)); + if ((year < 0) || (year > 9999)) return null; + break; + case 'yyyy': + year = parseInt(matchGroup, 10); + if ((year < 0) || (year > 9999)) return null; + break; + case 'h': case 'hh': + hour = parseInt(matchGroup, 10); + if (hour === 12) hour = 0; + if ((hour < 0) || (hour > 11)) return null; + break; + case 'H': case 'HH': + hour = parseInt(matchGroup, 10); + if ((hour < 0) || (hour > 23)) return null; + break; + case 'm': case 'mm': + min = parseInt(matchGroup, 10); + if ((min < 0) || (min > 59)) return null; + break; + case 's': case 'ss': + sec = parseInt(matchGroup, 10); + if ((sec < 0) || (sec > 59)) return null; + break; + case 'tt': case 't': + var upperToken = matchGroup.toUpperCase(); + pmHour = (upperToken === dtf.PMDesignator.toUpperCase()); + if (!pmHour && (upperToken !== dtf.AMDesignator.toUpperCase())) return null; + break; + case 'f': + msec = parseInt(matchGroup, 10) * 100; + if ((msec < 0) || (msec > 999)) return null; + break; + case 'ff': + msec = parseInt(matchGroup, 10) * 10; + if ((msec < 0) || (msec > 999)) return null; + break; + case 'fff': + msec = parseInt(matchGroup, 10); + if ((msec < 0) || (msec > 999)) return null; + break; + case 'dddd': + weekDay = cultureInfo._getDayIndex(matchGroup); + if ((weekDay < 0) || (weekDay > 6)) return null; + break; + case 'ddd': + weekDay = cultureInfo._getAbbrDayIndex(matchGroup); + if ((weekDay < 0) || (weekDay > 6)) return null; + break; + case 'zzz': + var offsets = matchGroup.split(/:/); + if (offsets.length !== 2) return null; + hourOffset = parseInt(offsets[0], 10); + if ((hourOffset < -12) || (hourOffset > 13)) return null; + var minOffset = parseInt(offsets[1], 10); + if ((minOffset < 0) || (minOffset > 59)) return null; + tzMinOffset = (hourOffset * 60) + (matchGroup.startsWith('-')? -minOffset : minOffset); + break; + case 'z': case 'zz': + hourOffset = parseInt(matchGroup, 10); + if ((hourOffset < -12) || (hourOffset > 13)) return null; + tzMinOffset = hourOffset * 60; + break; + case 'g': case 'gg': + var eraName = matchGroup; + if (!eraName || !dtf.eras) return null; + eraName = eraName.toLowerCase().trim(); + for (var i = 0, l = dtf.eras.length; i < l; i += 4) { + if (eraName === dtf.eras[i + 1].toLowerCase()) { + era = i; + break; + } + } + if (era === null) return null; + break; + } + } + } + var result = new Date(), defaults, convert = dtf.Calendar.convert; + if (convert) { + defaults = convert.fromGregorian(result); + } + if (!convert) { + defaults = [result.getFullYear(), result.getMonth(), result.getDate()]; + } + if (year === null) { + year = defaults[0]; + } + else if (dtf.eras) { + year += dtf.eras[(era || 0) + 3]; + } + if (month === null) { + month = defaults[1]; + } + if (date === null) { + date = defaults[2]; + } + if (convert) { + result = convert.toGregorian(year, month, date); + if (result === null) return null; + } + else { + result.setFullYear(year, month, date); + if (result.getDate() !== date) return null; + if ((weekDay !== null) && (result.getDay() !== weekDay)) { + return null; + } + } + if (pmHour && (hour < 12)) { + hour += 12; + } + result.setHours(hour, min, sec, msec); + if (tzMinOffset !== null) { + var adjustedMin = result.getMinutes() - (tzMinOffset + result.getTimezoneOffset()); + result.setHours(result.getHours() + parseInt(adjustedMin/60, 10), adjustedMin%60); + } + return result; +} +Date.prototype.format = function Date$format(format) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "format", type: String} + ]); + if (e) throw e; + return this._toFormattedString(format, Sys.CultureInfo.InvariantCulture); +} +Date.prototype.localeFormat = function Date$localeFormat(format) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "format", type: String} + ]); + if (e) throw e; + return this._toFormattedString(format, Sys.CultureInfo.CurrentCulture); +} +Date.prototype._toFormattedString = function Date$_toFormattedString(format, cultureInfo) { + var dtf = cultureInfo.dateTimeFormat, + convert = dtf.Calendar.convert; + if (!format || !format.length || (format === 'i')) { + if (cultureInfo && cultureInfo.name.length) { + if (convert) { + return this._toFormattedString(dtf.FullDateTimePattern, cultureInfo); + } + else { + var eraDate = new Date(this.getTime()); + var era = Date._getEra(this, dtf.eras); + eraDate.setFullYear(Date._getEraYear(this, dtf, era)); + return eraDate.toLocaleString(); + } + } + else { + return this.toString(); + } + } + var eras = dtf.eras, + sortable = (format === "s"); + format = Date._expandFormat(dtf, format); + var ret = new Sys.StringBuilder(); + var hour; + function addLeadingZero(num) { + if (num < 10) { + return '0' + num; + } + return num.toString(); + } + function addLeadingZeros(num) { + if (num < 10) { + return '00' + num; + } + if (num < 100) { + return '0' + num; + } + return num.toString(); + } + function padYear(year) { + if (year < 10) { + return '000' + year; + } + else if (year < 100) { + return '00' + year; + } + else if (year < 1000) { + return '0' + year; + } + return year.toString(); + } + + var foundDay, checkedDay, dayPartRegExp = /([^d]|^)(d|dd)([^d]|$)/g; + function hasDay() { + if (foundDay || checkedDay) { + return foundDay; + } + foundDay = dayPartRegExp.test(format); + checkedDay = true; + return foundDay; + } + + var quoteCount = 0, + tokenRegExp = Date._getTokenRegExp(), + converted; + if (!sortable && convert) { + converted = convert.fromGregorian(this); + } + for (;;) { + var index = tokenRegExp.lastIndex; + var ar = tokenRegExp.exec(format); + var preMatch = format.slice(index, ar ? ar.index : format.length); + quoteCount += Date._appendPreOrPostMatch(preMatch, ret); + if (!ar) break; + if ((quoteCount%2) === 1) { + ret.append(ar[0]); + continue; + } + + function getPart(date, part) { + if (converted) { + return converted[part]; + } + switch (part) { + case 0: return date.getFullYear(); + case 1: return date.getMonth(); + case 2: return date.getDate(); + } + } + switch (ar[0]) { + case "dddd": + ret.append(dtf.DayNames[this.getDay()]); + break; + case "ddd": + ret.append(dtf.AbbreviatedDayNames[this.getDay()]); + break; + case "dd": + foundDay = true; + ret.append(addLeadingZero(getPart(this, 2))); + break; + case "d": + foundDay = true; + ret.append(getPart(this, 2)); + break; + case "MMMM": + ret.append((dtf.MonthGenitiveNames && hasDay()) + ? dtf.MonthGenitiveNames[getPart(this, 1)] + : dtf.MonthNames[getPart(this, 1)]); + break; + case "MMM": + ret.append((dtf.AbbreviatedMonthGenitiveNames && hasDay()) + ? dtf.AbbreviatedMonthGenitiveNames[getPart(this, 1)] + : dtf.AbbreviatedMonthNames[getPart(this, 1)]); + break; + case "MM": + ret.append(addLeadingZero(getPart(this, 1) + 1)); + break; + case "M": + ret.append(getPart(this, 1) + 1); + break; + case "yyyy": + ret.append(padYear(converted ? converted[0] : Date._getEraYear(this, dtf, Date._getEra(this, eras), sortable))); + break; + case "yy": + ret.append(addLeadingZero((converted ? converted[0] : Date._getEraYear(this, dtf, Date._getEra(this, eras), sortable)) % 100)); + break; + case "y": + ret.append((converted ? converted[0] : Date._getEraYear(this, dtf, Date._getEra(this, eras), sortable)) % 100); + break; + case "hh": + hour = this.getHours() % 12; + if (hour === 0) hour = 12; + ret.append(addLeadingZero(hour)); + break; + case "h": + hour = this.getHours() % 12; + if (hour === 0) hour = 12; + ret.append(hour); + break; + case "HH": + ret.append(addLeadingZero(this.getHours())); + break; + case "H": + ret.append(this.getHours()); + break; + case "mm": + ret.append(addLeadingZero(this.getMinutes())); + break; + case "m": + ret.append(this.getMinutes()); + break; + case "ss": + ret.append(addLeadingZero(this.getSeconds())); + break; + case "s": + ret.append(this.getSeconds()); + break; + case "tt": + ret.append((this.getHours() < 12) ? dtf.AMDesignator : dtf.PMDesignator); + break; + case "t": + ret.append(((this.getHours() < 12) ? dtf.AMDesignator : dtf.PMDesignator).charAt(0)); + break; + case "f": + ret.append(addLeadingZeros(this.getMilliseconds()).charAt(0)); + break; + case "ff": + ret.append(addLeadingZeros(this.getMilliseconds()).substr(0, 2)); + break; + case "fff": + ret.append(addLeadingZeros(this.getMilliseconds())); + break; + case "z": + hour = this.getTimezoneOffset() / 60; + ret.append(((hour <= 0) ? '+' : '-') + Math.floor(Math.abs(hour))); + break; + case "zz": + hour = this.getTimezoneOffset() / 60; + ret.append(((hour <= 0) ? '+' : '-') + addLeadingZero(Math.floor(Math.abs(hour)))); + break; + case "zzz": + hour = this.getTimezoneOffset() / 60; + ret.append(((hour <= 0) ? '+' : '-') + addLeadingZero(Math.floor(Math.abs(hour))) + + ":" + addLeadingZero(Math.abs(this.getTimezoneOffset() % 60))); + break; + case "g": + case "gg": + if (dtf.eras) { + ret.append(dtf.eras[Date._getEra(this, eras) + 1]); + } + break; + case "/": + ret.append(dtf.DateSeparator); + break; + default: + Sys.Debug.fail("Invalid date format pattern"); + } + } + return ret.toString(); +} +String.localeFormat = function String$localeFormat(format, args) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "format", type: String}, + {name: "args", mayBeNull: true, parameterArray: true} + ]); + if (e) throw e; + return String._toFormattedString(true, arguments); +} +Number.parseLocale = function Number$parseLocale(value) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "value", type: String} + ], false); + if (e) throw e; + return Number._parse(value, Sys.CultureInfo.CurrentCulture); +} +Number.parseInvariant = function Number$parseInvariant(value) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "value", type: String} + ], false); + if (e) throw e; + return Number._parse(value, Sys.CultureInfo.InvariantCulture); +} +Number._parse = function Number$_parse(value, cultureInfo) { + value = value.trim(); + + if (value.match(/^[+-]?infinity$/i)) { + return parseFloat(value); + } + if (value.match(/^0x[a-f0-9]+$/i)) { + return parseInt(value); + } + var numFormat = cultureInfo.numberFormat; + var signInfo = Number._parseNumberNegativePattern(value, numFormat, numFormat.NumberNegativePattern); + var sign = signInfo[0]; + var num = signInfo[1]; + + if ((sign === '') && (numFormat.NumberNegativePattern !== 1)) { + signInfo = Number._parseNumberNegativePattern(value, numFormat, 1); + sign = signInfo[0]; + num = signInfo[1]; + } + if (sign === '') sign = '+'; + + var exponent; + var intAndFraction; + var exponentPos = num.indexOf('e'); + if (exponentPos < 0) exponentPos = num.indexOf('E'); + if (exponentPos < 0) { + intAndFraction = num; + exponent = null; + } + else { + intAndFraction = num.substr(0, exponentPos); + exponent = num.substr(exponentPos + 1); + } + + var integer; + var fraction; + var decimalPos = intAndFraction.indexOf(numFormat.NumberDecimalSeparator); + if (decimalPos < 0) { + integer = intAndFraction; + fraction = null; + } + else { + integer = intAndFraction.substr(0, decimalPos); + fraction = intAndFraction.substr(decimalPos + numFormat.NumberDecimalSeparator.length); + } + + integer = integer.split(numFormat.NumberGroupSeparator).join(''); + var altNumGroupSeparator = numFormat.NumberGroupSeparator.replace(/\u00A0/g, " "); + if (numFormat.NumberGroupSeparator !== altNumGroupSeparator) { + integer = integer.split(altNumGroupSeparator).join(''); + } + + var p = sign + integer; + if (fraction !== null) { + p += '.' + fraction; + } + if (exponent !== null) { + var expSignInfo = Number._parseNumberNegativePattern(exponent, numFormat, 1); + if (expSignInfo[0] === '') { + expSignInfo[0] = '+'; + } + p += 'e' + expSignInfo[0] + expSignInfo[1]; + } + if (p.match(/^[+-]?\d*\.?\d*(e[+-]?\d+)?$/)) { + return parseFloat(p); + } + return Number.NaN; +} +Number._parseNumberNegativePattern = function Number$_parseNumberNegativePattern(value, numFormat, numberNegativePattern) { + var neg = numFormat.NegativeSign; + var pos = numFormat.PositiveSign; + switch (numberNegativePattern) { + case 4: + neg = ' ' + neg; + pos = ' ' + pos; + case 3: + if (value.endsWith(neg)) { + return ['-', value.substr(0, value.length - neg.length)]; + } + else if (value.endsWith(pos)) { + return ['+', value.substr(0, value.length - pos.length)]; + } + break; + case 2: + neg += ' '; + pos += ' '; + case 1: + if (value.startsWith(neg)) { + return ['-', value.substr(neg.length)]; + } + else if (value.startsWith(pos)) { + return ['+', value.substr(pos.length)]; + } + break; + case 0: + if (value.startsWith('(') && value.endsWith(')')) { + return ['-', value.substr(1, value.length - 2)]; + } + break; + default: + Sys.Debug.fail(""); + } + return ['', value]; +} +Number.prototype.format = function Number$format(format) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "format", type: String} + ]); + if (e) throw e; + return this._toFormattedString(format, Sys.CultureInfo.InvariantCulture); +} +Number.prototype.localeFormat = function Number$localeFormat(format) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "format", type: String} + ]); + if (e) throw e; + return this._toFormattedString(format, Sys.CultureInfo.CurrentCulture); +} +Number.prototype._toFormattedString = function Number$_toFormattedString(format, cultureInfo) { + if (!format || (format.length === 0) || (format === 'i')) { + if (cultureInfo && (cultureInfo.name.length > 0)) { + return this.toLocaleString(); + } + else { + return this.toString(); + } + } + + var _percentPositivePattern = ["n %", "n%", "%n" ]; + var _percentNegativePattern = ["-n %", "-n%", "-%n"]; + var _numberNegativePattern = ["(n)","-n","- n","n-","n -"]; + var _currencyPositivePattern = ["$n","n$","$ n","n $"]; + var _currencyNegativePattern = ["($n)","-$n","$-n","$n-","(n$)","-n$","n-$","n$-","-n $","-$ n","n $-","$ n-","$ -n","n- $","($ n)","(n $)"]; + function zeroPad(str, count, left) { + for (var l=str.length; l < count; l++) { + str = (left ? ('0' + str) : (str + '0')); + } + return str; + } + + function expandNumber(number, precision, groupSizes, sep, decimalChar) { + Sys.Debug.assert(groupSizes.length > 0, "groupSizes must be an array of at least 1"); + var curSize = groupSizes[0]; + var curGroupIndex = 1; + var factor = Math.pow(10, precision); + var rounded = (Math.round(number * factor) / factor); + if (!isFinite(rounded)) { + rounded = number; + } + number = rounded; + + var numberString = number.toString(); + var right = ""; + var exponent; + + + var split = numberString.split(/e/i); + numberString = split[0]; + exponent = (split.length > 1 ? parseInt(split[1]) : 0); + split = numberString.split('.'); + numberString = split[0]; + right = split.length > 1 ? split[1] : ""; + + var l; + if (exponent > 0) { + right = zeroPad(right, exponent, false); + numberString += right.slice(0, exponent); + right = right.substr(exponent); + } + else if (exponent < 0) { + exponent = -exponent; + numberString = zeroPad(numberString, exponent+1, true); + right = numberString.slice(-exponent, numberString.length) + right; + numberString = numberString.slice(0, -exponent); + } + if (precision > 0) { + if (right.length > precision) { + right = right.slice(0, precision); + } + else { + right = zeroPad(right, precision, false); + } + right = decimalChar + right; + } + else { + right = ""; + } + var stringIndex = numberString.length-1; + var ret = ""; + while (stringIndex >= 0) { + if (curSize === 0 || curSize > stringIndex) { + if (ret.length > 0) + return numberString.slice(0, stringIndex + 1) + sep + ret + right; + else + return numberString.slice(0, stringIndex + 1) + right; + } + if (ret.length > 0) + ret = numberString.slice(stringIndex - curSize + 1, stringIndex+1) + sep + ret; + else + ret = numberString.slice(stringIndex - curSize + 1, stringIndex+1); + stringIndex -= curSize; + if (curGroupIndex < groupSizes.length) { + curSize = groupSizes[curGroupIndex]; + curGroupIndex++; + } + } + return numberString.slice(0, stringIndex + 1) + sep + ret + right; + } + var nf = cultureInfo.numberFormat; + var number = Math.abs(this); + if (!format) + format = "D"; + var precision = -1; + if (format.length > 1) precision = parseInt(format.slice(1), 10); + var pattern; + switch (format.charAt(0)) { + case "d": + case "D": + pattern = 'n'; + if (precision !== -1) { + number = zeroPad(""+number, precision, true); + } + if (this < 0) number = -number; + break; + case "c": + case "C": + if (this < 0) pattern = _currencyNegativePattern[nf.CurrencyNegativePattern]; + else pattern = _currencyPositivePattern[nf.CurrencyPositivePattern]; + if (precision === -1) precision = nf.CurrencyDecimalDigits; + number = expandNumber(Math.abs(this), precision, nf.CurrencyGroupSizes, nf.CurrencyGroupSeparator, nf.CurrencyDecimalSeparator); + break; + case "n": + case "N": + if (this < 0) pattern = _numberNegativePattern[nf.NumberNegativePattern]; + else pattern = 'n'; + if (precision === -1) precision = nf.NumberDecimalDigits; + number = expandNumber(Math.abs(this), precision, nf.NumberGroupSizes, nf.NumberGroupSeparator, nf.NumberDecimalSeparator); + break; + case "p": + case "P": + if (this < 0) pattern = _percentNegativePattern[nf.PercentNegativePattern]; + else pattern = _percentPositivePattern[nf.PercentPositivePattern]; + if (precision === -1) precision = nf.PercentDecimalDigits; + number = expandNumber(Math.abs(this) * 100, precision, nf.PercentGroupSizes, nf.PercentGroupSeparator, nf.PercentDecimalSeparator); + break; + default: + throw Error.format(Sys.Res.formatBadFormatSpecifier); + } + var regex = /n|\$|-|%/g; + var ret = ""; + for (;;) { + var index = regex.lastIndex; + var ar = regex.exec(pattern); + ret += pattern.slice(index, ar ? ar.index : pattern.length); + if (!ar) + break; + switch (ar[0]) { + case "n": + ret += number; + break; + case "$": + ret += nf.CurrencySymbol; + break; + case "-": + if (/[1-9]/.test(number)) { + ret += nf.NegativeSign; + } + break; + case "%": + ret += nf.PercentSymbol; + break; + default: + Sys.Debug.fail("Invalid number format pattern"); + } + } + return ret; +} + +Sys.CultureInfo = function Sys$CultureInfo(name, numberFormat, dateTimeFormat) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "name", type: String}, + {name: "numberFormat", type: Object}, + {name: "dateTimeFormat", type: Object} + ]); + if (e) throw e; + this.name = name; + this.numberFormat = numberFormat; + this.dateTimeFormat = dateTimeFormat; +} + function Sys$CultureInfo$_getDateTimeFormats() { + if (! this._dateTimeFormats) { + var dtf = this.dateTimeFormat; + this._dateTimeFormats = + [ dtf.MonthDayPattern, + dtf.YearMonthPattern, + dtf.ShortDatePattern, + dtf.ShortTimePattern, + dtf.LongDatePattern, + dtf.LongTimePattern, + dtf.FullDateTimePattern, + dtf.RFC1123Pattern, + dtf.SortableDateTimePattern, + dtf.UniversalSortableDateTimePattern ]; + } + return this._dateTimeFormats; + } + function Sys$CultureInfo$_getIndex(value, a1, a2) { + var upper = this._toUpper(value), + i = Array.indexOf(a1, upper); + if (i === -1) { + i = Array.indexOf(a2, upper); + } + return i; + } + function Sys$CultureInfo$_getMonthIndex(value) { + if (!this._upperMonths) { + this._upperMonths = this._toUpperArray(this.dateTimeFormat.MonthNames); + this._upperMonthsGenitive = this._toUpperArray(this.dateTimeFormat.MonthGenitiveNames); + } + return this._getIndex(value, this._upperMonths, this._upperMonthsGenitive); + } + function Sys$CultureInfo$_getAbbrMonthIndex(value) { + if (!this._upperAbbrMonths) { + this._upperAbbrMonths = this._toUpperArray(this.dateTimeFormat.AbbreviatedMonthNames); + this._upperAbbrMonthsGenitive = this._toUpperArray(this.dateTimeFormat.AbbreviatedMonthGenitiveNames); + } + return this._getIndex(value, this._upperAbbrMonths, this._upperAbbrMonthsGenitive); + } + function Sys$CultureInfo$_getDayIndex(value) { + if (!this._upperDays) { + this._upperDays = this._toUpperArray(this.dateTimeFormat.DayNames); + } + return Array.indexOf(this._upperDays, this._toUpper(value)); + } + function Sys$CultureInfo$_getAbbrDayIndex(value) { + if (!this._upperAbbrDays) { + this._upperAbbrDays = this._toUpperArray(this.dateTimeFormat.AbbreviatedDayNames); + } + return Array.indexOf(this._upperAbbrDays, this._toUpper(value)); + } + function Sys$CultureInfo$_toUpperArray(arr) { + var result = []; + for (var i = 0, il = arr.length; i < il; i++) { + result[i] = this._toUpper(arr[i]); + } + return result; + } + function Sys$CultureInfo$_toUpper(value) { + return value.split("\u00A0").join(' ').toUpperCase(); + } +Sys.CultureInfo.prototype = { + _getDateTimeFormats: Sys$CultureInfo$_getDateTimeFormats, + _getIndex: Sys$CultureInfo$_getIndex, + _getMonthIndex: Sys$CultureInfo$_getMonthIndex, + _getAbbrMonthIndex: Sys$CultureInfo$_getAbbrMonthIndex, + _getDayIndex: Sys$CultureInfo$_getDayIndex, + _getAbbrDayIndex: Sys$CultureInfo$_getAbbrDayIndex, + _toUpperArray: Sys$CultureInfo$_toUpperArray, + _toUpper: Sys$CultureInfo$_toUpper +} +Sys.CultureInfo.registerClass('Sys.CultureInfo'); +Sys.CultureInfo._parse = function Sys$CultureInfo$_parse(value) { + var dtf = value.dateTimeFormat; + if (dtf && !dtf.eras) { + dtf.eras = value.eras; + } + return new Sys.CultureInfo(value.name, value.numberFormat, dtf); +} +Sys.CultureInfo.InvariantCulture = Sys.CultureInfo._parse({"name":"","numberFormat":{"CurrencyDecimalDigits":2,"CurrencyDecimalSeparator":".","IsReadOnly":true,"CurrencyGroupSizes":[3],"NumberGroupSizes":[3],"PercentGroupSizes":[3],"CurrencyGroupSeparator":",","CurrencySymbol":"\u00A4","NaNSymbol":"NaN","CurrencyNegativePattern":0,"NumberNegativePattern":1,"PercentPositivePattern":0,"PercentNegativePattern":0,"NegativeInfinitySymbol":"-Infinity","NegativeSign":"-","NumberDecimalDigits":2,"NumberDecimalSeparator":".","NumberGroupSeparator":",","CurrencyPositivePattern":0,"PositiveInfinitySymbol":"Infinity","PositiveSign":"+","PercentDecimalDigits":2,"PercentDecimalSeparator":".","PercentGroupSeparator":",","PercentSymbol":"%","PerMilleSymbol":"\u2030","NativeDigits":["0","1","2","3","4","5","6","7","8","9"],"DigitSubstitution":1},"dateTimeFormat":{"AMDesignator":"AM","Calendar":{"MinSupportedDateTime":"@-62135568000000@","MaxSupportedDateTime":"@253402300799999@","AlgorithmType":1,"CalendarType":1,"Eras":[1],"TwoDigitYearMax":2029,"IsReadOnly":true},"DateSeparator":"/","FirstDayOfWeek":0,"CalendarWeekRule":0,"FullDateTimePattern":"dddd, dd MMMM yyyy HH:mm:ss","LongDatePattern":"dddd, dd MMMM yyyy","LongTimePattern":"HH:mm:ss","MonthDayPattern":"MMMM dd","PMDesignator":"PM","RFC1123Pattern":"ddd, dd MMM yyyy HH\':\'mm\':\'ss \'GMT\'","ShortDatePattern":"MM/dd/yyyy","ShortTimePattern":"HH:mm","SortableDateTimePattern":"yyyy\'-\'MM\'-\'dd\'T\'HH\':\'mm\':\'ss","TimeSeparator":":","UniversalSortableDateTimePattern":"yyyy\'-\'MM\'-\'dd HH\':\'mm\':\'ss\'Z\'","YearMonthPattern":"yyyy MMMM","AbbreviatedDayNames":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"ShortestDayNames":["Su","Mo","Tu","We","Th","Fr","Sa"],"DayNames":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"AbbreviatedMonthNames":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec",""],"MonthNames":["January","February","March","April","May","June","July","August","September","October","November","December",""],"IsReadOnly":true,"NativeCalendarName":"Gregorian Calendar","AbbreviatedMonthGenitiveNames":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec",""],"MonthGenitiveNames":["January","February","March","April","May","June","July","August","September","October","November","December",""]},"eras":[1,"A.D.",null,0]}); +if (typeof(__cultureInfo) === "object") { + Sys.CultureInfo.CurrentCulture = Sys.CultureInfo._parse(__cultureInfo); + delete __cultureInfo; +} +else { + Sys.CultureInfo.CurrentCulture = Sys.CultureInfo._parse({"name":"en-US","numberFormat":{"CurrencyDecimalDigits":2,"CurrencyDecimalSeparator":".","IsReadOnly":false,"CurrencyGroupSizes":[3],"NumberGroupSizes":[3],"PercentGroupSizes":[3],"CurrencyGroupSeparator":",","CurrencySymbol":"$","NaNSymbol":"NaN","CurrencyNegativePattern":0,"NumberNegativePattern":1,"PercentPositivePattern":0,"PercentNegativePattern":0,"NegativeInfinitySymbol":"-Infinity","NegativeSign":"-","NumberDecimalDigits":2,"NumberDecimalSeparator":".","NumberGroupSeparator":",","CurrencyPositivePattern":0,"PositiveInfinitySymbol":"Infinity","PositiveSign":"+","PercentDecimalDigits":2,"PercentDecimalSeparator":".","PercentGroupSeparator":",","PercentSymbol":"%","PerMilleSymbol":"\u2030","NativeDigits":["0","1","2","3","4","5","6","7","8","9"],"DigitSubstitution":1},"dateTimeFormat":{"AMDesignator":"AM","Calendar":{"MinSupportedDateTime":"@-62135568000000@","MaxSupportedDateTime":"@253402300799999@","AlgorithmType":1,"CalendarType":1,"Eras":[1],"TwoDigitYearMax":2029,"IsReadOnly":false},"DateSeparator":"/","FirstDayOfWeek":0,"CalendarWeekRule":0,"FullDateTimePattern":"dddd, MMMM dd, yyyy h:mm:ss tt","LongDatePattern":"dddd, MMMM dd, yyyy","LongTimePattern":"h:mm:ss tt","MonthDayPattern":"MMMM dd","PMDesignator":"PM","RFC1123Pattern":"ddd, dd MMM yyyy HH\':\'mm\':\'ss \'GMT\'","ShortDatePattern":"M/d/yyyy","ShortTimePattern":"h:mm tt","SortableDateTimePattern":"yyyy\'-\'MM\'-\'dd\'T\'HH\':\'mm\':\'ss","TimeSeparator":":","UniversalSortableDateTimePattern":"yyyy\'-\'MM\'-\'dd HH\':\'mm\':\'ss\'Z\'","YearMonthPattern":"MMMM, yyyy","AbbreviatedDayNames":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"ShortestDayNames":["Su","Mo","Tu","We","Th","Fr","Sa"],"DayNames":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"AbbreviatedMonthNames":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec",""],"MonthNames":["January","February","March","April","May","June","July","August","September","October","November","December",""],"IsReadOnly":false,"NativeCalendarName":"Gregorian Calendar","AbbreviatedMonthGenitiveNames":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec",""],"MonthGenitiveNames":["January","February","March","April","May","June","July","August","September","October","November","December",""]},"eras":[1,"A.D.",null,0]}); +} +Type.registerNamespace('Sys.Serialization'); +Sys.Serialization.JavaScriptSerializer = function Sys$Serialization$JavaScriptSerializer() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); +} +Sys.Serialization.JavaScriptSerializer.registerClass('Sys.Serialization.JavaScriptSerializer'); +Sys.Serialization.JavaScriptSerializer._charsToEscapeRegExs = []; +Sys.Serialization.JavaScriptSerializer._charsToEscape = []; +Sys.Serialization.JavaScriptSerializer._dateRegEx = new RegExp('(^|[^\\\\])\\"\\\\/Date\\((-?[0-9]+)(?:[a-zA-Z]|(?:\\+|-)[0-9]{4})?\\)\\\\/\\"', 'g'); +Sys.Serialization.JavaScriptSerializer._escapeChars = {}; +Sys.Serialization.JavaScriptSerializer._escapeRegEx = new RegExp('["\\\\\\x00-\\x1F]', 'i'); +Sys.Serialization.JavaScriptSerializer._escapeRegExGlobal = new RegExp('["\\\\\\x00-\\x1F]', 'g'); +Sys.Serialization.JavaScriptSerializer._jsonRegEx = new RegExp('[^,:{}\\[\\]0-9.\\-+Eaeflnr-u \\n\\r\\t]', 'g'); +Sys.Serialization.JavaScriptSerializer._jsonStringRegEx = new RegExp('"(\\\\.|[^"\\\\])*"', 'g'); +Sys.Serialization.JavaScriptSerializer._serverTypeFieldName = '__type'; +Sys.Serialization.JavaScriptSerializer._init = function Sys$Serialization$JavaScriptSerializer$_init() { + var replaceChars = ['\\u0000','\\u0001','\\u0002','\\u0003','\\u0004','\\u0005','\\u0006','\\u0007', + '\\b','\\t','\\n','\\u000b','\\f','\\r','\\u000e','\\u000f','\\u0010','\\u0011', + '\\u0012','\\u0013','\\u0014','\\u0015','\\u0016','\\u0017','\\u0018','\\u0019', + '\\u001a','\\u001b','\\u001c','\\u001d','\\u001e','\\u001f']; + Sys.Serialization.JavaScriptSerializer._charsToEscape[0] = '\\'; + Sys.Serialization.JavaScriptSerializer._charsToEscapeRegExs['\\'] = new RegExp('\\\\', 'g'); + Sys.Serialization.JavaScriptSerializer._escapeChars['\\'] = '\\\\'; + Sys.Serialization.JavaScriptSerializer._charsToEscape[1] = '"'; + Sys.Serialization.JavaScriptSerializer._charsToEscapeRegExs['"'] = new RegExp('"', 'g'); + Sys.Serialization.JavaScriptSerializer._escapeChars['"'] = '\\"'; + for (var i = 0; i < 32; i++) { + var c = String.fromCharCode(i); + Sys.Serialization.JavaScriptSerializer._charsToEscape[i+2] = c; + Sys.Serialization.JavaScriptSerializer._charsToEscapeRegExs[c] = new RegExp(c, 'g'); + Sys.Serialization.JavaScriptSerializer._escapeChars[c] = replaceChars[i]; + } +} +Sys.Serialization.JavaScriptSerializer._serializeBooleanWithBuilder = function Sys$Serialization$JavaScriptSerializer$_serializeBooleanWithBuilder(object, stringBuilder) { + stringBuilder.append(object.toString()); +} +Sys.Serialization.JavaScriptSerializer._serializeNumberWithBuilder = function Sys$Serialization$JavaScriptSerializer$_serializeNumberWithBuilder(object, stringBuilder) { + if (isFinite(object)) { + stringBuilder.append(String(object)); + } + else { + throw Error.invalidOperation(Sys.Res.cannotSerializeNonFiniteNumbers); + } +} +Sys.Serialization.JavaScriptSerializer._serializeStringWithBuilder = function Sys$Serialization$JavaScriptSerializer$_serializeStringWithBuilder(string, stringBuilder) { + stringBuilder.append('"'); + if (Sys.Serialization.JavaScriptSerializer._escapeRegEx.test(string)) { + if (Sys.Serialization.JavaScriptSerializer._charsToEscape.length === 0) { + Sys.Serialization.JavaScriptSerializer._init(); + } + if (string.length < 128) { + string = string.replace(Sys.Serialization.JavaScriptSerializer._escapeRegExGlobal, + function(x) { return Sys.Serialization.JavaScriptSerializer._escapeChars[x]; }); + } + else { + for (var i = 0; i < 34; i++) { + var c = Sys.Serialization.JavaScriptSerializer._charsToEscape[i]; + if (string.indexOf(c) !== -1) { + if (Sys.Browser.agent === Sys.Browser.Opera || Sys.Browser.agent === Sys.Browser.FireFox) { + string = string.split(c).join(Sys.Serialization.JavaScriptSerializer._escapeChars[c]); + } + else { + string = string.replace(Sys.Serialization.JavaScriptSerializer._charsToEscapeRegExs[c], + Sys.Serialization.JavaScriptSerializer._escapeChars[c]); + } + } + } + } + } + stringBuilder.append(string); + stringBuilder.append('"'); +} +Sys.Serialization.JavaScriptSerializer._serializeWithBuilder = function Sys$Serialization$JavaScriptSerializer$_serializeWithBuilder(object, stringBuilder, sort, prevObjects) { + var i; + switch (typeof object) { + case 'object': + if (object) { + if (prevObjects){ + for( var j = 0; j < prevObjects.length; j++) { + if (prevObjects[j] === object) { + throw Error.invalidOperation(Sys.Res.cannotSerializeObjectWithCycle); + } + } + } + else { + prevObjects = new Array(); + } + try { + Array.add(prevObjects, object); + + if (Number.isInstanceOfType(object)){ + Sys.Serialization.JavaScriptSerializer._serializeNumberWithBuilder(object, stringBuilder); + } + else if (Boolean.isInstanceOfType(object)){ + Sys.Serialization.JavaScriptSerializer._serializeBooleanWithBuilder(object, stringBuilder); + } + else if (String.isInstanceOfType(object)){ + Sys.Serialization.JavaScriptSerializer._serializeStringWithBuilder(object, stringBuilder); + } + + else if (Array.isInstanceOfType(object)) { + stringBuilder.append('['); + + for (i = 0; i < object.length; ++i) { + if (i > 0) { + stringBuilder.append(','); + } + Sys.Serialization.JavaScriptSerializer._serializeWithBuilder(object[i], stringBuilder,false,prevObjects); + } + stringBuilder.append(']'); + } + else { + if (Date.isInstanceOfType(object)) { + stringBuilder.append('"\\/Date('); + stringBuilder.append(object.getTime()); + stringBuilder.append(')\\/"'); + break; + } + var properties = []; + var propertyCount = 0; + for (var name in object) { + if (name.startsWith('$')) { + continue; + } + if (name === Sys.Serialization.JavaScriptSerializer._serverTypeFieldName && propertyCount !== 0){ + properties[propertyCount++] = properties[0]; + properties[0] = name; + } + else{ + properties[propertyCount++] = name; + } + } + if (sort) properties.sort(); + stringBuilder.append('{'); + var needComma = false; + + for (i=0; i + /// + /// + var e = Function._validateParams(arguments, [ + {name: "object", mayBeNull: true} + ]); + if (e) throw e; + var stringBuilder = new Sys.StringBuilder(); + Sys.Serialization.JavaScriptSerializer._serializeWithBuilder(object, stringBuilder, false); + return stringBuilder.toString(); +} +Sys.Serialization.JavaScriptSerializer.deserialize = function Sys$Serialization$JavaScriptSerializer$deserialize(data, secure) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "data", type: String}, + {name: "secure", type: Boolean, optional: true} + ]); + if (e) throw e; + + if (data.length === 0) throw Error.argument('data', Sys.Res.cannotDeserializeEmptyString); + try { + var exp = data.replace(Sys.Serialization.JavaScriptSerializer._dateRegEx, "$1new Date($2)"); + + if (secure && Sys.Serialization.JavaScriptSerializer._jsonRegEx.test( + exp.replace(Sys.Serialization.JavaScriptSerializer._jsonStringRegEx, ''))) throw null; + return eval('(' + exp + ')'); + } + catch (e) { + throw Error.argument('data', Sys.Res.cannotDeserializeInvalidJson); + } +} +Type.registerNamespace('Sys.UI'); + +Sys.EventHandlerList = function Sys$EventHandlerList() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + this._list = {}; +} + function Sys$EventHandlerList$_addHandler(id, handler) { + Array.add(this._getEvent(id, true), handler); + } + function Sys$EventHandlerList$addHandler(id, handler) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "id", type: String}, + {name: "handler", type: Function} + ]); + if (e) throw e; + this._addHandler(id, handler); + } + function Sys$EventHandlerList$_removeHandler(id, handler) { + var evt = this._getEvent(id); + if (!evt) return; + Array.remove(evt, handler); + } + function Sys$EventHandlerList$removeHandler(id, handler) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "id", type: String}, + {name: "handler", type: Function} + ]); + if (e) throw e; + this._removeHandler(id, handler); + } + function Sys$EventHandlerList$getHandler(id) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "id", type: String} + ]); + if (e) throw e; + var evt = this._getEvent(id); + if (!evt || (evt.length === 0)) return null; + evt = Array.clone(evt); + return function(source, args) { + for (var i = 0, l = evt.length; i < l; i++) { + evt[i](source, args); + } + }; + } + function Sys$EventHandlerList$_getEvent(id, create) { + if (!this._list[id]) { + if (!create) return null; + this._list[id] = []; + } + return this._list[id]; + } +Sys.EventHandlerList.prototype = { + _addHandler: Sys$EventHandlerList$_addHandler, + addHandler: Sys$EventHandlerList$addHandler, + _removeHandler: Sys$EventHandlerList$_removeHandler, + removeHandler: Sys$EventHandlerList$removeHandler, + getHandler: Sys$EventHandlerList$getHandler, + _getEvent: Sys$EventHandlerList$_getEvent +} +Sys.EventHandlerList.registerClass('Sys.EventHandlerList'); +Sys.CommandEventArgs = function Sys$CommandEventArgs(commandName, commandArgument, commandSource) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "commandName", type: String}, + {name: "commandArgument", mayBeNull: true}, + {name: "commandSource", mayBeNull: true} + ]); + if (e) throw e; + Sys.CommandEventArgs.initializeBase(this); + this._commandName = commandName; + this._commandArgument = commandArgument; + this._commandSource = commandSource; +} + function Sys$CommandEventArgs$get_commandName() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._commandName; + } + function Sys$CommandEventArgs$get_commandArgument() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._commandArgument; + } + function Sys$CommandEventArgs$get_commandSource() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._commandSource; + } +Sys.CommandEventArgs.prototype = { + _commandName: null, + _commandArgument: null, + _commandSource: null, + get_commandName: Sys$CommandEventArgs$get_commandName, + get_commandArgument: Sys$CommandEventArgs$get_commandArgument, + get_commandSource: Sys$CommandEventArgs$get_commandSource +} +Sys.CommandEventArgs.registerClass("Sys.CommandEventArgs", Sys.CancelEventArgs); + +Sys.INotifyPropertyChange = function Sys$INotifyPropertyChange() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); +} + function Sys$INotifyPropertyChange$add_propertyChanged(handler) { + /// + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + throw Error.notImplemented(); + } + function Sys$INotifyPropertyChange$remove_propertyChanged(handler) { + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + throw Error.notImplemented(); + } +Sys.INotifyPropertyChange.prototype = { + add_propertyChanged: Sys$INotifyPropertyChange$add_propertyChanged, + remove_propertyChanged: Sys$INotifyPropertyChange$remove_propertyChanged +} +Sys.INotifyPropertyChange.registerInterface('Sys.INotifyPropertyChange'); + +Sys.PropertyChangedEventArgs = function Sys$PropertyChangedEventArgs(propertyName) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "propertyName", type: String} + ]); + if (e) throw e; + Sys.PropertyChangedEventArgs.initializeBase(this); + this._propertyName = propertyName; +} + + function Sys$PropertyChangedEventArgs$get_propertyName() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._propertyName; + } +Sys.PropertyChangedEventArgs.prototype = { + get_propertyName: Sys$PropertyChangedEventArgs$get_propertyName +} +Sys.PropertyChangedEventArgs.registerClass('Sys.PropertyChangedEventArgs', Sys.EventArgs); + +Sys.INotifyDisposing = function Sys$INotifyDisposing() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); +} + function Sys$INotifyDisposing$add_disposing(handler) { + /// + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + throw Error.notImplemented(); + } + function Sys$INotifyDisposing$remove_disposing(handler) { + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + throw Error.notImplemented(); + } +Sys.INotifyDisposing.prototype = { + add_disposing: Sys$INotifyDisposing$add_disposing, + remove_disposing: Sys$INotifyDisposing$remove_disposing +} +Sys.INotifyDisposing.registerInterface("Sys.INotifyDisposing"); + +Sys.Component = function Sys$Component() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (Sys.Application) Sys.Application.registerDisposableObject(this); +} + function Sys$Component$get_events() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (!this._events) { + this._events = new Sys.EventHandlerList(); + } + return this._events; + } + function Sys$Component$get_id() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._id; + } + function Sys$Component$set_id(value) { + var e = Function._validateParams(arguments, [{name: "value", type: String}]); + if (e) throw e; + if (this._idSet) throw Error.invalidOperation(Sys.Res.componentCantSetIdTwice); + this._idSet = true; + var oldId = this.get_id(); + if (oldId && Sys.Application.findComponent(oldId)) throw Error.invalidOperation(Sys.Res.componentCantSetIdAfterAddedToApp); + this._id = value; + } + function Sys$Component$get_isInitialized() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._initialized; + } + function Sys$Component$get_isUpdating() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._updating; + } + function Sys$Component$add_disposing(handler) { + /// + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this.get_events().addHandler("disposing", handler); + } + function Sys$Component$remove_disposing(handler) { + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this.get_events().removeHandler("disposing", handler); + } + function Sys$Component$add_propertyChanged(handler) { + /// + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this.get_events().addHandler("propertyChanged", handler); + } + function Sys$Component$remove_propertyChanged(handler) { + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this.get_events().removeHandler("propertyChanged", handler); + } + function Sys$Component$beginUpdate() { + this._updating = true; + } + function Sys$Component$dispose() { + if (this._events) { + var handler = this._events.getHandler("disposing"); + if (handler) { + handler(this, Sys.EventArgs.Empty); + } + } + delete this._events; + Sys.Application.unregisterDisposableObject(this); + Sys.Application.removeComponent(this); + } + function Sys$Component$endUpdate() { + this._updating = false; + if (!this._initialized) this.initialize(); + this.updated(); + } + function Sys$Component$initialize() { + this._initialized = true; + } + function Sys$Component$raisePropertyChanged(propertyName) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "propertyName", type: String} + ]); + if (e) throw e; + if (!this._events) return; + var handler = this._events.getHandler("propertyChanged"); + if (handler) { + handler(this, new Sys.PropertyChangedEventArgs(propertyName)); + } + } + function Sys$Component$updated() { + } +Sys.Component.prototype = { + _id: null, + _idSet: false, + _initialized: false, + _updating: false, + get_events: Sys$Component$get_events, + get_id: Sys$Component$get_id, + set_id: Sys$Component$set_id, + get_isInitialized: Sys$Component$get_isInitialized, + get_isUpdating: Sys$Component$get_isUpdating, + add_disposing: Sys$Component$add_disposing, + remove_disposing: Sys$Component$remove_disposing, + add_propertyChanged: Sys$Component$add_propertyChanged, + remove_propertyChanged: Sys$Component$remove_propertyChanged, + beginUpdate: Sys$Component$beginUpdate, + dispose: Sys$Component$dispose, + endUpdate: Sys$Component$endUpdate, + initialize: Sys$Component$initialize, + raisePropertyChanged: Sys$Component$raisePropertyChanged, + updated: Sys$Component$updated +} +Sys.Component.registerClass('Sys.Component', null, Sys.IDisposable, Sys.INotifyPropertyChange, Sys.INotifyDisposing); +function Sys$Component$_setProperties(target, properties) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "target"}, + {name: "properties"} + ]); + if (e) throw e; + var current; + var targetType = Object.getType(target); + var isObject = (targetType === Object) || (targetType === Sys.UI.DomElement); + var isComponent = Sys.Component.isInstanceOfType(target) && !target.get_isUpdating(); + if (isComponent) target.beginUpdate(); + for (var name in properties) { + var val = properties[name]; + var getter = isObject ? null : target["get_" + name]; + if (isObject || typeof(getter) !== 'function') { + var targetVal = target[name]; + if (!isObject && typeof(targetVal) === 'undefined') throw Error.invalidOperation(String.format(Sys.Res.propertyUndefined, name)); + if (!val || (typeof(val) !== 'object') || (isObject && !targetVal)) { + target[name] = val; + } + else { + Sys$Component$_setProperties(targetVal, val); + } + } + else { + var setter = target["set_" + name]; + if (typeof(setter) === 'function') { + setter.apply(target, [val]); + } + else if (val instanceof Array) { + current = getter.apply(target); + if (!(current instanceof Array)) throw new Error.invalidOperation(String.format(Sys.Res.propertyNotAnArray, name)); + for (var i = 0, j = current.length, l= val.length; i < l; i++, j++) { + current[j] = val[i]; + } + } + else if ((typeof(val) === 'object') && (Object.getType(val) === Object)) { + current = getter.apply(target); + if ((typeof(current) === 'undefined') || (current === null)) throw new Error.invalidOperation(String.format(Sys.Res.propertyNullOrUndefined, name)); + Sys$Component$_setProperties(current, val); + } + else { + throw new Error.invalidOperation(String.format(Sys.Res.propertyNotWritable, name)); + } + } + } + if (isComponent) target.endUpdate(); +} +function Sys$Component$_setReferences(component, references) { + for (var name in references) { + var setter = component["set_" + name]; + var reference = $find(references[name]); + if (typeof(setter) !== 'function') throw new Error.invalidOperation(String.format(Sys.Res.propertyNotWritable, name)); + if (!reference) throw Error.invalidOperation(String.format(Sys.Res.referenceNotFound, references[name])); + setter.apply(component, [reference]); + } +} +var $create = Sys.Component.create = function Sys$Component$create(type, properties, events, references, element) { + /// + /// + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "type", type: Type}, + {name: "properties", mayBeNull: true, optional: true}, + {name: "events", mayBeNull: true, optional: true}, + {name: "references", mayBeNull: true, optional: true}, + {name: "element", mayBeNull: true, domElement: true, optional: true} + ]); + if (e) throw e; + if (!type.inheritsFrom(Sys.Component)) { + throw Error.argument('type', String.format(Sys.Res.createNotComponent, type.getName())); + } + if (type.inheritsFrom(Sys.UI.Behavior) || type.inheritsFrom(Sys.UI.Control)) { + if (!element) throw Error.argument('element', Sys.Res.createNoDom); + } + else if (element) throw Error.argument('element', Sys.Res.createComponentOnDom); + var component = (element ? new type(element): new type()); + var app = Sys.Application; + var creatingComponents = app.get_isCreatingComponents(); + component.beginUpdate(); + if (properties) { + Sys$Component$_setProperties(component, properties); + } + if (events) { + for (var name in events) { + if (!(component["add_" + name] instanceof Function)) throw new Error.invalidOperation(String.format(Sys.Res.undefinedEvent, name)); + if (!(events[name] instanceof Function)) throw new Error.invalidOperation(Sys.Res.eventHandlerNotFunction); + component["add_" + name](events[name]); + } + } + if (component.get_id()) { + app.addComponent(component); + } + if (creatingComponents) { + app._createdComponents[app._createdComponents.length] = component; + if (references) { + app._addComponentToSecondPass(component, references); + } + else { + component.endUpdate(); + } + } + else { + if (references) { + Sys$Component$_setReferences(component, references); + } + component.endUpdate(); + } + return component; +} + +Sys.UI.MouseButton = function Sys$UI$MouseButton() { + /// + /// + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); +} +Sys.UI.MouseButton.prototype = { + leftButton: 0, + middleButton: 1, + rightButton: 2 +} +Sys.UI.MouseButton.registerEnum("Sys.UI.MouseButton"); + +Sys.UI.Key = function Sys$UI$Key() { + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); +} +Sys.UI.Key.prototype = { + backspace: 8, + tab: 9, + enter: 13, + esc: 27, + space: 32, + pageUp: 33, + pageDown: 34, + end: 35, + home: 36, + left: 37, + up: 38, + right: 39, + down: 40, + del: 127 +} +Sys.UI.Key.registerEnum("Sys.UI.Key"); + +Sys.UI.Point = function Sys$UI$Point(x, y) { + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "x", type: Number, integer: true}, + {name: "y", type: Number, integer: true} + ]); + if (e) throw e; + this.x = x; + this.y = y; +} +Sys.UI.Point.registerClass('Sys.UI.Point'); + +Sys.UI.Bounds = function Sys$UI$Bounds(x, y, width, height) { + /// + /// + /// + /// + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "x", type: Number, integer: true}, + {name: "y", type: Number, integer: true}, + {name: "width", type: Number, integer: true}, + {name: "height", type: Number, integer: true} + ]); + if (e) throw e; + this.x = x; + this.y = y; + this.height = height; + this.width = width; +} +Sys.UI.Bounds.registerClass('Sys.UI.Bounds'); + +Sys.UI.DomEvent = function Sys$UI$DomEvent(eventObject) { + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "eventObject"} + ]); + if (e) throw e; + var ev = eventObject; + var etype = this.type = ev.type.toLowerCase(); + this.rawEvent = ev; + this.altKey = ev.altKey; + if (typeof(ev.button) !== 'undefined') { + this.button = (typeof(ev.which) !== 'undefined') ? ev.button : + (ev.button === 4) ? Sys.UI.MouseButton.middleButton : + (ev.button === 2) ? Sys.UI.MouseButton.rightButton : + Sys.UI.MouseButton.leftButton; + } + if (etype === 'keypress') { + this.charCode = ev.charCode || ev.keyCode; + } + else if (ev.keyCode && (ev.keyCode === 46)) { + this.keyCode = 127; + } + else { + this.keyCode = ev.keyCode; + } + this.clientX = ev.clientX; + this.clientY = ev.clientY; + this.ctrlKey = ev.ctrlKey; + this.target = ev.target ? ev.target : ev.srcElement; + if (!etype.startsWith('key')) { + if ((typeof(ev.offsetX) !== 'undefined') && (typeof(ev.offsetY) !== 'undefined')) { + this.offsetX = ev.offsetX; + this.offsetY = ev.offsetY; + } + else if (this.target && (this.target.nodeType !== 3) && (typeof(ev.clientX) === 'number')) { + var loc = Sys.UI.DomElement.getLocation(this.target); + var w = Sys.UI.DomElement._getWindow(this.target); + this.offsetX = (w.pageXOffset || 0) + ev.clientX - loc.x; + this.offsetY = (w.pageYOffset || 0) + ev.clientY - loc.y; + } + } + this.screenX = ev.screenX; + this.screenY = ev.screenY; + this.shiftKey = ev.shiftKey; +} + function Sys$UI$DomEvent$preventDefault() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (this.rawEvent.preventDefault) { + this.rawEvent.preventDefault(); + } + else if (window.event) { + this.rawEvent.returnValue = false; + } + } + function Sys$UI$DomEvent$stopPropagation() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (this.rawEvent.stopPropagation) { + this.rawEvent.stopPropagation(); + } + else if (window.event) { + this.rawEvent.cancelBubble = true; + } + } +Sys.UI.DomEvent.prototype = { + preventDefault: Sys$UI$DomEvent$preventDefault, + stopPropagation: Sys$UI$DomEvent$stopPropagation +} +Sys.UI.DomEvent.registerClass('Sys.UI.DomEvent'); +var $addHandler = Sys.UI.DomEvent.addHandler = function Sys$UI$DomEvent$addHandler(element, eventName, handler, autoRemove) { + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element"}, + {name: "eventName", type: String}, + {name: "handler", type: Function}, + {name: "autoRemove", type: Boolean, optional: true} + ]); + if (e) throw e; + Sys.UI.DomEvent._ensureDomNode(element); + if (eventName === "error") throw Error.invalidOperation(Sys.Res.addHandlerCantBeUsedForError); + if (!element._events) { + element._events = {}; + } + var eventCache = element._events[eventName]; + if (!eventCache) { + element._events[eventName] = eventCache = []; + } + var browserHandler; + if (element.addEventListener) { + browserHandler = function(e) { + return handler.call(element, new Sys.UI.DomEvent(e)); + } + element.addEventListener(eventName, browserHandler, false); + } + else if (element.attachEvent) { + browserHandler = function() { + var e = {}; + try {e = Sys.UI.DomElement._getWindow(element).event} catch(ex) {} + return handler.call(element, new Sys.UI.DomEvent(e)); + } + element.attachEvent('on' + eventName, browserHandler); + } + eventCache[eventCache.length] = {handler: handler, browserHandler: browserHandler, autoRemove: autoRemove }; + if (autoRemove) { + var d = element.dispose; + if (d !== Sys.UI.DomEvent._disposeHandlers) { + element.dispose = Sys.UI.DomEvent._disposeHandlers; + if (typeof(d) !== "undefined") { + element._chainDispose = d; + } + } + } +} +var $addHandlers = Sys.UI.DomEvent.addHandlers = function Sys$UI$DomEvent$addHandlers(element, events, handlerOwner, autoRemove) { + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element"}, + {name: "events", type: Object}, + {name: "handlerOwner", optional: true}, + {name: "autoRemove", type: Boolean, optional: true} + ]); + if (e) throw e; + Sys.UI.DomEvent._ensureDomNode(element); + for (var name in events) { + var handler = events[name]; + if (typeof(handler) !== 'function') throw Error.invalidOperation(Sys.Res.cantAddNonFunctionhandler); + if (handlerOwner) { + handler = Function.createDelegate(handlerOwner, handler); + } + $addHandler(element, name, handler, autoRemove || false); + } +} +var $clearHandlers = Sys.UI.DomEvent.clearHandlers = function Sys$UI$DomEvent$clearHandlers(element) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element"} + ]); + if (e) throw e; + Sys.UI.DomEvent._ensureDomNode(element); + Sys.UI.DomEvent._clearHandlers(element, false); +} +Sys.UI.DomEvent._clearHandlers = function Sys$UI$DomEvent$_clearHandlers(element, autoRemoving) { + if (element._events) { + var cache = element._events; + for (var name in cache) { + var handlers = cache[name]; + for (var i = handlers.length - 1; i >= 0; i--) { + var entry = handlers[i]; + if (!autoRemoving || entry.autoRemove) { + $removeHandler(element, name, entry.handler); + } + } + } + element._events = null; + } +} +Sys.UI.DomEvent._disposeHandlers = function Sys$UI$DomEvent$_disposeHandlers() { + Sys.UI.DomEvent._clearHandlers(this, true); + var d = this._chainDispose, type = typeof(d); + if (type !== "undefined") { + this.dispose = d; + this._chainDispose = null; + if (type === "function") { + this.dispose(); + } + } +} +var $removeHandler = Sys.UI.DomEvent.removeHandler = function Sys$UI$DomEvent$removeHandler(element, eventName, handler) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element"}, + {name: "eventName", type: String}, + {name: "handler", type: Function} + ]); + if (e) throw e; + Sys.UI.DomEvent._removeHandler(element, eventName, handler); +} +Sys.UI.DomEvent._removeHandler = function Sys$UI$DomEvent$_removeHandler(element, eventName, handler) { + Sys.UI.DomEvent._ensureDomNode(element); + var browserHandler = null; + if ((typeof(element._events) !== 'object') || !element._events) throw Error.invalidOperation(Sys.Res.eventHandlerInvalid); + var cache = element._events[eventName]; + if (!(cache instanceof Array)) throw Error.invalidOperation(Sys.Res.eventHandlerInvalid); + for (var i = 0, l = cache.length; i < l; i++) { + if (cache[i].handler === handler) { + browserHandler = cache[i].browserHandler; + break; + } + } + if (typeof(browserHandler) !== 'function') throw Error.invalidOperation(Sys.Res.eventHandlerInvalid); + if (element.removeEventListener) { + element.removeEventListener(eventName, browserHandler, false); + } + else if (element.detachEvent) { + element.detachEvent('on' + eventName, browserHandler); + } + cache.splice(i, 1); +} +Sys.UI.DomEvent._ensureDomNode = function Sys$UI$DomEvent$_ensureDomNode(element) { + if (element.tagName && (element.tagName.toUpperCase() === "SCRIPT")) return; + + var doc = element.ownerDocument || element.document || element; + if ((typeof(element.document) !== 'object') && (element != doc) && (typeof(element.nodeType) !== 'number')) { + throw Error.argument("element", Sys.Res.argumentDomNode); + } +} + +Sys.UI.DomElement = function Sys$UI$DomElement() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); +} +Sys.UI.DomElement.registerClass('Sys.UI.DomElement'); +Sys.UI.DomElement.addCssClass = function Sys$UI$DomElement$addCssClass(element, className) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true}, + {name: "className", type: String} + ]); + if (e) throw e; + if (!Sys.UI.DomElement.containsCssClass(element, className)) { + if (element.className === '') { + element.className = className; + } + else { + element.className += ' ' + className; + } + } +} +Sys.UI.DomElement.containsCssClass = function Sys$UI$DomElement$containsCssClass(element, className) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true}, + {name: "className", type: String} + ]); + if (e) throw e; + return Array.contains(element.className.split(' '), className); +} +Sys.UI.DomElement.getBounds = function Sys$UI$DomElement$getBounds(element) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true} + ]); + if (e) throw e; + var offset = Sys.UI.DomElement.getLocation(element); + return new Sys.UI.Bounds(offset.x, offset.y, element.offsetWidth || 0, element.offsetHeight || 0); +} +var $get = Sys.UI.DomElement.getElementById = function Sys$UI$DomElement$getElementById(id, element) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "id", type: String}, + {name: "element", mayBeNull: true, domElement: true, optional: true} + ]); + if (e) throw e; + if (!element) return document.getElementById(id); + if (element.getElementById) return element.getElementById(id); + var nodeQueue = []; + var childNodes = element.childNodes; + for (var i = 0; i < childNodes.length; i++) { + var node = childNodes[i]; + if (node.nodeType == 1) { + nodeQueue[nodeQueue.length] = node; + } + } + while (nodeQueue.length) { + node = nodeQueue.shift(); + if (node.id == id) { + return node; + } + childNodes = node.childNodes; + for (i = 0; i < childNodes.length; i++) { + node = childNodes[i]; + if (node.nodeType == 1) { + nodeQueue[nodeQueue.length] = node; + } + } + } + return null; +} +if (document.documentElement.getBoundingClientRect) { + Sys.UI.DomElement.getLocation = function Sys$UI$DomElement$getLocation(element) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true} + ]); + if (e) throw e; + if (element.self || element.nodeType === 9) return new Sys.UI.Point(0,0); + var clientRect = element.getBoundingClientRect(); + if (!clientRect) { + return new Sys.UI.Point(0,0); + } + var documentElement = element.ownerDocument.documentElement, + offsetX = Math.floor(clientRect.left + 0.5) + documentElement.scrollLeft, + offsetY = Math.floor(clientRect.top + 0.5) + documentElement.scrollTop; + if (Sys.Browser.agent === Sys.Browser.InternetExplorer) { + try { + var f = element.ownerDocument.parentWindow.frameElement || null; + if (f) { + var offset = (f.frameBorder === "0" || f.frameBorder === "no") ? 2 : 0; + offsetX += offset; + offsetY += offset; + } + } + catch(ex) { + } + if (Sys.Browser.version <= 7) { + + var multiplier, before, rect, d = document.createElement("div"); + d.style.cssText = "position:absolute !important;left:0px !important;right:0px !important;height:0px !important;width:1px !important;display:hidden !important"; + try { + before = document.body.childNodes[0]; + document.body.insertBefore(d, before); + rect = d.getBoundingClientRect(); + document.body.removeChild(d); + multiplier = (rect.right - rect.left); + } + catch (e) { + } + if (multiplier && (multiplier !== 1)) { + offsetX = Math.floor(offsetX / multiplier); + offsetY = Math.floor(offsetY / multiplier); + } + } + if ((document.documentMode || 0) < 8) { + offsetX -= 2; + offsetY -= 2; + } + } + return new Sys.UI.Point(offsetX, offsetY); + } +} +else if (Sys.Browser.agent === Sys.Browser.Safari) { + Sys.UI.DomElement.getLocation = function Sys$UI$DomElement$getLocation(element) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true} + ]); + if (e) throw e; + if ((element.window && (element.window === element)) || element.nodeType === 9) return new Sys.UI.Point(0,0); + var offsetX = 0, offsetY = 0, + parent, + previous = null, + previousStyle = null, + currentStyle; + for (parent = element; parent; previous = parent, previousStyle = currentStyle, parent = parent.offsetParent) { + currentStyle = Sys.UI.DomElement._getCurrentStyle(parent); + var tagName = parent.tagName ? parent.tagName.toUpperCase() : null; + if ((parent.offsetLeft || parent.offsetTop) && + ((tagName !== "BODY") || (!previousStyle || previousStyle.position !== "absolute"))) { + offsetX += parent.offsetLeft; + offsetY += parent.offsetTop; + } + if (previous && Sys.Browser.version >= 3) { + offsetX += parseInt(currentStyle.borderLeftWidth); + offsetY += parseInt(currentStyle.borderTopWidth); + } + } + currentStyle = Sys.UI.DomElement._getCurrentStyle(element); + var elementPosition = currentStyle ? currentStyle.position : null; + if (!elementPosition || (elementPosition !== "absolute")) { + for (parent = element.parentNode; parent; parent = parent.parentNode) { + tagName = parent.tagName ? parent.tagName.toUpperCase() : null; + if ((tagName !== "BODY") && (tagName !== "HTML") && (parent.scrollLeft || parent.scrollTop)) { + offsetX -= (parent.scrollLeft || 0); + offsetY -= (parent.scrollTop || 0); + } + currentStyle = Sys.UI.DomElement._getCurrentStyle(parent); + var parentPosition = currentStyle ? currentStyle.position : null; + if (parentPosition && (parentPosition === "absolute")) break; + } + } + return new Sys.UI.Point(offsetX, offsetY); + } +} +else { + Sys.UI.DomElement.getLocation = function Sys$UI$DomElement$getLocation(element) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true} + ]); + if (e) throw e; + if ((element.window && (element.window === element)) || element.nodeType === 9) return new Sys.UI.Point(0,0); + var offsetX = 0, offsetY = 0, + parent, + previous = null, + previousStyle = null, + currentStyle = null; + for (parent = element; parent; previous = parent, previousStyle = currentStyle, parent = parent.offsetParent) { + var tagName = parent.tagName ? parent.tagName.toUpperCase() : null; + currentStyle = Sys.UI.DomElement._getCurrentStyle(parent); + if ((parent.offsetLeft || parent.offsetTop) && + !((tagName === "BODY") && + (!previousStyle || previousStyle.position !== "absolute"))) { + offsetX += parent.offsetLeft; + offsetY += parent.offsetTop; + } + if (previous !== null && currentStyle) { + if ((tagName !== "TABLE") && (tagName !== "TD") && (tagName !== "HTML")) { + offsetX += parseInt(currentStyle.borderLeftWidth) || 0; + offsetY += parseInt(currentStyle.borderTopWidth) || 0; + } + if (tagName === "TABLE" && + (currentStyle.position === "relative" || currentStyle.position === "absolute")) { + offsetX += parseInt(currentStyle.marginLeft) || 0; + offsetY += parseInt(currentStyle.marginTop) || 0; + } + } + } + currentStyle = Sys.UI.DomElement._getCurrentStyle(element); + var elementPosition = currentStyle ? currentStyle.position : null; + if (!elementPosition || (elementPosition !== "absolute")) { + for (parent = element.parentNode; parent; parent = parent.parentNode) { + tagName = parent.tagName ? parent.tagName.toUpperCase() : null; + if ((tagName !== "BODY") && (tagName !== "HTML") && (parent.scrollLeft || parent.scrollTop)) { + offsetX -= (parent.scrollLeft || 0); + offsetY -= (parent.scrollTop || 0); + currentStyle = Sys.UI.DomElement._getCurrentStyle(parent); + if (currentStyle) { + offsetX += parseInt(currentStyle.borderLeftWidth) || 0; + offsetY += parseInt(currentStyle.borderTopWidth) || 0; + } + } + } + } + return new Sys.UI.Point(offsetX, offsetY); + } +} +Sys.UI.DomElement.isDomElement = function Sys$UI$DomElement$isDomElement(obj) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "obj"} + ]); + if (e) throw e; + return Sys._isDomElement(obj); +} +Sys.UI.DomElement.removeCssClass = function Sys$UI$DomElement$removeCssClass(element, className) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true}, + {name: "className", type: String} + ]); + if (e) throw e; + var currentClassName = ' ' + element.className + ' '; + var index = currentClassName.indexOf(' ' + className + ' '); + if (index >= 0) { + element.className = (currentClassName.substr(0, index) + ' ' + + currentClassName.substring(index + className.length + 1, currentClassName.length)).trim(); + } +} +Sys.UI.DomElement.resolveElement = function Sys$UI$DomElement$resolveElement(elementOrElementId, containerElement) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "elementOrElementId", mayBeNull: true}, + {name: "containerElement", mayBeNull: true, domElement: true, optional: true} + ]); + if (e) throw e; + var el = elementOrElementId; + if (!el) return null; + if (typeof(el) === "string") { + el = Sys.UI.DomElement.getElementById(el, containerElement); + if (!el) { + throw Error.argument("elementOrElementId", String.format(Sys.Res.elementNotFound, elementOrElementId)); + } + } + else if(!Sys.UI.DomElement.isDomElement(el)) { + throw Error.argument("elementOrElementId", Sys.Res.expectedElementOrId); + } + return el; +} +Sys.UI.DomElement.raiseBubbleEvent = function Sys$UI$DomElement$raiseBubbleEvent(source, args) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "source", domElement: true}, + {name: "args", type: Sys.EventArgs} + ]); + if (e) throw e; + var target = source; + while (target) { + var control = target.control; + if (control && control.onBubbleEvent && control.raiseBubbleEvent) { + Sys.UI.DomElement._raiseBubbleEventFromControl(control, source, args); + return; + } + target = target.parentNode; + } +} +Sys.UI.DomElement._raiseBubbleEventFromControl = function Sys$UI$DomElement$_raiseBubbleEventFromControl(control, source, args) { + if (!control.onBubbleEvent(source, args)) { + control._raiseBubbleEvent(source, args); + } +} +Sys.UI.DomElement.setLocation = function Sys$UI$DomElement$setLocation(element, x, y) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true}, + {name: "x", type: Number, integer: true}, + {name: "y", type: Number, integer: true} + ]); + if (e) throw e; + var style = element.style; + style.position = 'absolute'; + style.left = x + "px"; + style.top = y + "px"; +} +Sys.UI.DomElement.toggleCssClass = function Sys$UI$DomElement$toggleCssClass(element, className) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true}, + {name: "className", type: String} + ]); + if (e) throw e; + if (Sys.UI.DomElement.containsCssClass(element, className)) { + Sys.UI.DomElement.removeCssClass(element, className); + } + else { + Sys.UI.DomElement.addCssClass(element, className); + } +} +Sys.UI.DomElement.getVisibilityMode = function Sys$UI$DomElement$getVisibilityMode(element) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true} + ]); + if (e) throw e; + return (element._visibilityMode === Sys.UI.VisibilityMode.hide) ? + Sys.UI.VisibilityMode.hide : + Sys.UI.VisibilityMode.collapse; +} +Sys.UI.DomElement.setVisibilityMode = function Sys$UI$DomElement$setVisibilityMode(element, value) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true}, + {name: "value", type: Sys.UI.VisibilityMode} + ]); + if (e) throw e; + Sys.UI.DomElement._ensureOldDisplayMode(element); + if (element._visibilityMode !== value) { + element._visibilityMode = value; + if (Sys.UI.DomElement.getVisible(element) === false) { + if (element._visibilityMode === Sys.UI.VisibilityMode.hide) { + element.style.display = element._oldDisplayMode; + } + else { + element.style.display = 'none'; + } + } + element._visibilityMode = value; + } +} +Sys.UI.DomElement.getVisible = function Sys$UI$DomElement$getVisible(element) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true} + ]); + if (e) throw e; + var style = element.currentStyle || Sys.UI.DomElement._getCurrentStyle(element); + if (!style) return true; + return (style.visibility !== 'hidden') && (style.display !== 'none'); +} +Sys.UI.DomElement.setVisible = function Sys$UI$DomElement$setVisible(element, value) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true}, + {name: "value", type: Boolean} + ]); + if (e) throw e; + if (value !== Sys.UI.DomElement.getVisible(element)) { + Sys.UI.DomElement._ensureOldDisplayMode(element); + element.style.visibility = value ? 'visible' : 'hidden'; + if (value || (element._visibilityMode === Sys.UI.VisibilityMode.hide)) { + element.style.display = element._oldDisplayMode; + } + else { + element.style.display = 'none'; + } + } +} +Sys.UI.DomElement._ensureOldDisplayMode = function Sys$UI$DomElement$_ensureOldDisplayMode(element) { + if (!element._oldDisplayMode) { + var style = element.currentStyle || Sys.UI.DomElement._getCurrentStyle(element); + element._oldDisplayMode = style ? style.display : null; + if (!element._oldDisplayMode || element._oldDisplayMode === 'none') { + switch(element.tagName.toUpperCase()) { + case 'DIV': case 'P': case 'ADDRESS': case 'BLOCKQUOTE': case 'BODY': case 'COL': + case 'COLGROUP': case 'DD': case 'DL': case 'DT': case 'FIELDSET': case 'FORM': + case 'H1': case 'H2': case 'H3': case 'H4': case 'H5': case 'H6': case 'HR': + case 'IFRAME': case 'LEGEND': case 'OL': case 'PRE': case 'TABLE': case 'TD': + case 'TH': case 'TR': case 'UL': + element._oldDisplayMode = 'block'; + break; + case 'LI': + element._oldDisplayMode = 'list-item'; + break; + default: + element._oldDisplayMode = 'inline'; + } + } + } +} +Sys.UI.DomElement._getWindow = function Sys$UI$DomElement$_getWindow(element) { + var doc = element.ownerDocument || element.document || element; + return doc.defaultView || doc.parentWindow; +} +Sys.UI.DomElement._getCurrentStyle = function Sys$UI$DomElement$_getCurrentStyle(element) { + if (element.nodeType === 3) return null; + var w = Sys.UI.DomElement._getWindow(element); + if (element.documentElement) element = element.documentElement; + var computedStyle = (w && (element !== w) && w.getComputedStyle) ? + w.getComputedStyle(element, null) : + element.currentStyle || element.style; + if (!computedStyle && (Sys.Browser.agent === Sys.Browser.Safari) && element.style) { + var oldDisplay = element.style.display; + var oldPosition = element.style.position; + element.style.position = 'absolute'; + element.style.display = 'block'; + var style = w.getComputedStyle(element, null); + element.style.display = oldDisplay; + element.style.position = oldPosition; + computedStyle = {}; + for (var n in style) { + computedStyle[n] = style[n]; + } + computedStyle.display = 'none'; + } + return computedStyle; +} + +Sys.IContainer = function Sys$IContainer() { + throw Error.notImplemented(); +} + function Sys$IContainer$addComponent(component) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "component", type: Sys.Component} + ]); + if (e) throw e; + throw Error.notImplemented(); + } + function Sys$IContainer$removeComponent(component) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "component", type: Sys.Component} + ]); + if (e) throw e; + throw Error.notImplemented(); + } + function Sys$IContainer$findComponent(id) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "id", type: String} + ]); + if (e) throw e; + throw Error.notImplemented(); + } + function Sys$IContainer$getComponents() { + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); + } +Sys.IContainer.prototype = { + addComponent: Sys$IContainer$addComponent, + removeComponent: Sys$IContainer$removeComponent, + findComponent: Sys$IContainer$findComponent, + getComponents: Sys$IContainer$getComponents +} +Sys.IContainer.registerInterface("Sys.IContainer"); + +Sys.ApplicationLoadEventArgs = function Sys$ApplicationLoadEventArgs(components, isPartialLoad) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "components", type: Array, elementType: Sys.Component}, + {name: "isPartialLoad", type: Boolean} + ]); + if (e) throw e; + Sys.ApplicationLoadEventArgs.initializeBase(this); + this._components = components; + this._isPartialLoad = isPartialLoad; +} + + function Sys$ApplicationLoadEventArgs$get_components() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._components; + } + function Sys$ApplicationLoadEventArgs$get_isPartialLoad() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._isPartialLoad; + } +Sys.ApplicationLoadEventArgs.prototype = { + get_components: Sys$ApplicationLoadEventArgs$get_components, + get_isPartialLoad: Sys$ApplicationLoadEventArgs$get_isPartialLoad +} +Sys.ApplicationLoadEventArgs.registerClass('Sys.ApplicationLoadEventArgs', Sys.EventArgs); + +Sys._Application = function Sys$_Application() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + Sys._Application.initializeBase(this); + this._disposableObjects = []; + this._components = {}; + this._createdComponents = []; + this._secondPassComponents = []; + this._unloadHandlerDelegate = Function.createDelegate(this, this._unloadHandler); + Sys.UI.DomEvent.addHandler(window, "unload", this._unloadHandlerDelegate); + this._domReady(); +} + function Sys$_Application$get_isCreatingComponents() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._creatingComponents; + } + function Sys$_Application$get_isDisposing() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._disposing; + } + function Sys$_Application$add_init(handler) { + /// + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + if (this._initialized) { + handler(this, Sys.EventArgs.Empty); + } + else { + this.get_events().addHandler("init", handler); + } + } + function Sys$_Application$remove_init(handler) { + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this.get_events().removeHandler("init", handler); + } + function Sys$_Application$add_load(handler) { + /// + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this.get_events().addHandler("load", handler); + } + function Sys$_Application$remove_load(handler) { + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this.get_events().removeHandler("load", handler); + } + function Sys$_Application$add_unload(handler) { + /// + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this.get_events().addHandler("unload", handler); + } + function Sys$_Application$remove_unload(handler) { + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this.get_events().removeHandler("unload", handler); + } + function Sys$_Application$addComponent(component) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "component", type: Sys.Component} + ]); + if (e) throw e; + var id = component.get_id(); + if (!id) throw Error.invalidOperation(Sys.Res.cantAddWithoutId); + if (typeof(this._components[id]) !== 'undefined') throw Error.invalidOperation(String.format(Sys.Res.appDuplicateComponent, id)); + this._components[id] = component; + } + function Sys$_Application$beginCreateComponents() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + this._creatingComponents = true; + } + function Sys$_Application$dispose() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (!this._disposing) { + this._disposing = true; + if (this._timerCookie) { + window.clearTimeout(this._timerCookie); + delete this._timerCookie; + } + if (this._endRequestHandler) { + Sys.WebForms.PageRequestManager.getInstance().remove_endRequest(this._endRequestHandler); + delete this._endRequestHandler; + } + if (this._beginRequestHandler) { + Sys.WebForms.PageRequestManager.getInstance().remove_beginRequest(this._beginRequestHandler); + delete this._beginRequestHandler; + } + if (window.pageUnload) { + window.pageUnload(this, Sys.EventArgs.Empty); + } + var unloadHandler = this.get_events().getHandler("unload"); + if (unloadHandler) { + unloadHandler(this, Sys.EventArgs.Empty); + } + var disposableObjects = Array.clone(this._disposableObjects); + for (var i = 0, l = disposableObjects.length; i < l; i++) { + var object = disposableObjects[i]; + if (typeof(object) !== "undefined") { + object.dispose(); + } + } + Array.clear(this._disposableObjects); + Sys.UI.DomEvent.removeHandler(window, "unload", this._unloadHandlerDelegate); + if (Sys._ScriptLoader) { + var sl = Sys._ScriptLoader.getInstance(); + if(sl) { + sl.dispose(); + } + } + Sys._Application.callBaseMethod(this, 'dispose'); + } + } + function Sys$_Application$disposeElement(element, childNodesOnly) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element"}, + {name: "childNodesOnly", type: Boolean} + ]); + if (e) throw e; + if (element.nodeType === 1) { + var children = element.getElementsByTagName("*"); + for (var i = children.length - 1; i >= 0; i--) { + this._disposeElementInternal(children[i]); + } + if (!childNodesOnly) { + this._disposeElementInternal(element); + } + } + } + function Sys$_Application$endCreateComponents() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + var components = this._secondPassComponents; + for (var i = 0, l = components.length; i < l; i++) { + var component = components[i].component; + Sys$Component$_setReferences(component, components[i].references); + component.endUpdate(); + } + this._secondPassComponents = []; + this._creatingComponents = false; + } + function Sys$_Application$findComponent(id, parent) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "id", type: String}, + {name: "parent", mayBeNull: true, optional: true} + ]); + if (e) throw e; + return (parent ? + ((Sys.IContainer.isInstanceOfType(parent)) ? + parent.findComponent(id) : + parent[id] || null) : + Sys.Application._components[id] || null); + } + function Sys$_Application$getComponents() { + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + var res = []; + var components = this._components; + for (var name in components) { + res[res.length] = components[name]; + } + return res; + } + function Sys$_Application$initialize() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if(!this.get_isInitialized() && !this._disposing) { + Sys._Application.callBaseMethod(this, 'initialize'); + this._raiseInit(); + if (this.get_stateString) { + if (Sys.WebForms && Sys.WebForms.PageRequestManager) { + this._beginRequestHandler = Function.createDelegate(this, this._onPageRequestManagerBeginRequest); + Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(this._beginRequestHandler); + this._endRequestHandler = Function.createDelegate(this, this._onPageRequestManagerEndRequest); + Sys.WebForms.PageRequestManager.getInstance().add_endRequest(this._endRequestHandler); + } + var loadedEntry = this.get_stateString(); + if (loadedEntry !== this._currentEntry) { + this._navigate(loadedEntry); + } + else { + this._ensureHistory(); + } + } + this.raiseLoad(); + } + } + function Sys$_Application$notifyScriptLoaded() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + } + function Sys$_Application$registerDisposableObject(object) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "object", type: Sys.IDisposable} + ]); + if (e) throw e; + if (!this._disposing) { + var objects = this._disposableObjects, + i = objects.length; + objects[i] = object; + object.__msdisposeindex = i; + } + } + function Sys$_Application$raiseLoad() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + var h = this.get_events().getHandler("load"); + var args = new Sys.ApplicationLoadEventArgs(Array.clone(this._createdComponents), !!this._loaded); + this._loaded = true; + if (h) { + h(this, args); + } + if (window.pageLoad) { + window.pageLoad(this, args); + } + this._createdComponents = []; + } + function Sys$_Application$removeComponent(component) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "component", type: Sys.Component} + ]); + if (e) throw e; + var id = component.get_id(); + if (id) delete this._components[id]; + } + function Sys$_Application$unregisterDisposableObject(object) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "object", type: Sys.IDisposable} + ]); + if (e) throw e; + if (!this._disposing) { + var i = object.__msdisposeindex; + if (typeof(i) === "number") { + var disposableObjects = this._disposableObjects; + delete disposableObjects[i]; + delete object.__msdisposeindex; + if (++this._deleteCount > 1000) { + var newArray = []; + for (var j = 0, l = disposableObjects.length; j < l; j++) { + object = disposableObjects[j]; + if (typeof(object) !== "undefined") { + object.__msdisposeindex = newArray.length; + newArray.push(object); + } + } + this._disposableObjects = newArray; + this._deleteCount = 0; + } + } + } + } + function Sys$_Application$_addComponentToSecondPass(component, references) { + this._secondPassComponents[this._secondPassComponents.length] = {component: component, references: references}; + } + function Sys$_Application$_disposeComponents(list) { + if (list) { + for (var i = list.length - 1; i >= 0; i--) { + var item = list[i]; + if (typeof(item.dispose) === "function") { + item.dispose(); + } + } + } + } + function Sys$_Application$_disposeElementInternal(element) { + var d = element.dispose; + if (d && typeof(d) === "function") { + element.dispose(); + } + else { + var c = element.control; + if (c && typeof(c.dispose) === "function") { + c.dispose(); + } + } + var list = element._behaviors; + if (list) { + this._disposeComponents(list); + } + list = element._components; + if (list) { + this._disposeComponents(list); + element._components = null; + } + } + function Sys$_Application$_domReady() { + var check, er, app = this; + function init() { app.initialize(); } + var onload = function() { + Sys.UI.DomEvent.removeHandler(window, "load", onload); + init(); + } + Sys.UI.DomEvent.addHandler(window, "load", onload); + + if (document.addEventListener) { + try { + document.addEventListener("DOMContentLoaded", check = function() { + document.removeEventListener("DOMContentLoaded", check, false); + init(); + }, false); + } + catch (er) { } + } + else if (document.attachEvent) { + if ((window == window.top) && document.documentElement.doScroll) { + var timeout, el = document.createElement("div"); + check = function() { + try { + el.doScroll("left"); + } + catch (er) { + timeout = window.setTimeout(check, 0); + return; + } + el = null; + init(); + } + check(); + } + else { + document.attachEvent("onreadystatechange", check = function() { + if (document.readyState === "complete") { + document.detachEvent("onreadystatechange", check); + init(); + } + }); + } + } + } + function Sys$_Application$_raiseInit() { + var handler = this.get_events().getHandler("init"); + if (handler) { + this.beginCreateComponents(); + handler(this, Sys.EventArgs.Empty); + this.endCreateComponents(); + } + } + function Sys$_Application$_unloadHandler(event) { + this.dispose(); + } +Sys._Application.prototype = { + _creatingComponents: false, + _disposing: false, + _deleteCount: 0, + get_isCreatingComponents: Sys$_Application$get_isCreatingComponents, + get_isDisposing: Sys$_Application$get_isDisposing, + add_init: Sys$_Application$add_init, + remove_init: Sys$_Application$remove_init, + add_load: Sys$_Application$add_load, + remove_load: Sys$_Application$remove_load, + add_unload: Sys$_Application$add_unload, + remove_unload: Sys$_Application$remove_unload, + addComponent: Sys$_Application$addComponent, + beginCreateComponents: Sys$_Application$beginCreateComponents, + dispose: Sys$_Application$dispose, + disposeElement: Sys$_Application$disposeElement, + endCreateComponents: Sys$_Application$endCreateComponents, + findComponent: Sys$_Application$findComponent, + getComponents: Sys$_Application$getComponents, + initialize: Sys$_Application$initialize, + notifyScriptLoaded: Sys$_Application$notifyScriptLoaded, + registerDisposableObject: Sys$_Application$registerDisposableObject, + raiseLoad: Sys$_Application$raiseLoad, + removeComponent: Sys$_Application$removeComponent, + unregisterDisposableObject: Sys$_Application$unregisterDisposableObject, + _addComponentToSecondPass: Sys$_Application$_addComponentToSecondPass, + _disposeComponents: Sys$_Application$_disposeComponents, + _disposeElementInternal: Sys$_Application$_disposeElementInternal, + _domReady: Sys$_Application$_domReady, + _raiseInit: Sys$_Application$_raiseInit, + _unloadHandler: Sys$_Application$_unloadHandler +} +Sys._Application.registerClass('Sys._Application', Sys.Component, Sys.IContainer); +Sys.Application = new Sys._Application(); +var $find = Sys.Application.findComponent; + +Sys.UI.Behavior = function Sys$UI$Behavior(element) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true} + ]); + if (e) throw e; + Sys.UI.Behavior.initializeBase(this); + this._element = element; + var behaviors = element._behaviors; + if (!behaviors) { + element._behaviors = [this]; + } + else { + behaviors[behaviors.length] = this; + } +} + function Sys$UI$Behavior$get_element() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._element; + } + function Sys$UI$Behavior$get_id() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + var baseId = Sys.UI.Behavior.callBaseMethod(this, 'get_id'); + if (baseId) return baseId; + if (!this._element || !this._element.id) return ''; + return this._element.id + '$' + this.get_name(); + } + function Sys$UI$Behavior$get_name() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (this._name) return this._name; + var name = Object.getTypeName(this); + var i = name.lastIndexOf('.'); + if (i !== -1) name = name.substr(i + 1); + if (!this.get_isInitialized()) this._name = name; + return name; + } + function Sys$UI$Behavior$set_name(value) { + var e = Function._validateParams(arguments, [{name: "value", type: String}]); + if (e) throw e; + if ((value === '') || (value.charAt(0) === ' ') || (value.charAt(value.length - 1) === ' ')) + throw Error.argument('value', Sys.Res.invalidId); + if (typeof(this._element[value]) !== 'undefined') + throw Error.invalidOperation(String.format(Sys.Res.behaviorDuplicateName, value)); + if (this.get_isInitialized()) throw Error.invalidOperation(Sys.Res.cantSetNameAfterInit); + this._name = value; + } + function Sys$UI$Behavior$initialize() { + Sys.UI.Behavior.callBaseMethod(this, 'initialize'); + var name = this.get_name(); + if (name) this._element[name] = this; + } + function Sys$UI$Behavior$dispose() { + Sys.UI.Behavior.callBaseMethod(this, 'dispose'); + var e = this._element; + if (e) { + var name = this.get_name(); + if (name) { + e[name] = null; + } + var behaviors = e._behaviors; + Array.remove(behaviors, this); + if (behaviors.length === 0) { + e._behaviors = null; + } + delete this._element; + } + } +Sys.UI.Behavior.prototype = { + _name: null, + get_element: Sys$UI$Behavior$get_element, + get_id: Sys$UI$Behavior$get_id, + get_name: Sys$UI$Behavior$get_name, + set_name: Sys$UI$Behavior$set_name, + initialize: Sys$UI$Behavior$initialize, + dispose: Sys$UI$Behavior$dispose +} +Sys.UI.Behavior.registerClass('Sys.UI.Behavior', Sys.Component); +Sys.UI.Behavior.getBehaviorByName = function Sys$UI$Behavior$getBehaviorByName(element, name) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true}, + {name: "name", type: String} + ]); + if (e) throw e; + var b = element[name]; + return (b && Sys.UI.Behavior.isInstanceOfType(b)) ? b : null; +} +Sys.UI.Behavior.getBehaviors = function Sys$UI$Behavior$getBehaviors(element) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true} + ]); + if (e) throw e; + if (!element._behaviors) return []; + return Array.clone(element._behaviors); +} +Sys.UI.Behavior.getBehaviorsByType = function Sys$UI$Behavior$getBehaviorsByType(element, type) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true}, + {name: "type", type: Type} + ]); + if (e) throw e; + var behaviors = element._behaviors; + var results = []; + if (behaviors) { + for (var i = 0, l = behaviors.length; i < l; i++) { + if (type.isInstanceOfType(behaviors[i])) { + results[results.length] = behaviors[i]; + } + } + } + return results; +} + +Sys.UI.VisibilityMode = function Sys$UI$VisibilityMode() { + /// + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); +} +Sys.UI.VisibilityMode.prototype = { + hide: 0, + collapse: 1 +} +Sys.UI.VisibilityMode.registerEnum("Sys.UI.VisibilityMode"); + +Sys.UI.Control = function Sys$UI$Control(element) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "element", domElement: true} + ]); + if (e) throw e; + if (typeof(element.control) !== 'undefined') throw Error.invalidOperation(Sys.Res.controlAlreadyDefined); + Sys.UI.Control.initializeBase(this); + this._element = element; + element.control = this; + var role = this.get_role(); + if (role) { + element.setAttribute("role", role); + } +} + function Sys$UI$Control$get_element() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._element; + } + function Sys$UI$Control$get_id() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (!this._element) return ''; + return this._element.id; + } + function Sys$UI$Control$set_id(value) { + var e = Function._validateParams(arguments, [{name: "value", type: String}]); + if (e) throw e; + throw Error.invalidOperation(Sys.Res.cantSetId); + } + function Sys$UI$Control$get_parent() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (this._parent) return this._parent; + if (!this._element) return null; + + var parentElement = this._element.parentNode; + while (parentElement) { + if (parentElement.control) { + return parentElement.control; + } + parentElement = parentElement.parentNode; + } + return null; + } + function Sys$UI$Control$set_parent(value) { + var e = Function._validateParams(arguments, [{name: "value", type: Sys.UI.Control}]); + if (e) throw e; + if (!this._element) throw Error.invalidOperation(Sys.Res.cantBeCalledAfterDispose); + var parents = [this]; + var current = value; + while (current) { + if (Array.contains(parents, current)) throw Error.invalidOperation(Sys.Res.circularParentChain); + parents[parents.length] = current; + current = current.get_parent(); + } + this._parent = value; + } + function Sys$UI$Control$get_role() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return null; + } + function Sys$UI$Control$get_visibilityMode() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (!this._element) throw Error.invalidOperation(Sys.Res.cantBeCalledAfterDispose); + return Sys.UI.DomElement.getVisibilityMode(this._element); + } + function Sys$UI$Control$set_visibilityMode(value) { + var e = Function._validateParams(arguments, [{name: "value", type: Sys.UI.VisibilityMode}]); + if (e) throw e; + if (!this._element) throw Error.invalidOperation(Sys.Res.cantBeCalledAfterDispose); + Sys.UI.DomElement.setVisibilityMode(this._element, value); + } + function Sys$UI$Control$get_visible() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (!this._element) throw Error.invalidOperation(Sys.Res.cantBeCalledAfterDispose); + return Sys.UI.DomElement.getVisible(this._element); + } + function Sys$UI$Control$set_visible(value) { + var e = Function._validateParams(arguments, [{name: "value", type: Boolean}]); + if (e) throw e; + if (!this._element) throw Error.invalidOperation(Sys.Res.cantBeCalledAfterDispose); + Sys.UI.DomElement.setVisible(this._element, value) + } + function Sys$UI$Control$addCssClass(className) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "className", type: String} + ]); + if (e) throw e; + if (!this._element) throw Error.invalidOperation(Sys.Res.cantBeCalledAfterDispose); + Sys.UI.DomElement.addCssClass(this._element, className); + } + function Sys$UI$Control$dispose() { + Sys.UI.Control.callBaseMethod(this, 'dispose'); + if (this._element) { + this._element.control = null; + delete this._element; + } + if (this._parent) delete this._parent; + } + function Sys$UI$Control$onBubbleEvent(source, args) { + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "source"}, + {name: "args", type: Sys.EventArgs} + ]); + if (e) throw e; + return false; + } + function Sys$UI$Control$raiseBubbleEvent(source, args) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "source"}, + {name: "args", type: Sys.EventArgs} + ]); + if (e) throw e; + this._raiseBubbleEvent(source, args); + } + function Sys$UI$Control$_raiseBubbleEvent(source, args) { + var currentTarget = this.get_parent(); + while (currentTarget) { + if (currentTarget.onBubbleEvent(source, args)) { + return; + } + currentTarget = currentTarget.get_parent(); + } + } + function Sys$UI$Control$removeCssClass(className) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "className", type: String} + ]); + if (e) throw e; + if (!this._element) throw Error.invalidOperation(Sys.Res.cantBeCalledAfterDispose); + Sys.UI.DomElement.removeCssClass(this._element, className); + } + function Sys$UI$Control$toggleCssClass(className) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "className", type: String} + ]); + if (e) throw e; + if (!this._element) throw Error.invalidOperation(Sys.Res.cantBeCalledAfterDispose); + Sys.UI.DomElement.toggleCssClass(this._element, className); + } +Sys.UI.Control.prototype = { + _parent: null, + _visibilityMode: Sys.UI.VisibilityMode.hide, + get_element: Sys$UI$Control$get_element, + get_id: Sys$UI$Control$get_id, + set_id: Sys$UI$Control$set_id, + get_parent: Sys$UI$Control$get_parent, + set_parent: Sys$UI$Control$set_parent, + get_role: Sys$UI$Control$get_role, + get_visibilityMode: Sys$UI$Control$get_visibilityMode, + set_visibilityMode: Sys$UI$Control$set_visibilityMode, + get_visible: Sys$UI$Control$get_visible, + set_visible: Sys$UI$Control$set_visible, + addCssClass: Sys$UI$Control$addCssClass, + dispose: Sys$UI$Control$dispose, + onBubbleEvent: Sys$UI$Control$onBubbleEvent, + raiseBubbleEvent: Sys$UI$Control$raiseBubbleEvent, + _raiseBubbleEvent: Sys$UI$Control$_raiseBubbleEvent, + removeCssClass: Sys$UI$Control$removeCssClass, + toggleCssClass: Sys$UI$Control$toggleCssClass +} +Sys.UI.Control.registerClass('Sys.UI.Control', Sys.Component); +Sys.HistoryEventArgs = function Sys$HistoryEventArgs(state) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "state", type: Object} + ]); + if (e) throw e; + Sys.HistoryEventArgs.initializeBase(this); + this._state = state; +} + function Sys$HistoryEventArgs$get_state() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._state; + } +Sys.HistoryEventArgs.prototype = { + get_state: Sys$HistoryEventArgs$get_state +} +Sys.HistoryEventArgs.registerClass('Sys.HistoryEventArgs', Sys.EventArgs); +Sys.Application._appLoadHandler = null; +Sys.Application._beginRequestHandler = null; +Sys.Application._clientId = null; +Sys.Application._currentEntry = ''; +Sys.Application._endRequestHandler = null; +Sys.Application._history = null; +Sys.Application._enableHistory = false; +Sys.Application._historyEnabledInScriptManager = false; +Sys.Application._historyFrame = null; +Sys.Application._historyInitialized = false; +Sys.Application._historyPointIsNew = false; +Sys.Application._ignoreTimer = false; +Sys.Application._initialState = null; +Sys.Application._state = {}; +Sys.Application._timerCookie = 0; +Sys.Application._timerHandler = null; +Sys.Application._uniqueId = null; +Sys._Application.prototype.get_stateString = function Sys$_Application$get_stateString() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + var hash = null; + + if (Sys.Browser.agent === Sys.Browser.Firefox) { + var href = window.location.href; + var hashIndex = href.indexOf('#'); + if (hashIndex !== -1) { + hash = href.substring(hashIndex + 1); + } + else { + hash = ""; + } + return hash; + } + else { + hash = window.location.hash; + } + + if ((hash.length > 0) && (hash.charAt(0) === '#')) { + hash = hash.substring(1); + } + return hash; +}; +Sys._Application.prototype.get_enableHistory = function Sys$_Application$get_enableHistory() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._enableHistory; +}; +Sys._Application.prototype.set_enableHistory = function Sys$_Application$set_enableHistory(value) { + if (this._initialized && !this._initializing) { + throw Error.invalidOperation(Sys.Res.historyCannotEnableHistory); + } + else if (this._historyEnabledInScriptManager && !value) { + throw Error.invalidOperation(Sys.Res.invalidHistorySettingCombination); + } + this._enableHistory = value; +}; +Sys._Application.prototype.add_navigate = function Sys$_Application$add_navigate(handler) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "handler", type: Function} + ]); + if (e) throw e; + this.get_events().addHandler("navigate", handler); +}; +Sys._Application.prototype.remove_navigate = function Sys$_Application$remove_navigate(handler) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "handler", type: Function} + ]); + if (e) throw e; + this.get_events().removeHandler("navigate", handler); +}; +Sys._Application.prototype.addHistoryPoint = function Sys$_Application$addHistoryPoint(state, title) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "state", type: Object}, + {name: "title", type: String, mayBeNull: true, optional: true} + ]); + if (e) throw e; + if (!this._enableHistory) throw Error.invalidOperation(Sys.Res.historyCannotAddHistoryPointWithHistoryDisabled); + for (var n in state) { + var v = state[n]; + var t = typeof(v); + if ((v !== null) && ((t === 'object') || (t === 'function') || (t === 'undefined'))) { + throw Error.argument('state', Sys.Res.stateMustBeStringDictionary); + } + } + this._ensureHistory(); + var initialState = this._state; + for (var key in state) { + var value = state[key]; + if (value === null) { + if (typeof(initialState[key]) !== 'undefined') { + delete initialState[key]; + } + } + else { + initialState[key] = value; + } + } + var entry = this._serializeState(initialState); + this._historyPointIsNew = true; + this._setState(entry, title); + this._raiseNavigate(); +}; +Sys._Application.prototype.setServerId = function Sys$_Application$setServerId(clientId, uniqueId) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "clientId", type: String}, + {name: "uniqueId", type: String} + ]); + if (e) throw e; + this._clientId = clientId; + this._uniqueId = uniqueId; +}; +Sys._Application.prototype.setServerState = function Sys$_Application$setServerState(value) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "value", type: String} + ]); + if (e) throw e; + this._ensureHistory(); + this._state.__s = value; + this._updateHiddenField(value); +}; +Sys._Application.prototype._deserializeState = function Sys$_Application$_deserializeState(entry) { + var result = {}; + entry = entry || ''; + var serverSeparator = entry.indexOf('&&'); + if ((serverSeparator !== -1) && (serverSeparator + 2 < entry.length)) { + result.__s = entry.substr(serverSeparator + 2); + entry = entry.substr(0, serverSeparator); + } + var tokens = entry.split('&'); + for (var i = 0, l = tokens.length; i < l; i++) { + var token = tokens[i]; + var equal = token.indexOf('='); + if ((equal !== -1) && (equal + 1 < token.length)) { + var name = token.substr(0, equal); + var value = token.substr(equal + 1); + result[name] = decodeURIComponent(value); + } + } + return result; +}; +Sys._Application.prototype._enableHistoryInScriptManager = function Sys$_Application$_enableHistoryInScriptManager() { + this._enableHistory = true; + this._historyEnabledInScriptManager = true; +}; +Sys._Application.prototype._ensureHistory = function Sys$_Application$_ensureHistory() { + if (!this._historyInitialized && this._enableHistory) { + if ((Sys.Browser.agent === Sys.Browser.InternetExplorer) && (Sys.Browser.documentMode < 8)) { + this._historyFrame = document.getElementById('__historyFrame'); + if (!this._historyFrame) throw Error.invalidOperation(Sys.Res.historyMissingFrame); + this._ignoreIFrame = true; + } + this._timerHandler = Function.createDelegate(this, this._onIdle); + this._timerCookie = window.setTimeout(this._timerHandler, 100); + + try { + this._initialState = this._deserializeState(this.get_stateString()); + } catch(e) {} + + this._historyInitialized = true; + } +}; +Sys._Application.prototype._navigate = function Sys$_Application$_navigate(entry) { + this._ensureHistory(); + var state = this._deserializeState(entry); + + if (this._uniqueId) { + var oldServerEntry = this._state.__s || ''; + var newServerEntry = state.__s || ''; + if (newServerEntry !== oldServerEntry) { + this._updateHiddenField(newServerEntry); + __doPostBack(this._uniqueId, newServerEntry); + this._state = state; + return; + } + } + this._setState(entry); + this._state = state; + this._raiseNavigate(); +}; +Sys._Application.prototype._onIdle = function Sys$_Application$_onIdle() { + delete this._timerCookie; + + var entry = this.get_stateString(); + if (entry !== this._currentEntry) { + if (!this._ignoreTimer) { + this._historyPointIsNew = false; + this._navigate(entry); + } + } + else { + this._ignoreTimer = false; + } + this._timerCookie = window.setTimeout(this._timerHandler, 100); +}; +Sys._Application.prototype._onIFrameLoad = function Sys$_Application$_onIFrameLoad(entry) { + this._ensureHistory(); + if (!this._ignoreIFrame) { + this._historyPointIsNew = false; + this._navigate(entry); + } + this._ignoreIFrame = false; +}; +Sys._Application.prototype._onPageRequestManagerBeginRequest = function Sys$_Application$_onPageRequestManagerBeginRequest(sender, args) { + this._ignoreTimer = true; +}; +Sys._Application.prototype._onPageRequestManagerEndRequest = function Sys$_Application$_onPageRequestManagerEndRequest(sender, args) { + var dataItem = args.get_dataItems()[this._clientId]; + var eventTarget = document.getElementById("__EVENTTARGET"); + if (eventTarget && eventTarget.value === this._uniqueId) { + eventTarget.value = ''; + } + if (typeof(dataItem) !== 'undefined') { + this.setServerState(dataItem); + this._historyPointIsNew = true; + } + else { + this._ignoreTimer = false; + } + var entry = this._serializeState(this._state); + if (entry !== this._currentEntry) { + this._ignoreTimer = true; + this._setState(entry); + this._raiseNavigate(); + } +}; +Sys._Application.prototype._raiseNavigate = function Sys$_Application$_raiseNavigate() { + var h = this.get_events().getHandler("navigate"); + var stateClone = {}; + for (var key in this._state) { + if (key !== '__s') { + stateClone[key] = this._state[key]; + } + } + var args = new Sys.HistoryEventArgs(stateClone); + if (h) { + h(this, args); + } + var err; + try { + if ((Sys.Browser.agent === Sys.Browser.Firefox) && window.location.hash && + (!window.frameElement || window.top.location.hash)) { + window.history.go(0); + } + } + catch(err) { + } +}; +Sys._Application.prototype._serializeState = function Sys$_Application$_serializeState(state) { + var serialized = []; + for (var key in state) { + var value = state[key]; + if (key === '__s') { + var serverState = value; + } + else { + if (key.indexOf('=') !== -1) throw Error.argument('state', Sys.Res.stateFieldNameInvalid); + serialized[serialized.length] = key + '=' + encodeURIComponent(value); + } + } + return serialized.join('&') + (serverState ? '&&' + serverState : ''); +}; +Sys._Application.prototype._setState = function Sys$_Application$_setState(entry, title) { + if (this._enableHistory) { + entry = entry || ''; + if (entry !== this._currentEntry) { + if (window.theForm) { + var action = window.theForm.action; + var hashIndex = action.indexOf('#'); + window.theForm.action = ((hashIndex !== -1) ? action.substring(0, hashIndex) : action) + '#' + entry; + } + + if (this._historyFrame && this._historyPointIsNew) { + this._ignoreIFrame = true; + var frameDoc = this._historyFrame.contentWindow.document; + frameDoc.open("javascript:''"); + frameDoc.write("" + (title || document.title) + + "parent.Sys.Application._onIFrameLoad(" + + Sys.Serialization.JavaScriptSerializer.serialize(entry) + + ");"); + frameDoc.close(); + } + this._ignoreTimer = false; + this._currentEntry = entry; + if (this._historyFrame || this._historyPointIsNew) { + var currentHash = this.get_stateString(); + if (entry !== currentHash) { + var loc = document.location; + if (loc.href.length - loc.hash.length + entry.length > 1024) { + throw Error.invalidOperation(Sys.Res.urlMustBeLessThan1024chars); + } + window.location.hash = entry; + this._currentEntry = this.get_stateString(); + if ((typeof(title) !== 'undefined') && (title !== null)) { + document.title = title; + } + } + } + this._historyPointIsNew = false; + } + } +}; +Sys._Application.prototype._updateHiddenField = function Sys$_Application$_updateHiddenField(value) { + if (this._clientId) { + var serverStateField = document.getElementById(this._clientId); + if (serverStateField) { + serverStateField.value = value; + } + } +}; + +if (!window.XMLHttpRequest) { + window.XMLHttpRequest = function window$XMLHttpRequest() { + var progIDs = [ 'Msxml2.XMLHTTP.3.0', 'Msxml2.XMLHTTP' ]; + for (var i = 0, l = progIDs.length; i < l; i++) { + try { + return new ActiveXObject(progIDs[i]); + } + catch (ex) { + } + } + return null; + } +} +Type.registerNamespace('Sys.Net'); + +Sys.Net.WebRequestExecutor = function Sys$Net$WebRequestExecutor() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + this._webRequest = null; + this._resultObject = null; +} + function Sys$Net$WebRequestExecutor$get_webRequest() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._webRequest; + } + function Sys$Net$WebRequestExecutor$_set_webRequest(value) { + if (this.get_started()) { + throw Error.invalidOperation(String.format(Sys.Res.cannotCallOnceStarted, 'set_webRequest')); + } + this._webRequest = value; + } + function Sys$Net$WebRequestExecutor$get_started() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); + } + function Sys$Net$WebRequestExecutor$get_responseAvailable() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); + } + function Sys$Net$WebRequestExecutor$get_timedOut() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); + } + function Sys$Net$WebRequestExecutor$get_aborted() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); + } + function Sys$Net$WebRequestExecutor$get_responseData() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); + } + function Sys$Net$WebRequestExecutor$get_statusCode() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); + } + function Sys$Net$WebRequestExecutor$get_statusText() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); + } + function Sys$Net$WebRequestExecutor$get_xml() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); + } + function Sys$Net$WebRequestExecutor$get_object() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (!this._resultObject) { + this._resultObject = Sys.Serialization.JavaScriptSerializer.deserialize(this.get_responseData()); + } + return this._resultObject; + } + function Sys$Net$WebRequestExecutor$executeRequest() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); + } + function Sys$Net$WebRequestExecutor$abort() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); + } + function Sys$Net$WebRequestExecutor$getResponseHeader(header) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "header", type: String} + ]); + if (e) throw e; + throw Error.notImplemented(); + } + function Sys$Net$WebRequestExecutor$getAllResponseHeaders() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + throw Error.notImplemented(); + } +Sys.Net.WebRequestExecutor.prototype = { + get_webRequest: Sys$Net$WebRequestExecutor$get_webRequest, + _set_webRequest: Sys$Net$WebRequestExecutor$_set_webRequest, + get_started: Sys$Net$WebRequestExecutor$get_started, + get_responseAvailable: Sys$Net$WebRequestExecutor$get_responseAvailable, + get_timedOut: Sys$Net$WebRequestExecutor$get_timedOut, + get_aborted: Sys$Net$WebRequestExecutor$get_aborted, + get_responseData: Sys$Net$WebRequestExecutor$get_responseData, + get_statusCode: Sys$Net$WebRequestExecutor$get_statusCode, + get_statusText: Sys$Net$WebRequestExecutor$get_statusText, + get_xml: Sys$Net$WebRequestExecutor$get_xml, + get_object: Sys$Net$WebRequestExecutor$get_object, + executeRequest: Sys$Net$WebRequestExecutor$executeRequest, + abort: Sys$Net$WebRequestExecutor$abort, + getResponseHeader: Sys$Net$WebRequestExecutor$getResponseHeader, + getAllResponseHeaders: Sys$Net$WebRequestExecutor$getAllResponseHeaders +} +Sys.Net.WebRequestExecutor.registerClass('Sys.Net.WebRequestExecutor'); + +Sys.Net.XMLDOM = function Sys$Net$XMLDOM(markup) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "markup", type: String} + ]); + if (e) throw e; + if (!window.DOMParser) { + var progIDs = [ 'Msxml2.DOMDocument.3.0', 'Msxml2.DOMDocument' ]; + for (var i = 0, l = progIDs.length; i < l; i++) { + try { + var xmlDOM = new ActiveXObject(progIDs[i]); + xmlDOM.async = false; + xmlDOM.loadXML(markup); + xmlDOM.setProperty('SelectionLanguage', 'XPath'); + return xmlDOM; + } + catch (ex) { + } + } + } + else { + try { + var domParser = new window.DOMParser(); + return domParser.parseFromString(markup, 'text/xml'); + } + catch (ex) { + } + } + return null; +} +Sys.Net.XMLHttpExecutor = function Sys$Net$XMLHttpExecutor() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + Sys.Net.XMLHttpExecutor.initializeBase(this); + var _this = this; + this._xmlHttpRequest = null; + this._webRequest = null; + this._responseAvailable = false; + this._timedOut = false; + this._timer = null; + this._aborted = false; + this._started = false; + this._onReadyStateChange = (function () { + + if (_this._xmlHttpRequest.readyState === 4 ) { + try { + if (typeof(_this._xmlHttpRequest.status) === "undefined") { + return; + } + } + catch(ex) { + return; + } + + _this._clearTimer(); + _this._responseAvailable = true; + _this._webRequest.completed(Sys.EventArgs.Empty); + if (_this._xmlHttpRequest != null) { + _this._xmlHttpRequest.onreadystatechange = Function.emptyMethod; + _this._xmlHttpRequest = null; + } + } + }); + this._clearTimer = (function() { + if (_this._timer != null) { + window.clearTimeout(_this._timer); + _this._timer = null; + } + }); + this._onTimeout = (function() { + if (!_this._responseAvailable) { + _this._clearTimer(); + _this._timedOut = true; + _this._xmlHttpRequest.onreadystatechange = Function.emptyMethod; + _this._xmlHttpRequest.abort(); + _this._webRequest.completed(Sys.EventArgs.Empty); + _this._xmlHttpRequest = null; + } + }); +} + function Sys$Net$XMLHttpExecutor$get_timedOut() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._timedOut; + } + function Sys$Net$XMLHttpExecutor$get_started() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._started; + } + function Sys$Net$XMLHttpExecutor$get_responseAvailable() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._responseAvailable; + } + function Sys$Net$XMLHttpExecutor$get_aborted() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._aborted; + } + function Sys$Net$XMLHttpExecutor$executeRequest() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + this._webRequest = this.get_webRequest(); + if (this._started) { + throw Error.invalidOperation(String.format(Sys.Res.cannotCallOnceStarted, 'executeRequest')); + } + if (this._webRequest === null) { + throw Error.invalidOperation(Sys.Res.nullWebRequest); + } + var body = this._webRequest.get_body(); + var headers = this._webRequest.get_headers(); + this._xmlHttpRequest = new XMLHttpRequest(); + this._xmlHttpRequest.onreadystatechange = this._onReadyStateChange; + var verb = this._webRequest.get_httpVerb(); + this._xmlHttpRequest.open(verb, this._webRequest.getResolvedUrl(), true ); + this._xmlHttpRequest.setRequestHeader("X-Requested-With", "XMLHttpRequest"); + if (headers) { + for (var header in headers) { + var val = headers[header]; + if (typeof(val) !== "function") + this._xmlHttpRequest.setRequestHeader(header, val); + } + } + if (verb.toLowerCase() === "post") { + if ((headers === null) || !headers['Content-Type']) { + this._xmlHttpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8'); + } + if (!body) { + body = ""; + } + } + var timeout = this._webRequest.get_timeout(); + if (timeout > 0) { + this._timer = window.setTimeout(Function.createDelegate(this, this._onTimeout), timeout); + } + this._xmlHttpRequest.send(body); + this._started = true; + } + function Sys$Net$XMLHttpExecutor$getResponseHeader(header) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "header", type: String} + ]); + if (e) throw e; + if (!this._responseAvailable) { + throw Error.invalidOperation(String.format(Sys.Res.cannotCallBeforeResponse, 'getResponseHeader')); + } + if (!this._xmlHttpRequest) { + throw Error.invalidOperation(String.format(Sys.Res.cannotCallOutsideHandler, 'getResponseHeader')); + } + var result; + try { + result = this._xmlHttpRequest.getResponseHeader(header); + } catch (e) { + } + if (!result) result = ""; + return result; + } + function Sys$Net$XMLHttpExecutor$getAllResponseHeaders() { + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (!this._responseAvailable) { + throw Error.invalidOperation(String.format(Sys.Res.cannotCallBeforeResponse, 'getAllResponseHeaders')); + } + if (!this._xmlHttpRequest) { + throw Error.invalidOperation(String.format(Sys.Res.cannotCallOutsideHandler, 'getAllResponseHeaders')); + } + return this._xmlHttpRequest.getAllResponseHeaders(); + } + function Sys$Net$XMLHttpExecutor$get_responseData() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (!this._responseAvailable) { + throw Error.invalidOperation(String.format(Sys.Res.cannotCallBeforeResponse, 'get_responseData')); + } + if (!this._xmlHttpRequest) { + throw Error.invalidOperation(String.format(Sys.Res.cannotCallOutsideHandler, 'get_responseData')); + } + return this._xmlHttpRequest.responseText; + } + function Sys$Net$XMLHttpExecutor$get_statusCode() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (!this._responseAvailable) { + throw Error.invalidOperation(String.format(Sys.Res.cannotCallBeforeResponse, 'get_statusCode')); + } + if (!this._xmlHttpRequest) { + throw Error.invalidOperation(String.format(Sys.Res.cannotCallOutsideHandler, 'get_statusCode')); + } + var result = 0; + try { + result = this._xmlHttpRequest.status; + } + catch(ex) { + } + return result; + } + function Sys$Net$XMLHttpExecutor$get_statusText() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (!this._responseAvailable) { + throw Error.invalidOperation(String.format(Sys.Res.cannotCallBeforeResponse, 'get_statusText')); + } + if (!this._xmlHttpRequest) { + throw Error.invalidOperation(String.format(Sys.Res.cannotCallOutsideHandler, 'get_statusText')); + } + return this._xmlHttpRequest.statusText; + } + function Sys$Net$XMLHttpExecutor$get_xml() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (!this._responseAvailable) { + throw Error.invalidOperation(String.format(Sys.Res.cannotCallBeforeResponse, 'get_xml')); + } + if (!this._xmlHttpRequest) { + throw Error.invalidOperation(String.format(Sys.Res.cannotCallOutsideHandler, 'get_xml')); + } + var xml = this._xmlHttpRequest.responseXML; + if (!xml || !xml.documentElement) { + xml = Sys.Net.XMLDOM(this._xmlHttpRequest.responseText); + if (!xml || !xml.documentElement) + return null; + } + else if (navigator.userAgent.indexOf('MSIE') !== -1) { + xml.setProperty('SelectionLanguage', 'XPath'); + } + if (xml.documentElement.namespaceURI === "http://www.mozilla.org/newlayout/xml/parsererror.xml" && + xml.documentElement.tagName === "parsererror") { + return null; + } + + if (xml.documentElement.firstChild && xml.documentElement.firstChild.tagName === "parsererror") { + return null; + } + + return xml; + } + function Sys$Net$XMLHttpExecutor$abort() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (!this._started) { + throw Error.invalidOperation(Sys.Res.cannotAbortBeforeStart); + } + if (this._aborted || this._responseAvailable || this._timedOut) + return; + this._aborted = true; + this._clearTimer(); + if (this._xmlHttpRequest && !this._responseAvailable) { + this._xmlHttpRequest.onreadystatechange = Function.emptyMethod; + this._xmlHttpRequest.abort(); + + this._xmlHttpRequest = null; + this._webRequest.completed(Sys.EventArgs.Empty); + } + } +Sys.Net.XMLHttpExecutor.prototype = { + get_timedOut: Sys$Net$XMLHttpExecutor$get_timedOut, + get_started: Sys$Net$XMLHttpExecutor$get_started, + get_responseAvailable: Sys$Net$XMLHttpExecutor$get_responseAvailable, + get_aborted: Sys$Net$XMLHttpExecutor$get_aborted, + executeRequest: Sys$Net$XMLHttpExecutor$executeRequest, + getResponseHeader: Sys$Net$XMLHttpExecutor$getResponseHeader, + getAllResponseHeaders: Sys$Net$XMLHttpExecutor$getAllResponseHeaders, + get_responseData: Sys$Net$XMLHttpExecutor$get_responseData, + get_statusCode: Sys$Net$XMLHttpExecutor$get_statusCode, + get_statusText: Sys$Net$XMLHttpExecutor$get_statusText, + get_xml: Sys$Net$XMLHttpExecutor$get_xml, + abort: Sys$Net$XMLHttpExecutor$abort +} +Sys.Net.XMLHttpExecutor.registerClass('Sys.Net.XMLHttpExecutor', Sys.Net.WebRequestExecutor); + +Sys.Net._WebRequestManager = function Sys$Net$_WebRequestManager() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + this._defaultTimeout = 0; + this._defaultExecutorType = "Sys.Net.XMLHttpExecutor"; +} + function Sys$Net$_WebRequestManager$add_invokingRequest(handler) { + /// + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this._get_eventHandlerList().addHandler("invokingRequest", handler); + } + function Sys$Net$_WebRequestManager$remove_invokingRequest(handler) { + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this._get_eventHandlerList().removeHandler("invokingRequest", handler); + } + function Sys$Net$_WebRequestManager$add_completedRequest(handler) { + /// + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this._get_eventHandlerList().addHandler("completedRequest", handler); + } + function Sys$Net$_WebRequestManager$remove_completedRequest(handler) { + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this._get_eventHandlerList().removeHandler("completedRequest", handler); + } + function Sys$Net$_WebRequestManager$_get_eventHandlerList() { + if (!this._events) { + this._events = new Sys.EventHandlerList(); + } + return this._events; + } + function Sys$Net$_WebRequestManager$get_defaultTimeout() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._defaultTimeout; + } + function Sys$Net$_WebRequestManager$set_defaultTimeout(value) { + var e = Function._validateParams(arguments, [{name: "value", type: Number}]); + if (e) throw e; + if (value < 0) { + throw Error.argumentOutOfRange("value", value, Sys.Res.invalidTimeout); + } + this._defaultTimeout = value; + } + function Sys$Net$_WebRequestManager$get_defaultExecutorType() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._defaultExecutorType; + } + function Sys$Net$_WebRequestManager$set_defaultExecutorType(value) { + var e = Function._validateParams(arguments, [{name: "value", type: String}]); + if (e) throw e; + this._defaultExecutorType = value; + } + function Sys$Net$_WebRequestManager$executeRequest(webRequest) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "webRequest", type: Sys.Net.WebRequest} + ]); + if (e) throw e; + var executor = webRequest.get_executor(); + if (!executor) { + var failed = false; + try { + var executorType = eval(this._defaultExecutorType); + executor = new executorType(); + } catch (e) { + failed = true; + } + if (failed || !Sys.Net.WebRequestExecutor.isInstanceOfType(executor) || !executor) { + throw Error.argument("defaultExecutorType", String.format(Sys.Res.invalidExecutorType, this._defaultExecutorType)); + } + webRequest.set_executor(executor); + } + if (executor.get_aborted()) { + return; + } + var evArgs = new Sys.Net.NetworkRequestEventArgs(webRequest); + var handler = this._get_eventHandlerList().getHandler("invokingRequest"); + if (handler) { + handler(this, evArgs); + } + if (!evArgs.get_cancel()) { + executor.executeRequest(); + } + } +Sys.Net._WebRequestManager.prototype = { + add_invokingRequest: Sys$Net$_WebRequestManager$add_invokingRequest, + remove_invokingRequest: Sys$Net$_WebRequestManager$remove_invokingRequest, + add_completedRequest: Sys$Net$_WebRequestManager$add_completedRequest, + remove_completedRequest: Sys$Net$_WebRequestManager$remove_completedRequest, + _get_eventHandlerList: Sys$Net$_WebRequestManager$_get_eventHandlerList, + get_defaultTimeout: Sys$Net$_WebRequestManager$get_defaultTimeout, + set_defaultTimeout: Sys$Net$_WebRequestManager$set_defaultTimeout, + get_defaultExecutorType: Sys$Net$_WebRequestManager$get_defaultExecutorType, + set_defaultExecutorType: Sys$Net$_WebRequestManager$set_defaultExecutorType, + executeRequest: Sys$Net$_WebRequestManager$executeRequest +} +Sys.Net._WebRequestManager.registerClass('Sys.Net._WebRequestManager'); +Sys.Net.WebRequestManager = new Sys.Net._WebRequestManager(); + +Sys.Net.NetworkRequestEventArgs = function Sys$Net$NetworkRequestEventArgs(webRequest) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "webRequest", type: Sys.Net.WebRequest} + ]); + if (e) throw e; + Sys.Net.NetworkRequestEventArgs.initializeBase(this); + this._webRequest = webRequest; +} + function Sys$Net$NetworkRequestEventArgs$get_webRequest() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._webRequest; + } +Sys.Net.NetworkRequestEventArgs.prototype = { + get_webRequest: Sys$Net$NetworkRequestEventArgs$get_webRequest +} +Sys.Net.NetworkRequestEventArgs.registerClass('Sys.Net.NetworkRequestEventArgs', Sys.CancelEventArgs); + +Sys.Net.WebRequest = function Sys$Net$WebRequest() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + this._url = ""; + this._headers = { }; + this._body = null; + this._userContext = null; + this._httpVerb = null; + this._executor = null; + this._invokeCalled = false; + this._timeout = 0; +} + function Sys$Net$WebRequest$add_completed(handler) { + /// + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this._get_eventHandlerList().addHandler("completed", handler); + } + function Sys$Net$WebRequest$remove_completed(handler) { + var e = Function._validateParams(arguments, [{name: "handler", type: Function}]); + if (e) throw e; + this._get_eventHandlerList().removeHandler("completed", handler); + } + function Sys$Net$WebRequest$completed(eventArgs) { + /// + /// + var e = Function._validateParams(arguments, [ + {name: "eventArgs", type: Sys.EventArgs} + ]); + if (e) throw e; + var handler = Sys.Net.WebRequestManager._get_eventHandlerList().getHandler("completedRequest"); + if (handler) { + handler(this._executor, eventArgs); + } + handler = this._get_eventHandlerList().getHandler("completed"); + if (handler) { + handler(this._executor, eventArgs); + } + } + function Sys$Net$WebRequest$_get_eventHandlerList() { + if (!this._events) { + this._events = new Sys.EventHandlerList(); + } + return this._events; + } + function Sys$Net$WebRequest$get_url() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._url; + } + function Sys$Net$WebRequest$set_url(value) { + var e = Function._validateParams(arguments, [{name: "value", type: String}]); + if (e) throw e; + this._url = value; + } + function Sys$Net$WebRequest$get_headers() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._headers; + } + function Sys$Net$WebRequest$get_httpVerb() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (this._httpVerb === null) { + if (this._body === null) { + return "GET"; + } + return "POST"; + } + return this._httpVerb; + } + function Sys$Net$WebRequest$set_httpVerb(value) { + var e = Function._validateParams(arguments, [{name: "value", type: String}]); + if (e) throw e; + if (value.length === 0) { + throw Error.argument('value', Sys.Res.invalidHttpVerb); + } + this._httpVerb = value; + } + function Sys$Net$WebRequest$get_body() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._body; + } + function Sys$Net$WebRequest$set_body(value) { + var e = Function._validateParams(arguments, [{name: "value", mayBeNull: true}]); + if (e) throw e; + this._body = value; + } + function Sys$Net$WebRequest$get_userContext() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._userContext; + } + function Sys$Net$WebRequest$set_userContext(value) { + var e = Function._validateParams(arguments, [{name: "value", mayBeNull: true}]); + if (e) throw e; + this._userContext = value; + } + function Sys$Net$WebRequest$get_executor() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._executor; + } + function Sys$Net$WebRequest$set_executor(value) { + var e = Function._validateParams(arguments, [{name: "value", type: Sys.Net.WebRequestExecutor}]); + if (e) throw e; + if (this._executor !== null && this._executor.get_started()) { + throw Error.invalidOperation(Sys.Res.setExecutorAfterActive); + } + this._executor = value; + this._executor._set_webRequest(this); + } + function Sys$Net$WebRequest$get_timeout() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (this._timeout === 0) { + return Sys.Net.WebRequestManager.get_defaultTimeout(); + } + return this._timeout; + } + function Sys$Net$WebRequest$set_timeout(value) { + var e = Function._validateParams(arguments, [{name: "value", type: Number}]); + if (e) throw e; + if (value < 0) { + throw Error.argumentOutOfRange("value", value, Sys.Res.invalidTimeout); + } + this._timeout = value; + } + function Sys$Net$WebRequest$getResolvedUrl() { + /// + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return Sys.Net.WebRequest._resolveUrl(this._url); + } + function Sys$Net$WebRequest$invoke() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + if (this._invokeCalled) { + throw Error.invalidOperation(Sys.Res.invokeCalledTwice); + } + Sys.Net.WebRequestManager.executeRequest(this); + this._invokeCalled = true; + } +Sys.Net.WebRequest.prototype = { + add_completed: Sys$Net$WebRequest$add_completed, + remove_completed: Sys$Net$WebRequest$remove_completed, + completed: Sys$Net$WebRequest$completed, + _get_eventHandlerList: Sys$Net$WebRequest$_get_eventHandlerList, + get_url: Sys$Net$WebRequest$get_url, + set_url: Sys$Net$WebRequest$set_url, + get_headers: Sys$Net$WebRequest$get_headers, + get_httpVerb: Sys$Net$WebRequest$get_httpVerb, + set_httpVerb: Sys$Net$WebRequest$set_httpVerb, + get_body: Sys$Net$WebRequest$get_body, + set_body: Sys$Net$WebRequest$set_body, + get_userContext: Sys$Net$WebRequest$get_userContext, + set_userContext: Sys$Net$WebRequest$set_userContext, + get_executor: Sys$Net$WebRequest$get_executor, + set_executor: Sys$Net$WebRequest$set_executor, + get_timeout: Sys$Net$WebRequest$get_timeout, + set_timeout: Sys$Net$WebRequest$set_timeout, + getResolvedUrl: Sys$Net$WebRequest$getResolvedUrl, + invoke: Sys$Net$WebRequest$invoke +} +Sys.Net.WebRequest._resolveUrl = function Sys$Net$WebRequest$_resolveUrl(url, baseUrl) { + if (url && url.indexOf('://') !== -1) { + return url; + } + if (!baseUrl || baseUrl.length === 0) { + var baseElement = document.getElementsByTagName('base')[0]; + if (baseElement && baseElement.href && baseElement.href.length > 0) { + baseUrl = baseElement.href; + } + else { + baseUrl = document.URL; + } + } + var qsStart = baseUrl.indexOf('?'); + if (qsStart !== -1) { + baseUrl = baseUrl.substr(0, qsStart); + } + qsStart = baseUrl.indexOf('#'); + if (qsStart !== -1) { + baseUrl = baseUrl.substr(0, qsStart); + } + baseUrl = baseUrl.substr(0, baseUrl.lastIndexOf('/') + 1); + if (!url || url.length === 0) { + return baseUrl; + } + if (url.charAt(0) === '/') { + var slashslash = baseUrl.indexOf('://'); + if (slashslash === -1) { + throw Error.argument("baseUrl", Sys.Res.badBaseUrl1); + } + var nextSlash = baseUrl.indexOf('/', slashslash + 3); + if (nextSlash === -1) { + throw Error.argument("baseUrl", Sys.Res.badBaseUrl2); + } + return baseUrl.substr(0, nextSlash) + url; + } + else { + var lastSlash = baseUrl.lastIndexOf('/'); + if (lastSlash === -1) { + throw Error.argument("baseUrl", Sys.Res.badBaseUrl3); + } + return baseUrl.substr(0, lastSlash+1) + url; + } +} +Sys.Net.WebRequest._createQueryString = function Sys$Net$WebRequest$_createQueryString(queryString, encodeMethod, addParams) { + encodeMethod = encodeMethod || encodeURIComponent; + var i = 0, obj, val, arg, sb = new Sys.StringBuilder(); + if (queryString) { + for (arg in queryString) { + obj = queryString[arg]; + if (typeof(obj) === "function") continue; + val = Sys.Serialization.JavaScriptSerializer.serialize(obj); + if (i++) { + sb.append('&'); + } + sb.append(arg); + sb.append('='); + sb.append(encodeMethod(val)); + } + } + if (addParams) { + if (i) { + sb.append('&'); + } + sb.append(addParams); + } + return sb.toString(); +} +Sys.Net.WebRequest._createUrl = function Sys$Net$WebRequest$_createUrl(url, queryString, addParams) { + if (!queryString && !addParams) { + return url; + } + var qs = Sys.Net.WebRequest._createQueryString(queryString, null, addParams); + return qs.length + ? url + ((url && url.indexOf('?') >= 0) ? "&" : "?") + qs + : url; +} +Sys.Net.WebRequest.registerClass('Sys.Net.WebRequest'); + +Sys._ScriptLoaderTask = function Sys$_ScriptLoaderTask(scriptElement, completedCallback) { + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "scriptElement", domElement: true}, + {name: "completedCallback", type: Function} + ]); + if (e) throw e; + this._scriptElement = scriptElement; + this._completedCallback = completedCallback; +} + function Sys$_ScriptLoaderTask$get_scriptElement() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._scriptElement; + } + function Sys$_ScriptLoaderTask$dispose() { + if(this._disposed) { + return; + } + this._disposed = true; + this._removeScriptElementHandlers(); + Sys._ScriptLoaderTask._clearScript(this._scriptElement); + this._scriptElement = null; + } + function Sys$_ScriptLoaderTask$execute() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + this._addScriptElementHandlers(); + var headElements = document.getElementsByTagName('head'); + if (headElements.length === 0) { + throw new Error.invalidOperation(Sys.Res.scriptLoadFailedNoHead); + } + else { + headElements[0].appendChild(this._scriptElement); + } + } + function Sys$_ScriptLoaderTask$_addScriptElementHandlers() { + this._scriptLoadDelegate = Function.createDelegate(this, this._scriptLoadHandler); + + if (Sys.Browser.agent !== Sys.Browser.InternetExplorer) { + this._scriptElement.readyState = 'loaded'; + $addHandler(this._scriptElement, 'load', this._scriptLoadDelegate); + } + else { + $addHandler(this._scriptElement, 'readystatechange', this._scriptLoadDelegate); + } + if (this._scriptElement.addEventListener) { + this._scriptErrorDelegate = Function.createDelegate(this, this._scriptErrorHandler); + this._scriptElement.addEventListener('error', this._scriptErrorDelegate, false); + } + } + function Sys$_ScriptLoaderTask$_removeScriptElementHandlers() { + if(this._scriptLoadDelegate) { + var scriptElement = this.get_scriptElement(); + if (Sys.Browser.agent !== Sys.Browser.InternetExplorer) { + $removeHandler(scriptElement, 'load', this._scriptLoadDelegate); + } + else { + $removeHandler(scriptElement, 'readystatechange', this._scriptLoadDelegate); + } + if (this._scriptErrorDelegate) { + this._scriptElement.removeEventListener('error', this._scriptErrorDelegate, false); + this._scriptErrorDelegate = null; + } + this._scriptLoadDelegate = null; + } + } + function Sys$_ScriptLoaderTask$_scriptErrorHandler() { + if(this._disposed) { + return; + } + + this._completedCallback(this.get_scriptElement(), false); + } + function Sys$_ScriptLoaderTask$_scriptLoadHandler() { + if(this._disposed) { + return; + } + var scriptElement = this.get_scriptElement(); + if ((scriptElement.readyState !== 'loaded') && + (scriptElement.readyState !== 'complete')) { + return; + } + + this._completedCallback(scriptElement, true); + } +Sys._ScriptLoaderTask.prototype = { + get_scriptElement: Sys$_ScriptLoaderTask$get_scriptElement, + dispose: Sys$_ScriptLoaderTask$dispose, + execute: Sys$_ScriptLoaderTask$execute, + _addScriptElementHandlers: Sys$_ScriptLoaderTask$_addScriptElementHandlers, + _removeScriptElementHandlers: Sys$_ScriptLoaderTask$_removeScriptElementHandlers, + _scriptErrorHandler: Sys$_ScriptLoaderTask$_scriptErrorHandler, + _scriptLoadHandler: Sys$_ScriptLoaderTask$_scriptLoadHandler +} +Sys._ScriptLoaderTask.registerClass("Sys._ScriptLoaderTask", null, Sys.IDisposable); +Sys._ScriptLoaderTask._clearScript = function Sys$_ScriptLoaderTask$_clearScript(scriptElement) { + if (!Sys.Debug.isDebug) { + scriptElement.parentNode.removeChild(scriptElement); + } +} +Type.registerNamespace('Sys.Net'); + +Sys.Net.WebServiceProxy = function Sys$Net$WebServiceProxy() { +} + function Sys$Net$WebServiceProxy$get_timeout() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._timeout || 0; + } + function Sys$Net$WebServiceProxy$set_timeout(value) { + var e = Function._validateParams(arguments, [{name: "value", type: Number}]); + if (e) throw e; + if (value < 0) { throw Error.argumentOutOfRange('value', value, Sys.Res.invalidTimeout); } + this._timeout = value; + } + function Sys$Net$WebServiceProxy$get_defaultUserContext() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return (typeof(this._userContext) === "undefined") ? null : this._userContext; + } + function Sys$Net$WebServiceProxy$set_defaultUserContext(value) { + var e = Function._validateParams(arguments, [{name: "value", mayBeNull: true}]); + if (e) throw e; + this._userContext = value; + } + function Sys$Net$WebServiceProxy$get_defaultSucceededCallback() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._succeeded || null; + } + function Sys$Net$WebServiceProxy$set_defaultSucceededCallback(value) { + var e = Function._validateParams(arguments, [{name: "value", type: Function, mayBeNull: true}]); + if (e) throw e; + this._succeeded = value; + } + function Sys$Net$WebServiceProxy$get_defaultFailedCallback() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._failed || null; + } + function Sys$Net$WebServiceProxy$set_defaultFailedCallback(value) { + var e = Function._validateParams(arguments, [{name: "value", type: Function, mayBeNull: true}]); + if (e) throw e; + this._failed = value; + } + function Sys$Net$WebServiceProxy$get_enableJsonp() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return !!this._jsonp; + } + function Sys$Net$WebServiceProxy$set_enableJsonp(value) { + var e = Function._validateParams(arguments, [{name: "value", type: Boolean}]); + if (e) throw e; + this._jsonp = value; + } + function Sys$Net$WebServiceProxy$get_path() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._path || null; + } + function Sys$Net$WebServiceProxy$set_path(value) { + var e = Function._validateParams(arguments, [{name: "value", type: String}]); + if (e) throw e; + this._path = value; + } + function Sys$Net$WebServiceProxy$get_jsonpCallbackParameter() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._callbackParameter || "callback"; + } + function Sys$Net$WebServiceProxy$set_jsonpCallbackParameter(value) { + var e = Function._validateParams(arguments, [{name: "value", type: String}]); + if (e) throw e; + this._callbackParameter = value; + } + function Sys$Net$WebServiceProxy$_invoke(servicePath, methodName, useGet, params, onSuccess, onFailure, userContext) { + /// + /// + /// + /// + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "servicePath", type: String}, + {name: "methodName", type: String}, + {name: "useGet", type: Boolean}, + {name: "params"}, + {name: "onSuccess", type: Function, mayBeNull: true, optional: true}, + {name: "onFailure", type: Function, mayBeNull: true, optional: true}, + {name: "userContext", mayBeNull: true, optional: true} + ]); + if (e) throw e; + onSuccess = onSuccess || this.get_defaultSucceededCallback(); + onFailure = onFailure || this.get_defaultFailedCallback(); + if (userContext === null || typeof userContext === 'undefined') userContext = this.get_defaultUserContext(); + return Sys.Net.WebServiceProxy.invoke(servicePath, methodName, useGet, params, onSuccess, onFailure, userContext, this.get_timeout(), this.get_enableJsonp(), this.get_jsonpCallbackParameter()); + } +Sys.Net.WebServiceProxy.prototype = { + get_timeout: Sys$Net$WebServiceProxy$get_timeout, + set_timeout: Sys$Net$WebServiceProxy$set_timeout, + get_defaultUserContext: Sys$Net$WebServiceProxy$get_defaultUserContext, + set_defaultUserContext: Sys$Net$WebServiceProxy$set_defaultUserContext, + get_defaultSucceededCallback: Sys$Net$WebServiceProxy$get_defaultSucceededCallback, + set_defaultSucceededCallback: Sys$Net$WebServiceProxy$set_defaultSucceededCallback, + get_defaultFailedCallback: Sys$Net$WebServiceProxy$get_defaultFailedCallback, + set_defaultFailedCallback: Sys$Net$WebServiceProxy$set_defaultFailedCallback, + get_enableJsonp: Sys$Net$WebServiceProxy$get_enableJsonp, + set_enableJsonp: Sys$Net$WebServiceProxy$set_enableJsonp, + get_path: Sys$Net$WebServiceProxy$get_path, + set_path: Sys$Net$WebServiceProxy$set_path, + get_jsonpCallbackParameter: Sys$Net$WebServiceProxy$get_jsonpCallbackParameter, + set_jsonpCallbackParameter: Sys$Net$WebServiceProxy$set_jsonpCallbackParameter, + _invoke: Sys$Net$WebServiceProxy$_invoke +} +Sys.Net.WebServiceProxy.registerClass('Sys.Net.WebServiceProxy'); +Sys.Net.WebServiceProxy.invoke = function Sys$Net$WebServiceProxy$invoke(servicePath, methodName, useGet, params, onSuccess, onFailure, userContext, timeout, enableJsonp, jsonpCallbackParameter) { + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "servicePath", type: String}, + {name: "methodName", type: String, mayBeNull: true, optional: true}, + {name: "useGet", type: Boolean, optional: true}, + {name: "params", mayBeNull: true, optional: true}, + {name: "onSuccess", type: Function, mayBeNull: true, optional: true}, + {name: "onFailure", type: Function, mayBeNull: true, optional: true}, + {name: "userContext", mayBeNull: true, optional: true}, + {name: "timeout", type: Number, optional: true}, + {name: "enableJsonp", type: Boolean, mayBeNull: true, optional: true}, + {name: "jsonpCallbackParameter", type: String, mayBeNull: true, optional: true} + ]); + if (e) throw e; + var schemeHost = (enableJsonp !== false) ? Sys.Net.WebServiceProxy._xdomain.exec(servicePath) : null, + tempCallback, jsonp = schemeHost && (schemeHost.length === 3) && + ((schemeHost[1] !== location.protocol) || (schemeHost[2] !== location.host)); + useGet = jsonp || useGet; + if (jsonp) { + jsonpCallbackParameter = jsonpCallbackParameter || "callback"; + tempCallback = "_jsonp" + Sys._jsonp++; + } + if (!params) params = {}; + var urlParams = params; + if (!useGet || !urlParams) urlParams = {}; + var script, error, timeoutcookie = null, loader, body = null, + url = Sys.Net.WebRequest._createUrl(methodName + ? (servicePath+"/"+encodeURIComponent(methodName)) + : servicePath, urlParams, jsonp ? (jsonpCallbackParameter + "=Sys." + tempCallback) : null); + if (jsonp) { + script = document.createElement("script"); + script.src = url; + loader = new Sys._ScriptLoaderTask(script, function(script, loaded) { + if (!loaded || tempCallback) { + jsonpComplete({ Message: String.format(Sys.Res.webServiceFailedNoMsg, methodName) }, -1); + } + }); + function jsonpComplete(data, statusCode) { + if (timeoutcookie !== null) { + window.clearTimeout(timeoutcookie); + timeoutcookie = null; + } + loader.dispose(); + delete Sys[tempCallback]; + tempCallback = null; + if ((typeof(statusCode) !== "undefined") && (statusCode !== 200)) { + if (onFailure) { + error = new Sys.Net.WebServiceError(false, + data.Message || String.format(Sys.Res.webServiceFailedNoMsg, methodName), + data.StackTrace || null, + data.ExceptionType || null, + data); + error._statusCode = statusCode; + onFailure(error, userContext, methodName); + } + else { + if (data.StackTrace && data.Message) { + error = data.StackTrace + "-- " + data.Message; + } + else { + error = data.StackTrace || data.Message; + } + error = String.format(error ? Sys.Res.webServiceFailed : Sys.Res.webServiceFailedNoMsg, methodName, error); + throw Sys.Net.WebServiceProxy._createFailedError(methodName, String.format(Sys.Res.webServiceFailed, methodName, error)); + } + } + else if (onSuccess) { + onSuccess(data, userContext, methodName); + } + } + Sys[tempCallback] = jsonpComplete; + loader.execute(); + return null; + } + var request = new Sys.Net.WebRequest(); + request.set_url(url); + request.get_headers()['Content-Type'] = 'application/json; charset=utf-8'; + if (!useGet) { + body = Sys.Serialization.JavaScriptSerializer.serialize(params); + if (body === "{}") body = ""; + } + request.set_body(body); + request.add_completed(onComplete); + if (timeout && timeout > 0) request.set_timeout(timeout); + request.invoke(); + + function onComplete(response, eventArgs) { + if (response.get_responseAvailable()) { + var statusCode = response.get_statusCode(); + var result = null; + + try { + var contentType = response.getResponseHeader("Content-Type"); + if (contentType.startsWith("application/json")) { + result = response.get_object(); + } + else if (contentType.startsWith("text/xml")) { + result = response.get_xml(); + } + else { + result = response.get_responseData(); + } + } catch (ex) { + } + var error = response.getResponseHeader("jsonerror"); + var errorObj = (error === "true"); + if (errorObj) { + if (result) { + result = new Sys.Net.WebServiceError(false, result.Message, result.StackTrace, result.ExceptionType, result); + } + } + else if (contentType.startsWith("application/json")) { + result = (!result || (typeof(result.d) === "undefined")) ? result : result.d; + } + if (((statusCode < 200) || (statusCode >= 300)) || errorObj) { + if (onFailure) { + if (!result || !errorObj) { + result = new Sys.Net.WebServiceError(false , String.format(Sys.Res.webServiceFailedNoMsg, methodName)); + } + result._statusCode = statusCode; + onFailure(result, userContext, methodName); + } + else { + if (result && errorObj) { + error = result.get_exceptionType() + "-- " + result.get_message(); + } + else { + error = response.get_responseData(); + } + throw Sys.Net.WebServiceProxy._createFailedError(methodName, String.format(Sys.Res.webServiceFailed, methodName, error)); + } + } + else if (onSuccess) { + onSuccess(result, userContext, methodName); + } + } + else { + var msg; + if (response.get_timedOut()) { + msg = String.format(Sys.Res.webServiceTimedOut, methodName); + } + else { + msg = String.format(Sys.Res.webServiceFailedNoMsg, methodName) + } + if (onFailure) { + onFailure(new Sys.Net.WebServiceError(response.get_timedOut(), msg, "", ""), userContext, methodName); + } + else { + throw Sys.Net.WebServiceProxy._createFailedError(methodName, msg); + } + } + } + return request; +} +Sys.Net.WebServiceProxy._createFailedError = function Sys$Net$WebServiceProxy$_createFailedError(methodName, errorMessage) { + var displayMessage = "Sys.Net.WebServiceFailedException: " + errorMessage; + var e = Error.create(displayMessage, { 'name': 'Sys.Net.WebServiceFailedException', 'methodName': methodName }); + e.popStackFrame(); + return e; +} +Sys.Net.WebServiceProxy._defaultFailedCallback = function Sys$Net$WebServiceProxy$_defaultFailedCallback(err, methodName) { + var error = err.get_exceptionType() + "-- " + err.get_message(); + throw Sys.Net.WebServiceProxy._createFailedError(methodName, String.format(Sys.Res.webServiceFailed, methodName, error)); +} +Sys.Net.WebServiceProxy._generateTypedConstructor = function Sys$Net$WebServiceProxy$_generateTypedConstructor(type) { + return function(properties) { + if (properties) { + for (var name in properties) { + this[name] = properties[name]; + } + } + this.__type = type; + } +} +Sys._jsonp = 0; +Sys.Net.WebServiceProxy._xdomain = /^\s*([a-zA-Z0-9\+\-\.]+\:)\/\/([^?#\/]+)/; + +Sys.Net.WebServiceError = function Sys$Net$WebServiceError(timedOut, message, stackTrace, exceptionType, errorObject) { + /// + /// + /// + /// + /// + /// + var e = Function._validateParams(arguments, [ + {name: "timedOut", type: Boolean}, + {name: "message", type: String, mayBeNull: true}, + {name: "stackTrace", type: String, mayBeNull: true, optional: true}, + {name: "exceptionType", type: String, mayBeNull: true, optional: true}, + {name: "errorObject", type: Object, mayBeNull: true, optional: true} + ]); + if (e) throw e; + this._timedOut = timedOut; + this._message = message; + this._stackTrace = stackTrace; + this._exceptionType = exceptionType; + this._errorObject = errorObject; + this._statusCode = -1; +} + function Sys$Net$WebServiceError$get_timedOut() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._timedOut; + } + function Sys$Net$WebServiceError$get_statusCode() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._statusCode; + } + function Sys$Net$WebServiceError$get_message() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._message; + } + function Sys$Net$WebServiceError$get_stackTrace() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._stackTrace || ""; + } + function Sys$Net$WebServiceError$get_exceptionType() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._exceptionType || ""; + } + function Sys$Net$WebServiceError$get_errorObject() { + /// + if (arguments.length !== 0) throw Error.parameterCount(); + return this._errorObject || null; + } +Sys.Net.WebServiceError.prototype = { + get_timedOut: Sys$Net$WebServiceError$get_timedOut, + get_statusCode: Sys$Net$WebServiceError$get_statusCode, + get_message: Sys$Net$WebServiceError$get_message, + get_stackTrace: Sys$Net$WebServiceError$get_stackTrace, + get_exceptionType: Sys$Net$WebServiceError$get_exceptionType, + get_errorObject: Sys$Net$WebServiceError$get_errorObject +} +Sys.Net.WebServiceError.registerClass('Sys.Net.WebServiceError'); + + +Type.registerNamespace('Sys'); + +Sys.Res={ +'urlMustBeLessThan1024chars':'The history state must be small enough to not make the url larger than 1024 characters.', +'argumentTypeName':'Value is not the name of an existing type.', +'cantBeCalledAfterDispose':'Can\'t be called after dispose.', +'componentCantSetIdAfterAddedToApp':'The id property of a component can\'t be set after it\'s been added to the Application object.', +'behaviorDuplicateName':'A behavior with name \'{0}\' already exists or it is the name of an existing property on the target element.', +'notATypeName':'Value is not a valid type name.', +'elementNotFound':'An element with id \'{0}\' could not be found.', +'stateMustBeStringDictionary':'The state object can only have null and string fields.', +'boolTrueOrFalse':'Value must be \'true\' or \'false\'.', +'scriptLoadFailedNoHead':'ScriptLoader requires pages to contain a element.', +'stringFormatInvalid':'The format string is invalid.', +'referenceNotFound':'Component \'{0}\' was not found.', +'enumReservedName':'\'{0}\' is a reserved name that can\'t be used as an enum value name.', +'circularParentChain':'The chain of control parents can\'t have circular references.', +'namespaceContainsNonObject':'Object {0} already exists and is not an object.', +'undefinedEvent':'\'{0}\' is not an event.', +'propertyUndefined':'\'{0}\' is not a property or an existing field.', +'observableConflict':'Object already contains a member with the name \'{0}\'.', +'historyCannotEnableHistory':'Cannot set enableHistory after initialization.', +'eventHandlerInvalid':'Handler was not added through the Sys.UI.DomEvent.addHandler method.', +'scriptLoadFailedDebug':'The script \'{0}\' failed to load. Check for:\r\n Inaccessible path.\r\n Script errors. (IE) Enable \'Display a notification about every script error\' under advanced settings.', +'propertyNotWritable':'\'{0}\' is not a writable property.', +'enumInvalidValueName':'\'{0}\' is not a valid name for an enum value.', +'controlAlreadyDefined':'A control is already associated with the element.', +'addHandlerCantBeUsedForError':'Can\'t add a handler for the error event using this method. Please set the window.onerror property instead.', +'cantAddNonFunctionhandler':'Can\'t add a handler that is not a function.', +'invalidNameSpace':'Value is not a valid namespace identifier.', +'notAnInterface':'Value is not a valid interface.', +'eventHandlerNotFunction':'Handler must be a function.', +'propertyNotAnArray':'\'{0}\' is not an Array property.', +'namespaceContainsClass':'Object {0} already exists as a class, enum, or interface.', +'typeRegisteredTwice':'Type {0} has already been registered. The type may be defined multiple times or the script file that defines it may have already been loaded. A possible cause is a change of settings during a partial update.', +'cantSetNameAfterInit':'The name property can\'t be set on this object after initialization.', +'historyMissingFrame':'For the history feature to work in IE, the page must have an iFrame element with id \'__historyFrame\' pointed to a page that gets its title from the \'title\' query string parameter and calls Sys.Application._onIFrameLoad() on the parent window. This can be done by setting EnableHistory to true on ScriptManager.', +'appDuplicateComponent':'Two components with the same id \'{0}\' can\'t be added to the application.', +'historyCannotAddHistoryPointWithHistoryDisabled':'A history point can only be added if enableHistory is set to true.', +'baseNotAClass':'Value is not a class.', +'expectedElementOrId':'Value must be a DOM element or DOM element Id.', +'methodNotFound':'No method found with name \'{0}\'.', +'arrayParseBadFormat':'Value must be a valid string representation for an array. It must start with a \'[\' and end with a \']\'.', +'stateFieldNameInvalid':'State field names must not contain any \'=\' characters.', +'cantSetId':'The id property can\'t be set on this object.', +'stringFormatBraceMismatch':'The format string contains an unmatched opening or closing brace.', +'enumValueNotInteger':'An enumeration definition can only contain integer values.', +'propertyNullOrUndefined':'Cannot set the properties of \'{0}\' because it returned a null value.', +'argumentDomNode':'Value must be a DOM element or a text node.', +'componentCantSetIdTwice':'The id property of a component can\'t be set more than once.', +'createComponentOnDom':'Value must be null for Components that are not Controls or Behaviors.', +'createNotComponent':'{0} does not derive from Sys.Component.', +'createNoDom':'Value must not be null for Controls and Behaviors.', +'cantAddWithoutId':'Can\'t add a component that doesn\'t have an id.', +'notObservable':'Instances of type \'{0}\' cannot be observed.', +'badTypeName':'Value is not the name of the type being registered or the name is a reserved word.', +'argumentInteger':'Value must be an integer.', +'invokeCalledTwice':'Cannot call invoke more than once.', +'webServiceFailed':'The server method \'{0}\' failed with the following error: {1}', +'argumentType':'Object cannot be converted to the required type.', +'argumentNull':'Value cannot be null.', +'scriptAlreadyLoaded':'The script \'{0}\' has been referenced multiple times. If referencing Microsoft AJAX scripts explicitly, set the MicrosoftAjaxMode property of the ScriptManager to Explicit.', +'scriptDependencyNotFound':'The script \'{0}\' failed to load because it is dependent on script \'{1}\'.', +'formatBadFormatSpecifier':'Format specifier was invalid.', +'requiredScriptReferenceNotIncluded':'\'{0}\' requires that you have included a script reference to \'{1}\'.', +'webServiceFailedNoMsg':'The server method \'{0}\' failed.', +'argumentDomElement':'Value must be a DOM element.', +'invalidExecutorType':'Could not create a valid Sys.Net.WebRequestExecutor from: {0}.', +'cannotCallBeforeResponse':'Cannot call {0} when responseAvailable is false.', +'actualValue':'Actual value was {0}.', +'enumInvalidValue':'\'{0}\' is not a valid value for enum {1}.', +'scriptLoadFailed':'The script \'{0}\' could not be loaded.', +'parameterCount':'Parameter count mismatch.', +'cannotDeserializeEmptyString':'Cannot deserialize empty string.', +'formatInvalidString':'Input string was not in a correct format.', +'invalidTimeout':'Value must be greater than or equal to zero.', +'cannotAbortBeforeStart':'Cannot abort when executor has not started.', +'argument':'Value does not fall within the expected range.', +'cannotDeserializeInvalidJson':'Cannot deserialize. The data does not correspond to valid JSON.', +'invalidHttpVerb':'httpVerb cannot be set to an empty or null string.', +'nullWebRequest':'Cannot call executeRequest with a null webRequest.', +'eventHandlerInvalid':'Handler was not added through the Sys.UI.DomEvent.addHandler method.', +'cannotSerializeNonFiniteNumbers':'Cannot serialize non finite numbers.', +'argumentUndefined':'Value cannot be undefined.', +'webServiceInvalidReturnType':'The server method \'{0}\' returned an invalid type. Expected type: {1}', +'servicePathNotSet':'The path to the web service has not been set.', +'argumentTypeWithTypes':'Object of type \'{0}\' cannot be converted to type \'{1}\'.', +'cannotCallOnceStarted':'Cannot call {0} once started.', +'badBaseUrl1':'Base URL does not contain ://.', +'badBaseUrl2':'Base URL does not contain another /.', +'badBaseUrl3':'Cannot find last / in base URL.', +'setExecutorAfterActive':'Cannot set executor after it has become active.', +'paramName':'Parameter name: {0}', +'nullReferenceInPath':'Null reference while evaluating data path: \'{0}\'.', +'cannotCallOutsideHandler':'Cannot call {0} outside of a completed event handler.', +'cannotSerializeObjectWithCycle':'Cannot serialize object with cyclic reference within child properties.', +'format':'One of the identified items was in an invalid format.', +'assertFailedCaller':'Assertion Failed: {0}\r\nat {1}', +'argumentOutOfRange':'Specified argument was out of the range of valid values.', +'webServiceTimedOut':'The server method \'{0}\' timed out.', +'notImplemented':'The method or operation is not implemented.', +'assertFailed':'Assertion Failed: {0}', +'invalidOperation':'Operation is not valid due to the current state of the object.', +'breakIntoDebugger':'{0}\r\n\r\nBreak into debugger?' +}; diff --git a/OnPremise/WebSite/Scripts/MicrosoftAjax.js b/OnPremise/WebSite/Scripts/MicrosoftAjax.js new file mode 100644 index 0000000..52e6626 --- /dev/null +++ b/OnPremise/WebSite/Scripts/MicrosoftAjax.js @@ -0,0 +1,6 @@ +//---------------------------------------------------------- +// Copyright (C) Microsoft Corporation. All rights reserved. +//---------------------------------------------------------- +// MicrosoftAjax.js +Function.__typeName="Function";Function.__class=true;Function.createCallback=function(b,a){return function(){var e=arguments.length;if(e>0){var d=[];for(var c=0;c=d)break;a=Function._validateParameter(g[b],f,h);if(a){a.popStackFrame();return a}}return null};Function._validateParameterCount=function(j,d,i){var a,c,b=d.length,e=j.length;if(eb){c=true;for(a=0;a0&&(d=0};Array.dequeue=function(a){return a.shift()};Array.forEach=function(b,e,d){for(var a=0,f=b.length;a=0)b.splice(a,1);return a>=0};Array.removeAt=function(a,b){a.splice(b,1)};Sys._indexOf=function(d,e,a){if(typeof e==="undefined")return -1;var c=d.length;if(c!==0){a=a-0;if(isNaN(a))a=0;else{if(isFinite(a))a=a-a%1;if(a<0)a=Math.max(0,c+a)}for(var b=a;b-1){Sys.Browser.agent=Sys.Browser.InternetExplorer;Sys.Browser.version=parseFloat(navigator.userAgent.match(/MSIE (\d+\.\d+)/)[1]);if(Sys.Browser.version>=8)if(document.documentMode>=7)Sys.Browser.documentMode=document.documentMode;Sys.Browser.hasDebuggerStatement=true}else if(navigator.userAgent.indexOf(" Firefox/")>-1){Sys.Browser.agent=Sys.Browser.Firefox;Sys.Browser.version=parseFloat(navigator.userAgent.match(/Firefox\/(\d+\.\d+)/)[1]);Sys.Browser.name="Firefox";Sys.Browser.hasDebuggerStatement=true}else if(navigator.userAgent.indexOf(" AppleWebKit/")>-1){Sys.Browser.agent=Sys.Browser.Safari;Sys.Browser.version=parseFloat(navigator.userAgent.match(/AppleWebKit\/(\d+(\.\d+)?)/)[1]);Sys.Browser.name="Safari"}else if(navigator.userAgent.indexOf("Opera/")>-1)Sys.Browser.agent=Sys.Browser.Opera;Sys.EventArgs=function(){};Sys.EventArgs.registerClass("Sys.EventArgs");Sys.EventArgs.Empty=new Sys.EventArgs;Sys.CancelEventArgs=function(){Sys.CancelEventArgs.initializeBase(this);this._cancel=false};Sys.CancelEventArgs.prototype={get_cancel:function(){return this._cancel},set_cancel:function(a){this._cancel=a}};Sys.CancelEventArgs.registerClass("Sys.CancelEventArgs",Sys.EventArgs);Type.registerNamespace("Sys.UI");Sys._Debug=function(){};Sys._Debug.prototype={_appendConsole:function(a){if(typeof Debug!=="undefined"&&Debug.writeln)Debug.writeln(a);if(window.console&&window.console.log)window.console.log(a);if(window.opera)window.opera.postError(a);if(window.debugService)window.debugService.trace(a)},_appendTrace:function(b){var a=document.getElementById("TraceConsole");if(a&&a.tagName.toUpperCase()==="TEXTAREA")a.value+=b+"\n"},assert:function(c,a,b){if(!c){a=b&&this.assert.caller?String.format(Sys.Res.assertFailedCaller,a,this.assert.caller):String.format(Sys.Res.assertFailed,a);if(confirm(String.format(Sys.Res.breakIntoDebugger,a)))this.fail(a)}},clearTrace:function(){var a=document.getElementById("TraceConsole");if(a&&a.tagName.toUpperCase()==="TEXTAREA")a.value=""},fail:function(message){this._appendConsole(message);if(Sys.Browser.hasDebuggerStatement)eval("debugger")},trace:function(a){this._appendConsole(a);this._appendTrace(a)},traceDump:function(a,b){var c=this._traceDump(a,b,true)},_traceDump:function(a,c,f,b,d){c=c?c:"traceDump";b=b?b:"";if(a===null){this.trace(b+c+": null");return}switch(typeof a){case "undefined":this.trace(b+c+": Undefined");break;case "number":case "string":case "boolean":this.trace(b+c+": "+a);break;default:if(Date.isInstanceOfType(a)||RegExp.isInstanceOfType(a)){this.trace(b+c+": "+a.toString());break}if(!d)d=[];else if(Array.contains(d,a)){this.trace(b+c+": ...");return}Array.add(d,a);if(a==window||a===document||window.HTMLElement&&a instanceof HTMLElement||typeof a.nodeName==="string"){var k=a.tagName?a.tagName:"DomElement";if(a.id)k+=" - "+a.id;this.trace(b+c+" {"+k+"}")}else{var i=Object.getTypeName(a);this.trace(b+c+(typeof i==="string"?" {"+i+"}":""));if(b===""||f){b+=" ";var e,j,l,g,h;if(Array.isInstanceOfType(a)){j=a.length;for(e=0;e=0;d--){var k=h[d].trim();b=a[k];if(typeof b!=="number")throw Error.argument("value",String.format(Sys.Res.enumInvalidValue,c.split(",")[d].trim(),this.__typeName));j|=b}return j}}function Sys$Enum$toString(c){if(typeof c==="undefined"||c===null)return this.__string;var d=this.prototype,a;if(!this.__flags||c===0){for(a in d)if(d[a]===c)return a}else{var b=this.__sortedValues;if(!b){b=[];for(a in d)b[b.length]={key:a,value:d[a]};b.sort(function(a,b){return a.value-b.value});this.__sortedValues=b}var e=[],g=c;for(a=b.length-1;a>=0;a--){var h=b[a],f=h.value;if(f===0)continue;if((f&c)===f){e[e.length]=h.key;g-=f;if(g===0)break}}if(e.length&&g===0)return e.reverse().join(", ")}return ""}Type.prototype.registerEnum=function(b,c){Sys.__upperCaseTypes[b.toUpperCase()]=this;for(var a in this.prototype)this[a]=this.prototype[a];this.__typeName=b;this.parse=Sys$Enum$parse;this.__string=this.toString();this.toString=Sys$Enum$toString;this.__flags=c;this.__enum=true};Type.isEnum=function(a){if(typeof a==="undefined"||a===null)return false;return !!a.__enum};Type.isFlags=function(a){if(typeof a==="undefined"||a===null)return false;return !!a.__flags};Sys.CollectionChange=function(e,a,c,b,d){this.action=e;if(a)if(!(a instanceof Array))a=[a];this.newItems=a||null;if(typeof c!=="number")c=-1;this.newStartingIndex=c;if(b)if(!(b instanceof Array))b=[b];this.oldItems=b||null;if(typeof d!=="number")d=-1;this.oldStartingIndex=d};Sys.CollectionChange.registerClass("Sys.CollectionChange");Sys.NotifyCollectionChangedAction=function(){throw Error.notImplemented()};Sys.NotifyCollectionChangedAction.prototype={add:0,remove:1,reset:2};Sys.NotifyCollectionChangedAction.registerEnum("Sys.NotifyCollectionChangedAction");Sys.NotifyCollectionChangedEventArgs=function(a){this._changes=a;Sys.NotifyCollectionChangedEventArgs.initializeBase(this)};Sys.NotifyCollectionChangedEventArgs.prototype={get_changes:function(){return this._changes||[]}};Sys.NotifyCollectionChangedEventArgs.registerClass("Sys.NotifyCollectionChangedEventArgs",Sys.EventArgs);Sys.Observer=function(){};Sys.Observer.registerClass("Sys.Observer");Sys.Observer.makeObservable=function(a){var c=a instanceof Array,b=Sys.Observer;if(a.setValue===b._observeMethods.setValue)return a;b._addMethods(a,b._observeMethods);if(c)b._addMethods(a,b._arrayMethods);return a};Sys.Observer._addMethods=function(c,b){for(var a in b)c[a]=b[a]};Sys.Observer._addEventHandler=function(c,a,b){Sys.Observer._getContext(c,true).events._addHandler(a,b)};Sys.Observer.addEventHandler=function(c,a,b){Sys.Observer._addEventHandler(c,a,b)};Sys.Observer._removeEventHandler=function(c,a,b){Sys.Observer._getContext(c,true).events._removeHandler(a,b)};Sys.Observer.removeEventHandler=function(c,a,b){Sys.Observer._removeEventHandler(c,a,b)};Sys.Observer.raiseEvent=function(b,e,d){var c=Sys.Observer._getContext(b);if(!c)return;var a=c.events.getHandler(e);if(a)a(b,d)};Sys.Observer.addPropertyChanged=function(b,a){Sys.Observer._addEventHandler(b,"propertyChanged",a)};Sys.Observer.removePropertyChanged=function(b,a){Sys.Observer._removeEventHandler(b,"propertyChanged",a)};Sys.Observer.beginUpdate=function(a){Sys.Observer._getContext(a,true).updating=true};Sys.Observer.endUpdate=function(b){var a=Sys.Observer._getContext(b);if(!a||!a.updating)return;a.updating=false;var d=a.dirty;a.dirty=false;if(d){if(b instanceof Array){var c=a.changes;a.changes=null;Sys.Observer.raiseCollectionChanged(b,c)}Sys.Observer.raisePropertyChanged(b,"")}};Sys.Observer.isUpdating=function(b){var a=Sys.Observer._getContext(b);return a?a.updating:false};Sys.Observer._setValue=function(a,j,g){var b,f,k=a,d=j.split(".");for(var i=0,m=d.length-1;i-1&&ac.Calendar.TwoDigitYearMax)a-=100}return a};Date._getEra=function(e,c){if(!c)return 0;var b,d=e.getTime();for(var a=0,f=c.length;a=b)return a}return 0};Date._getEraYear=function(d,b,e,c){var a=d.getFullYear();if(!c&&b.eras)a-=b.eras[e+3];return a};Date._getParseRegExp=function(b,e){if(!b._parseRegExp)b._parseRegExp={};else if(b._parseRegExp[e])return b._parseRegExp[e];var c=Date._expandFormat(b,e);c=c.replace(/([\^\$\.\*\+\?\|\[\]\(\)\{\}])/g,"\\\\$1");var a=new Sys.StringBuilder("^"),j=[],f=0,i=0,h=Date._getTokenRegExp(),d;while((d=h.exec(c))!==null){var l=c.slice(f,d.index);f=h.lastIndex;i+=Date._appendPreOrPostMatch(l,a);if(i%2===1){a.append(d[0]);continue}switch(d[0]){case "dddd":case "ddd":case "MMMM":case "MMM":case "gg":case "g":a.append("(\\D+)");break;case "tt":case "t":a.append("(\\D*)");break;case "yyyy":a.append("(\\d{4})");break;case "fff":a.append("(\\d{3})");break;case "ff":a.append("(\\d{2})");break;case "f":a.append("(\\d)");break;case "dd":case "d":case "MM":case "M":case "yy":case "y":case "HH":case "H":case "hh":case "h":case "mm":case "m":case "ss":case "s":a.append("(\\d\\d?)");break;case "zzz":a.append("([+-]?\\d\\d?:\\d{2})");break;case "zz":case "z":a.append("([+-]?\\d\\d?)");break;case "/":a.append("(\\"+b.DateSeparator+")")}Array.add(j,d[0])}Date._appendPreOrPostMatch(c.slice(f),a);a.append("$");var k=a.toString().replace(/\s+/g,"\\s+"),g={"regExp":k,"groups":j};b._parseRegExp[e]=g;return g};Date._getTokenRegExp=function(){return /\/|dddd|ddd|dd|d|MMMM|MMM|MM|M|yyyy|yy|y|hh|h|HH|H|mm|m|ss|s|tt|t|fff|ff|f|zzz|zz|z|gg|g/g};Date.parseLocale=function(a){return Date._parse(a,Sys.CultureInfo.CurrentCulture,arguments)};Date.parseInvariant=function(a){return Date._parse(a,Sys.CultureInfo.InvariantCulture,arguments)};Date._parse=function(h,d,i){var a,c,b,f,e,g=false;for(a=1,c=i.length;a31)return null;break;case "MMMM":c=k._getMonthIndex(a);if(c<0||c>11)return null;break;case "MMM":c=k._getAbbrMonthIndex(a);if(c<0||c>11)return null;break;case "M":case "MM":c=parseInt(a,10)-1;if(c<0||c>11)return null;break;case "y":case "yy":e=Date._expandYear(g,parseInt(a,10));if(e<0||e>9999)return null;break;case "yyyy":e=parseInt(a,10);if(e<0||e>9999)return null;break;case "h":case "hh":d=parseInt(a,10);if(d===12)d=0;if(d<0||d>11)return null;break;case "H":case "HH":d=parseInt(a,10);if(d<0||d>23)return null;break;case "m":case "mm":q=parseInt(a,10);if(q<0||q>59)return null;break;case "s":case "ss":r=parseInt(a,10);if(r<0||r>59)return null;break;case "tt":case "t":var z=a.toUpperCase();v=z===g.PMDesignator.toUpperCase();if(!v&&z!==g.AMDesignator.toUpperCase())return null;break;case "f":f=parseInt(a,10)*100;if(f<0||f>999)return null;break;case "ff":f=parseInt(a,10)*10;if(f<0||f>999)return null;break;case "fff":f=parseInt(a,10);if(f<0||f>999)return null;break;case "dddd":i=k._getDayIndex(a);if(i<0||i>6)return null;break;case "ddd":i=k._getAbbrDayIndex(a);if(i<0||i>6)return null;break;case "zzz":var u=a.split(/:/);if(u.length!==2)return null;h=parseInt(u[0],10);if(h<-12||h>13)return null;var o=parseInt(u[1],10);if(o<0||o>59)return null;n=h*60+(a.startsWith("-")?-o:o);break;case "z":case "zz":h=parseInt(a,10);if(h<-12||h>13)return null;n=h*60;break;case "g":case "gg":var p=a;if(!p||!g.eras)return null;p=p.toLowerCase().trim();for(var s=0,F=g.eras.length;s0)return this.toLocaleString();else return this.toString();var o=["n %","n%","%n"],n=["-n %","-n%","-%n"],p=["(n)","-n","- n","n-","n -"],m=["$n","n$","$ n","n $"],l=["($n)","-$n","$-n","$n-","(n$)","-n$","n-$","n$-","-n $","-$ n","n $-","$ n-","$ -n","n- $","($ n)","(n $)"];function g(a,c,d){for(var b=a.length;b1?parseInt(e[1]):0;e=b.split(".");b=e[0];a=e.length>1?e[1]:"";var q;if(c>0){a=g(a,c,false);b+=a.slice(0,c);a=a.substr(c)}else if(c<0){c=-c;b=g(b,c+1,true);a=b.slice(-c,b.length)+a;b=b.slice(0,-c)}if(i>0){if(a.length>i)a=a.slice(0,i);else a=g(a,i,false);a=p+a}else a="";var d=b.length-1,f="";while(d>=0){if(h===0||h>d)if(f.length>0)return b.slice(0,d+1)+n+f+a;else return b.slice(0,d+1)+a;if(f.length>0)f=b.slice(d-h+1,d+1)+n+f;else f=b.slice(d-h+1,d+1);d-=h;if(k1)b=parseInt(e.slice(1),10);var c;switch(e.charAt(0)){case "d":case "D":c="n";if(b!==-1)d=g(""+d,b,true);if(this<0)d=-d;break;case "c":case "C":if(this<0)c=l[a.CurrencyNegativePattern];else c=m[a.CurrencyPositivePattern];if(b===-1)b=a.CurrencyDecimalDigits;d=i(Math.abs(this),b,a.CurrencyGroupSizes,a.CurrencyGroupSeparator,a.CurrencyDecimalSeparator);break;case "n":case "N":if(this<0)c=p[a.NumberNegativePattern];else c="n";if(b===-1)b=a.NumberDecimalDigits;d=i(Math.abs(this),b,a.NumberGroupSizes,a.NumberGroupSeparator,a.NumberDecimalSeparator);break;case "p":case "P":if(this<0)c=n[a.PercentNegativePattern];else c=o[a.PercentPositivePattern];if(b===-1)b=a.PercentDecimalDigits;d=i(Math.abs(this)*100,b,a.PercentGroupSizes,a.PercentGroupSeparator,a.PercentDecimalSeparator);break;default:throw Error.format(Sys.Res.formatBadFormatSpecifier)}var k=/n|\$|-|%/g,f="";for(;true;){var q=k.lastIndex,h=k.exec(c);f+=c.slice(q,h?h.index:c.length);if(!h)break;switch(h[0]){case "n":f+=d;break;case "$":f+=a.CurrencySymbol;break;case "-":if(/[1-9]/.test(d))f+=a.NegativeSign;break;case "%":f+=a.PercentSymbol}}return f};Sys.CultureInfo=function(c,b,a){this.name=c;this.numberFormat=b;this.dateTimeFormat=a};Sys.CultureInfo.prototype={_getDateTimeFormats:function(){if(!this._dateTimeFormats){var a=this.dateTimeFormat;this._dateTimeFormats=[a.MonthDayPattern,a.YearMonthPattern,a.ShortDatePattern,a.ShortTimePattern,a.LongDatePattern,a.LongTimePattern,a.FullDateTimePattern,a.RFC1123Pattern,a.SortableDateTimePattern,a.UniversalSortableDateTimePattern]}return this._dateTimeFormats},_getIndex:function(c,d,e){var b=this._toUpper(c),a=Array.indexOf(d,b);if(a===-1)a=Array.indexOf(e,b);return a},_getMonthIndex:function(a){if(!this._upperMonths){this._upperMonths=this._toUpperArray(this.dateTimeFormat.MonthNames);this._upperMonthsGenitive=this._toUpperArray(this.dateTimeFormat.MonthGenitiveNames)}return this._getIndex(a,this._upperMonths,this._upperMonthsGenitive)},_getAbbrMonthIndex:function(a){if(!this._upperAbbrMonths){this._upperAbbrMonths=this._toUpperArray(this.dateTimeFormat.AbbreviatedMonthNames);this._upperAbbrMonthsGenitive=this._toUpperArray(this.dateTimeFormat.AbbreviatedMonthGenitiveNames)}return this._getIndex(a,this._upperAbbrMonths,this._upperAbbrMonthsGenitive)},_getDayIndex:function(a){if(!this._upperDays)this._upperDays=this._toUpperArray(this.dateTimeFormat.DayNames);return Array.indexOf(this._upperDays,this._toUpper(a))},_getAbbrDayIndex:function(a){if(!this._upperAbbrDays)this._upperAbbrDays=this._toUpperArray(this.dateTimeFormat.AbbreviatedDayNames);return Array.indexOf(this._upperAbbrDays,this._toUpper(a))},_toUpperArray:function(c){var b=[];for(var a=0,d=c.length;a0)a.append(",");Sys.Serialization.JavaScriptSerializer._serializeWithBuilder(b[c],a,false,g)}a.append("]")}else{if(Date.isInstanceOfType(b)){a.append('"\\/Date(');a.append(b.getTime());a.append(')\\/"');break}var d=[],f=0;for(var e in b){if(e.startsWith("$"))continue;if(e===Sys.Serialization.JavaScriptSerializer._serverTypeFieldName&&f!==0){d[f++]=d[0];d[0]=e}else d[f++]=e}if(i)d.sort();a.append("{");var j=false;for(c=0;c=0;c--){var f=d[c];if(!g||f.autoRemove)$removeHandler(a,b,f.handler)}}a._events=null}};Sys.UI.DomEvent._disposeHandlers=function(){Sys.UI.DomEvent._clearHandlers(this,true);var b=this._chainDispose,a=typeof b;if(a!=="undefined"){this.dispose=b;this._chainDispose=null;if(a==="function")this.dispose()}};var $removeHandler=Sys.UI.DomEvent.removeHandler=function(b,a,c){Sys.UI.DomEvent._removeHandler(b,a,c)};Sys.UI.DomEvent._removeHandler=function(a,e,f){var d=null,c=a._events[e];for(var b=0,g=c.length;b=3){d+=parseInt(b.borderLeftWidth);e+=parseInt(b.borderTopWidth)}}b=Sys.UI.DomElement._getCurrentStyle(c);var h=b?b.position:null;if(!h||h!=="absolute")for(a=c.parentNode;a;a=a.parentNode){f=a.tagName?a.tagName.toUpperCase():null;if(f!=="BODY"&&f!=="HTML"&&(a.scrollLeft||a.scrollTop)){d-=a.scrollLeft||0;e-=a.scrollTop||0}b=Sys.UI.DomElement._getCurrentStyle(a);var i=b?b.position:null;if(i&&i==="absolute")break}return new Sys.UI.Point(d,e)};else Sys.UI.DomElement.getLocation=function(d){if(d.window&&d.window===d||d.nodeType===9)return new Sys.UI.Point(0,0);var e=0,f=0,a,i=null,g=null,b=null;for(a=d;a;i=a,(g=b,a=a.offsetParent)){var c=a.tagName?a.tagName.toUpperCase():null;b=Sys.UI.DomElement._getCurrentStyle(a);if((a.offsetLeft||a.offsetTop)&&!(c==="BODY"&&(!g||g.position!=="absolute"))){e+=a.offsetLeft;f+=a.offsetTop}if(i!==null&&b){if(c!=="TABLE"&&c!=="TD"&&c!=="HTML"){e+=parseInt(b.borderLeftWidth)||0;f+=parseInt(b.borderTopWidth)||0}if(c==="TABLE"&&(b.position==="relative"||b.position==="absolute")){e+=parseInt(b.marginLeft)||0;f+=parseInt(b.marginTop)||0}}}b=Sys.UI.DomElement._getCurrentStyle(d);var h=b?b.position:null;if(!h||h!=="absolute")for(a=d.parentNode;a;a=a.parentNode){c=a.tagName?a.tagName.toUpperCase():null;if(c!=="BODY"&&c!=="HTML"&&(a.scrollLeft||a.scrollTop)){e-=a.scrollLeft||0;f-=a.scrollTop||0;b=Sys.UI.DomElement._getCurrentStyle(a);if(b){e+=parseInt(b.borderLeftWidth)||0;f+=parseInt(b.borderTopWidth)||0}}}return new Sys.UI.Point(e,f)};Sys.UI.DomElement.isDomElement=function(a){return Sys._isDomElement(a)};Sys.UI.DomElement.removeCssClass=function(d,c){var a=" "+d.className+" ",b=a.indexOf(" "+c+" ");if(b>=0)d.className=(a.substr(0,b)+" "+a.substring(b+c.length+1,a.length)).trim()};Sys.UI.DomElement.resolveElement=function(b,c){var a=b;if(!a)return null;if(typeof a==="string")a=Sys.UI.DomElement.getElementById(a,c);return a};Sys.UI.DomElement.raiseBubbleEvent=function(c,d){var b=c;while(b){var a=b.control;if(a&&a.onBubbleEvent&&a.raiseBubbleEvent){Sys.UI.DomElement._raiseBubbleEventFromControl(a,c,d);return}b=b.parentNode}};Sys.UI.DomElement._raiseBubbleEventFromControl=function(a,b,c){if(!a.onBubbleEvent(b,c))a._raiseBubbleEvent(b,c)};Sys.UI.DomElement.setLocation=function(b,c,d){var a=b.style;a.position="absolute";a.left=c+"px";a.top=d+"px"};Sys.UI.DomElement.toggleCssClass=function(b,a){if(Sys.UI.DomElement.containsCssClass(b,a))Sys.UI.DomElement.removeCssClass(b,a);else Sys.UI.DomElement.addCssClass(b,a)};Sys.UI.DomElement.getVisibilityMode=function(a){return a._visibilityMode===Sys.UI.VisibilityMode.hide?Sys.UI.VisibilityMode.hide:Sys.UI.VisibilityMode.collapse};Sys.UI.DomElement.setVisibilityMode=function(a,b){Sys.UI.DomElement._ensureOldDisplayMode(a);if(a._visibilityMode!==b){a._visibilityMode=b;if(Sys.UI.DomElement.getVisible(a)===false)if(a._visibilityMode===Sys.UI.VisibilityMode.hide)a.style.display=a._oldDisplayMode;else a.style.display="none";a._visibilityMode=b}};Sys.UI.DomElement.getVisible=function(b){var a=b.currentStyle||Sys.UI.DomElement._getCurrentStyle(b);if(!a)return true;return a.visibility!=="hidden"&&a.display!=="none"};Sys.UI.DomElement.setVisible=function(a,b){if(b!==Sys.UI.DomElement.getVisible(a)){Sys.UI.DomElement._ensureOldDisplayMode(a);a.style.visibility=b?"visible":"hidden";if(b||a._visibilityMode===Sys.UI.VisibilityMode.hide)a.style.display=a._oldDisplayMode;else a.style.display="none"}};Sys.UI.DomElement._ensureOldDisplayMode=function(a){if(!a._oldDisplayMode){var b=a.currentStyle||Sys.UI.DomElement._getCurrentStyle(a);a._oldDisplayMode=b?b.display:null;if(!a._oldDisplayMode||a._oldDisplayMode==="none")switch(a.tagName.toUpperCase()){case "DIV":case "P":case "ADDRESS":case "BLOCKQUOTE":case "BODY":case "COL":case "COLGROUP":case "DD":case "DL":case "DT":case "FIELDSET":case "FORM":case "H1":case "H2":case "H3":case "H4":case "H5":case "H6":case "HR":case "IFRAME":case "LEGEND":case "OL":case "PRE":case "TABLE":case "TD":case "TH":case "TR":case "UL":a._oldDisplayMode="block";break;case "LI":a._oldDisplayMode="list-item";break;default:a._oldDisplayMode="inline"}}};Sys.UI.DomElement._getWindow=function(a){var b=a.ownerDocument||a.document||a;return b.defaultView||b.parentWindow};Sys.UI.DomElement._getCurrentStyle=function(a){if(a.nodeType===3)return null;var c=Sys.UI.DomElement._getWindow(a);if(a.documentElement)a=a.documentElement;var b=c&&a!==c&&c.getComputedStyle?c.getComputedStyle(a,null):a.currentStyle||a.style;if(!b&&Sys.Browser.agent===Sys.Browser.Safari&&a.style){var g=a.style.display,f=a.style.position;a.style.position="absolute";a.style.display="block";var e=c.getComputedStyle(a,null);a.style.display=g;a.style.position=f;b={};for(var d in e)b[d]=e[d];b.display="none"}return b};Sys.IContainer=function(){};Sys.IContainer.prototype={};Sys.IContainer.registerInterface("Sys.IContainer");Sys.ApplicationLoadEventArgs=function(b,a){Sys.ApplicationLoadEventArgs.initializeBase(this);this._components=b;this._isPartialLoad=a};Sys.ApplicationLoadEventArgs.prototype={get_components:function(){return this._components},get_isPartialLoad:function(){return this._isPartialLoad}};Sys.ApplicationLoadEventArgs.registerClass("Sys.ApplicationLoadEventArgs",Sys.EventArgs);Sys._Application=function(){Sys._Application.initializeBase(this);this._disposableObjects=[];this._components={};this._createdComponents=[];this._secondPassComponents=[];this._unloadHandlerDelegate=Function.createDelegate(this,this._unloadHandler);Sys.UI.DomEvent.addHandler(window,"unload",this._unloadHandlerDelegate);this._domReady()};Sys._Application.prototype={_creatingComponents:false,_disposing:false,_deleteCount:0,get_isCreatingComponents:function(){return this._creatingComponents},get_isDisposing:function(){return this._disposing},add_init:function(a){if(this._initialized)a(this,Sys.EventArgs.Empty);else this.get_events().addHandler("init",a)},remove_init:function(a){this.get_events().removeHandler("init",a)},add_load:function(a){this.get_events().addHandler("load",a)},remove_load:function(a){this.get_events().removeHandler("load",a)},add_unload:function(a){this.get_events().addHandler("unload",a)},remove_unload:function(a){this.get_events().removeHandler("unload",a)},addComponent:function(a){this._components[a.get_id()]=a},beginCreateComponents:function(){this._creatingComponents=true},dispose:function(){if(!this._disposing){this._disposing=true;if(this._timerCookie){window.clearTimeout(this._timerCookie);delete this._timerCookie}if(this._endRequestHandler){Sys.WebForms.PageRequestManager.getInstance().remove_endRequest(this._endRequestHandler);delete this._endRequestHandler}if(this._beginRequestHandler){Sys.WebForms.PageRequestManager.getInstance().remove_beginRequest(this._beginRequestHandler);delete this._beginRequestHandler}if(window.pageUnload)window.pageUnload(this,Sys.EventArgs.Empty);var c=this.get_events().getHandler("unload");if(c)c(this,Sys.EventArgs.Empty);var b=Array.clone(this._disposableObjects);for(var a=0,f=b.length;a=0;b--)this._disposeElementInternal(c[b]);if(!d)this._disposeElementInternal(a)}},endCreateComponents:function(){var b=this._secondPassComponents;for(var a=0,d=b.length;a1000){var c=[];for(var d=0,f=b.length;d=0;b--){var c=a[b];if(typeof c.dispose==="function")c.dispose()}},_disposeElementInternal:function(a){var d=a.dispose;if(d&&typeof d==="function")a.dispose();else{var c=a.control;if(c&&typeof c.dispose==="function")c.dispose()}var b=a._behaviors;if(b)this._disposeComponents(b);b=a._components;if(b){this._disposeComponents(b);a._components=null}},_domReady:function(){var a,g,f=this;function b(){f.initialize()}var c=function(){Sys.UI.DomEvent.removeHandler(window,"load",c);b()};Sys.UI.DomEvent.addHandler(window,"load",c);if(document.addEventListener)try{document.addEventListener("DOMContentLoaded",a=function(){document.removeEventListener("DOMContentLoaded",a,false);b()},false)}catch(h){}else if(document.attachEvent)if(window==window.top&&document.documentElement.doScroll){var e,d=document.createElement("div");a=function(){try{d.doScroll("left")}catch(c){e=window.setTimeout(a,0);return}d=null;b()};a()}else document.attachEvent("onreadystatechange",a=function(){if(document.readyState==="complete"){document.detachEvent("onreadystatechange",a);b()}})},_raiseInit:function(){var a=this.get_events().getHandler("init");if(a){this.beginCreateComponents();a(this,Sys.EventArgs.Empty);this.endCreateComponents()}},_unloadHandler:function(){this.dispose()}};Sys._Application.registerClass("Sys._Application",Sys.Component,Sys.IContainer);Sys.Application=new Sys._Application;var $find=Sys.Application.findComponent;Sys.UI.Behavior=function(b){Sys.UI.Behavior.initializeBase(this);this._element=b;var a=b._behaviors;if(!a)b._behaviors=[this];else a[a.length]=this};Sys.UI.Behavior.prototype={_name:null,get_element:function(){return this._element},get_id:function(){var a=Sys.UI.Behavior.callBaseMethod(this,"get_id");if(a)return a;if(!this._element||!this._element.id)return "";return this._element.id+"$"+this.get_name()},get_name:function(){if(this._name)return this._name;var a=Object.getTypeName(this),b=a.lastIndexOf(".");if(b!==-1)a=a.substr(b+1);if(!this.get_isInitialized())this._name=a;return a},set_name:function(a){this._name=a},initialize:function(){Sys.UI.Behavior.callBaseMethod(this,"initialize");var a=this.get_name();if(a)this._element[a]=this},dispose:function(){Sys.UI.Behavior.callBaseMethod(this,"dispose");var a=this._element;if(a){var c=this.get_name();if(c)a[c]=null;var b=a._behaviors;Array.remove(b,this);if(b.length===0)a._behaviors=null;delete this._element}}};Sys.UI.Behavior.registerClass("Sys.UI.Behavior",Sys.Component);Sys.UI.Behavior.getBehaviorByName=function(b,c){var a=b[c];return a&&Sys.UI.Behavior.isInstanceOfType(a)?a:null};Sys.UI.Behavior.getBehaviors=function(a){if(!a._behaviors)return [];return Array.clone(a._behaviors)};Sys.UI.Behavior.getBehaviorsByType=function(d,e){var a=d._behaviors,c=[];if(a)for(var b=0,f=a.length;b0&&a.charAt(0)==="#")a=a.substring(1);return a};Sys._Application.prototype.get_enableHistory=function(){return this._enableHistory};Sys._Application.prototype.set_enableHistory=function(a){this._enableHistory=a};Sys._Application.prototype.add_navigate=function(a){this.get_events().addHandler("navigate",a)};Sys._Application.prototype.remove_navigate=function(a){this.get_events().removeHandler("navigate",a)};Sys._Application.prototype.addHistoryPoint=function(c,f){this._ensureHistory();var b=this._state;for(var a in c){var d=c[a];if(d===null){if(typeof b[a]!=="undefined")delete b[a]}else b[a]=d}var e=this._serializeState(b);this._historyPointIsNew=true;this._setState(e,f);this._raiseNavigate()};Sys._Application.prototype.setServerId=function(a,b){this._clientId=a;this._uniqueId=b};Sys._Application.prototype.setServerState=function(a){this._ensureHistory();this._state.__s=a;this._updateHiddenField(a)};Sys._Application.prototype._deserializeState=function(a){var e={};a=a||"";var b=a.indexOf("&&");if(b!==-1&&b+2'");c.write(""+(b||document.title)+"parent.Sys.Application._onIFrameLoad('+Sys.Serialization.JavaScriptSerializer.serialize(a)+");");c.close()}this._ignoreTimer=false;this._currentEntry=a;if(this._historyFrame||this._historyPointIsNew){var f=this.get_stateString();if(a!==f){window.location.hash=a;this._currentEntry=this.get_stateString();if(typeof b!=="undefined"&&b!==null)document.title=b}}this._historyPointIsNew=false}}};Sys._Application.prototype._updateHiddenField=function(b){if(this._clientId){var a=document.getElementById(this._clientId);if(a)a.value=b}};if(!window.XMLHttpRequest)window.XMLHttpRequest=function(){var b=["Msxml2.XMLHTTP.3.0","Msxml2.XMLHTTP"];for(var a=0,c=b.length;a0)this._timer=window.setTimeout(Function.createDelegate(this,this._onTimeout),d);this._xmlHttpRequest.send(c);this._started=true},getResponseHeader:function(b){var a;try{a=this._xmlHttpRequest.getResponseHeader(b)}catch(c){}if(!a)a="";return a},getAllResponseHeaders:function(){return this._xmlHttpRequest.getAllResponseHeaders()},get_responseData:function(){return this._xmlHttpRequest.responseText},get_statusCode:function(){var a=0;try{a=this._xmlHttpRequest.status}catch(b){}return a},get_statusText:function(){return this._xmlHttpRequest.statusText},get_xml:function(){var a=this._xmlHttpRequest.responseXML;if(!a||!a.documentElement){a=Sys.Net.XMLDOM(this._xmlHttpRequest.responseText);if(!a||!a.documentElement)return null}else if(navigator.userAgent.indexOf("MSIE")!==-1)a.setProperty("SelectionLanguage","XPath");if(a.documentElement.namespaceURI==="http://www.mozilla.org/newlayout/xml/parsererror.xml"&&a.documentElement.tagName==="parsererror")return null;if(a.documentElement.firstChild&&a.documentElement.firstChild.tagName==="parsererror")return null;return a},abort:function(){if(this._aborted||this._responseAvailable||this._timedOut)return;this._aborted=true;this._clearTimer();if(this._xmlHttpRequest&&!this._responseAvailable){this._xmlHttpRequest.onreadystatechange=Function.emptyMethod;this._xmlHttpRequest.abort();this._xmlHttpRequest=null;this._webRequest.completed(Sys.EventArgs.Empty)}}};Sys.Net.XMLHttpExecutor.registerClass("Sys.Net.XMLHttpExecutor",Sys.Net.WebRequestExecutor);Sys.Net._WebRequestManager=function(){this._defaultTimeout=0;this._defaultExecutorType="Sys.Net.XMLHttpExecutor"};Sys.Net._WebRequestManager.prototype={add_invokingRequest:function(a){this._get_eventHandlerList().addHandler("invokingRequest",a)},remove_invokingRequest:function(a){this._get_eventHandlerList().removeHandler("invokingRequest",a)},add_completedRequest:function(a){this._get_eventHandlerList().addHandler("completedRequest",a)},remove_completedRequest:function(a){this._get_eventHandlerList().removeHandler("completedRequest",a)},_get_eventHandlerList:function(){if(!this._events)this._events=new Sys.EventHandlerList;return this._events},get_defaultTimeout:function(){return this._defaultTimeout},set_defaultTimeout:function(a){this._defaultTimeout=a},get_defaultExecutorType:function(){return this._defaultExecutorType},set_defaultExecutorType:function(a){this._defaultExecutorType=a},executeRequest:function(webRequest){var executor=webRequest.get_executor();if(!executor){var failed=false;try{var executorType=eval(this._defaultExecutorType);executor=new executorType}catch(a){failed=true}webRequest.set_executor(executor)}if(executor.get_aborted())return;var evArgs=new Sys.Net.NetworkRequestEventArgs(webRequest),handler=this._get_eventHandlerList().getHandler("invokingRequest");if(handler)handler(this,evArgs);if(!evArgs.get_cancel())executor.executeRequest()}};Sys.Net._WebRequestManager.registerClass("Sys.Net._WebRequestManager");Sys.Net.WebRequestManager=new Sys.Net._WebRequestManager;Sys.Net.NetworkRequestEventArgs=function(a){Sys.Net.NetworkRequestEventArgs.initializeBase(this);this._webRequest=a};Sys.Net.NetworkRequestEventArgs.prototype={get_webRequest:function(){return this._webRequest}};Sys.Net.NetworkRequestEventArgs.registerClass("Sys.Net.NetworkRequestEventArgs",Sys.CancelEventArgs);Sys.Net.WebRequest=function(){this._url="";this._headers={};this._body=null;this._userContext=null;this._httpVerb=null;this._executor=null;this._invokeCalled=false;this._timeout=0};Sys.Net.WebRequest.prototype={add_completed:function(a){this._get_eventHandlerList().addHandler("completed",a)},remove_completed:function(a){this._get_eventHandlerList().removeHandler("completed",a)},completed:function(b){var a=Sys.Net.WebRequestManager._get_eventHandlerList().getHandler("completedRequest");if(a)a(this._executor,b);a=this._get_eventHandlerList().getHandler("completed");if(a)a(this._executor,b)},_get_eventHandlerList:function(){if(!this._events)this._events=new Sys.EventHandlerList;return this._events},get_url:function(){return this._url},set_url:function(a){this._url=a},get_headers:function(){return this._headers},get_httpVerb:function(){if(this._httpVerb===null){if(this._body===null)return "GET";return "POST"}return this._httpVerb},set_httpVerb:function(a){this._httpVerb=a},get_body:function(){return this._body},set_body:function(a){this._body=a},get_userContext:function(){return this._userContext},set_userContext:function(a){this._userContext=a},get_executor:function(){return this._executor},set_executor:function(a){this._executor=a;this._executor._set_webRequest(this)},get_timeout:function(){if(this._timeout===0)return Sys.Net.WebRequestManager.get_defaultTimeout();return this._timeout},set_timeout:function(a){this._timeout=a},getResolvedUrl:function(){return Sys.Net.WebRequest._resolveUrl(this._url)},invoke:function(){Sys.Net.WebRequestManager.executeRequest(this);this._invokeCalled=true}};Sys.Net.WebRequest._resolveUrl=function(b,a){if(b&&b.indexOf("://")!==-1)return b;if(!a||a.length===0){var d=document.getElementsByTagName("base")[0];if(d&&d.href&&d.href.length>0)a=d.href;else a=document.URL}var c=a.indexOf("?");if(c!==-1)a=a.substr(0,c);c=a.indexOf("#");if(c!==-1)a=a.substr(0,c);a=a.substr(0,a.lastIndexOf("/")+1);if(!b||b.length===0)return a;if(b.charAt(0)==="/"){var e=a.indexOf("://"),g=a.indexOf("/",e+3);return a.substr(0,g)+b}else{var f=a.lastIndexOf("/");return a.substr(0,f+1)+b}};Sys.Net.WebRequest._createQueryString=function(c,b,f){b=b||encodeURIComponent;var h=0,e,g,d,a=new Sys.StringBuilder;if(c)for(d in c){e=c[d];if(typeof e==="function")continue;g=Sys.Serialization.JavaScriptSerializer.serialize(e);if(h++)a.append("&");a.append(d);a.append("=");a.append(b(g))}if(f){if(h)a.append("&");a.append(f)}return a.toString()};Sys.Net.WebRequest._createUrl=function(a,b,c){if(!b&&!c)return a;var d=Sys.Net.WebRequest._createQueryString(b,null,c);return d.length?a+(a&&a.indexOf("?")>=0?"&":"?")+d:a};Sys.Net.WebRequest.registerClass("Sys.Net.WebRequest");Sys._ScriptLoaderTask=function(b,a){this._scriptElement=b;this._completedCallback=a};Sys._ScriptLoaderTask.prototype={get_scriptElement:function(){return this._scriptElement},dispose:function(){if(this._disposed)return;this._disposed=true;this._removeScriptElementHandlers();Sys._ScriptLoaderTask._clearScript(this._scriptElement);this._scriptElement=null},execute:function(){this._addScriptElementHandlers();document.getElementsByTagName("head")[0].appendChild(this._scriptElement)},_addScriptElementHandlers:function(){this._scriptLoadDelegate=Function.createDelegate(this,this._scriptLoadHandler);if(Sys.Browser.agent!==Sys.Browser.InternetExplorer){this._scriptElement.readyState="loaded";$addHandler(this._scriptElement,"load",this._scriptLoadDelegate)}else $addHandler(this._scriptElement,"readystatechange",this._scriptLoadDelegate);if(this._scriptElement.addEventListener){this._scriptErrorDelegate=Function.createDelegate(this,this._scriptErrorHandler);this._scriptElement.addEventListener("error",this._scriptErrorDelegate,false)}},_removeScriptElementHandlers:function(){if(this._scriptLoadDelegate){var a=this.get_scriptElement();if(Sys.Browser.agent!==Sys.Browser.InternetExplorer)$removeHandler(a,"load",this._scriptLoadDelegate);else $removeHandler(a,"readystatechange",this._scriptLoadDelegate);if(this._scriptErrorDelegate){this._scriptElement.removeEventListener("error",this._scriptErrorDelegate,false);this._scriptErrorDelegate=null}this._scriptLoadDelegate=null}},_scriptErrorHandler:function(){if(this._disposed)return;this._completedCallback(this.get_scriptElement(),false)},_scriptLoadHandler:function(){if(this._disposed)return;var a=this.get_scriptElement();if(a.readyState!=="loaded"&&a.readyState!=="complete")return;this._completedCallback(a,true)}};Sys._ScriptLoaderTask.registerClass("Sys._ScriptLoaderTask",null,Sys.IDisposable);Sys._ScriptLoaderTask._clearScript=function(a){if(!Sys.Debug.isDebug)a.parentNode.removeChild(a)};Type.registerNamespace("Sys.Net");Sys.Net.WebServiceProxy=function(){};Sys.Net.WebServiceProxy.prototype={get_timeout:function(){return this._timeout||0},set_timeout:function(a){if(a<0)throw Error.argumentOutOfRange("value",a,Sys.Res.invalidTimeout);this._timeout=a},get_defaultUserContext:function(){return typeof this._userContext==="undefined"?null:this._userContext},set_defaultUserContext:function(a){this._userContext=a},get_defaultSucceededCallback:function(){return this._succeeded||null},set_defaultSucceededCallback:function(a){this._succeeded=a},get_defaultFailedCallback:function(){return this._failed||null},set_defaultFailedCallback:function(a){this._failed=a},get_enableJsonp:function(){return !!this._jsonp},set_enableJsonp:function(a){this._jsonp=a},get_path:function(){return this._path||null},set_path:function(a){this._path=a},get_jsonpCallbackParameter:function(){return this._callbackParameter||"callback"},set_jsonpCallbackParameter:function(a){this._callbackParameter=a},_invoke:function(d,e,g,f,c,b,a){c=c||this.get_defaultSucceededCallback();b=b||this.get_defaultFailedCallback();if(a===null||typeof a==="undefined")a=this.get_defaultUserContext();return Sys.Net.WebServiceProxy.invoke(d,e,g,f,c,b,a,this.get_timeout(),this.get_enableJsonp(),this.get_jsonpCallbackParameter())}};Sys.Net.WebServiceProxy.registerClass("Sys.Net.WebServiceProxy");Sys.Net.WebServiceProxy.invoke=function(q,a,m,l,j,b,g,e,w,p){var i=w!==false?Sys.Net.WebServiceProxy._xdomain.exec(q):null,c,n=i&&i.length===3&&(i[1]!==location.protocol||i[2]!==location.host);m=n||m;if(n){p=p||"callback";c="_jsonp"+Sys._jsonp++}if(!l)l={};var r=l;if(!m||!r)r={};var s,h,f=null,k,o=null,u=Sys.Net.WebRequest._createUrl(a?q+"/"+encodeURIComponent(a):q,r,n?p+"=Sys."+c:null);if(n){s=document.createElement("script");s.src=u;k=new Sys._ScriptLoaderTask(s,function(d,b){if(!b||c)t({Message:String.format(Sys.Res.webServiceFailedNoMsg,a)},-1)});function v(){if(f===null)return;f=null;h=new Sys.Net.WebServiceError(true,String.format(Sys.Res.webServiceTimedOut,a));k.dispose();delete Sys[c];if(b)b(h,g,a)}function t(d,e){if(f!==null){window.clearTimeout(f);f=null}k.dispose();delete Sys[c];c=null;if(typeof e!=="undefined"&&e!==200){if(b){h=new Sys.Net.WebServiceError(false,d.Message||String.format(Sys.Res.webServiceFailedNoMsg,a),d.StackTrace||null,d.ExceptionType||null,d);h._statusCode=e;b(h,g,a)}}else if(j)j(d,g,a)}Sys[c]=t;e=e||Sys.Net.WebRequestManager.get_defaultTimeout();if(e>0)f=window.setTimeout(v,e);k.execute();return null}var d=new Sys.Net.WebRequest;d.set_url(u);d.get_headers()["Content-Type"]="application/json; charset=utf-8";if(!m){o=Sys.Serialization.JavaScriptSerializer.serialize(l);if(o==="{}")o=""}d.set_body(o);d.add_completed(x);if(e&&e>0)d.set_timeout(e);d.invoke();function x(d){if(d.get_responseAvailable()){var f=d.get_statusCode(),c=null;try{var e=d.getResponseHeader("Content-Type");if(e.startsWith("application/json"))c=d.get_object();else if(e.startsWith("text/xml"))c=d.get_xml();else c=d.get_responseData()}catch(m){}var k=d.getResponseHeader("jsonerror"),h=k==="true";if(h){if(c)c=new Sys.Net.WebServiceError(false,c.Message,c.StackTrace,c.ExceptionType,c)}else if(e.startsWith("application/json"))c=!c||typeof c.d==="undefined"?c:c.d;if(f<200||f>=300||h){if(b){if(!c||!h)c=new Sys.Net.WebServiceError(false,String.format(Sys.Res.webServiceFailedNoMsg,a));c._statusCode=f;b(c,g,a)}}else if(j)j(c,g,a)}else{var i;if(d.get_timedOut())i=String.format(Sys.Res.webServiceTimedOut,a);else i=String.format(Sys.Res.webServiceFailedNoMsg,a);if(b)b(new Sys.Net.WebServiceError(d.get_timedOut(),i,"",""),g,a)}}return d};Sys.Net.WebServiceProxy._generateTypedConstructor=function(a){return function(b){if(b)for(var c in b)this[c]=b[c];this.__type=a}};Sys._jsonp=0;Sys.Net.WebServiceProxy._xdomain=/^\s*([a-zA-Z0-9\+\-\.]+\:)\/\/([^?#\/]+)/;Sys.Net.WebServiceError=function(d,e,c,a,b){this._timedOut=d;this._message=e;this._stackTrace=c;this._exceptionType=a;this._errorObject=b;this._statusCode=-1};Sys.Net.WebServiceError.prototype={get_timedOut:function(){return this._timedOut},get_statusCode:function(){return this._statusCode},get_message:function(){return this._message},get_stackTrace:function(){return this._stackTrace||""},get_exceptionType:function(){return this._exceptionType||""},get_errorObject:function(){return this._errorObject||null}};Sys.Net.WebServiceError.registerClass("Sys.Net.WebServiceError"); +Type.registerNamespace('Sys');Sys.Res={'argumentInteger':'Value must be an integer.','invokeCalledTwice':'Cannot call invoke more than once.','webServiceFailed':'The server method \'{0}\' failed with the following error: {1}','argumentType':'Object cannot be converted to the required type.','argumentNull':'Value cannot be null.','scriptAlreadyLoaded':'The script \'{0}\' has been referenced multiple times. If referencing Microsoft AJAX scripts explicitly, set the MicrosoftAjaxMode property of the ScriptManager to Explicit.','scriptDependencyNotFound':'The script \'{0}\' failed to load because it is dependent on script \'{1}\'.','formatBadFormatSpecifier':'Format specifier was invalid.','requiredScriptReferenceNotIncluded':'\'{0}\' requires that you have included a script reference to \'{1}\'.','webServiceFailedNoMsg':'The server method \'{0}\' failed.','argumentDomElement':'Value must be a DOM element.','invalidExecutorType':'Could not create a valid Sys.Net.WebRequestExecutor from: {0}.','cannotCallBeforeResponse':'Cannot call {0} when responseAvailable is false.','actualValue':'Actual value was {0}.','enumInvalidValue':'\'{0}\' is not a valid value for enum {1}.','scriptLoadFailed':'The script \'{0}\' could not be loaded.','parameterCount':'Parameter count mismatch.','cannotDeserializeEmptyString':'Cannot deserialize empty string.','formatInvalidString':'Input string was not in a correct format.','invalidTimeout':'Value must be greater than or equal to zero.','cannotAbortBeforeStart':'Cannot abort when executor has not started.','argument':'Value does not fall within the expected range.','cannotDeserializeInvalidJson':'Cannot deserialize. The data does not correspond to valid JSON.','invalidHttpVerb':'httpVerb cannot be set to an empty or null string.','nullWebRequest':'Cannot call executeRequest with a null webRequest.','eventHandlerInvalid':'Handler was not added through the Sys.UI.DomEvent.addHandler method.','cannotSerializeNonFiniteNumbers':'Cannot serialize non finite numbers.','argumentUndefined':'Value cannot be undefined.','webServiceInvalidReturnType':'The server method \'{0}\' returned an invalid type. Expected type: {1}','servicePathNotSet':'The path to the web service has not been set.','argumentTypeWithTypes':'Object of type \'{0}\' cannot be converted to type \'{1}\'.','cannotCallOnceStarted':'Cannot call {0} once started.','badBaseUrl1':'Base URL does not contain ://.','badBaseUrl2':'Base URL does not contain another /.','badBaseUrl3':'Cannot find last / in base URL.','setExecutorAfterActive':'Cannot set executor after it has become active.','paramName':'Parameter name: {0}','nullReferenceInPath':'Null reference while evaluating data path: \'{0}\'.','cannotCallOutsideHandler':'Cannot call {0} outside of a completed event handler.','cannotSerializeObjectWithCycle':'Cannot serialize object with cyclic reference within child properties.','format':'One of the identified items was in an invalid format.','assertFailedCaller':'Assertion Failed: {0}\r\nat {1}','argumentOutOfRange':'Specified argument was out of the range of valid values.','webServiceTimedOut':'The server method \'{0}\' timed out.','notImplemented':'The method or operation is not implemented.','assertFailed':'Assertion Failed: {0}','invalidOperation':'Operation is not valid due to the current state of the object.','breakIntoDebugger':'{0}\r\n\r\nBreak into debugger?'}; diff --git a/OnPremise/WebSite/Scripts/MicrosoftMvcAjax.debug.js b/OnPremise/WebSite/Scripts/MicrosoftMvcAjax.debug.js new file mode 100644 index 0000000..eb68ba7 --- /dev/null +++ b/OnPremise/WebSite/Scripts/MicrosoftMvcAjax.debug.js @@ -0,0 +1,408 @@ +//!---------------------------------------------------------- +//! Copyright (C) Microsoft Corporation. All rights reserved. +//!---------------------------------------------------------- +//! MicrosoftMvcAjax.js + +Type.registerNamespace('Sys.Mvc'); + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.AjaxOptions + +Sys.Mvc.$create_AjaxOptions = function Sys_Mvc_AjaxOptions() { return {}; } + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.InsertionMode + +Sys.Mvc.InsertionMode = function() { + /// + /// + /// + /// + /// + /// +}; +Sys.Mvc.InsertionMode.prototype = { + replace: 0, + insertBefore: 1, + insertAfter: 2 +} +Sys.Mvc.InsertionMode.registerEnum('Sys.Mvc.InsertionMode', false); + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.AjaxContext + +Sys.Mvc.AjaxContext = function Sys_Mvc_AjaxContext(request, updateTarget, loadingElement, insertionMode) { + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + this._request = request; + this._updateTarget = updateTarget; + this._loadingElement = loadingElement; + this._insertionMode = insertionMode; +} +Sys.Mvc.AjaxContext.prototype = { + _insertionMode: 0, + _loadingElement: null, + _response: null, + _request: null, + _updateTarget: null, + + get_data: function Sys_Mvc_AjaxContext$get_data() { + /// + if (this._response) { + return this._response.get_responseData(); + } + else { + return null; + } + }, + + get_insertionMode: function Sys_Mvc_AjaxContext$get_insertionMode() { + /// + return this._insertionMode; + }, + + get_loadingElement: function Sys_Mvc_AjaxContext$get_loadingElement() { + /// + return this._loadingElement; + }, + + get_object: function Sys_Mvc_AjaxContext$get_object() { + /// + var executor = this.get_response(); + return (executor) ? executor.get_object() : null; + }, + + get_response: function Sys_Mvc_AjaxContext$get_response() { + /// + return this._response; + }, + set_response: function Sys_Mvc_AjaxContext$set_response(value) { + /// + this._response = value; + return value; + }, + + get_request: function Sys_Mvc_AjaxContext$get_request() { + /// + return this._request; + }, + + get_updateTarget: function Sys_Mvc_AjaxContext$get_updateTarget() { + /// + return this._updateTarget; + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.AsyncHyperlink + +Sys.Mvc.AsyncHyperlink = function Sys_Mvc_AsyncHyperlink() { +} +Sys.Mvc.AsyncHyperlink.handleClick = function Sys_Mvc_AsyncHyperlink$handleClick(anchor, evt, ajaxOptions) { + /// + /// + /// + /// + /// + /// + evt.preventDefault(); + Sys.Mvc.MvcHelpers._asyncRequest(anchor.href, 'post', '', anchor, ajaxOptions); +} + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.MvcHelpers + +Sys.Mvc.MvcHelpers = function Sys_Mvc_MvcHelpers() { +} +Sys.Mvc.MvcHelpers._serializeSubmitButton = function Sys_Mvc_MvcHelpers$_serializeSubmitButton(element, offsetX, offsetY) { + /// + /// + /// + /// + /// + /// + /// + if (element.disabled) { + return null; + } + var name = element.name; + if (name) { + var tagName = element.tagName.toUpperCase(); + var encodedName = encodeURIComponent(name); + var inputElement = element; + if (tagName === 'INPUT') { + var type = inputElement.type; + if (type === 'submit') { + return encodedName + '=' + encodeURIComponent(inputElement.value); + } + else if (type === 'image') { + return encodedName + '.x=' + offsetX + '&' + encodedName + '.y=' + offsetY; + } + } + else if ((tagName === 'BUTTON') && (name.length) && (inputElement.type === 'submit')) { + return encodedName + '=' + encodeURIComponent(inputElement.value); + } + } + return null; +} +Sys.Mvc.MvcHelpers._serializeForm = function Sys_Mvc_MvcHelpers$_serializeForm(form) { + /// + /// + /// + var formElements = form.elements; + var formBody = new Sys.StringBuilder(); + var count = formElements.length; + for (var i = 0; i < count; i++) { + var element = formElements[i]; + var name = element.name; + if (!name || !name.length) { + continue; + } + var tagName = element.tagName.toUpperCase(); + if (tagName === 'INPUT') { + var inputElement = element; + var type = inputElement.type; + if ((type === 'text') || (type === 'password') || (type === 'hidden') || (((type === 'checkbox') || (type === 'radio')) && element.checked)) { + formBody.append(encodeURIComponent(name)); + formBody.append('='); + formBody.append(encodeURIComponent(inputElement.value)); + formBody.append('&'); + } + } + else if (tagName === 'SELECT') { + var selectElement = element; + var optionCount = selectElement.options.length; + for (var j = 0; j < optionCount; j++) { + var optionElement = selectElement.options[j]; + if (optionElement.selected) { + formBody.append(encodeURIComponent(name)); + formBody.append('='); + formBody.append(encodeURIComponent(optionElement.value)); + formBody.append('&'); + } + } + } + else if (tagName === 'TEXTAREA') { + formBody.append(encodeURIComponent(name)); + formBody.append('='); + formBody.append(encodeURIComponent((element.value))); + formBody.append('&'); + } + } + var additionalInput = form._additionalInput; + if (additionalInput) { + formBody.append(additionalInput); + formBody.append('&'); + } + return formBody.toString(); +} +Sys.Mvc.MvcHelpers._asyncRequest = function Sys_Mvc_MvcHelpers$_asyncRequest(url, verb, body, triggerElement, ajaxOptions) { + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + if (ajaxOptions.confirm) { + if (!confirm(ajaxOptions.confirm)) { + return; + } + } + if (ajaxOptions.url) { + url = ajaxOptions.url; + } + if (ajaxOptions.httpMethod) { + verb = ajaxOptions.httpMethod; + } + if (body.length > 0 && !body.endsWith('&')) { + body += '&'; + } + body += 'X-Requested-With=XMLHttpRequest'; + var upperCaseVerb = verb.toUpperCase(); + var isGetOrPost = (upperCaseVerb === 'GET' || upperCaseVerb === 'POST'); + if (!isGetOrPost) { + body += '&'; + body += 'X-HTTP-Method-Override=' + upperCaseVerb; + } + var requestBody = ''; + if (upperCaseVerb === 'GET' || upperCaseVerb === 'DELETE') { + if (url.indexOf('?') > -1) { + if (!url.endsWith('&')) { + url += '&'; + } + url += body; + } + else { + url += '?'; + url += body; + } + } + else { + requestBody = body; + } + var request = new Sys.Net.WebRequest(); + request.set_url(url); + if (isGetOrPost) { + request.set_httpVerb(verb); + } + else { + request.set_httpVerb('POST'); + request.get_headers()['X-HTTP-Method-Override'] = upperCaseVerb; + } + request.set_body(requestBody); + if (verb.toUpperCase() === 'PUT') { + request.get_headers()['Content-Type'] = 'application/x-www-form-urlencoded;'; + } + request.get_headers()['X-Requested-With'] = 'XMLHttpRequest'; + var updateElement = null; + if (ajaxOptions.updateTargetId) { + updateElement = $get(ajaxOptions.updateTargetId); + } + var loadingElement = null; + if (ajaxOptions.loadingElementId) { + loadingElement = $get(ajaxOptions.loadingElementId); + } + var ajaxContext = new Sys.Mvc.AjaxContext(request, updateElement, loadingElement, ajaxOptions.insertionMode); + var continueRequest = true; + if (ajaxOptions.onBegin) { + continueRequest = ajaxOptions.onBegin(ajaxContext) !== false; + } + if (loadingElement) { + Sys.UI.DomElement.setVisible(ajaxContext.get_loadingElement(), true); + } + if (continueRequest) { + request.add_completed(Function.createDelegate(null, function(executor) { + Sys.Mvc.MvcHelpers._onComplete(request, ajaxOptions, ajaxContext); + })); + request.invoke(); + } +} +Sys.Mvc.MvcHelpers._onComplete = function Sys_Mvc_MvcHelpers$_onComplete(request, ajaxOptions, ajaxContext) { + /// + /// + /// + /// + /// + /// + ajaxContext.set_response(request.get_executor()); + if (ajaxOptions.onComplete && ajaxOptions.onComplete(ajaxContext) === false) { + return; + } + var statusCode = ajaxContext.get_response().get_statusCode(); + if ((statusCode >= 200 && statusCode < 300) || statusCode === 304 || statusCode === 1223) { + if (statusCode !== 204 && statusCode !== 304 && statusCode !== 1223) { + var contentType = ajaxContext.get_response().getResponseHeader('Content-Type'); + if ((contentType) && (contentType.indexOf('application/x-javascript') !== -1)) { + eval(ajaxContext.get_data()); + } + else { + Sys.Mvc.MvcHelpers.updateDomElement(ajaxContext.get_updateTarget(), ajaxContext.get_insertionMode(), ajaxContext.get_data()); + } + } + if (ajaxOptions.onSuccess) { + ajaxOptions.onSuccess(ajaxContext); + } + } + else { + if (ajaxOptions.onFailure) { + ajaxOptions.onFailure(ajaxContext); + } + } + if (ajaxContext.get_loadingElement()) { + Sys.UI.DomElement.setVisible(ajaxContext.get_loadingElement(), false); + } +} +Sys.Mvc.MvcHelpers.updateDomElement = function Sys_Mvc_MvcHelpers$updateDomElement(target, insertionMode, content) { + /// + /// + /// + /// + /// + /// + if (target) { + switch (insertionMode) { + case Sys.Mvc.InsertionMode.replace: + target.innerHTML = content; + break; + case Sys.Mvc.InsertionMode.insertBefore: + if (content && content.length > 0) { + target.innerHTML = content + target.innerHTML.trimStart(); + } + break; + case Sys.Mvc.InsertionMode.insertAfter: + if (content && content.length > 0) { + target.innerHTML = target.innerHTML.trimEnd() + content; + } + break; + } + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.AsyncForm + +Sys.Mvc.AsyncForm = function Sys_Mvc_AsyncForm() { +} +Sys.Mvc.AsyncForm.handleClick = function Sys_Mvc_AsyncForm$handleClick(form, evt) { + /// + /// + /// + /// + var additionalInput = Sys.Mvc.MvcHelpers._serializeSubmitButton(evt.target, evt.offsetX, evt.offsetY); + form._additionalInput = additionalInput; +} +Sys.Mvc.AsyncForm.handleSubmit = function Sys_Mvc_AsyncForm$handleSubmit(form, evt, ajaxOptions) { + /// + /// + /// + /// + /// + /// + evt.preventDefault(); + var validationCallbacks = form.validationCallbacks; + if (validationCallbacks) { + for (var i = 0; i < validationCallbacks.length; i++) { + var callback = validationCallbacks[i]; + if (!callback()) { + return; + } + } + } + var body = Sys.Mvc.MvcHelpers._serializeForm(form); + Sys.Mvc.MvcHelpers._asyncRequest(form.action, form.method || 'post', body, form, ajaxOptions); +} + + +Sys.Mvc.AjaxContext.registerClass('Sys.Mvc.AjaxContext'); +Sys.Mvc.AsyncHyperlink.registerClass('Sys.Mvc.AsyncHyperlink'); +Sys.Mvc.MvcHelpers.registerClass('Sys.Mvc.MvcHelpers'); +Sys.Mvc.AsyncForm.registerClass('Sys.Mvc.AsyncForm'); + +// ---- Do not remove this footer ---- +// Generated using Script# v0.5.0.0 (http://projects.nikhilk.net) +// ----------------------------------- diff --git a/OnPremise/WebSite/Scripts/MicrosoftMvcAjax.js b/OnPremise/WebSite/Scripts/MicrosoftMvcAjax.js new file mode 100644 index 0000000..c5a6165 --- /dev/null +++ b/OnPremise/WebSite/Scripts/MicrosoftMvcAjax.js @@ -0,0 +1,25 @@ +//---------------------------------------------------------- +// Copyright (C) Microsoft Corporation. All rights reserved. +//---------------------------------------------------------- +// MicrosoftMvcAjax.js + +Type.registerNamespace('Sys.Mvc');Sys.Mvc.$create_AjaxOptions=function(){return {};} +Sys.Mvc.InsertionMode=function(){};Sys.Mvc.InsertionMode.prototype = {replace:0,insertBefore:1,insertAfter:2} +Sys.Mvc.InsertionMode.registerEnum('Sys.Mvc.InsertionMode',false);Sys.Mvc.AjaxContext=function(request,updateTarget,loadingElement,insertionMode){this.$3=request;this.$4=updateTarget;this.$1=loadingElement;this.$0=insertionMode;} +Sys.Mvc.AjaxContext.prototype={$0:0,$1:null,$2:null,$3:null,$4:null,get_data:function(){if(this.$2){return this.$2.get_responseData();}else{return null;}},get_insertionMode:function(){return this.$0;},get_loadingElement:function(){return this.$1;},get_object:function(){var $0=this.get_response();return ($0)?$0.get_object():null;},get_response:function(){return this.$2;},set_response:function(value){this.$2=value;return value;},get_request:function(){return this.$3;},get_updateTarget:function(){return this.$4;}} +Sys.Mvc.AsyncHyperlink=function(){} +Sys.Mvc.AsyncHyperlink.handleClick=function(anchor,evt,ajaxOptions){evt.preventDefault();Sys.Mvc.MvcHelpers.$2(anchor.href,'post','',anchor,ajaxOptions);} +Sys.Mvc.MvcHelpers=function(){} +Sys.Mvc.MvcHelpers.$0=function($p0,$p1,$p2){if($p0.disabled){return null;}var $0=$p0.name;if($0){var $1=$p0.tagName.toUpperCase();var $2=encodeURIComponent($0);var $3=$p0;if($1==='INPUT'){var $4=$3.type;if($4==='submit'){return $2+'='+encodeURIComponent($3.value);}else if($4==='image'){return $2+'.x='+$p1+'&'+$2+'.y='+$p2;}}else if(($1==='BUTTON')&&($0.length)&&($3.type==='submit')){return $2+'='+encodeURIComponent($3.value);}}return null;} +Sys.Mvc.MvcHelpers.$1=function($p0){var $0=$p0.elements;var $1=new Sys.StringBuilder();var $2=$0.length;for(var $4=0;$4<$2;$4++){var $5=$0[$4];var $6=$5.name;if(!$6||!$6.length){continue;}var $7=$5.tagName.toUpperCase();if($7==='INPUT'){var $8=$5;var $9=$8.type;if(($9==='text')||($9==='password')||($9==='hidden')||((($9==='checkbox')||($9==='radio'))&&$5.checked)){$1.append(encodeURIComponent($6));$1.append('=');$1.append(encodeURIComponent($8.value));$1.append('&');}}else if($7==='SELECT'){var $A=$5;var $B=$A.options.length;for(var $C=0;$C<$B;$C++){var $D=$A.options[$C];if($D.selected){$1.append(encodeURIComponent($6));$1.append('=');$1.append(encodeURIComponent($D.value));$1.append('&');}}}else if($7==='TEXTAREA'){$1.append(encodeURIComponent($6));$1.append('=');$1.append(encodeURIComponent(($5.value)));$1.append('&');}}var $3=$p0._additionalInput;if($3){$1.append($3);$1.append('&');}return $1.toString();} +Sys.Mvc.MvcHelpers.$2=function($p0,$p1,$p2,$p3,$p4){if($p4.confirm){if(!confirm($p4.confirm)){return;}}if($p4.url){$p0=$p4.url;}if($p4.httpMethod){$p1=$p4.httpMethod;}if($p2.length>0&&!$p2.endsWith('&')){$p2+='&';}$p2+='X-Requested-With=XMLHttpRequest';var $0=$p1.toUpperCase();var $1=($0==='GET'||$0==='POST');if(!$1){$p2+='&';$p2+='X-HTTP-Method-Override='+$0;}var $2='';if($0==='GET'||$0==='DELETE'){if($p0.indexOf('?')>-1){if(!$p0.endsWith('&')){$p0+='&';}$p0+=$p2;}else{$p0+='?';$p0+=$p2;}}else{$2=$p2;}var $3=new Sys.Net.WebRequest();$3.set_url($p0);if($1){$3.set_httpVerb($p1);}else{$3.set_httpVerb('POST');$3.get_headers()['X-HTTP-Method-Override']=$0;}$3.set_body($2);if($p1.toUpperCase()==='PUT'){$3.get_headers()['Content-Type']='application/x-www-form-urlencoded;';}$3.get_headers()['X-Requested-With']='XMLHttpRequest';var $4=null;if($p4.updateTargetId){$4=$get($p4.updateTargetId);}var $5=null;if($p4.loadingElementId){$5=$get($p4.loadingElementId);}var $6=new Sys.Mvc.AjaxContext($3,$4,$5,$p4.insertionMode);var $7=true;if($p4.onBegin){$7=$p4.onBegin($6)!==false;}if($5){Sys.UI.DomElement.setVisible($6.get_loadingElement(),true);}if($7){$3.add_completed(Function.createDelegate(null,function($p1_0){ +Sys.Mvc.MvcHelpers.$3($3,$p4,$6);}));$3.invoke();}} +Sys.Mvc.MvcHelpers.$3=function($p0,$p1,$p2){$p2.set_response($p0.get_executor());if($p1.onComplete&&$p1.onComplete($p2)===false){return;}var $0=$p2.get_response().get_statusCode();if(($0>=200&&$0<300)||$0===304||$0===1223){if($0!==204&&$0!==304&&$0!==1223){var $1=$p2.get_response().getResponseHeader('Content-Type');if(($1)&&($1.indexOf('application/x-javascript')!==-1)){eval($p2.get_data());}else{Sys.Mvc.MvcHelpers.updateDomElement($p2.get_updateTarget(),$p2.get_insertionMode(),$p2.get_data());}}if($p1.onSuccess){$p1.onSuccess($p2);}}else{if($p1.onFailure){$p1.onFailure($p2);}}if($p2.get_loadingElement()){Sys.UI.DomElement.setVisible($p2.get_loadingElement(),false);}} +Sys.Mvc.MvcHelpers.updateDomElement=function(target,insertionMode,content){if(target){switch(insertionMode){case 0:target.innerHTML=content;break;case 1:if(content&&content.length>0){target.innerHTML=content+target.innerHTML.trimStart();}break;case 2:if(content&&content.length>0){target.innerHTML=target.innerHTML.trimEnd()+content;}break;}}} +Sys.Mvc.AsyncForm=function(){} +Sys.Mvc.AsyncForm.handleClick=function(form,evt){var $0=Sys.Mvc.MvcHelpers.$0(evt.target,evt.offsetX,evt.offsetY);form._additionalInput = $0;} +Sys.Mvc.AsyncForm.handleSubmit=function(form,evt,ajaxOptions){evt.preventDefault();var $0=form.validationCallbacks;if($0){for(var $2=0;$2<$0.length;$2++){var $3=$0[$2];if(!$3()){return;}}}var $1=Sys.Mvc.MvcHelpers.$1(form);Sys.Mvc.MvcHelpers.$2(form.action,form.method||'post',$1,form,ajaxOptions);} +Sys.Mvc.AjaxContext.registerClass('Sys.Mvc.AjaxContext');Sys.Mvc.AsyncHyperlink.registerClass('Sys.Mvc.AsyncHyperlink');Sys.Mvc.MvcHelpers.registerClass('Sys.Mvc.MvcHelpers');Sys.Mvc.AsyncForm.registerClass('Sys.Mvc.AsyncForm'); +// ---- Do not remove this footer ---- +// Generated using Script# v0.5.0.0 (http://projects.nikhilk.net) +// ----------------------------------- diff --git a/OnPremise/WebSite/Scripts/MicrosoftMvcValidation.debug.js b/OnPremise/WebSite/Scripts/MicrosoftMvcValidation.debug.js new file mode 100644 index 0000000..346ba48 --- /dev/null +++ b/OnPremise/WebSite/Scripts/MicrosoftMvcValidation.debug.js @@ -0,0 +1,883 @@ +//!---------------------------------------------------------- +//! Copyright (C) Microsoft Corporation. All rights reserved. +//!---------------------------------------------------------- +//! MicrosoftMvcValidation.js + + +Type.registerNamespace('Sys.Mvc'); + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.Validation + +Sys.Mvc.$create_Validation = function Sys_Mvc_Validation() { return {}; } + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.JsonValidationField + +Sys.Mvc.$create_JsonValidationField = function Sys_Mvc_JsonValidationField() { return {}; } + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.JsonValidationOptions + +Sys.Mvc.$create_JsonValidationOptions = function Sys_Mvc_JsonValidationOptions() { return {}; } + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.JsonValidationRule + +Sys.Mvc.$create_JsonValidationRule = function Sys_Mvc_JsonValidationRule() { return {}; } + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.ValidationContext + +Sys.Mvc.$create_ValidationContext = function Sys_Mvc_ValidationContext() { return {}; } + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.NumberValidator + +Sys.Mvc.NumberValidator = function Sys_Mvc_NumberValidator() { +} +Sys.Mvc.NumberValidator.create = function Sys_Mvc_NumberValidator$create(rule) { + /// + /// + /// + return Function.createDelegate(new Sys.Mvc.NumberValidator(), new Sys.Mvc.NumberValidator().validate); +} +Sys.Mvc.NumberValidator.prototype = { + + validate: function Sys_Mvc_NumberValidator$validate(value, context) { + /// + /// + /// + /// + /// + if (Sys.Mvc._validationUtil.stringIsNullOrEmpty(value)) { + return true; + } + var n = Number.parseLocale(value); + return (!isNaN(n)); + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.FormContext + +Sys.Mvc.FormContext = function Sys_Mvc_FormContext(formElement, validationSummaryElement) { + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + this._errors = []; + this.fields = new Array(0); + this._formElement = formElement; + this._validationSummaryElement = validationSummaryElement; + formElement[Sys.Mvc.FormContext._formValidationTag] = this; + if (validationSummaryElement) { + var ulElements = validationSummaryElement.getElementsByTagName('ul'); + if (ulElements.length > 0) { + this._validationSummaryULElement = ulElements[0]; + } + } + this._onClickHandler = Function.createDelegate(this, this._form_OnClick); + this._onSubmitHandler = Function.createDelegate(this, this._form_OnSubmit); +} +Sys.Mvc.FormContext._Application_Load = function Sys_Mvc_FormContext$_Application_Load() { + var allFormOptions = window.mvcClientValidationMetadata; + if (allFormOptions) { + while (allFormOptions.length > 0) { + var thisFormOptions = allFormOptions.pop(); + Sys.Mvc.FormContext._parseJsonOptions(thisFormOptions); + } + } +} +Sys.Mvc.FormContext._getFormElementsWithName = function Sys_Mvc_FormContext$_getFormElementsWithName(formElement, name) { + /// + /// + /// + /// + /// + var allElementsWithNameInForm = []; + var allElementsWithName = document.getElementsByName(name); + for (var i = 0; i < allElementsWithName.length; i++) { + var thisElement = allElementsWithName[i]; + if (Sys.Mvc.FormContext._isElementInHierarchy(formElement, thisElement)) { + Array.add(allElementsWithNameInForm, thisElement); + } + } + return allElementsWithNameInForm; +} +Sys.Mvc.FormContext.getValidationForForm = function Sys_Mvc_FormContext$getValidationForForm(formElement) { + /// + /// + /// + return formElement[Sys.Mvc.FormContext._formValidationTag]; +} +Sys.Mvc.FormContext._isElementInHierarchy = function Sys_Mvc_FormContext$_isElementInHierarchy(parent, child) { + /// + /// + /// + /// + /// + while (child) { + if (parent === child) { + return true; + } + child = child.parentNode; + } + return false; +} +Sys.Mvc.FormContext._parseJsonOptions = function Sys_Mvc_FormContext$_parseJsonOptions(options) { + /// + /// + /// + var formElement = $get(options.FormId); + var validationSummaryElement = (!Sys.Mvc._validationUtil.stringIsNullOrEmpty(options.ValidationSummaryId)) ? $get(options.ValidationSummaryId) : null; + var formContext = new Sys.Mvc.FormContext(formElement, validationSummaryElement); + formContext.enableDynamicValidation(); + formContext.replaceValidationSummary = options.ReplaceValidationSummary; + for (var i = 0; i < options.Fields.length; i++) { + var field = options.Fields[i]; + var fieldElements = Sys.Mvc.FormContext._getFormElementsWithName(formElement, field.FieldName); + var validationMessageElement = (!Sys.Mvc._validationUtil.stringIsNullOrEmpty(field.ValidationMessageId)) ? $get(field.ValidationMessageId) : null; + var fieldContext = new Sys.Mvc.FieldContext(formContext); + Array.addRange(fieldContext.elements, fieldElements); + fieldContext.validationMessageElement = validationMessageElement; + fieldContext.replaceValidationMessageContents = field.ReplaceValidationMessageContents; + for (var j = 0; j < field.ValidationRules.length; j++) { + var rule = field.ValidationRules[j]; + var validator = Sys.Mvc.ValidatorRegistry.getValidator(rule); + if (validator) { + var validation = Sys.Mvc.$create_Validation(); + validation.fieldErrorMessage = rule.ErrorMessage; + validation.validator = validator; + Array.add(fieldContext.validations, validation); + } + } + fieldContext.enableDynamicValidation(); + Array.add(formContext.fields, fieldContext); + } + var registeredValidatorCallbacks = formElement.validationCallbacks; + if (!registeredValidatorCallbacks) { + registeredValidatorCallbacks = []; + formElement.validationCallbacks = registeredValidatorCallbacks; + } + registeredValidatorCallbacks.push(Function.createDelegate(null, function() { + return Sys.Mvc._validationUtil.arrayIsNullOrEmpty(formContext.validate('submit')); + })); + return formContext; +} +Sys.Mvc.FormContext.prototype = { + _onClickHandler: null, + _onSubmitHandler: null, + _submitButtonClicked: null, + _validationSummaryElement: null, + _validationSummaryULElement: null, + _formElement: null, + replaceValidationSummary: false, + + addError: function Sys_Mvc_FormContext$addError(message) { + /// + /// + this.addErrors([ message ]); + }, + + addErrors: function Sys_Mvc_FormContext$addErrors(messages) { + /// + /// + if (!Sys.Mvc._validationUtil.arrayIsNullOrEmpty(messages)) { + Array.addRange(this._errors, messages); + this._onErrorCountChanged(); + } + }, + + clearErrors: function Sys_Mvc_FormContext$clearErrors() { + Array.clear(this._errors); + this._onErrorCountChanged(); + }, + + _displayError: function Sys_Mvc_FormContext$_displayError() { + if (this._validationSummaryElement) { + if (this._validationSummaryULElement) { + Sys.Mvc._validationUtil.removeAllChildren(this._validationSummaryULElement); + for (var i = 0; i < this._errors.length; i++) { + var liElement = document.createElement('li'); + Sys.Mvc._validationUtil.setInnerText(liElement, this._errors[i]); + this._validationSummaryULElement.appendChild(liElement); + } + } + Sys.UI.DomElement.removeCssClass(this._validationSummaryElement, Sys.Mvc.FormContext._validationSummaryValidCss); + Sys.UI.DomElement.addCssClass(this._validationSummaryElement, Sys.Mvc.FormContext._validationSummaryErrorCss); + } + }, + + _displaySuccess: function Sys_Mvc_FormContext$_displaySuccess() { + var validationSummaryElement = this._validationSummaryElement; + if (validationSummaryElement) { + var validationSummaryULElement = this._validationSummaryULElement; + if (validationSummaryULElement) { + validationSummaryULElement.innerHTML = ''; + } + Sys.UI.DomElement.removeCssClass(validationSummaryElement, Sys.Mvc.FormContext._validationSummaryErrorCss); + Sys.UI.DomElement.addCssClass(validationSummaryElement, Sys.Mvc.FormContext._validationSummaryValidCss); + } + }, + + enableDynamicValidation: function Sys_Mvc_FormContext$enableDynamicValidation() { + Sys.UI.DomEvent.addHandler(this._formElement, 'click', this._onClickHandler); + Sys.UI.DomEvent.addHandler(this._formElement, 'submit', this._onSubmitHandler); + }, + + _findSubmitButton: function Sys_Mvc_FormContext$_findSubmitButton(element) { + /// + /// + /// + if (element.disabled) { + return null; + } + var tagName = element.tagName.toUpperCase(); + var inputElement = element; + if (tagName === 'INPUT') { + var type = inputElement.type; + if (type === 'submit' || type === 'image') { + return inputElement; + } + } + else if ((tagName === 'BUTTON') && (inputElement.type === 'submit')) { + return inputElement; + } + return null; + }, + + _form_OnClick: function Sys_Mvc_FormContext$_form_OnClick(e) { + /// + /// + this._submitButtonClicked = this._findSubmitButton(e.target); + }, + + _form_OnSubmit: function Sys_Mvc_FormContext$_form_OnSubmit(e) { + /// + /// + var form = e.target; + var submitButton = this._submitButtonClicked; + if (submitButton && submitButton.disableValidation) { + return; + } + var errorMessages = this.validate('submit'); + if (!Sys.Mvc._validationUtil.arrayIsNullOrEmpty(errorMessages)) { + e.preventDefault(); + } + }, + + _onErrorCountChanged: function Sys_Mvc_FormContext$_onErrorCountChanged() { + if (!this._errors.length) { + this._displaySuccess(); + } + else { + this._displayError(); + } + }, + + validate: function Sys_Mvc_FormContext$validate(eventName) { + /// + /// + /// + var fields = this.fields; + var errors = []; + for (var i = 0; i < fields.length; i++) { + var field = fields[i]; + if (!field.elements[0].disabled) { + var thisErrors = field.validate(eventName); + if (thisErrors) { + Array.addRange(errors, thisErrors); + } + } + } + if (this.replaceValidationSummary) { + this.clearErrors(); + this.addErrors(errors); + } + return errors; + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.FieldContext + +Sys.Mvc.FieldContext = function Sys_Mvc_FieldContext(formContext) { + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + this._errors = []; + this.elements = new Array(0); + this.validations = new Array(0); + this.formContext = formContext; + this._onBlurHandler = Function.createDelegate(this, this._element_OnBlur); + this._onChangeHandler = Function.createDelegate(this, this._element_OnChange); + this._onInputHandler = Function.createDelegate(this, this._element_OnInput); + this._onPropertyChangeHandler = Function.createDelegate(this, this._element_OnPropertyChange); +} +Sys.Mvc.FieldContext.prototype = { + _onBlurHandler: null, + _onChangeHandler: null, + _onInputHandler: null, + _onPropertyChangeHandler: null, + defaultErrorMessage: null, + formContext: null, + replaceValidationMessageContents: false, + validationMessageElement: null, + + addError: function Sys_Mvc_FieldContext$addError(message) { + /// + /// + this.addErrors([ message ]); + }, + + addErrors: function Sys_Mvc_FieldContext$addErrors(messages) { + /// + /// + if (!Sys.Mvc._validationUtil.arrayIsNullOrEmpty(messages)) { + Array.addRange(this._errors, messages); + this._onErrorCountChanged(); + } + }, + + clearErrors: function Sys_Mvc_FieldContext$clearErrors() { + Array.clear(this._errors); + this._onErrorCountChanged(); + }, + + _displayError: function Sys_Mvc_FieldContext$_displayError() { + var validationMessageElement = this.validationMessageElement; + if (validationMessageElement) { + if (this.replaceValidationMessageContents) { + Sys.Mvc._validationUtil.setInnerText(validationMessageElement, this._errors[0]); + } + Sys.UI.DomElement.removeCssClass(validationMessageElement, Sys.Mvc.FieldContext._validationMessageValidCss); + Sys.UI.DomElement.addCssClass(validationMessageElement, Sys.Mvc.FieldContext._validationMessageErrorCss); + } + var elements = this.elements; + for (var i = 0; i < elements.length; i++) { + var element = elements[i]; + Sys.UI.DomElement.removeCssClass(element, Sys.Mvc.FieldContext._inputElementValidCss); + Sys.UI.DomElement.addCssClass(element, Sys.Mvc.FieldContext._inputElementErrorCss); + } + }, + + _displaySuccess: function Sys_Mvc_FieldContext$_displaySuccess() { + var validationMessageElement = this.validationMessageElement; + if (validationMessageElement) { + if (this.replaceValidationMessageContents) { + Sys.Mvc._validationUtil.setInnerText(validationMessageElement, ''); + } + Sys.UI.DomElement.removeCssClass(validationMessageElement, Sys.Mvc.FieldContext._validationMessageErrorCss); + Sys.UI.DomElement.addCssClass(validationMessageElement, Sys.Mvc.FieldContext._validationMessageValidCss); + } + var elements = this.elements; + for (var i = 0; i < elements.length; i++) { + var element = elements[i]; + Sys.UI.DomElement.removeCssClass(element, Sys.Mvc.FieldContext._inputElementErrorCss); + Sys.UI.DomElement.addCssClass(element, Sys.Mvc.FieldContext._inputElementValidCss); + } + }, + + _element_OnBlur: function Sys_Mvc_FieldContext$_element_OnBlur(e) { + /// + /// + if (e.target[Sys.Mvc.FieldContext._hasTextChangedTag] || e.target[Sys.Mvc.FieldContext._hasValidationFiredTag]) { + this.validate('blur'); + } + }, + + _element_OnChange: function Sys_Mvc_FieldContext$_element_OnChange(e) { + /// + /// + e.target[Sys.Mvc.FieldContext._hasTextChangedTag] = true; + }, + + _element_OnInput: function Sys_Mvc_FieldContext$_element_OnInput(e) { + /// + /// + e.target[Sys.Mvc.FieldContext._hasTextChangedTag] = true; + if (e.target[Sys.Mvc.FieldContext._hasValidationFiredTag]) { + this.validate('input'); + } + }, + + _element_OnPropertyChange: function Sys_Mvc_FieldContext$_element_OnPropertyChange(e) { + /// + /// + if (e.rawEvent.propertyName === 'value') { + e.target[Sys.Mvc.FieldContext._hasTextChangedTag] = true; + if (e.target[Sys.Mvc.FieldContext._hasValidationFiredTag]) { + this.validate('input'); + } + } + }, + + enableDynamicValidation: function Sys_Mvc_FieldContext$enableDynamicValidation() { + var elements = this.elements; + for (var i = 0; i < elements.length; i++) { + var element = elements[i]; + if (Sys.Mvc._validationUtil.elementSupportsEvent(element, 'onpropertychange')) { + var compatMode = document.documentMode; + if (compatMode && compatMode >= 8) { + Sys.UI.DomEvent.addHandler(element, 'propertychange', this._onPropertyChangeHandler); + } + } + else { + Sys.UI.DomEvent.addHandler(element, 'input', this._onInputHandler); + } + Sys.UI.DomEvent.addHandler(element, 'change', this._onChangeHandler); + Sys.UI.DomEvent.addHandler(element, 'blur', this._onBlurHandler); + } + }, + + _getErrorString: function Sys_Mvc_FieldContext$_getErrorString(validatorReturnValue, fieldErrorMessage) { + /// + /// + /// + /// + /// + var fallbackErrorMessage = fieldErrorMessage || this.defaultErrorMessage; + if (Boolean.isInstanceOfType(validatorReturnValue)) { + return (validatorReturnValue) ? null : fallbackErrorMessage; + } + if (String.isInstanceOfType(validatorReturnValue)) { + return ((validatorReturnValue).length) ? validatorReturnValue : fallbackErrorMessage; + } + return null; + }, + + _getStringValue: function Sys_Mvc_FieldContext$_getStringValue() { + /// + var elements = this.elements; + return (elements.length > 0) ? elements[0].value : null; + }, + + _markValidationFired: function Sys_Mvc_FieldContext$_markValidationFired() { + var elements = this.elements; + for (var i = 0; i < elements.length; i++) { + var element = elements[i]; + element[Sys.Mvc.FieldContext._hasValidationFiredTag] = true; + } + }, + + _onErrorCountChanged: function Sys_Mvc_FieldContext$_onErrorCountChanged() { + if (!this._errors.length) { + this._displaySuccess(); + } + else { + this._displayError(); + } + }, + + validate: function Sys_Mvc_FieldContext$validate(eventName) { + /// + /// + /// + var validations = this.validations; + var errors = []; + var value = this._getStringValue(); + for (var i = 0; i < validations.length; i++) { + var validation = validations[i]; + var context = Sys.Mvc.$create_ValidationContext(); + context.eventName = eventName; + context.fieldContext = this; + context.validation = validation; + var retVal = validation.validator(value, context); + var errorMessage = this._getErrorString(retVal, validation.fieldErrorMessage); + if (!Sys.Mvc._validationUtil.stringIsNullOrEmpty(errorMessage)) { + Array.add(errors, errorMessage); + } + } + this._markValidationFired(); + this.clearErrors(); + this.addErrors(errors); + return errors; + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.RangeValidator + +Sys.Mvc.RangeValidator = function Sys_Mvc_RangeValidator(minimum, maximum) { + /// + /// + /// + /// + /// + /// + /// + /// + this._minimum = minimum; + this._maximum = maximum; +} +Sys.Mvc.RangeValidator.create = function Sys_Mvc_RangeValidator$create(rule) { + /// + /// + /// + var min = rule.ValidationParameters['min']; + var max = rule.ValidationParameters['max']; + return Function.createDelegate(new Sys.Mvc.RangeValidator(min, max), new Sys.Mvc.RangeValidator(min, max).validate); +} +Sys.Mvc.RangeValidator.prototype = { + _minimum: null, + _maximum: null, + + validate: function Sys_Mvc_RangeValidator$validate(value, context) { + /// + /// + /// + /// + /// + if (Sys.Mvc._validationUtil.stringIsNullOrEmpty(value)) { + return true; + } + var n = Number.parseLocale(value); + return (!isNaN(n) && this._minimum <= n && n <= this._maximum); + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.RegularExpressionValidator + +Sys.Mvc.RegularExpressionValidator = function Sys_Mvc_RegularExpressionValidator(pattern) { + /// + /// + /// + /// + this._pattern = pattern; +} +Sys.Mvc.RegularExpressionValidator.create = function Sys_Mvc_RegularExpressionValidator$create(rule) { + /// + /// + /// + var pattern = rule.ValidationParameters['pattern']; + return Function.createDelegate(new Sys.Mvc.RegularExpressionValidator(pattern), new Sys.Mvc.RegularExpressionValidator(pattern).validate); +} +Sys.Mvc.RegularExpressionValidator.prototype = { + _pattern: null, + + validate: function Sys_Mvc_RegularExpressionValidator$validate(value, context) { + /// + /// + /// + /// + /// + if (Sys.Mvc._validationUtil.stringIsNullOrEmpty(value)) { + return true; + } + var regExp = new RegExp(this._pattern); + var matches = regExp.exec(value); + return (!Sys.Mvc._validationUtil.arrayIsNullOrEmpty(matches) && matches[0].length === value.length); + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.RequiredValidator + +Sys.Mvc.RequiredValidator = function Sys_Mvc_RequiredValidator() { +} +Sys.Mvc.RequiredValidator.create = function Sys_Mvc_RequiredValidator$create(rule) { + /// + /// + /// + return Function.createDelegate(new Sys.Mvc.RequiredValidator(), new Sys.Mvc.RequiredValidator().validate); +} +Sys.Mvc.RequiredValidator._isRadioInputElement = function Sys_Mvc_RequiredValidator$_isRadioInputElement(element) { + /// + /// + /// + if (element.tagName.toUpperCase() === 'INPUT') { + var inputType = (element.type).toUpperCase(); + if (inputType === 'RADIO') { + return true; + } + } + return false; +} +Sys.Mvc.RequiredValidator._isSelectInputElement = function Sys_Mvc_RequiredValidator$_isSelectInputElement(element) { + /// + /// + /// + if (element.tagName.toUpperCase() === 'SELECT') { + return true; + } + return false; +} +Sys.Mvc.RequiredValidator._isTextualInputElement = function Sys_Mvc_RequiredValidator$_isTextualInputElement(element) { + /// + /// + /// + if (element.tagName.toUpperCase() === 'INPUT') { + var inputType = (element.type).toUpperCase(); + switch (inputType) { + case 'TEXT': + case 'PASSWORD': + case 'FILE': + return true; + } + } + if (element.tagName.toUpperCase() === 'TEXTAREA') { + return true; + } + return false; +} +Sys.Mvc.RequiredValidator._validateRadioInput = function Sys_Mvc_RequiredValidator$_validateRadioInput(elements) { + /// + /// + /// + for (var i = 0; i < elements.length; i++) { + var element = elements[i]; + if (element.checked) { + return true; + } + } + return false; +} +Sys.Mvc.RequiredValidator._validateSelectInput = function Sys_Mvc_RequiredValidator$_validateSelectInput(optionElements) { + /// + /// + /// + for (var i = 0; i < optionElements.length; i++) { + var element = optionElements[i]; + if (element.selected) { + if (!Sys.Mvc._validationUtil.stringIsNullOrEmpty(element.value)) { + return true; + } + } + } + return false; +} +Sys.Mvc.RequiredValidator._validateTextualInput = function Sys_Mvc_RequiredValidator$_validateTextualInput(element) { + /// + /// + /// + return (!Sys.Mvc._validationUtil.stringIsNullOrEmpty(element.value)); +} +Sys.Mvc.RequiredValidator.prototype = { + + validate: function Sys_Mvc_RequiredValidator$validate(value, context) { + /// + /// + /// + /// + /// + var elements = context.fieldContext.elements; + if (!elements.length) { + return true; + } + var sampleElement = elements[0]; + if (Sys.Mvc.RequiredValidator._isTextualInputElement(sampleElement)) { + return Sys.Mvc.RequiredValidator._validateTextualInput(sampleElement); + } + if (Sys.Mvc.RequiredValidator._isRadioInputElement(sampleElement)) { + return Sys.Mvc.RequiredValidator._validateRadioInput(elements); + } + if (Sys.Mvc.RequiredValidator._isSelectInputElement(sampleElement)) { + return Sys.Mvc.RequiredValidator._validateSelectInput((sampleElement).options); + } + return true; + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.StringLengthValidator + +Sys.Mvc.StringLengthValidator = function Sys_Mvc_StringLengthValidator(minLength, maxLength) { + /// + /// + /// + /// + /// + /// + /// + /// + this._minLength = minLength; + this._maxLength = maxLength; +} +Sys.Mvc.StringLengthValidator.create = function Sys_Mvc_StringLengthValidator$create(rule) { + /// + /// + /// + var minLength = (rule.ValidationParameters['min'] || 0); + var maxLength = (rule.ValidationParameters['max'] || Number.MAX_VALUE); + return Function.createDelegate(new Sys.Mvc.StringLengthValidator(minLength, maxLength), new Sys.Mvc.StringLengthValidator(minLength, maxLength).validate); +} +Sys.Mvc.StringLengthValidator.prototype = { + _maxLength: 0, + _minLength: 0, + + validate: function Sys_Mvc_StringLengthValidator$validate(value, context) { + /// + /// + /// + /// + /// + if (Sys.Mvc._validationUtil.stringIsNullOrEmpty(value)) { + return true; + } + return (this._minLength <= value.length && value.length <= this._maxLength); + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc._validationUtil + +Sys.Mvc._validationUtil = function Sys_Mvc__validationUtil() { +} +Sys.Mvc._validationUtil.arrayIsNullOrEmpty = function Sys_Mvc__validationUtil$arrayIsNullOrEmpty(array) { + /// + /// + /// + return (!array || !array.length); +} +Sys.Mvc._validationUtil.stringIsNullOrEmpty = function Sys_Mvc__validationUtil$stringIsNullOrEmpty(value) { + /// + /// + /// + return (!value || !value.length); +} +Sys.Mvc._validationUtil.elementSupportsEvent = function Sys_Mvc__validationUtil$elementSupportsEvent(element, eventAttributeName) { + /// + /// + /// + /// + /// + return (eventAttributeName in element); +} +Sys.Mvc._validationUtil.removeAllChildren = function Sys_Mvc__validationUtil$removeAllChildren(element) { + /// + /// + while (element.firstChild) { + element.removeChild(element.firstChild); + } +} +Sys.Mvc._validationUtil.setInnerText = function Sys_Mvc__validationUtil$setInnerText(element, innerText) { + /// + /// + /// + /// + var textNode = document.createTextNode(innerText); + Sys.Mvc._validationUtil.removeAllChildren(element); + element.appendChild(textNode); +} + + +//////////////////////////////////////////////////////////////////////////////// +// Sys.Mvc.ValidatorRegistry + +Sys.Mvc.ValidatorRegistry = function Sys_Mvc_ValidatorRegistry() { + /// + /// +} +Sys.Mvc.ValidatorRegistry.getValidator = function Sys_Mvc_ValidatorRegistry$getValidator(rule) { + /// + /// + /// + var creator = Sys.Mvc.ValidatorRegistry.validators[rule.ValidationType]; + return (creator) ? creator(rule) : null; +} +Sys.Mvc.ValidatorRegistry._getDefaultValidators = function Sys_Mvc_ValidatorRegistry$_getDefaultValidators() { + /// + return { required: Function.createDelegate(null, Sys.Mvc.RequiredValidator.create), length: Function.createDelegate(null, Sys.Mvc.StringLengthValidator.create), regex: Function.createDelegate(null, Sys.Mvc.RegularExpressionValidator.create), range: Function.createDelegate(null, Sys.Mvc.RangeValidator.create), number: Function.createDelegate(null, Sys.Mvc.NumberValidator.create) }; +} + + +Sys.Mvc.NumberValidator.registerClass('Sys.Mvc.NumberValidator'); +Sys.Mvc.FormContext.registerClass('Sys.Mvc.FormContext'); +Sys.Mvc.FieldContext.registerClass('Sys.Mvc.FieldContext'); +Sys.Mvc.RangeValidator.registerClass('Sys.Mvc.RangeValidator'); +Sys.Mvc.RegularExpressionValidator.registerClass('Sys.Mvc.RegularExpressionValidator'); +Sys.Mvc.RequiredValidator.registerClass('Sys.Mvc.RequiredValidator'); +Sys.Mvc.StringLengthValidator.registerClass('Sys.Mvc.StringLengthValidator'); +Sys.Mvc._validationUtil.registerClass('Sys.Mvc._validationUtil'); +Sys.Mvc.ValidatorRegistry.registerClass('Sys.Mvc.ValidatorRegistry'); +Sys.Mvc.FormContext._validationSummaryErrorCss = 'validation-summary-errors'; +Sys.Mvc.FormContext._validationSummaryValidCss = 'validation-summary-valid'; +Sys.Mvc.FormContext._formValidationTag = '__MVC_FormValidation'; +Sys.Mvc.FieldContext._hasTextChangedTag = '__MVC_HasTextChanged'; +Sys.Mvc.FieldContext._hasValidationFiredTag = '__MVC_HasValidationFired'; +Sys.Mvc.FieldContext._inputElementErrorCss = 'input-validation-error'; +Sys.Mvc.FieldContext._inputElementValidCss = 'input-validation-valid'; +Sys.Mvc.FieldContext._validationMessageErrorCss = 'field-validation-error'; +Sys.Mvc.FieldContext._validationMessageValidCss = 'field-validation-valid'; +Sys.Mvc.ValidatorRegistry.validators = Sys.Mvc.ValidatorRegistry._getDefaultValidators(); + +// ---- Do not remove this footer ---- +// Generated using Script# v0.5.0.0 (http://projects.nikhilk.net) +// ----------------------------------- + +// register validation +Sys.Application.add_load(function() { + Sys.Application.remove_load(arguments.callee); + Sys.Mvc.FormContext._Application_Load(); +}); diff --git a/OnPremise/WebSite/Scripts/MicrosoftMvcValidation.js b/OnPremise/WebSite/Scripts/MicrosoftMvcValidation.js new file mode 100644 index 0000000..9483492 --- /dev/null +++ b/OnPremise/WebSite/Scripts/MicrosoftMvcValidation.js @@ -0,0 +1,55 @@ +//---------------------------------------------------------- +// Copyright (C) Microsoft Corporation. All rights reserved. +//---------------------------------------------------------- +// MicrosoftMvcValidation.js + +Type.registerNamespace('Sys.Mvc');Sys.Mvc.$create_Validation=function(){return {};} +Sys.Mvc.$create_JsonValidationField=function(){return {};} +Sys.Mvc.$create_JsonValidationOptions=function(){return {};} +Sys.Mvc.$create_JsonValidationRule=function(){return {};} +Sys.Mvc.$create_ValidationContext=function(){return {};} +Sys.Mvc.NumberValidator=function(){} +Sys.Mvc.NumberValidator.create=function(rule){return Function.createDelegate(new Sys.Mvc.NumberValidator(),new Sys.Mvc.NumberValidator().validate);} +Sys.Mvc.NumberValidator.prototype={validate:function(value,context){if(Sys.Mvc._ValidationUtil.$1(value)){return true;}var $0=Number.parseLocale(value);return (!isNaN($0));}} +Sys.Mvc.FormContext=function(formElement,validationSummaryElement){this.$5=[];this.fields=new Array(0);this.$9=formElement;this.$7=validationSummaryElement;formElement['__MVC_FormValidation'] = this;if(validationSummaryElement){var $0=validationSummaryElement.getElementsByTagName('ul');if($0.length>0){this.$8=$0[0];}}this.$3=Function.createDelegate(this,this.$D);this.$4=Function.createDelegate(this,this.$E);} +Sys.Mvc.FormContext._Application_Load=function(){var $0=window.mvcClientValidationMetadata;if($0){while($0.length>0){var $1=$0.pop();Sys.Mvc.FormContext.$12($1);}}} +Sys.Mvc.FormContext.$F=function($p0,$p1){var $0=[];var $1=document.getElementsByName($p1);for(var $2=0;$2<$1.length;$2++){var $3=$1[$2];if(Sys.Mvc.FormContext.$10($p0,$3)){Array.add($0,$3);}}return $0;} +Sys.Mvc.FormContext.getValidationForForm=function(formElement){return formElement['__MVC_FormValidation'];} +Sys.Mvc.FormContext.$10=function($p0,$p1){while($p1){if($p0===$p1){return true;}$p1=$p1.parentNode;}return false;} +Sys.Mvc.FormContext.$12=function($p0){var $0=$get($p0.FormId);var $1=(!Sys.Mvc._ValidationUtil.$1($p0.ValidationSummaryId))?$get($p0.ValidationSummaryId):null;var $2=new Sys.Mvc.FormContext($0,$1);$2.enableDynamicValidation();$2.replaceValidationSummary=$p0.ReplaceValidationSummary;for(var $4=0;$4<$p0.Fields.length;$4++){var $5=$p0.Fields[$4];var $6=Sys.Mvc.FormContext.$F($0,$5.FieldName);var $7=(!Sys.Mvc._ValidationUtil.$1($5.ValidationMessageId))?$get($5.ValidationMessageId):null;var $8=new Sys.Mvc.FieldContext($2);Array.addRange($8.elements,$6);$8.validationMessageElement=$7;$8.replaceValidationMessageContents=$5.ReplaceValidationMessageContents;for(var $9=0;$9<$5.ValidationRules.length;$9++){var $A=$5.ValidationRules[$9];var $B=Sys.Mvc.ValidatorRegistry.getValidator($A);if($B){var $C=Sys.Mvc.$create_Validation();$C.fieldErrorMessage=$A.ErrorMessage;$C.validator=$B;Array.add($8.validations,$C);}}$8.enableDynamicValidation();Array.add($2.fields,$8);}var $3=$0.validationCallbacks;if(!$3){$3=[];$0.validationCallbacks = $3;}$3.push(Function.createDelegate(null,function(){ +return Sys.Mvc._ValidationUtil.$0($2.validate('submit'));}));return $2;} +Sys.Mvc.FormContext.prototype={$3:null,$4:null,$6:null,$7:null,$8:null,$9:null,replaceValidationSummary:false,addError:function(message){this.addErrors([message]);},addErrors:function(messages){if(!Sys.Mvc._ValidationUtil.$0(messages)){Array.addRange(this.$5,messages);this.$11();}},clearErrors:function(){Array.clear(this.$5);this.$11();},$A:function(){if(this.$7){if(this.$8){Sys.Mvc._ValidationUtil.$3(this.$8);for(var $0=0;$0=8){Sys.UI.DomEvent.addHandler($2,'propertychange',this.$9);}}else{Sys.UI.DomEvent.addHandler($2,'input',this.$8);}Sys.UI.DomEvent.addHandler($2,'change',this.$7);Sys.UI.DomEvent.addHandler($2,'blur',this.$6);}},$11:function($p0,$p1){var $0=$p1||this.defaultErrorMessage;if(Boolean.isInstanceOfType($p0)){return ($p0)?null:$0;}if(String.isInstanceOfType($p0)){return (($p0).length)?$p0:$0;}return null;},$12:function(){var $0=this.elements;return ($0.length>0)?$0[0].value:null;},$13:function(){var $0=this.elements;for(var $1=0;$1<$0.length;$1++){var $2=$0[$1];$2['__MVC_HasValidationFired'] = true;}},$14:function(){if(!this.$A.length){this.$C();}else{this.$B();}},validate:function(eventName){var $0=this.validations;var $1=[];var $2=this.$12();for(var $3=0;$3<$0.length;$3++){var $4=$0[$3];var $5=Sys.Mvc.$create_ValidationContext();$5.eventName=eventName;$5.fieldContext=this;$5.validation=$4;var $6=$4.validator($2,$5);var $7=this.$11($6,$4.fieldErrorMessage);if(!Sys.Mvc._ValidationUtil.$1($7)){Array.add($1,$7);}}this.$13();this.clearErrors();this.addErrors($1);return $1;}} +Sys.Mvc.RangeValidator=function(minimum,maximum){this.$0=minimum;this.$1=maximum;} +Sys.Mvc.RangeValidator.create=function(rule){var $0=rule.ValidationParameters['min'];var $1=rule.ValidationParameters['max'];return Function.createDelegate(new Sys.Mvc.RangeValidator($0,$1),new Sys.Mvc.RangeValidator($0,$1).validate);} +Sys.Mvc.RangeValidator.prototype={$0:null,$1:null,validate:function(value,context){if(Sys.Mvc._ValidationUtil.$1(value)){return true;}var $0=Number.parseLocale(value);return (!isNaN($0)&&this.$0<=$0&&$0<=this.$1);}} +Sys.Mvc.RegularExpressionValidator=function(pattern){this.$0=pattern;} +Sys.Mvc.RegularExpressionValidator.create=function(rule){var $0=rule.ValidationParameters['pattern'];return Function.createDelegate(new Sys.Mvc.RegularExpressionValidator($0),new Sys.Mvc.RegularExpressionValidator($0).validate);} +Sys.Mvc.RegularExpressionValidator.prototype={$0:null,validate:function(value,context){if(Sys.Mvc._ValidationUtil.$1(value)){return true;}var $0=new RegExp(this.$0);var $1=$0.exec(value);return (!Sys.Mvc._ValidationUtil.$0($1)&&$1[0].length===value.length);}} +Sys.Mvc.RequiredValidator=function(){} +Sys.Mvc.RequiredValidator.create=function(rule){return Function.createDelegate(new Sys.Mvc.RequiredValidator(),new Sys.Mvc.RequiredValidator().validate);} +Sys.Mvc.RequiredValidator.$0=function($p0){if($p0.tagName.toUpperCase()==='INPUT'){var $0=($p0.type).toUpperCase();if($0==='RADIO'){return true;}}return false;} +Sys.Mvc.RequiredValidator.$1=function($p0){if($p0.tagName.toUpperCase()==='SELECT'){return true;}return false;} +Sys.Mvc.RequiredValidator.$2=function($p0){if($p0.tagName.toUpperCase()==='INPUT'){var $0=($p0.type).toUpperCase();switch($0){case 'TEXT':case 'PASSWORD':case 'FILE':return true;}}if($p0.tagName.toUpperCase()==='TEXTAREA'){return true;}return false;} +Sys.Mvc.RequiredValidator.$3=function($p0){for(var $0=0;$0<$p0.length;$0++){var $1=$p0[$0];if($1.checked){return true;}}return false;} +Sys.Mvc.RequiredValidator.$4=function($p0){for(var $0=0;$0<$p0.length;$0++){var $1=$p0[$0];if($1.selected){if(!Sys.Mvc._ValidationUtil.$1($1.value)){return true;}}}return false;} +Sys.Mvc.RequiredValidator.$5=function($p0){return (!Sys.Mvc._ValidationUtil.$1($p0.value));} +Sys.Mvc.RequiredValidator.prototype={validate:function(value,context){var $0=context.fieldContext.elements;if(!$0.length){return true;}var $1=$0[0];if(Sys.Mvc.RequiredValidator.$2($1)){return Sys.Mvc.RequiredValidator.$5($1);}if(Sys.Mvc.RequiredValidator.$0($1)){return Sys.Mvc.RequiredValidator.$3($0);}if(Sys.Mvc.RequiredValidator.$1($1)){return Sys.Mvc.RequiredValidator.$4(($1).options);}return true;}} +Sys.Mvc.StringLengthValidator=function(minLength,maxLength){this.$1=minLength;this.$0=maxLength;} +Sys.Mvc.StringLengthValidator.create=function(rule){var $0=(rule.ValidationParameters['min']||0);var $1=(rule.ValidationParameters['max']||Number.MAX_VALUE);return Function.createDelegate(new Sys.Mvc.StringLengthValidator($0,$1),new Sys.Mvc.StringLengthValidator($0,$1).validate);} +Sys.Mvc.StringLengthValidator.prototype={$0:0,$1:0,validate:function(value,context){if(Sys.Mvc._ValidationUtil.$1(value)){return true;}return (this.$1<=value.length&&value.length<=this.$0);}} +Sys.Mvc._ValidationUtil=function(){} +Sys.Mvc._ValidationUtil.$0=function($p0){return (!$p0||!$p0.length);} +Sys.Mvc._ValidationUtil.$1=function($p0){return (!$p0||!$p0.length);} +Sys.Mvc._ValidationUtil.$2=function($p0,$p1){return ($p1 in $p0);} +Sys.Mvc._ValidationUtil.$3=function($p0){while($p0.firstChild){$p0.removeChild($p0.firstChild);}} +Sys.Mvc._ValidationUtil.$4=function($p0,$p1){var $0=document.createTextNode($p1);Sys.Mvc._ValidationUtil.$3($p0);$p0.appendChild($0);} +Sys.Mvc.ValidatorRegistry=function(){} +Sys.Mvc.ValidatorRegistry.getValidator=function(rule){var $0=Sys.Mvc.ValidatorRegistry.validators[rule.ValidationType];return ($0)?$0(rule):null;} +Sys.Mvc.ValidatorRegistry.$0=function(){return {required:Function.createDelegate(null,Sys.Mvc.RequiredValidator.create),length:Function.createDelegate(null,Sys.Mvc.StringLengthValidator.create),regex:Function.createDelegate(null,Sys.Mvc.RegularExpressionValidator.create),range:Function.createDelegate(null,Sys.Mvc.RangeValidator.create),number:Function.createDelegate(null,Sys.Mvc.NumberValidator.create)};} +Sys.Mvc.NumberValidator.registerClass('Sys.Mvc.NumberValidator');Sys.Mvc.FormContext.registerClass('Sys.Mvc.FormContext');Sys.Mvc.FieldContext.registerClass('Sys.Mvc.FieldContext');Sys.Mvc.RangeValidator.registerClass('Sys.Mvc.RangeValidator');Sys.Mvc.RegularExpressionValidator.registerClass('Sys.Mvc.RegularExpressionValidator');Sys.Mvc.RequiredValidator.registerClass('Sys.Mvc.RequiredValidator');Sys.Mvc.StringLengthValidator.registerClass('Sys.Mvc.StringLengthValidator');Sys.Mvc._ValidationUtil.registerClass('Sys.Mvc._ValidationUtil');Sys.Mvc.ValidatorRegistry.registerClass('Sys.Mvc.ValidatorRegistry');Sys.Mvc.ValidatorRegistry.validators=Sys.Mvc.ValidatorRegistry.$0(); +// ---- Do not remove this footer ---- +// Generated using Script# v0.5.0.0 (http://projects.nikhilk.net) +// ----------------------------------- +Sys.Application.add_load(function(){Sys.Application.remove_load(arguments.callee);Sys.Mvc.FormContext._Application_Load();}); \ No newline at end of file diff --git a/OnPremise/WebSite/Scripts/jquery-1.7.1-vsdoc.js b/OnPremise/WebSite/Scripts/jquery-1.7.1-vsdoc.js new file mode 100644 index 0000000..ac2e76a --- /dev/null +++ b/OnPremise/WebSite/Scripts/jquery-1.7.1-vsdoc.js @@ -0,0 +1,7153 @@ +/* +* This file has been generated 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.7.1 +*/ + +/*! +* jQuery JavaScript Library v1.7.1 +* http://jquery.com/ +* +* Distributed in whole under the terms of the MIT +* +* Copyright 2010, John Resig +* +* 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. +* +* Includes Sizzle.js +* http://sizzlejs.com/ +* Copyright 2010, The Dojo Foundation +* Released under the MIT and BSD Licenses. +*/ + +(function ( window, undefined ) { +var jQuery = function( selector, context ) { +/// +/// 1: Accepts a string containing a CSS selector which is then used to match a set of elements. +/// 1.1 - $(selector, context) +/// 1.2 - $(element) +/// 1.3 - $(object) +/// 1.4 - $(elementArray) +/// 1.5 - $(jQuery object) +/// 1.6 - $() +/// 2: Creates DOM elements on the fly from the provided string of raw HTML. +/// 2.1 - $(html, ownerDocument) +/// 2.2 - $(html, props) +/// 3: Binds a function to be executed when the DOM has finished loading. +/// 3.1 - $(callback) +/// +/// +/// A string containing a selector expression +/// +/// +/// A DOM Element, Document, or jQuery to use as context +/// +/// + + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }; +jQuery.Callbacks = function( flags ) { +/// +/// A multi-purpose callbacks list object that provides a powerful way to manage callback lists. +/// +/// +/// An optional list of space-separated flags that change how the callback list behaves. +/// + + + // Convert flags from String-formatted to Object-formatted + // (we check in cache first) + flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {}; + + var // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = [], + // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list is currently firing + firing, + // First callback to fire (used internally by add and fireWith) + firingStart, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // Add one or several callbacks to the list + add = function( args ) { + var i, + length, + elem, + type, + actual; + for ( i = 0, length = args.length; i < length; i++ ) { + elem = args[ i ]; + type = jQuery.type( elem ); + if ( type === "array" ) { + // Inspect recursively + add( elem ); + } else if ( type === "function" ) { + // Add if not in unique mode and callback is not in + if ( !flags.unique || !self.has( elem ) ) { + list.push( elem ); + } + } + } + }, + // Fire callbacks + fire = function( context, args ) { + args = args || []; + memory = !flags.memory || [ context, args ]; + firing = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) { + memory = true; // Mark as halted + break; + } + } + firing = false; + if ( list ) { + if ( !flags.once ) { + if ( stack && stack.length ) { + memory = stack.shift(); + self.fireWith( memory[ 0 ], memory[ 1 ] ); + } + } else if ( memory === true ) { + self.disable(); + } else { + list = []; + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + var length = list.length; + add( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away, unless previous + // firing was halted (stopOnFalse) + } else if ( memory && memory !== true ) { + firingStart = length; + fire( memory[ 0 ], memory[ 1 ] ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + var args = arguments, + argIndex = 0, + argLength = args.length; + for ( ; argIndex < argLength ; argIndex++ ) { + for ( var i = 0; i < list.length; i++ ) { + if ( args[ argIndex ] === list[ i ] ) { + // Handle firingIndex and firingLength + if ( firing ) { + if ( i <= firingLength ) { + firingLength--; + if ( i <= firingIndex ) { + firingIndex--; + } + } + } + // Remove the element + list.splice( i--, 1 ); + // If we have some unicity property then + // we only need to do this once + if ( flags.unique ) { + break; + } + } + } + } + } + return this; + }, + // Control if a given callback is in the list + has: function( fn ) { + if ( list ) { + var i = 0, + length = list.length; + for ( ; i < length; i++ ) { + if ( fn === list[ i ] ) { + return true; + } + } + } + return false; + }, + // Remove all callbacks from the list + empty: function() { + list = []; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory || memory === true ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( stack ) { + if ( firing ) { + if ( !flags.once ) { + stack.push( [ context, args ] ); + } + } else if ( !( flags.once && memory ) ) { + fire( context, args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!memory; + } + }; + + return self; +}; +jQuery.Deferred = function( func ) { + + var doneList = jQuery.Callbacks( "once memory" ), + failList = jQuery.Callbacks( "once memory" ), + progressList = jQuery.Callbacks( "memory" ), + state = "pending", + lists = { + resolve: doneList, + reject: failList, + notify: progressList + }, + promise = { + done: doneList.add, + fail: failList.add, + progress: progressList.add, + + state: function() { + return state; + }, + + // Deprecated + isResolved: doneList.fired, + isRejected: failList.fired, + + then: function( doneCallbacks, failCallbacks, progressCallbacks ) { + deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks ); + return this; + }, + always: function() { + deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments ); + return this; + }, + pipe: function( fnDone, fnFail, fnProgress ) { + return jQuery.Deferred(function( newDefer ) { + jQuery.each( { + done: [ fnDone, "resolve" ], + fail: [ fnFail, "reject" ], + progress: [ fnProgress, "notify" ] + }, function( handler, data ) { + var fn = data[ 0 ], + action = data[ 1 ], + returned; + if ( jQuery.isFunction( fn ) ) { + deferred[ handler ](function() { + returned = fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify ); + } else { + newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] ); + } + }); + } else { + deferred[ handler ]( newDefer[ action ] ); + } + }); + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + if ( obj == null ) { + obj = promise; + } else { + for ( var key in promise ) { + obj[ key ] = promise[ key ]; + } + } + return obj; + } + }, + deferred = promise.promise({}), + key; + + for ( key in lists ) { + deferred[ key ] = lists[ key ].fire; + deferred[ key + "With" ] = lists[ key ].fireWith; + } + + // Handle state + deferred.done( function() { + state = "resolved"; + }, failList.disable, progressList.lock ).fail( function() { + state = "rejected"; + }, doneList.disable, progressList.lock ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }; +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; +jQuery._data = function( elem, name, data ) { + + return jQuery.data( elem, name, data, true ); + }; +jQuery._mark = function( elem, type ) { + + if ( elem ) { + type = ( type || "fx" ) + "mark"; + jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 ); + } + }; +jQuery._unmark = function( force, elem, type ) { + + if ( force !== true ) { + type = elem; + elem = force; + force = false; + } + if ( elem ) { + type = type || "fx"; + var key = type + "mark", + count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 ); + if ( count ) { + jQuery._data( elem, key, count ); + } else { + jQuery.removeData( elem, key, true ); + handleQueueMarkDefer( elem, type, "mark" ); + } + } + }; +jQuery.acceptData = function( elem ) { + + if ( elem.nodeName ) { + var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; + + if ( match ) { + return !(match === true || elem.getAttribute("classid") !== match); + } + } + + return true; + }; +jQuery.access = function( elems, key, value, exec, fn, pass ) { + + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + jQuery.access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : undefined; + }; +jQuery.active = 0; +jQuery.ajax = function( url, options ) { +/// +/// Perform an asynchronous HTTP (Ajax) request. +/// 1 - jQuery.ajax(url, settings) +/// 2 - jQuery.ajax(settings) +/// +/// +/// A string containing the URL to which the request is sent. +/// +/// +/// A set of key/value pairs that configure the Ajax request. All settings are optional. A default can be set for any option with $.ajaxSetup(). See jQuery.ajax( settings ) below for a complete list of all settings. +/// + + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + // Callbacks context + callbackContext = s.context || s, + // Context for global events + // It's the callbackContext if one was provided in the options + // and if it's a DOM node or a jQuery collection + globalEventContext = callbackContext !== s && + ( callbackContext.nodeType || callbackContext instanceof jQuery ) ? + jQuery( callbackContext ) : jQuery.event, + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + // Status-dependent callbacks + statusCode = s.statusCode || {}, + // ifModified key + ifModifiedKey, + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + // Response headers + responseHeadersString, + responseHeaders, + // transport + transport, + // timeout handle + timeoutTimer, + // Cross-domain detection vars + parts, + // The jqXHR state + state = 0, + // To know if global events are to be dispatched + fireGlobals, + // Loop variable + i, + // Fake xhr + jqXHR = { + + readyState: 0, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( !state ) { + var lname = name.toLowerCase(); + name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Raw string + getAllResponseHeaders: function() { + return state === 2 ? responseHeadersString : null; + }, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( state === 2 ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[1].toLowerCase() ] = match[ 2 ]; + } + } + match = responseHeaders[ key.toLowerCase() ]; + } + return match === undefined ? null : match; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( !state ) { + s.mimeType = type; + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + statusText = statusText || "abort"; + if ( transport ) { + transport.abort( statusText ); + } + done( 0, statusText ); + return this; + } + }; + + // Callback for when everything is done + // It is defined here because jslint complains if it is declared + // at the end of the function (which would be more logical and readable) + function done( status, nativeStatusText, responses, headers ) { + + // Called once + if ( state === 2 ) { + return; + } + + // State is "done" now + state = 2; + + // Clear timeout if it exists + if ( timeoutTimer ) { + clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + var isSuccess, + success, + error, + statusText = nativeStatusText, + response = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined, + lastModified, + etag; + + // If successful, handle type chaining + if ( status >= 200 && status < 300 || status === 304 ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + + if ( ( lastModified = jqXHR.getResponseHeader( "Last-Modified" ) ) ) { + jQuery.lastModified[ ifModifiedKey ] = lastModified; + } + if ( ( etag = jqXHR.getResponseHeader( "Etag" ) ) ) { + jQuery.etag[ ifModifiedKey ] = etag; + } + } + + // If not modified + if ( status === 304 ) { + + statusText = "notmodified"; + isSuccess = true; + + // If we have data + } else { + + try { + success = ajaxConvert( s, response ); + statusText = "success"; + isSuccess = true; + } catch(e) { + // We have a parsererror + statusText = "parsererror"; + error = e; + } + } + } else { + // We extract error from statusText + // then normalize statusText and status for non-aborts + error = statusText; + if ( !statusText || status ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = "" + ( nativeStatusText || statusText ); + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ), + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + // Attach deferreds + deferred.promise( jqXHR ); + jqXHR.success = jqXHR.done; + jqXHR.error = jqXHR.fail; + jqXHR.complete = completeDeferred.add; + + // Status-dependent callbacks + jqXHR.statusCode = function( map ) { + if ( map ) { + var tmp; + if ( state < 2 ) { + for ( tmp in map ) { + statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ]; + } + } else { + tmp = map[ jqXHR.status ]; + jqXHR.then( tmp, tmp ); + } + } + return this; + }; + + // Remove hash character (#7531: and string promotion) + // Add protocol if not provided (#5866: IE7 issue with protocol-less urls) + // We also use the url parameter if available + s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" ); + + // Extract dataTypes list + s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax ); + + // Determine if a cross-domain request is in order + if ( s.crossDomain == null ) { + parts = rurl.exec( s.url.toLowerCase() ); + s.crossDomain = !!( parts && + ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] || + ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) != + ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) ) + ); + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefiler, stop there + if ( state === 2 ) { + return false; + } + + // We can fire global events as of now if asked to + fireGlobals = s.global; + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // If data is available, append data to url + if ( s.data ) { + s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data; + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Get ifModifiedKey before adding the anti-cache parameter + ifModifiedKey = s.url; + + // Add anti-cache in url if needed + if ( s.cache === false ) { + + var ts = jQuery.now(), + // try replacing _= if it is there + ret = s.url.replace( rts, "$1_=" + ts ); + + // if nothing was replaced, add timestamp to the end + s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + ifModifiedKey = ifModifiedKey || s.url; + if ( jQuery.lastModified[ ifModifiedKey ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] ); + } + if ( jQuery.etag[ ifModifiedKey ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] ); + } + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ? + s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) { + // Abort if not done already + jqXHR.abort(); + return false; + + } + + // Install callbacks on deferreds + for ( i in { success: 1, error: 1, complete: 1 } ) { + jqXHR[ i ]( s[ i ] ); + } + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = setTimeout( function(){ + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + state = 1; + transport.send( requestHeaders, done ); + } catch (e) { + // Propagate exception as error if not done + if ( state < 2 ) { + done( -1, e ); + // Simply rethrow otherwise + } else { + throw e; + } + } + } + + return jqXHR; + }; +jQuery.ajaxPrefilter = function( dataTypeExpression, func ) { +/// +/// Handle custom Ajax options or modify existing options before each request is sent and before they are processed by $.ajax(). +/// +/// +/// An optional string containing one or more space-separated dataTypes +/// +/// +/// A handler to set default values for future Ajax requests. +/// +/// + + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + if ( jQuery.isFunction( func ) ) { + var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ), + i = 0, + length = dataTypes.length, + dataType, + list, + placeBefore; + + // For each dataType in the dataTypeExpression + for ( ; i < length; i++ ) { + dataType = dataTypes[ i ]; + // We control if we're asked to add before + // any existing element + placeBefore = /^\+/.test( dataType ); + if ( placeBefore ) { + dataType = dataType.substr( 1 ) || "*"; + } + list = structure[ dataType ] = structure[ dataType ] || []; + // then we add to the structure accordingly + list[ placeBefore ? "unshift" : "push" ]( func ); + } + } + }; +jQuery.ajaxSettings = { "url": 'http://localhost:25813/', +"isLocal": false, +"global": true, +"type": 'GET', +"contentType": 'application/x-www-form-urlencoded', +"processData": true, +"async": true, +"accepts": {}, +"contents": {}, +"responseFields": {}, +"converters": {}, +"flatOptions": {}, +"jsonp": 'callback' }; +jQuery.ajaxSetup = function( target, settings ) { +/// +/// Set default values for future Ajax requests. +/// +/// +/// A set of key/value pairs that configure the default Ajax request. All options are optional. +/// + + if ( settings ) { + // Building a settings object + ajaxExtend( target, jQuery.ajaxSettings ); + } else { + // Extending ajaxSettings + settings = target; + target = jQuery.ajaxSettings; + } + ajaxExtend( target, settings ); + return target; + }; +jQuery.ajaxTransport = function( dataTypeExpression, func ) { + + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + if ( jQuery.isFunction( func ) ) { + var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ), + i = 0, + length = dataTypes.length, + dataType, + list, + placeBefore; + + // For each dataType in the dataTypeExpression + for ( ; i < length; i++ ) { + dataType = dataTypes[ i ]; + // We control if we're asked to add before + // any existing element + placeBefore = /^\+/.test( dataType ); + if ( placeBefore ) { + dataType = dataType.substr( 1 ) || "*"; + } + list = structure[ dataType ] = structure[ dataType ] || []; + // then we add to the structure accordingly + list[ placeBefore ? "unshift" : "push" ]( func ); + } + } + }; +jQuery.attr = function( elem, name, value, pass ) { + + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery( elem )[ name ]( value ); + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + // All attributes are lowercase + // Grab necessary hook if one is defined + if ( notxml ) { + name = name.toLowerCase(); + hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook ); + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + + } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, "" + value ); + return value; + } + + } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + + ret = elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return ret === null ? + undefined : + ret; + } + }; +jQuery.attrFn = { "val": true, +"css": true, +"html": true, +"text": true, +"data": true, +"width": true, +"height": true, +"offset": true, +"blur": true, +"focus": true, +"focusin": true, +"focusout": true, +"load": true, +"resize": true, +"scroll": true, +"unload": true, +"click": true, +"dblclick": true, +"mousedown": true, +"mouseup": true, +"mousemove": true, +"mouseover": true, +"mouseout": true, +"mouseenter": true, +"mouseleave": true, +"change": true, +"select": true, +"submit": true, +"keydown": true, +"keypress": true, +"keyup": true, +"error": true, +"contextmenu": true }; +jQuery.attrHooks = { "type": {}, +"value": {}, +"tabindex": {} }; +jQuery.bindReady = function() { + + if ( readyList ) { + return; + } + + readyList = jQuery.Callbacks( "once memory" ); + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + return setTimeout( jQuery.ready, 1 ); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", DOMContentLoaded ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }; +jQuery.boxModel = true; +jQuery.browser = { "msie": true, +"version": '9.0' }; +jQuery.buildFragment = function( args, nodes, scripts ) { + + var fragment, cacheable, cacheresults, doc, + first = args[ 0 ]; + + // nodes may contain either an explicit document object, + // a jQuery collection or context object. + // If nodes[0] contains a valid object to assign to doc + if ( nodes && nodes[0] ) { + doc = nodes[0].ownerDocument || nodes[0]; + } + + // Ensure that an attr object doesn't incorrectly stand in as a document object + // Chrome and Firefox seem to allow this to occur and will throw exception + // Fixes #8950 + if ( !doc.createDocumentFragment ) { + doc = document; + } + + // Only cache "small" (1/2 KB) HTML strings that are associated with the main document + // Cloning options loses the selected state, so don't cache them + // IE 6 doesn't like it when you put or elements in a fragment + // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache + // Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501 + if ( args.length === 1 && typeof first === "string" && first.length < 512 && doc === document && + first.charAt(0) === "<" && !rnocache.test( first ) && + (jQuery.support.checkClone || !rchecked.test( first )) && + (jQuery.support.html5Clone || !rnoshimcache.test( first )) ) { + + cacheable = true; + + cacheresults = jQuery.fragments[ first ]; + if ( cacheresults && cacheresults !== 1 ) { + fragment = cacheresults; + } + } + + if ( !fragment ) { + fragment = doc.createDocumentFragment(); + jQuery.clean( args, doc, fragment, scripts ); + } + + if ( cacheable ) { + jQuery.fragments[ first ] = cacheresults ? fragment : 1; + } + + return { fragment: fragment, cacheable: cacheable }; +}; +jQuery.cache = {}; +jQuery.camelCase = function( string ) { + + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }; +jQuery.clean = function( elems, context, fragment, scripts ) { + + var checkScriptType; + + context = context || document; + + // !context.createElement fails in IE with an error but returns typeof 'object' + if ( typeof context.createElement === "undefined" ) { + context = context.ownerDocument || context[0] && context[0].ownerDocument || document; + } + + var ret = [], j; + + for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { + if ( typeof elem === "number" ) { + elem += ""; + } + + if ( !elem ) { + continue; + } + + // Convert html string into DOM nodes + if ( typeof elem === "string" ) { + if ( !rhtml.test( elem ) ) { + elem = context.createTextNode( elem ); + } else { + // Fix "XHTML"-style tags in all browsers + elem = elem.replace(rxhtmlTag, "<$1>"); + + // Trim whitespace, otherwise indexOf won't work as expected + var tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(), + wrap = wrapMap[ tag ] || wrapMap._default, + depth = wrap[0], + div = context.createElement("div"); + + // Append wrapper element to unknown element safe doc fragment + if ( context === document ) { + // Use the fragment we've already created for this document + safeFragment.appendChild( div ); + } else { + // Use a fragment created with the owner document + createSafeFragment( context ).appendChild( div ); + } + + // Go to html and back, then peel off extra wrappers + div.innerHTML = wrap[1] + elem + wrap[2]; + + // Move to the right depth + while ( depth-- ) { + div = div.lastChild; + } + + // Remove IE's autoinserted from table fragments + if ( !jQuery.support.tbody ) { + + // String was a , *may* have spurious + var hasBody = rtbody.test(elem), + tbody = tag === "table" && !hasBody ? + div.firstChild && div.firstChild.childNodes : + + // String was a bare or + wrap[1] === "
" && !hasBody ? + div.childNodes : + []; + + for ( j = tbody.length - 1; j >= 0 ; --j ) { + if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) { + tbody[ j ].parentNode.removeChild( tbody[ j ] ); + } + } + } + + // IE completely kills leading whitespace when innerHTML is used + if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { + div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild ); + } + + elem = div.childNodes; + } + } + + // Resets defaultChecked for any radios and checkboxes + // about to be appended to the DOM in IE 6/7 (#8060) + var len; + if ( !jQuery.support.appendChecked ) { + if ( elem[0] && typeof (len = elem.length) === "number" ) { + for ( j = 0; j < len; j++ ) { + findInputs( elem[j] ); + } + } else { + findInputs( elem ); + } + } + + if ( elem.nodeType ) { + ret.push( elem ); + } else { + ret = jQuery.merge( ret, elem ); + } + } + + if ( fragment ) { + checkScriptType = function( elem ) { + return !elem.type || rscriptType.test( elem.type ); + }; + for ( i = 0; ret[i]; i++ ) { + if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) { + scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] ); + + } else { + if ( ret[i].nodeType === 1 ) { + var jsTags = jQuery.grep( ret[i].getElementsByTagName( "script" ), checkScriptType ); + + ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) ); + } + fragment.appendChild( ret[i] ); + } + } + } + + return ret; + }; +jQuery.cleanData = function( elems ) { + + var data, id, + cache = jQuery.cache, + special = jQuery.event.special, + deleteExpando = jQuery.support.deleteExpando; + + for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { + if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) { + continue; + } + + id = elem[ jQuery.expando ]; + + if ( id ) { + data = cache[ id ]; + + if ( data && data.events ) { + for ( var type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + + // Null the DOM reference to avoid IE6/7/8 leak (#7054) + if ( data.handle ) { + data.handle.elem = null; + } + } + + if ( deleteExpando ) { + delete elem[ jQuery.expando ]; + + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); + } + + delete cache[ id ]; + } + } + }; +jQuery.clone = function( elem, dataAndEvents, deepDataAndEvents ) { + + var srcElements, + destElements, + i, + // IE<=8 does not properly clone detached, unknown element nodes + clone = jQuery.support.html5Clone || !rnoshimcache.test( "<" + elem.nodeName ) ? + elem.cloneNode( true ) : + shimCloneNode( elem ); + + if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) && + (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { + // IE copies events bound via attachEvent when using cloneNode. + // Calling detachEvent on the clone will also remove the events + // from the original. In order to get around this, we use some + // proprietary methods to clear the events. Thanks to MooTools + // guys for this hotness. + + cloneFixAttributes( elem, clone ); + + // Using Sizzle here is crazy slow, so we use getElementsByTagName instead + srcElements = getAll( elem ); + destElements = getAll( clone ); + + // Weird iteration because IE will replace the length property + // with an element if you are cloning the body and one of the + // elements on the page has a name or id of "length" + for ( i = 0; srcElements[i]; ++i ) { + // Ensure that the destination node is not null; Fixes #9587 + if ( destElements[i] ) { + cloneFixAttributes( srcElements[i], destElements[i] ); + } + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + cloneCopyEvent( elem, clone ); + + if ( deepDataAndEvents ) { + srcElements = getAll( elem ); + destElements = getAll( clone ); + + for ( i = 0; srcElements[i]; ++i ) { + cloneCopyEvent( srcElements[i], destElements[i] ); + } + } + } + + srcElements = destElements = null; + + // Return the cloned set + return clone; + }; +jQuery.contains = function( a, b ) { +/// +/// Check to see if a DOM element is within another DOM element. +/// +/// +/// The DOM element that may contain the other element. +/// +/// +/// The DOM element that may be contained by the other element. +/// +/// + + return a !== b && (a.contains ? a.contains(b) : true); + }; +jQuery.css = function( elem, name, extra ) { + + var ret, hooks; + + // Make sure that we're working with the right name + name = jQuery.camelCase( name ); + hooks = jQuery.cssHooks[ name ]; + name = jQuery.cssProps[ name ] || name; + + // cssFloat needs a special treatment + if ( name === "cssFloat" ) { + name = "float"; + } + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) { + return ret; + + // Otherwise, if a way to get the computed value exists, use that + } else if ( curCSS ) { + return curCSS( elem, name ); + } + }; +jQuery.cssHooks = { "opacity": {}, +"height": {}, +"width": {} }; +jQuery.cssNumber = { "fillOpacity": true, +"fontWeight": true, +"lineHeight": true, +"opacity": true, +"orphans": true, +"widows": true, +"zIndex": true, +"zoom": true }; +jQuery.cssProps = { "float": 'cssFloat' }; +jQuery.curCSS = function( elem, name, extra ) { + + var ret, hooks; + + // Make sure that we're working with the right name + name = jQuery.camelCase( name ); + hooks = jQuery.cssHooks[ name ]; + name = jQuery.cssProps[ name ] || name; + + // cssFloat needs a special treatment + if ( name === "cssFloat" ) { + name = "float"; + } + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) { + return ret; + + // Otherwise, if a way to get the computed value exists, use that + } else if ( curCSS ) { + return curCSS( elem, name ); + } + }; +jQuery.data = function( elem, name, data, pvt /* Internal Use Only */ ) { +/// +/// 1: Store arbitrary data associated with the specified element. Returns the value that was set. +/// 1.1 - jQuery.data(element, key, value) +/// 2: Returns value at named data store for the element, as set by jQuery.data(element, name, value), or the full data store for the element. +/// 2.1 - jQuery.data(element, key) +/// 2.2 - jQuery.data(element) +/// +/// +/// The DOM element to associate with the data. +/// +/// +/// A string naming the piece of data to set. +/// +/// +/// The new data value. +/// +/// + + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var privateCache, thisCache, ret, + internalKey = jQuery.expando, + getByName = typeof name === "string", + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey, + isEvents = name === "events"; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + elem[ internalKey ] = id = ++jQuery.uuid; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + cache[ id ] = {}; + + // Avoids exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + privateCache = thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Users should not attempt to inspect the internal events object using jQuery.data, + // it is undocumented and subject to change. But does anyone listen? No. + if ( isEvents && !thisCache[ name ] ) { + return privateCache.events; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( getByName ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; + }; +jQuery.dequeue = function( elem, type ) { +/// +/// Execute the next function on the queue for the matched element. +/// +/// +/// A DOM element from which to remove and execute a queued function. +/// +/// +/// A string containing the name of the queue. Defaults to fx, the standard effects queue. +/// +/// + + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + fn = queue.shift(), + hooks = {}; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + jQuery._data( elem, type + ".run", hooks ); + fn.call( elem, function() { + jQuery.dequeue( elem, type ); + }, hooks ); + } + + if ( !queue.length ) { + jQuery.removeData( elem, type + "queue " + type + ".run", true ); + handleQueueMarkDefer( elem, type, "queue" ); + } + }; +jQuery.dir = function( elem, dir, until ) { + + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }; +jQuery.each = function( object, callback, args ) { +/// +/// A generic iterator function, which can be used to seamlessly iterate over both objects and arrays. Arrays and array-like objects with a length property (such as a function's arguments object) are iterated by numeric index, from 0 to length-1. Other objects are iterated via their named properties. +/// +/// +/// The object or array to iterate over. +/// +/// +/// The function that will be executed on every object. +/// +/// + + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction( object ); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { + break; + } + } + } + } + + return object; + }; +jQuery.easing = {}; +jQuery.error = function( msg ) { +/// +/// Takes a string and throws an exception containing it. +/// +/// +/// The message to send out. +/// + + throw new Error( msg ); + }; +jQuery.etag = {}; +jQuery.event = { "global": {}, +"customEvent": {}, +"props": ['attrChange','attrName','relatedNode','srcElement','altKey','bubbles','cancelable','ctrlKey','currentTarget','eventPhase','metaKey','relatedTarget','shiftKey','target','timeStamp','view','which'], +"fixHooks": {}, +"keyHooks": {}, +"mouseHooks": {}, +"special": {}, +"triggered": false }; +jQuery.expr = { "order": ['ID','CLASS','NAME','TAG'], +"match": {}, +"leftMatch": {}, +"attrMap": {}, +"attrHandle": {}, +"relative": {}, +"find": {}, +"preFilter": {}, +"filters": {}, +"setFilters": {}, +"filter": {}, +":": {} }; +jQuery.extend = function() { +/// +/// Merge the contents of two or more objects together into the first object. +/// 1 - jQuery.extend(target, object1, objectN) +/// 2 - jQuery.extend(deep, target, object1, objectN) +/// +/// +/// If true, the merge becomes recursive (aka. deep copy). +/// +/// +/// The object to extend. It will receive the new properties. +/// +/// +/// An object containing additional properties to merge in. +/// +/// +/// Additional objects containing properties to merge in. +/// +/// + + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; +jQuery.filter = function( expr, elems, not ) { + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }; +jQuery.find = function( query, context, extra, seed ) { + + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && !Sizzle.isXML(context) ) { + // See if we find a selector to speed up + var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); + + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { + // Speed-up: Sizzle("TAG") + if ( match[1] ) { + return makeArray( context.getElementsByTagName( query ), extra ); + + // Speed-up: Sizzle(".CLASS") + } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { + return makeArray( context.getElementsByClassName( match[2] ), extra ); + } + } + + if ( context.nodeType === 9 ) { + // Speed-up: Sizzle("body") + // The body element only exists once, optimize finding it + if ( query === "body" && context.body ) { + return makeArray( [ context.body ], extra ); + + // Speed-up: Sizzle("#ID") + } else if ( match && match[3] ) { + var elem = context.getElementById( match[3] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id === match[3] ) { + return makeArray( [ elem ], extra ); + } + + } else { + return makeArray( [], extra ); + } + } + + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(qsaError) {} + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + var oldContext = context, + old = context.getAttribute( "id" ), + nid = old || id, + hasParent = context.parentNode, + relativeHierarchySelector = /^\s*[+~]/.test( query ); + + if ( !old ) { + context.setAttribute( "id", nid ); + } else { + nid = nid.replace( /'/g, "\\$&" ); + } + if ( relativeHierarchySelector && hasParent ) { + context = context.parentNode; + } + + try { + if ( !relativeHierarchySelector || hasParent ) { + return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); + } + + } catch(pseudoError) { + } finally { + if ( !old ) { + oldContext.removeAttribute( "id" ); + } + } + } + } + + return oldSizzle(query, context, extra, seed); + }; +jQuery.fn = { "selector": '', +"jquery": '1.7.1', +"length": 0 }; +jQuery.fragments = {}; +jQuery.fx = function( elem, options, prop ) { + + this.options = options; + this.elem = elem; + this.prop = prop; + + options.orig = options.orig || {}; + }; +jQuery.get = function( url, data, callback, type ) { +/// +/// Load data from the server using a HTTP GET request. +/// +/// +/// A string containing the URL to which the request is sent. +/// +/// +/// A map or string that is sent to the server with the request. +/// +/// +/// A callback function that is executed if the request succeeds. +/// +/// +/// The type of data expected from the server. Default: Intelligent Guess (xml, json, script, or html). +/// + + // shift arguments if data argument was omitted + if ( jQuery.isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + return jQuery.ajax({ + type: method, + url: url, + data: data, + success: callback, + dataType: type + }); + }; +jQuery.getJSON = function( url, data, callback ) { +/// +/// Load JSON-encoded data from the server using a GET HTTP request. +/// +/// +/// A string containing the URL to which the request is sent. +/// +/// +/// A map or string that is sent to the server with the request. +/// +/// +/// A callback function that is executed if the request succeeds. +/// + + return jQuery.get( url, data, callback, "json" ); + }; +jQuery.getScript = function( url, callback ) { +/// +/// Load a JavaScript file from the server using a GET HTTP request, then execute it. +/// +/// +/// A string containing the URL to which the request is sent. +/// +/// +/// A callback function that is executed if the request succeeds. +/// + + return jQuery.get( url, undefined, callback, "script" ); + }; +jQuery.globalEval = function( data ) { +/// +/// Execute some JavaScript code globally. +/// +/// +/// The JavaScript code to execute. +/// + + if ( data && rnotwhite.test( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }; +jQuery.grep = function( elems, callback, inv ) { +/// +/// Finds the elements of an array which satisfy a filter function. The original array is not affected. +/// +/// +/// The array to search through. +/// +/// +/// The function to process each item against. The first argument to the function is the item, and the second argument is the index. The function should return a Boolean value. this will be the global window object. +/// +/// +/// If "invert" is false, or not provided, then the function returns an array consisting of all elements for which "callback" returns true. If "invert" is true, then the function returns an array consisting of all elements for which "callback" returns false. +/// +/// + + var ret = [], retVal; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }; +jQuery.guid = 1; +jQuery.hasData = function( elem ) { +/// +/// Determine whether an element has any jQuery data associated with it. +/// +/// +/// A DOM element to be checked for data. +/// +/// + + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }; +jQuery.holdReady = function( hold ) { +/// +/// Holds or releases the execution of jQuery's ready event. +/// +/// +/// Indicates whether the ready hold is being requested or released +/// +/// + + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }; +jQuery.inArray = function( elem, array, i ) { +/// +/// Search for a specified value within an array and return its index (or -1 if not found). +/// +/// +/// The value to search for. +/// +/// +/// An array through which to search. +/// +/// +/// The index of the array at which to begin the search. The default is 0, which will search the whole array. +/// +/// + + var len; + + if ( array ) { + if ( indexOf ) { + return indexOf.call( array, elem, i ); + } + + len = array.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + // Skip accessing in sparse arrays + if ( i in array && array[ i ] === elem ) { + return i; + } + } + } + + return -1; +}; +jQuery.isArray = Array.isArray || function (obj) { + /// + /// Determine whether the argument is an array. + /// + /// + /// Object to test whether or not it is an array. + /// + /// + + return jQuery.type(obj) === "array"; +}; +jQuery.isEmptyObject = function( obj ) { +/// +/// Check to see if an object is empty (contains no properties). +/// +/// +/// The object that will be checked to see if it's empty. +/// +/// + + for ( var name in obj ) { + return false; + } + return true; + }; +jQuery.isFunction = function( obj ) { +/// +/// Determine if the argument passed is a Javascript function object. +/// +/// +/// Object to test whether or not it is a function. +/// +/// + + return jQuery.type(obj) === "function"; + }; +jQuery.isNumeric = function( obj ) { +/// +/// Determines whether its argument is a number. +/// +/// +/// The value to be tested. +/// +/// + + return !isNaN( parseFloat(obj) ) && isFinite( obj ); + }; +jQuery.isPlainObject = function( obj ) { +/// +/// Check to see if an object is a plain object (created using "{}" or "new Object"). +/// +/// +/// The object that will be checked to see if it's a plain object. +/// +/// + + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }; +jQuery.isReady = true; +jQuery.isWindow = function( obj ) { +/// +/// Determine whether the argument is a window. +/// +/// +/// Object to test whether or not it is a window. +/// +/// + + return obj && typeof obj === "object" && "setInterval" in obj; + }; +jQuery.isXMLDoc = function( elem ) { +/// +/// Check to see if a DOM node is within an XML document (or is an XML document). +/// +/// +/// The DOM node that will be checked to see if it's in an XML document. +/// +/// + + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; +jQuery.lastModified = {}; +jQuery.makeArray = function( array, results ) { +/// +/// Convert an array-like object into a true JavaScript array. +/// +/// +/// Any object to turn into a native Array. +/// +/// + + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 + var type = jQuery.type( array ); + + if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }; +jQuery.map = function( elems, callback, arg ) { +/// +/// Translate all items in an array or object to new array of items. +/// 1 - jQuery.map(array, callback(elementOfArray, indexInArray)) +/// 2 - jQuery.map(arrayOrObject, callback( value, indexOrKey )) +/// +/// +/// The Array to translate. +/// +/// +/// The function to process each item against. The first argument to the function is the array item, the second argument is the index in array The function can return any value. Within the function, this refers to the global (window) object. +/// +/// + + var value, key, ret = [], + i = 0, + length = elems.length, + // jquery objects are treated as arrays + isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( key in elems ) { + value = callback( elems[ key ], key, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return ret.concat.apply( [], ret ); + }; +jQuery.merge = function( first, second ) { +/// +/// Merge the contents of two arrays together into the first array. +/// +/// +/// The first array to merge, the elements of second added. +/// +/// +/// The second array to merge into the first, unaltered. +/// +/// + + var i = first.length, + j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }; +jQuery.noConflict = function( deep ) { +/// +/// Relinquish jQuery's control of the $ variable. +/// +/// +/// A Boolean indicating whether to remove all jQuery variables from the global scope (including jQuery itself). +/// +/// + + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }; +jQuery.noData = { "embed": true, +"object": 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000', +"applet": true }; +jQuery.nodeName = function( elem, name ) { + + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }; +jQuery.noop = function() { +/// +/// An empty function. +/// +/// +}; +jQuery.now = function() { +/// +/// Return a number representing the current time. +/// +/// + + return ( new Date() ).getTime(); + }; +jQuery.nth = function( cur, result, dir, elem ) { + + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }; +jQuery.offset = {}; +jQuery.param = function( a, traditional ) { +/// +/// Create a serialized representation of an array or object, suitable for use in a URL query string or Ajax request. +/// 1 - jQuery.param(obj) +/// 2 - jQuery.param(obj, traditional) +/// +/// +/// An array or object to serialize. +/// +/// +/// A Boolean indicating whether to perform a traditional "shallow" serialization. +/// +/// + + var s = [], + add = function( key, value ) { + // If value is a function, invoke it and return its value + value = jQuery.isFunction( value ) ? value() : value; + s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value ); + }; + + // Set traditional to true for jQuery <= 1.3.2 behavior. + if ( traditional === undefined ) { + traditional = jQuery.ajaxSettings.traditional; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + }); + + } else { + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( var prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ).replace( r20, "+" ); + }; +jQuery.parseJSON = function( data ) { +/// +/// Takes a well-formed JSON string and returns the resulting JavaScript object. +/// +/// +/// The JSON string to parse. +/// +/// + + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return ( new Function( "return " + data ) )(); + + } + jQuery.error( "Invalid JSON: " + data ); + }; +jQuery.parseXML = function( data ) { +/// +/// Parses a string into an XML document. +/// +/// +/// a well-formed XML string to be parsed +/// +/// + + var xml, tmp; + try { + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + } catch( e ) { + xml = undefined; + } + if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; + }; +jQuery.post = function( url, data, callback, type ) { +/// +/// Load data from the server using a HTTP POST request. +/// +/// +/// A string containing the URL to which the request is sent. +/// +/// +/// A map or string that is sent to the server with the request. +/// +/// +/// A callback function that is executed if the request succeeds. +/// +/// +/// The type of data expected from the server. Default: Intelligent Guess (xml, json, script, or html). +/// + + // shift arguments if data argument was omitted + if ( jQuery.isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + return jQuery.ajax({ + type: method, + url: url, + data: data, + success: callback, + dataType: type + }); + }; +jQuery.prop = function( elem, name, value ) { + + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + return ( elem[ name ] = value ); + } + + } else { + if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + return elem[ name ]; + } + } + }; +jQuery.propFix = { "tabindex": 'tabIndex', +"readonly": 'readOnly', +"for": 'htmlFor', +"class": 'className', +"maxlength": 'maxLength', +"cellspacing": 'cellSpacing', +"cellpadding": 'cellPadding', +"rowspan": 'rowSpan', +"colspan": 'colSpan', +"usemap": 'useMap', +"frameborder": 'frameBorder', +"contenteditable": 'contentEditable' }; +jQuery.propHooks = { "tabIndex": {}, +"selected": {} }; +jQuery.proxy = function( fn, context ) { +/// +/// Takes a function and returns a new one that will always have a particular context. +/// 1 - jQuery.proxy(function, context) +/// 2 - jQuery.proxy(context, name) +/// +/// +/// The function whose context will be changed. +/// +/// +/// The object to which the context (this) of the function should be set. +/// +/// + + if ( typeof context === "string" ) { + var tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + var args = slice.call( arguments, 2 ), + proxy = function() { + return fn.apply( context, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + + return proxy; + }; +jQuery.queue = function( elem, type, data ) { +/// +/// 1: Show the queue of functions to be executed on the matched element. +/// 1.1 - jQuery.queue(element, queueName) +/// 2: Manipulate the queue of functions to be executed on the matched element. +/// 2.1 - jQuery.queue(element, queueName, newQueue) +/// 2.2 - jQuery.queue(element, queueName, callback()) +/// +/// +/// A DOM element where the array of queued functions is attached. +/// +/// +/// A string containing the name of the queue. Defaults to fx, the standard effects queue. +/// +/// +/// An array of functions to replace the current queue contents. +/// +/// + + var q; + if ( elem ) { + type = ( type || "fx" ) + "queue"; + q = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !q || jQuery.isArray(data) ) { + q = jQuery._data( elem, type, jQuery.makeArray(data) ); + } else { + q.push( data ); + } + } + return q || []; + } + }; +jQuery.ready = function( wait ) { + + // Either a released hold or an DOMready/load event and not yet ready + if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 1 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.fireWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger( "ready" ).off( "ready" ); + } + } + }; +jQuery.readyWait = 0; +jQuery.removeAttr = function( elem, value ) { + + var propName, attrNames, name, l, + i = 0; + + if ( value && elem.nodeType === 1 ) { + attrNames = value.toLowerCase().split( rspace ); + l = attrNames.length; + + for ( ; i < l; i++ ) { + name = attrNames[ i ]; + + if ( name ) { + propName = jQuery.propFix[ name ] || name; + + // See #9699 for explanation of this approach (setting first, then removal) + jQuery.attr( elem, name, "" ); + elem.removeAttribute( getSetAttribute ? name : propName ); + + // Set corresponding property to false for boolean attributes + if ( rboolean.test( name ) && propName in elem ) { + elem[ propName ] = false; + } + } + } + } + }; +jQuery.removeData = function( elem, name, pvt /* Internal Use Only */ ) { +/// +/// Remove a previously-stored piece of data. +/// +/// +/// A DOM element from which to remove data. +/// +/// +/// A string naming the piece of data to remove. +/// +/// + + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, i, l, + + // Reference to internal data cache key + internalKey = jQuery.expando, + + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + + // See jQuery.data for more information + id = isNode ? elem[ internalKey ] : internalKey; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split( " " ); + } + } + } + + for ( i = 0, l = name.length; i < l; i++ ) { + delete thisCache[ name[i] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject(cache[ id ]) ) { + return; + } + } + + // Browsers that fail expando deletion also refuse to delete expandos on + // the window, but it will allow it on all other JS objects; other browsers + // don't care + // Ensure that `cache` is not a window object #10080 + if ( jQuery.support.deleteExpando || !cache.setInterval ) { + delete cache[ id ]; + } else { + cache[ id ] = null; + } + + // We destroyed the cache and need to eliminate the expando on the node to avoid + // false lookups in the cache for entries that no longer exist + if ( isNode ) { + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( jQuery.support.deleteExpando ) { + delete elem[ internalKey ]; + } else if ( elem.removeAttribute ) { + elem.removeAttribute( internalKey ); + } else { + elem[ internalKey ] = null; + } + } + }; +jQuery.removeEvent = function( elem, type, handle ) { + + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + }; +jQuery.sibling = function( n, elem ) { + + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + }; +jQuery.speed = function( speed, easing, fn ) { + + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + jQuery.isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing + }; + + opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration : + opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default; + + // normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function( noUnmark ) { + if ( jQuery.isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } else if ( noUnmark !== false ) { + jQuery._unmark( this ); + } + }; + + return opt; + }; +jQuery.style = function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, origName = jQuery.camelCase( name ), + style = elem.style, hooks = jQuery.cssHooks[ origName ]; + + name = jQuery.cssProps[ origName ] || origName; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // convert relative number strings (+= or -=) to relative numbers. #7345 + if ( type === "string" && (ret = rrelNum.exec( value )) ) { + value = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) ); + // Fixes bug #9237 + type = "number"; + } + + // Make sure that NaN and null values aren't set. See: #7116 + if ( value == null || type === "number" && isNaN( value ) ) { + return; + } + + // If a number was passed in, add 'px' to the (except for certain CSS properties) + if ( type === "number" && !jQuery.cssNumber[ origName ] ) { + value += "px"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) { + // Wrapped to prevent IE from throwing errors when 'invalid' values are provided + // Fixes bug #5509 + try { + style[ name ] = value; + } catch(e) {} + } + + } else { + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }; +jQuery.sub = function() { +/// +/// Creates a new copy of jQuery whose properties and methods can be modified without affecting the original jQuery object. +/// +/// + + function jQuerySub( selector, context ) { + return new jQuerySub.fn.init( selector, context ); + } + jQuery.extend( true, jQuerySub, this ); + jQuerySub.superclass = this; + jQuerySub.fn = jQuerySub.prototype = this(); + jQuerySub.fn.constructor = jQuerySub; + jQuerySub.sub = this.sub; + jQuerySub.fn.init = function init( selector, context ) { + if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { + context = jQuerySub( context ); + } + + return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); + }; + jQuerySub.fn.init.prototype = jQuerySub.fn; + var rootjQuerySub = jQuerySub(document); + return jQuerySub; + }; +jQuery.support = { "leadingWhitespace": true, +"tbody": true, +"htmlSerialize": true, +"style": true, +"hrefNormalized": true, +"opacity": true, +"cssFloat": true, +"checkOn": true, +"optSelected": false, +"getSetAttribute": true, +"enctype": true, +"html5Clone": true, +"submitBubbles": true, +"changeBubbles": true, +"focusinBubbles": true, +"deleteExpando": true, +"noCloneEvent": true, +"inlineBlockNeedsLayout": false, +"shrinkWrapBlocks": false, +"reliableMarginRight": true, +"noCloneChecked": false, +"optDisabled": true, +"radioValue": false, +"checkClone": true, +"appendChecked": true, +"ajax": true, +"cors": false, +"reliableHiddenOffsets": true, +"boxModel": true, +"doesNotAddBorder": true, +"doesAddBorderForTableAndCells": true, +"fixedPosition": true, +"subtractsBorderForOverflowNotVisible": false, +"doesNotIncludeMarginInBodyOffset": true }; +jQuery.swap = function( elem, options, callback ) { + + var old = {}; + + // Remember the old values, and insert the new ones + for ( var name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + }; +jQuery.text = function( elem ) { + + var i, node, + nodeType = elem.nodeType, + ret = ""; + + if ( nodeType ) { + if ( nodeType === 1 || nodeType === 9 ) { + // Use textContent || innerText for elements + if ( typeof elem.textContent === 'string' ) { + return elem.textContent; + } else if ( typeof elem.innerText === 'string' ) { + // Replace IE's carriage returns + return elem.innerText.replace( rReturn, '' ); + } else { + // Traverse it's children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + } else { + + // If no nodeType, this is expected to be an array + for ( i = 0; (node = elem[i]); i++ ) { + // Do not traverse comment nodes + if ( node.nodeType !== 8 ) { + ret += getText( node ); + } + } + } + return ret; +}; +jQuery.trim = function( text ) { +/// +/// Remove the whitespace from the beginning and end of a string. +/// +/// +/// The string to trim. +/// +/// + + return text == null ? + "" : + trim.call( text ); + }; +jQuery.type = function( obj ) { +/// +/// Determine the internal JavaScript [[Class]] of an object. +/// +/// +/// Object to get the internal JavaScript [[Class]] of. +/// +/// + + return obj == null ? + String( obj ) : + class2type[ toString.call(obj) ] || "object"; + }; +jQuery.uaMatch = function( ua ) { + + ua = ua.toLowerCase(); + + var match = rwebkit.exec( ua ) || + ropera.exec( ua ) || + rmsie.exec( ua ) || + ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }; +jQuery.unique = function( results ) { +/// +/// Sorts an array of DOM elements, in place, with the duplicates removed. Note that this only works on arrays of DOM elements, not strings or numbers. +/// +/// +/// The Array of DOM elements. +/// +/// + + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[ i - 1 ] ) { + results.splice( i--, 1 ); + } + } + } + } + + return results; +}; +jQuery.uuid = 0; +jQuery.valHooks = { "option": {}, +"select": {}, +"radio": {}, +"checkbox": {} }; +jQuery.when = function( firstParam ) { +/// +/// Provides a way to execute callback functions based on one or more objects, usually Deferred objects that represent asynchronous events. +/// +/// +/// One or more Deferred objects, or plain JavaScript objects. +/// +/// + + var args = sliceDeferred.call( arguments, 0 ), + i = 0, + length = args.length, + pValues = new Array( length ), + count = length, + pCount = length, + deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? + firstParam : + jQuery.Deferred(), + promise = deferred.promise(); + function resolveFunc( i ) { + return function( value ) { + args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + if ( !( --count ) ) { + deferred.resolveWith( deferred, args ); + } + }; + } + function progressFunc( i ) { + return function( value ) { + pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + deferred.notifyWith( promise, pValues ); + }; + } + if ( length > 1 ) { + for ( ; i < length; i++ ) { + if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) { + args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) ); + } else { + --count; + } + } + if ( !count ) { + deferred.resolveWith( deferred, args ); + } + } else if ( deferred !== firstParam ) { + deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); + } + return promise; + }; +jQuery.Event.prototype.isDefaultPrevented = function returnFalse() { +/// +/// Returns whether event.preventDefault() was ever called on this event object. +/// +/// + + return false; +}; +jQuery.Event.prototype.isImmediatePropagationStopped = function returnFalse() { +/// +/// Returns whether event.stopImmediatePropagation() was ever called on this event object. +/// +/// + + return false; +}; +jQuery.Event.prototype.isPropagationStopped = function returnFalse() { +/// +/// Returns whether event.stopPropagation() was ever called on this event object. +/// +/// + + return false; +}; +jQuery.Event.prototype.preventDefault = function() { +/// +/// If this method is called, the default action of the event will not be triggered. +/// +/// + + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // otherwise set the returnValue property of the original event to false (IE) + } else { + e.returnValue = false; + } + }; +jQuery.Event.prototype.stopImmediatePropagation = function() { +/// +/// Keeps the rest of the handlers from being executed and prevents the event from bubbling up the DOM tree. +/// + + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }; +jQuery.Event.prototype.stopPropagation = function() { +/// +/// Prevents the event from bubbling up the DOM tree, preventing any parent handlers from being notified of the event. +/// + + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }; +jQuery.prototype._toggle = function( fn ) { + + // Save reference to arguments for access in closure + var args = arguments, + guid = fn.guid || jQuery.guid++, + i = 0, + toggler = function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + }; + + // link all the functions, so any of them can unbind this click handler + toggler.guid = guid; + while ( i < args.length ) { + args[ i++ ].guid = guid; + } + + return this.click( toggler ); + }; +jQuery.prototype.add = function( selector, context ) { +/// +/// Add elements to the set of matched elements. +/// 1 - add(selector) +/// 2 - add(elements) +/// 3 - add(html) +/// 4 - add(jQuery object) +/// 5 - add(selector, context) +/// +/// +/// A string representing a selector expression to find additional elements to add to the set of matched elements. +/// +/// +/// The point in the document at which the selector should begin matching; similar to the context argument of the $(selector, context) method. +/// +/// + + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }; +jQuery.prototype.addClass = function( value ) { +/// +/// Adds the specified class(es) to each of the set of matched elements. +/// 1 - addClass(className) +/// 2 - addClass(function(index, currentClass)) +/// +/// +/// One or more class names to be added to the class attribute of each matched element. +/// +/// + + var classNames, i, l, elem, + setClass, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call(this, j, this.className) ); + }); + } + + if ( value && typeof value === "string" ) { + classNames = value.split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className && classNames.length === 1 ) { + elem.className = value; + + } else { + setClass = " " + elem.className + " "; + + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { + setClass += classNames[ c ] + " "; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }; +jQuery.prototype.after = function() { +/// +/// Insert content, specified by the parameter, after each element in the set of matched elements. +/// 1 - after(content, content) +/// 2 - after(function(index)) +/// +/// +/// HTML string, DOM element, or jQuery object to insert after each element in the set of matched elements. +/// +/// +/// One or more additional DOM elements, arrays of elements, HTML strings, or jQuery objects to insert after each element in the set of matched elements. +/// +/// + + if ( this[0] && this[0].parentNode ) { + return this.domManip(arguments, false, function( elem ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + }); + } else if ( arguments.length ) { + var set = this.pushStack( this, "after", arguments ); + set.push.apply( set, jQuery.clean(arguments) ); + return set; + } + }; +jQuery.prototype.ajaxComplete = function( f ){ +/// +/// Register a handler to be called when Ajax requests complete. This is an Ajax Event. +/// +/// +/// The function to be invoked. +/// +/// + + return this.on( o, f ); + }; +jQuery.prototype.ajaxError = function( f ){ +/// +/// Register a handler to be called when Ajax requests complete with an error. This is an Ajax Event. +/// +/// +/// The function to be invoked. +/// +/// + + return this.on( o, f ); + }; +jQuery.prototype.ajaxSend = function( f ){ +/// +/// Attach a function to be executed before an Ajax request is sent. This is an Ajax Event. +/// +/// +/// The function to be invoked. +/// +/// + + return this.on( o, f ); + }; +jQuery.prototype.ajaxStart = function( f ){ +/// +/// Register a handler to be called when the first Ajax request begins. This is an Ajax Event. +/// +/// +/// The function to be invoked. +/// +/// + + return this.on( o, f ); + }; +jQuery.prototype.ajaxStop = function( f ){ +/// +/// Register a handler to be called when all Ajax requests have completed. This is an Ajax Event. +/// +/// +/// The function to be invoked. +/// +/// + + return this.on( o, f ); + }; +jQuery.prototype.ajaxSuccess = function( f ){ +/// +/// Attach a function to be executed whenever an Ajax request completes successfully. This is an Ajax Event. +/// +/// +/// The function to be invoked. +/// +/// + + return this.on( o, f ); + }; +jQuery.prototype.andSelf = function() { +/// +/// Add the previous set of elements on the stack to the current set. +/// +/// + + return this.add( this.prevObject ); + }; +jQuery.prototype.animate = function( prop, speed, easing, callback ) { +/// +/// Perform a custom animation of a set of CSS properties. +/// 1 - animate(properties, duration, easing, complete) +/// 2 - animate(properties, options) +/// +/// +/// A map of CSS properties that the animation will move toward. +/// +/// +/// A string or number determining how long the animation will run. +/// +/// +/// A string indicating which easing function to use for the transition. +/// +/// +/// A function to call once the animation is complete. +/// +/// + + var optall = jQuery.speed( speed, easing, callback ); + + if ( jQuery.isEmptyObject( prop ) ) { + return this.each( optall.complete, [ false ] ); + } + + // Do not change referenced properties as per-property easing will be lost + prop = jQuery.extend( {}, prop ); + + function doAnimation() { + // XXX 'this' does not always have a nodeName when running the + // test suite + + if ( optall.queue === false ) { + jQuery._mark( this ); + } + + var opt = jQuery.extend( {}, optall ), + isElement = this.nodeType === 1, + hidden = isElement && jQuery(this).is(":hidden"), + name, val, p, e, + parts, start, end, unit, + method; + + // will store per property easing and be used to determine when an animation is complete + opt.animatedProperties = {}; + + for ( p in prop ) { + + // property name normalization + name = jQuery.camelCase( p ); + if ( p !== name ) { + prop[ name ] = prop[ p ]; + delete prop[ p ]; + } + + val = prop[ name ]; + + // easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default) + if ( jQuery.isArray( val ) ) { + opt.animatedProperties[ name ] = val[ 1 ]; + val = prop[ name ] = val[ 0 ]; + } else { + opt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing'; + } + + if ( val === "hide" && hidden || val === "show" && !hidden ) { + return opt.complete.call( this ); + } + + if ( isElement && ( name === "height" || name === "width" ) ) { + // Make sure that nothing sneaks out + // Record all 3 overflow attributes because IE does not + // change the overflow attribute when overflowX and + // overflowY are set to the same value + opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ]; + + // Set display property to inline-block for height/width + // animations on inline elements that are having width/height animated + if ( jQuery.css( this, "display" ) === "inline" && + jQuery.css( this, "float" ) === "none" ) { + + // inline-level elements accept inline-block; + // block-level elements need to be inline with layout + if ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === "inline" ) { + this.style.display = "inline-block"; + + } else { + this.style.zoom = 1; + } + } + } + } + + if ( opt.overflow != null ) { + this.style.overflow = "hidden"; + } + + for ( p in prop ) { + e = new jQuery.fx( this, opt, p ); + val = prop[ p ]; + + if ( rfxtypes.test( val ) ) { + + // Tracks whether to show or hide based on private + // data attached to the element + method = jQuery._data( this, "toggle" + p ) || ( val === "toggle" ? hidden ? "show" : "hide" : 0 ); + if ( method ) { + jQuery._data( this, "toggle" + p, method === "show" ? "hide" : "show" ); + e[ method ](); + } else { + e[ val ](); + } + + } else { + parts = rfxnum.exec( val ); + start = e.cur(); + + if ( parts ) { + end = parseFloat( parts[2] ); + unit = parts[3] || ( jQuery.cssNumber[ p ] ? "" : "px" ); + + // We need to compute starting value + if ( unit !== "px" ) { + jQuery.style( this, p, (end || 1) + unit); + start = ( (end || 1) / e.cur() ) * start; + jQuery.style( this, p, start + unit); + } + + // If a +=/-= token was provided, we're doing a relative animation + if ( parts[1] ) { + end = ( (parts[ 1 ] === "-=" ? -1 : 1) * end ) + start; + } + + e.custom( start, end, unit ); + + } else { + e.custom( start, val, "" ); + } + } + } + + // For JS strict compliance + return true; + } + + return optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }; +jQuery.prototype.append = function() { +/// +/// Insert content, specified by the parameter, to the end of each element in the set of matched elements. +/// 1 - append(content, content) +/// 2 - append(function(index, html)) +/// +/// +/// DOM element, HTML string, or jQuery object to insert at the end of each element in the set of matched elements. +/// +/// +/// One or more additional DOM elements, arrays of elements, HTML strings, or jQuery objects to insert at the end of each element in the set of matched elements. +/// +/// + + return this.domManip(arguments, true, function( elem ) { + if ( this.nodeType === 1 ) { + this.appendChild( elem ); + } + }); + }; +jQuery.prototype.appendTo = function( selector ) { +/// +/// Insert every element in the set of matched elements to the end of the target. +/// +/// +/// A selector, element, HTML string, or jQuery object; the matched set of elements will be inserted at the end of the element(s) specified by this parameter. +/// +/// + + var ret = [], + insert = jQuery( selector ), + parent = this.length === 1 && this[0].parentNode; + + if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) { + insert[ original ]( this[0] ); + return this; + + } else { + for ( var i = 0, l = insert.length; i < l; i++ ) { + var elems = ( i > 0 ? this.clone(true) : this ).get(); + jQuery( insert[i] )[ original ]( elems ); + ret = ret.concat( elems ); + } + + return this.pushStack( ret, name, insert.selector ); + } + }; +jQuery.prototype.attr = function( name, value ) { +/// +/// 1: Get the value of an attribute for the first element in the set of matched elements. +/// 1.1 - attr(attributeName) +/// 2: Set one or more attributes for the set of matched elements. +/// 2.1 - attr(attributeName, value) +/// 2.2 - attr(map) +/// 2.3 - attr(attributeName, function(index, attr)) +/// +/// +/// The name of the attribute to set. +/// +/// +/// A value to set for the attribute. +/// +/// + + return jQuery.access( this, name, value, true, jQuery.attr ); + }; +jQuery.prototype.before = function() { +/// +/// Insert content, specified by the parameter, before each element in the set of matched elements. +/// 1 - before(content, content) +/// 2 - before(function) +/// +/// +/// HTML string, DOM element, or jQuery object to insert before each element in the set of matched elements. +/// +/// +/// One or more additional DOM elements, arrays of elements, HTML strings, or jQuery objects to insert before each element in the set of matched elements. +/// +/// + + if ( this[0] && this[0].parentNode ) { + return this.domManip(arguments, false, function( elem ) { + this.parentNode.insertBefore( elem, this ); + }); + } else if ( arguments.length ) { + var set = jQuery.clean( arguments ); + set.push.apply( set, this.toArray() ); + return this.pushStack( set, "before", arguments ); + } + }; +jQuery.prototype.bind = function( types, data, fn ) { +/// +/// Attach a handler to an event for the elements. +/// 1 - bind(eventType, eventData, handler(eventObject)) +/// 2 - bind(eventType, eventData, preventBubble) +/// 3 - bind(events) +/// +/// +/// A string containing one or more DOM event types, such as "click" or "submit," or custom event names. +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + return this.on( types, null, data, fn ); + }; +jQuery.prototype.blur = function( data, fn ) { +/// +/// Bind an event handler to the "blur" JavaScript event, or trigger that event on an element. +/// 1 - blur(handler(eventObject)) +/// 2 - blur(eventData, handler(eventObject)) +/// 3 - blur() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.change = function( data, fn ) { +/// +/// Bind an event handler to the "change" JavaScript event, or trigger that event on an element. +/// 1 - change(handler(eventObject)) +/// 2 - change(eventData, handler(eventObject)) +/// 3 - change() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.children = function( until, selector ) { +/// +/// Get the children of each element in the set of matched elements, optionally filtered by a selector. +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, slice.call( arguments ).join(",") ); + }; +jQuery.prototype.clearQueue = function( type ) { +/// +/// Remove from the queue all items that have not yet been run. +/// +/// +/// A string containing the name of the queue. Defaults to fx, the standard effects queue. +/// +/// + + return this.queue( type || "fx", [] ); + }; +jQuery.prototype.click = function( data, fn ) { +/// +/// Bind an event handler to the "click" JavaScript event, or trigger that event on an element. +/// 1 - click(handler(eventObject)) +/// 2 - click(eventData, handler(eventObject)) +/// 3 - click() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.clone = function( dataAndEvents, deepDataAndEvents ) { +/// +/// Create a deep copy of the set of matched elements. +/// 1 - clone(withDataAndEvents) +/// 2 - clone(withDataAndEvents, deepWithDataAndEvents) +/// +/// +/// A Boolean indicating whether event handlers and data should be copied along with the elements. The default value is false. *In jQuery 1.5.0 the default value was incorrectly true; it was changed back to false in 1.5.1 and up. +/// +/// +/// A Boolean indicating whether event handlers and data for all children of the cloned element should be copied. By default its value matches the first argument's value (which defaults to false). +/// +/// + + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function () { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + }); + }; +jQuery.prototype.closest = function( selectors, context ) { +/// +/// 1: Get the first element that matches the selector, beginning at the current element and progressing up through the DOM tree. +/// 1.1 - closest(selector) +/// 1.2 - closest(selector, context) +/// 1.3 - closest(jQuery object) +/// 1.4 - closest(element) +/// 2: Gets an array of all the elements and selectors matched against the current element up through the DOM tree. +/// 2.1 - closest(selectors, context) +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// +/// A DOM element within which a matching element may be found. If no context is passed in then the context of the jQuery set will be used instead. +/// +/// + + var ret = [], i, l, cur = this[0]; + + // Array (deprecated as of jQuery 1.7) + if ( jQuery.isArray( selectors ) ) { + var level = 1; + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( i = 0; i < selectors.length; i++ ) { + + if ( jQuery( cur ).is( selectors[ i ] ) ) { + ret.push({ selector: selectors[ i ], elem: cur, level: level }); + } + } + + cur = cur.parentNode; + level++; + } + + return ret; + } + + // String + var pos = POS.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( i = 0, l = this.length; i < l; i++ ) { + cur = this[i]; + + while ( cur ) { + if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + + } else { + cur = cur.parentNode; + if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { + break; + } + } + } + } + + ret = ret.length > 1 ? jQuery.unique( ret ) : ret; + + return this.pushStack( ret, "closest", selectors ); + }; +jQuery.prototype.constructor = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }; +jQuery.prototype.contents = function( until, selector ) { +/// +/// Get the children of each element in the set of matched elements, including text and comment nodes. +/// +/// + + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, slice.call( arguments ).join(",") ); + }; +jQuery.prototype.contextmenu = function( data, fn ) { + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.css = function( name, value ) { +/// +/// 1: Get the value of a style property for the first element in the set of matched elements. +/// 1.1 - css(propertyName) +/// 2: Set one or more CSS properties for the set of matched elements. +/// 2.1 - css(propertyName, value) +/// 2.2 - css(propertyName, function(index, value)) +/// 2.3 - css(map) +/// +/// +/// A CSS property name. +/// +/// +/// A value to set for the property. +/// +/// + + // Setting 'undefined' is a no-op + if ( arguments.length === 2 && value === undefined ) { + return this; + } + + return jQuery.access( this, name, value, true, function( elem, name, value ) { + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }); +}; +jQuery.prototype.data = function( key, value ) { +/// +/// 1: Store arbitrary data associated with the matched elements. +/// 1.1 - data(key, value) +/// 1.2 - data(obj) +/// 2: Returns value at named data store for the first element in the jQuery collection, as set by data(name, value). +/// 2.1 - data(key) +/// 2.2 - data() +/// +/// +/// A string naming the piece of data to set. +/// +/// +/// The new data value; it can be any Javascript type including Array or Object. +/// +/// + + var parts, attr, name, + data = null; + + if ( typeof key === "undefined" ) { + if ( this.length ) { + data = jQuery.data( this[0] ); + + if ( this[0].nodeType === 1 && !jQuery._data( this[0], "parsedAttrs" ) ) { + attr = this[0].attributes; + for ( var i = 0, l = attr.length; i < l; i++ ) { + name = attr[i].name; + + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.substring(5) ); + + dataAttr( this[0], name, data[ name ] ); + } + } + jQuery._data( this[0], "parsedAttrs", true ); + } + } + + return data; + + } else if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value === undefined ) { + data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + // Try to fetch any internally stored data first + if ( data === undefined && this.length ) { + data = jQuery.data( this[0], key ); + data = dataAttr( this[0], key, data ); + } + + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + + } else { + return this.each(function() { + var self = jQuery( this ), + args = [ parts[0], value ]; + + self.triggerHandler( "setData" + parts[1] + "!", args ); + jQuery.data( this, key, value ); + self.triggerHandler( "changeData" + parts[1] + "!", args ); + }); + } + }; +jQuery.prototype.dblclick = function( data, fn ) { +/// +/// Bind an event handler to the "dblclick" JavaScript event, or trigger that event on an element. +/// 1 - dblclick(handler(eventObject)) +/// 2 - dblclick(eventData, handler(eventObject)) +/// 3 - dblclick() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.delay = function( time, type ) { +/// +/// Set a timer to delay execution of subsequent items in the queue. +/// +/// +/// An integer indicating the number of milliseconds to delay execution of the next item in the queue. +/// +/// +/// A string containing the name of the queue. Defaults to fx, the standard effects queue. +/// +/// + + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = setTimeout( next, time ); + hooks.stop = function() { + clearTimeout( timeout ); + }; + }); + }; +jQuery.prototype.delegate = function( selector, types, data, fn ) { +/// +/// Attach a handler to one or more events for all elements that match the selector, now or in the future, based on a specific set of root elements. +/// 1 - delegate(selector, eventType, handler) +/// 2 - delegate(selector, eventType, eventData, handler) +/// 3 - delegate(selector, events) +/// +/// +/// A selector to filter the elements that trigger the event. +/// +/// +/// A string containing one or more space-separated JavaScript event types, such as "click" or "keydown," or custom event names. +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute at the time the event is triggered. +/// +/// + + return this.on( types, selector, data, fn ); + }; +jQuery.prototype.dequeue = function( type ) { +/// +/// Execute the next function on the queue for the matched elements. +/// +/// +/// A string containing the name of the queue. Defaults to fx, the standard effects queue. +/// +/// + + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }; +jQuery.prototype.detach = function( selector ) { +/// +/// Remove the set of matched elements from the DOM. +/// +/// +/// A selector expression that filters the set of matched elements to be removed. +/// +/// + + return this.remove( selector, true ); + }; +jQuery.prototype.die = function( types, fn ) { +/// +/// 1: Remove all event handlers previously attached using .live() from the elements. +/// 1.1 - die() +/// 2: Remove an event handler previously attached using .live() from the elements. +/// 2.1 - die(eventType, handler) +/// 2.2 - die(eventTypes) +/// +/// +/// A string containing a JavaScript event type, such as click or keydown. +/// +/// +/// The function that is no longer to be executed. +/// +/// + + jQuery( this.context ).off( types, this.selector || "**", fn ); + return this; + }; +jQuery.prototype.domManip = function( args, table, callback ) { + + var results, first, fragment, parent, + value = args[0], + scripts = []; + + // We can't cloneNode fragments that contain checked, in WebKit + if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) { + return this.each(function() { + jQuery(this).domManip( args, table, callback, true ); + }); + } + + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + args[0] = value.call(this, i, table ? self.html() : undefined); + self.domManip( args, table, callback ); + }); + } + + if ( this[0] ) { + parent = value && value.parentNode; + + // If we're in a fragment, just use that instead of building a new one + if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) { + results = { fragment: parent }; + + } else { + results = jQuery.buildFragment( args, this, scripts ); + } + + fragment = results.fragment; + + if ( fragment.childNodes.length === 1 ) { + first = fragment = fragment.firstChild; + } else { + first = fragment.firstChild; + } + + if ( first ) { + table = table && jQuery.nodeName( first, "tr" ); + + for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) { + callback.call( + table ? + root(this[i], first) : + this[i], + // Make sure that we do not leak memory by inadvertently discarding + // the original fragment (which might have attached data) instead of + // using it; in addition, use the original fragment object for the last + // item instead of first because it can end up being emptied incorrectly + // in certain situations (Bug #8070). + // Fragments from the fragment cache must always be cloned and never used + // in place. + results.cacheable || ( l > 1 && i < lastIndex ) ? + jQuery.clone( fragment, true, true ) : + fragment + ); + } + } + + if ( scripts.length ) { + jQuery.each( scripts, evalScript ); + } + } + + return this; + }; +jQuery.prototype.each = function( callback, args ) { +/// +/// Iterate over a jQuery object, executing a function for each matched element. +/// +/// +/// A function to execute for each matched element. +/// +/// + + return jQuery.each( this, callback, args ); + }; +jQuery.prototype.empty = function() { +/// +/// Remove all child nodes of the set of matched elements from the DOM. +/// +/// + + for ( var i = 0, elem; (elem = this[i]) != null; i++ ) { + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( elem.getElementsByTagName("*") ); + } + + // Remove any remaining nodes + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + } + + return this; + }; +jQuery.prototype.end = function() { +/// +/// End the most recent filtering operation in the current chain and return the set of matched elements to its previous state. +/// +/// + + return this.prevObject || this.constructor(null); + }; +jQuery.prototype.eq = function( i ) { +/// +/// Reduce the set of matched elements to the one at the specified index. +/// 1 - eq(index) +/// 2 - eq(-index) +/// +/// +/// An integer indicating the 0-based position of the element. +/// +/// + + i = +i; + return i === -1 ? + this.slice( i ) : + this.slice( i, i + 1 ); + }; +jQuery.prototype.error = function( data, fn ) { +/// +/// Bind an event handler to the "error" JavaScript event. +/// 1 - error(handler(eventObject)) +/// 2 - error(eventData, handler(eventObject)) +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.extend = function() { + + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; +jQuery.prototype.fadeIn = function( speed, easing, callback ) { +/// +/// Display the matched elements by fading them to opaque. +/// 1 - fadeIn(duration, callback) +/// 2 - fadeIn(duration, easing, callback) +/// +/// +/// A string or number determining how long the animation will run. +/// +/// +/// A string indicating which easing function to use for the transition. +/// +/// +/// A function to call once the animation is complete. +/// +/// + + return this.animate( props, speed, easing, callback ); + }; +jQuery.prototype.fadeOut = function( speed, easing, callback ) { +/// +/// Hide the matched elements by fading them to transparent. +/// 1 - fadeOut(duration, callback) +/// 2 - fadeOut(duration, easing, callback) +/// +/// +/// A string or number determining how long the animation will run. +/// +/// +/// A string indicating which easing function to use for the transition. +/// +/// +/// A function to call once the animation is complete. +/// +/// + + return this.animate( props, speed, easing, callback ); + }; +jQuery.prototype.fadeTo = function( speed, to, easing, callback ) { +/// +/// Adjust the opacity of the matched elements. +/// 1 - fadeTo(duration, opacity, callback) +/// 2 - fadeTo(duration, opacity, easing, callback) +/// +/// +/// A string or number determining how long the animation will run. +/// +/// +/// A number between 0 and 1 denoting the target opacity. +/// +/// +/// A string indicating which easing function to use for the transition. +/// +/// +/// A function to call once the animation is complete. +/// +/// + + return this.filter(":hidden").css("opacity", 0).show().end() + .animate({opacity: to}, speed, easing, callback); + }; +jQuery.prototype.fadeToggle = function( speed, easing, callback ) { +/// +/// Display or hide the matched elements by animating their opacity. +/// +/// +/// A string or number determining how long the animation will run. +/// +/// +/// A string indicating which easing function to use for the transition. +/// +/// +/// A function to call once the animation is complete. +/// +/// + + return this.animate( props, speed, easing, callback ); + }; +jQuery.prototype.filter = function( selector ) { +/// +/// Reduce the set of matched elements to those that match the selector or pass the function's test. +/// 1 - filter(selector) +/// 2 - filter(function(index)) +/// 3 - filter(element) +/// 4 - filter(jQuery object) +/// +/// +/// A string containing a selector expression to match the current set of elements against. +/// +/// + + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }; +jQuery.prototype.find = function( selector ) { +/// +/// Get the descendants of each element in the current set of matched elements, filtered by a selector, jQuery object, or element. +/// 1 - find(selector) +/// 2 - find(jQuery object) +/// 3 - find(element) +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + var self = this, + i, l; + + if ( typeof selector !== "string" ) { + return jQuery( selector ).filter(function() { + for ( i = 0, l = self.length; i < l; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }); + } + + var ret = this.pushStack( "", "find", selector ), + length, n, r; + + for ( i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( n = length; n < ret.length; n++ ) { + for ( r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }; +jQuery.prototype.first = function() { +/// +/// Reduce the set of matched elements to the first in the set. +/// +/// + + return this.eq( 0 ); + }; +jQuery.prototype.focus = function( data, fn ) { +/// +/// Bind an event handler to the "focus" JavaScript event, or trigger that event on an element. +/// 1 - focus(handler(eventObject)) +/// 2 - focus(eventData, handler(eventObject)) +/// 3 - focus() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.focusin = function( data, fn ) { +/// +/// Bind an event handler to the "focusin" event. +/// 1 - focusin(handler(eventObject)) +/// 2 - focusin(eventData, handler(eventObject)) +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.focusout = function( data, fn ) { +/// +/// Bind an event handler to the "focusout" JavaScript event. +/// 1 - focusout(handler(eventObject)) +/// 2 - focusout(eventData, handler(eventObject)) +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.get = function( num ) { +/// +/// Retrieve the DOM elements matched by the jQuery object. +/// +/// +/// A zero-based integer indicating which element to retrieve. +/// +/// + + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }; +jQuery.prototype.has = function( target ) { +/// +/// Reduce the set of matched elements to those that have a descendant that matches the selector or DOM element. +/// 1 - has(selector) +/// 2 - has(contained) +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }; +jQuery.prototype.hasClass = function( selector ) { +/// +/// Determine whether any of the matched elements are assigned the given class. +/// +/// +/// The class name to search for. +/// +/// + + var className = " " + selector + " ", + i = 0, + l = this.length; + for ( ; i < l; i++ ) { + if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }; +jQuery.prototype.height = function( size ) { +/// +/// 1: Get the current computed height for the first element in the set of matched elements. +/// 1.1 - height() +/// 2: Set the CSS height of every matched element. +/// 2.1 - height(value) +/// 2.2 - height(function(index, height)) +/// +/// +/// An integer representing the number of pixels, or an integer with an optional unit of measure appended (as a string). +/// +/// + + // Get window width or height + var elem = this[0]; + if ( !elem ) { + return size == null ? null : this; + } + + if ( jQuery.isFunction( size ) ) { + return this.each(function( i ) { + var self = jQuery( this ); + self[ type ]( size.call( this, i, self[ type ]() ) ); + }); + } + + if ( jQuery.isWindow( elem ) ) { + // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode + // 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat + var docElemProp = elem.document.documentElement[ "client" + name ], + body = elem.document.body; + return elem.document.compatMode === "CSS1Compat" && docElemProp || + body && body[ "client" + name ] || docElemProp; + + // Get document width or height + } else if ( elem.nodeType === 9 ) { + // Either scroll[Width/Height] or offset[Width/Height], whichever is greater + return Math.max( + elem.documentElement["client" + name], + elem.body["scroll" + name], elem.documentElement["scroll" + name], + elem.body["offset" + name], elem.documentElement["offset" + name] + ); + + // Get or set width or height on the element + } else if ( size === undefined ) { + var orig = jQuery.css( elem, type ), + ret = parseFloat( orig ); + + return jQuery.isNumeric( ret ) ? ret : orig; + + // Set the width or height on the element (default to pixels if value is unitless) + } else { + return this.css( type, typeof size === "string" ? size : size + "px" ); + } + }; +jQuery.prototype.hide = function( speed, easing, callback ) { +/// +/// Hide the matched elements. +/// 1 - hide() +/// 2 - hide(duration, callback) +/// 3 - hide(duration, easing, callback) +/// +/// +/// A string or number determining how long the animation will run. +/// +/// +/// A string indicating which easing function to use for the transition. +/// +/// +/// A function to call once the animation is complete. +/// +/// + + if ( speed || speed === 0 ) { + return this.animate( genFx("hide", 3), speed, easing, callback); + + } else { + var elem, display, + i = 0, + j = this.length; + + for ( ; i < j; i++ ) { + elem = this[i]; + if ( elem.style ) { + display = jQuery.css( elem, "display" ); + + if ( display !== "none" && !jQuery._data( elem, "olddisplay" ) ) { + jQuery._data( elem, "olddisplay", display ); + } + } + } + + // Set the display of the elements in a second loop + // to avoid the constant reflow + for ( i = 0; i < j; i++ ) { + if ( this[i].style ) { + this[i].style.display = "none"; + } + } + + return this; + } + }; +jQuery.prototype.hover = function( fnOver, fnOut ) { +/// +/// 1: Bind two handlers to the matched elements, to be executed when the mouse pointer enters and leaves the elements. +/// 1.1 - hover(handlerIn(eventObject), handlerOut(eventObject)) +/// 2: Bind a single handler to the matched elements, to be executed when the mouse pointer enters or leaves the elements. +/// 2.1 - hover(handlerInOut(eventObject)) +/// +/// +/// A function to execute when the mouse pointer enters the element. +/// +/// +/// A function to execute when the mouse pointer leaves the element. +/// +/// + + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + }; +jQuery.prototype.html = function( value ) { +/// +/// 1: Get the HTML contents of the first element in the set of matched elements. +/// 1.1 - html() +/// 2: Set the HTML contents of each element in the set of matched elements. +/// 2.1 - html(htmlString) +/// 2.2 - html(function(index, oldhtml)) +/// +/// +/// A string of HTML to set as the content of each matched element. +/// +/// + + if ( value === undefined ) { + return this[0] && this[0].nodeType === 1 ? + this[0].innerHTML.replace(rinlinejQuery, "") : + null; + + // See if we can take a shortcut and just use innerHTML + } else if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) && + !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) { + + value = value.replace(rxhtmlTag, "<$1>"); + + try { + for ( var i = 0, l = this.length; i < l; i++ ) { + // Remove element nodes and prevent memory leaks + if ( this[i].nodeType === 1 ) { + jQuery.cleanData( this[i].getElementsByTagName("*") ); + this[i].innerHTML = value; + } + } + + // If using innerHTML throws an exception, use the fallback method + } catch(e) { + this.empty().append( value ); + } + + } else if ( jQuery.isFunction( value ) ) { + this.each(function(i){ + var self = jQuery( this ); + + self.html( value.call(this, i, self.html()) ); + }); + + } else { + this.empty().append( value ); + } + + return this; + }; +jQuery.prototype.index = function( elem ) { +/// +/// Search for a given element from among the matched elements. +/// 1 - index() +/// 2 - index(selector) +/// 3 - index(element) +/// +/// +/// A selector representing a jQuery collection in which to look for an element. +/// +/// + + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }; +jQuery.prototype.init = function( selector, context, rootjQuery ) { + + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context && document.body ) { + this.context = document; + this[0] = document.body; + this.selector = selector; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = quickExpr.exec( selector ); + } + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + doc = ( context ? context.ownerDocument || context : document ); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }; +jQuery.prototype.innerHeight = function() { +/// +/// Get the current computed height for the first element in the set of matched elements, including padding but not border. +/// +/// + + var elem = this[0]; + return elem ? + elem.style ? + parseFloat( jQuery.css( elem, type, "padding" ) ) : + this[ type ]() : + null; + }; +jQuery.prototype.innerWidth = function() { +/// +/// Get the current computed width for the first element in the set of matched elements, including padding but not border. +/// +/// + + var elem = this[0]; + return elem ? + elem.style ? + parseFloat( jQuery.css( elem, type, "padding" ) ) : + this[ type ]() : + null; + }; +jQuery.prototype.insertAfter = function( selector ) { +/// +/// Insert every element in the set of matched elements after the target. +/// +/// +/// A selector, element, HTML string, or jQuery object; the matched set of elements will be inserted after the element(s) specified by this parameter. +/// +/// + + var ret = [], + insert = jQuery( selector ), + parent = this.length === 1 && this[0].parentNode; + + if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) { + insert[ original ]( this[0] ); + return this; + + } else { + for ( var i = 0, l = insert.length; i < l; i++ ) { + var elems = ( i > 0 ? this.clone(true) : this ).get(); + jQuery( insert[i] )[ original ]( elems ); + ret = ret.concat( elems ); + } + + return this.pushStack( ret, name, insert.selector ); + } + }; +jQuery.prototype.insertBefore = function( selector ) { +/// +/// Insert every element in the set of matched elements before the target. +/// +/// +/// A selector, element, HTML string, or jQuery object; the matched set of elements will be inserted before the element(s) specified by this parameter. +/// +/// + + var ret = [], + insert = jQuery( selector ), + parent = this.length === 1 && this[0].parentNode; + + if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) { + insert[ original ]( this[0] ); + return this; + + } else { + for ( var i = 0, l = insert.length; i < l; i++ ) { + var elems = ( i > 0 ? this.clone(true) : this ).get(); + jQuery( insert[i] )[ original ]( elems ); + ret = ret.concat( elems ); + } + + return this.pushStack( ret, name, insert.selector ); + } + }; +jQuery.prototype.is = function( selector ) { +/// +/// Check the current matched set of elements against a selector, element, or jQuery object and return true if at least one of these elements matches the given arguments. +/// 1 - is(selector) +/// 2 - is(function(index)) +/// 3 - is(jQuery object) +/// 4 - is(element) +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + return !!selector && ( + typeof selector === "string" ? + // If this is a positional selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + POS.test( selector ) ? + jQuery( selector, this.context ).index( this[0] ) >= 0 : + jQuery.filter( selector, this ).length > 0 : + this.filter( selector ).length > 0 ); + }; +jQuery.prototype.keydown = function( data, fn ) { +/// +/// Bind an event handler to the "keydown" JavaScript event, or trigger that event on an element. +/// 1 - keydown(handler(eventObject)) +/// 2 - keydown(eventData, handler(eventObject)) +/// 3 - keydown() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.keypress = function( data, fn ) { +/// +/// Bind an event handler to the "keypress" JavaScript event, or trigger that event on an element. +/// 1 - keypress(handler(eventObject)) +/// 2 - keypress(eventData, handler(eventObject)) +/// 3 - keypress() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.keyup = function( data, fn ) { +/// +/// Bind an event handler to the "keyup" JavaScript event, or trigger that event on an element. +/// 1 - keyup(handler(eventObject)) +/// 2 - keyup(eventData, handler(eventObject)) +/// 3 - keyup() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.last = function() { +/// +/// Reduce the set of matched elements to the final one in the set. +/// +/// + + return this.eq( -1 ); + }; +jQuery.prototype.length = 0; +jQuery.prototype.live = function( types, data, fn ) { +/// +/// Attach an event handler for all elements which match the current selector, now and in the future. +/// 1 - live(events, handler) +/// 2 - live(events, data, handler) +/// 3 - live(events-map) +/// +/// +/// A string containing a JavaScript event type, such as "click" or "keydown." As of jQuery 1.4 the string can contain multiple, space-separated event types or custom event names. +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute at the time the event is triggered. +/// +/// + + jQuery( this.context ).on( types, this.selector, data, fn ); + return this; + }; +jQuery.prototype.load = function( url, params, callback ) { +/// +/// 1: Bind an event handler to the "load" JavaScript event. +/// 1.1 - load(handler(eventObject)) +/// 1.2 - load(eventData, handler(eventObject)) +/// 2: Load data from the server and place the returned HTML into the matched element. +/// 2.1 - load(url, data, complete(responseText, textStatus, XMLHttpRequest)) +/// +/// +/// A string containing the URL to which the request is sent. +/// +/// +/// A map or string that is sent to the server with the request. +/// +/// +/// A callback function that is executed when the request completes. +/// +/// + + if ( typeof url !== "string" && _load ) { + return _load.apply( this, arguments ); + + // Don't do a request if no elements are being requested + } else if ( !this.length ) { + return this; + } + + var off = url.indexOf( " " ); + if ( off >= 0 ) { + var selector = url.slice( off, url.length ); + url = url.slice( 0, off ); + } + + // Default to a GET request + var type = "GET"; + + // If the second parameter was provided + if ( params ) { + // If it's a function + if ( jQuery.isFunction( params ) ) { + // We assume that it's the callback + callback = params; + params = undefined; + + // Otherwise, build a param string + } else if ( typeof params === "object" ) { + params = jQuery.param( params, jQuery.ajaxSettings.traditional ); + type = "POST"; + } + } + + var self = this; + + // Request the remote document + jQuery.ajax({ + url: url, + type: type, + dataType: "html", + data: params, + // Complete callback (responseText is used internally) + complete: function( jqXHR, status, responseText ) { + // Store the response as specified by the jqXHR object + responseText = jqXHR.responseText; + // If successful, inject the HTML into all the matched elements + if ( jqXHR.isResolved() ) { + // #4825: Get the actual response in case + // a dataFilter is present in ajaxSettings + jqXHR.done(function( r ) { + responseText = r; + }); + // See if a selector was specified + self.html( selector ? + // Create a dummy div to hold the results + jQuery("
") + // inject the contents of the document in, removing the scripts + // to avoid any 'Permission Denied' errors in IE + .append(responseText.replace(rscript, "")) + + // Locate the specified elements + .find(selector) : + + // If not, just inject the full result + responseText ); + } + + if ( callback ) { + self.each( callback, [ responseText, status, jqXHR ] ); + } + } + }); + + return this; + }; +jQuery.prototype.map = function( callback ) { +/// +/// Pass each element in the current matched set through a function, producing a new jQuery object containing the return values. +/// +/// +/// A function object that will be invoked for each element in the current set. +/// +/// + + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }; +jQuery.prototype.mousedown = function( data, fn ) { +/// +/// Bind an event handler to the "mousedown" JavaScript event, or trigger that event on an element. +/// 1 - mousedown(handler(eventObject)) +/// 2 - mousedown(eventData, handler(eventObject)) +/// 3 - mousedown() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.mouseenter = function( data, fn ) { +/// +/// Bind an event handler to be fired when the mouse enters an element, or trigger that handler on an element. +/// 1 - mouseenter(handler(eventObject)) +/// 2 - mouseenter(eventData, handler(eventObject)) +/// 3 - mouseenter() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.mouseleave = function( data, fn ) { +/// +/// Bind an event handler to be fired when the mouse leaves an element, or trigger that handler on an element. +/// 1 - mouseleave(handler(eventObject)) +/// 2 - mouseleave(eventData, handler(eventObject)) +/// 3 - mouseleave() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.mousemove = function( data, fn ) { +/// +/// Bind an event handler to the "mousemove" JavaScript event, or trigger that event on an element. +/// 1 - mousemove(handler(eventObject)) +/// 2 - mousemove(eventData, handler(eventObject)) +/// 3 - mousemove() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.mouseout = function( data, fn ) { +/// +/// Bind an event handler to the "mouseout" JavaScript event, or trigger that event on an element. +/// 1 - mouseout(handler(eventObject)) +/// 2 - mouseout(eventData, handler(eventObject)) +/// 3 - mouseout() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.mouseover = function( data, fn ) { +/// +/// Bind an event handler to the "mouseover" JavaScript event, or trigger that event on an element. +/// 1 - mouseover(handler(eventObject)) +/// 2 - mouseover(eventData, handler(eventObject)) +/// 3 - mouseover() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.mouseup = function( data, fn ) { +/// +/// Bind an event handler to the "mouseup" JavaScript event, or trigger that event on an element. +/// 1 - mouseup(handler(eventObject)) +/// 2 - mouseup(eventData, handler(eventObject)) +/// 3 - mouseup() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.next = function( until, selector ) { +/// +/// Get the immediately following sibling of each element in the set of matched elements. If a selector is provided, it retrieves the next sibling only if it matches that selector. +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, slice.call( arguments ).join(",") ); + }; +jQuery.prototype.nextAll = function( until, selector ) { +/// +/// Get all following siblings of each element in the set of matched elements, optionally filtered by a selector. +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, slice.call( arguments ).join(",") ); + }; +jQuery.prototype.nextUntil = function( until, selector ) { +/// +/// Get all following siblings of each element up to but not including the element matched by the selector, DOM node, or jQuery object passed. +/// 1 - nextUntil(selector, filter) +/// 2 - nextUntil(element, filter) +/// +/// +/// A string containing a selector expression to indicate where to stop matching following sibling elements. +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, slice.call( arguments ).join(",") ); + }; +jQuery.prototype.not = function( selector ) { +/// +/// Remove elements from the set of matched elements. +/// 1 - not(selector) +/// 2 - not(elements) +/// 3 - not(function(index)) +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + return this.pushStack( winnow(this, selector, false), "not", selector); + }; +jQuery.prototype.off = function( types, selector, fn ) { +/// +/// Remove an event handler. +/// 1 - off(events, selector, handler) +/// 2 - off(events-map, selector) +/// +/// +/// One or more space-separated event types and optional namespaces, or just namespaces, such as "click", "keydown.myPlugin", or ".myPlugin". +/// +/// +/// A selector which should match the one originally passed to .on() when attaching event handlers. +/// +/// +/// A handler function previously attached for the event(s), or the special value false. +/// +/// + + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + var handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace? handleObj.type + "." + handleObj.namespace : handleObj.type, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( var type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }; +jQuery.prototype.offset = function( options ) { +/// +/// 1: Get the current coordinates of the first element in the set of matched elements, relative to the document. +/// 1.1 - offset() +/// 2: Set the current coordinates of every element in the set of matched elements, relative to the document. +/// 2.1 - offset(coordinates) +/// 2.2 - offset(function(index, coords)) +/// +/// +/// An object containing the properties top and left, which are integers indicating the new top and left coordinates for the elements. +/// +/// + + var elem = this[0], box; + + if ( options ) { + return this.each(function( i ) { + jQuery.offset.setOffset( this, options, i ); + }); + } + + if ( !elem || !elem.ownerDocument ) { + return null; + } + + if ( elem === elem.ownerDocument.body ) { + return jQuery.offset.bodyOffset( elem ); + } + + try { + box = elem.getBoundingClientRect(); + } catch(e) {} + + var doc = elem.ownerDocument, + docElem = doc.documentElement; + + // Make sure we're not dealing with a disconnected DOM node + if ( !box || !jQuery.contains( docElem, elem ) ) { + return box ? { top: box.top, left: box.left } : { top: 0, left: 0 }; + } + + var body = doc.body, + win = getWindow(doc), + clientTop = docElem.clientTop || body.clientTop || 0, + clientLeft = docElem.clientLeft || body.clientLeft || 0, + scrollTop = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop, + scrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft, + top = box.top + scrollTop - clientTop, + left = box.left + scrollLeft - clientLeft; + + return { top: top, left: left }; + }; +jQuery.prototype.offsetParent = function() { +/// +/// Get the closest ancestor element that is positioned. +/// +/// + + return this.map(function() { + var offsetParent = this.offsetParent || document.body; + while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) { + offsetParent = offsetParent.offsetParent; + } + return offsetParent; + }); + }; +jQuery.prototype.on = function( types, selector, data, fn, /*INTERNAL*/ one ) { +/// +/// Attach an event handler function for one or more events to the selected elements. +/// 1 - on(events, selector, data, handler) +/// 2 - on(events-map, selector, data) +/// +/// +/// One or more space-separated event types and optional namespaces, such as "click" or "keydown.myPlugin". +/// +/// +/// A selector string to filter the descendants of the selected elements that trigger the event. If the selector is null or omitted, the event is always triggered when it reaches the selected element. +/// +/// +/// Data to be passed to the handler in event.data when an event is triggered. +/// +/// +/// A function to execute when the event is triggered. The value false is also allowed as a shorthand for a function that simply does return false. +/// +/// + + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + // ( types-Object, data ) + data = selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }; +jQuery.prototype.one = function( types, selector, data, fn ) { +/// +/// Attach a handler to an event for the elements. The handler is executed at most once per element. +/// 1 - one(events, data, handler) +/// 2 - one(events, selector, data, handler) +/// 3 - one(events-map, selector, data) +/// +/// +/// One or more space-separated event types and optional namespaces, such as "click" or "keydown.myPlugin". +/// +/// +/// A selector string to filter the descendants of the selected elements that trigger the event. If the selector is null or omitted, the event is always triggered when it reaches the selected element. +/// +/// +/// Data to be passed to the handler in event.data when an event is triggered. +/// +/// +/// A function to execute when the event is triggered. The value false is also allowed as a shorthand for a function that simply does return false. +/// +/// + + return this.on.call( this, types, selector, data, fn, 1 ); + }; +jQuery.prototype.outerHeight = function( margin ) { +/// +/// Get the current computed height for the first element in the set of matched elements, including padding, border, and optionally margin. Returns an integer (without "px") representation of the value or null if called on an empty set of elements. +/// +/// +/// A Boolean indicating whether to include the element's margin in the calculation. +/// +/// + + var elem = this[0]; + return elem ? + elem.style ? + parseFloat( jQuery.css( elem, type, margin ? "margin" : "border" ) ) : + this[ type ]() : + null; + }; +jQuery.prototype.outerWidth = function( margin ) { +/// +/// Get the current computed width for the first element in the set of matched elements, including padding and border. +/// +/// +/// A Boolean indicating whether to include the element's margin in the calculation. +/// +/// + + var elem = this[0]; + return elem ? + elem.style ? + parseFloat( jQuery.css( elem, type, margin ? "margin" : "border" ) ) : + this[ type ]() : + null; + }; +jQuery.prototype.parent = function( until, selector ) { +/// +/// Get the parent of each element in the current set of matched elements, optionally filtered by a selector. +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, slice.call( arguments ).join(",") ); + }; +jQuery.prototype.parents = function( until, selector ) { +/// +/// Get the ancestors of each element in the current set of matched elements, optionally filtered by a selector. +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, slice.call( arguments ).join(",") ); + }; +jQuery.prototype.parentsUntil = function( until, selector ) { +/// +/// Get the ancestors of each element in the current set of matched elements, up to but not including the element matched by the selector, DOM node, or jQuery object. +/// 1 - parentsUntil(selector, filter) +/// 2 - parentsUntil(element, filter) +/// +/// +/// A string containing a selector expression to indicate where to stop matching ancestor elements. +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, slice.call( arguments ).join(",") ); + }; +jQuery.prototype.position = function() { +/// +/// Get the current coordinates of the first element in the set of matched elements, relative to the offset parent. +/// +/// + + if ( !this[0] ) { + return null; + } + + var elem = this[0], + + // Get *real* offsetParent + offsetParent = this.offsetParent(), + + // Get correct offsets + offset = this.offset(), + parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset(); + + // Subtract element margins + // note: when an element has margin: auto the offsetLeft and marginLeft + // are the same in Safari causing offset.left to incorrectly be 0 + offset.top -= parseFloat( jQuery.css(elem, "marginTop") ) || 0; + offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0; + + // Add offsetParent borders + parentOffset.top += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0; + parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0; + + // Subtract the two offsets + return { + top: offset.top - parentOffset.top, + left: offset.left - parentOffset.left + }; + }; +jQuery.prototype.prepend = function() { +/// +/// Insert content, specified by the parameter, to the beginning of each element in the set of matched elements. +/// 1 - prepend(content, content) +/// 2 - prepend(function(index, html)) +/// +/// +/// DOM element, array of elements, HTML string, or jQuery object to insert at the beginning of each element in the set of matched elements. +/// +/// +/// One or more additional DOM elements, arrays of elements, HTML strings, or jQuery objects to insert at the beginning of each element in the set of matched elements. +/// +/// + + return this.domManip(arguments, true, function( elem ) { + if ( this.nodeType === 1 ) { + this.insertBefore( elem, this.firstChild ); + } + }); + }; +jQuery.prototype.prependTo = function( selector ) { +/// +/// Insert every element in the set of matched elements to the beginning of the target. +/// +/// +/// A selector, element, HTML string, or jQuery object; the matched set of elements will be inserted at the beginning of the element(s) specified by this parameter. +/// +/// + + var ret = [], + insert = jQuery( selector ), + parent = this.length === 1 && this[0].parentNode; + + if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) { + insert[ original ]( this[0] ); + return this; + + } else { + for ( var i = 0, l = insert.length; i < l; i++ ) { + var elems = ( i > 0 ? this.clone(true) : this ).get(); + jQuery( insert[i] )[ original ]( elems ); + ret = ret.concat( elems ); + } + + return this.pushStack( ret, name, insert.selector ); + } + }; +jQuery.prototype.prev = function( until, selector ) { +/// +/// Get the immediately preceding sibling of each element in the set of matched elements, optionally filtered by a selector. +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, slice.call( arguments ).join(",") ); + }; +jQuery.prototype.prevAll = function( until, selector ) { +/// +/// Get all preceding siblings of each element in the set of matched elements, optionally filtered by a selector. +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, slice.call( arguments ).join(",") ); + }; +jQuery.prototype.prevUntil = function( until, selector ) { +/// +/// Get all preceding siblings of each element up to but not including the element matched by the selector, DOM node, or jQuery object. +/// 1 - prevUntil(selector, filter) +/// 2 - prevUntil(element, filter) +/// +/// +/// A string containing a selector expression to indicate where to stop matching preceding sibling elements. +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, slice.call( arguments ).join(",") ); + }; +jQuery.prototype.promise = function( type, object ) { +/// +/// Return a Promise object to observe when all actions of a certain type bound to the collection, queued or not, have finished. +/// +/// +/// The type of queue that needs to be observed. +/// +/// +/// Object onto which the promise methods have to be attached +/// +/// + + if ( typeof type !== "string" ) { + object = type; + type = undefined; + } + type = type || "fx"; + var defer = jQuery.Deferred(), + elements = this, + i = elements.length, + count = 1, + deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + tmp; + function resolve() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + } + while( i-- ) { + if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || + ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || + jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && + jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) { + count++; + tmp.add( resolve ); + } + } + resolve(); + return defer.promise(); + }; +jQuery.prototype.prop = function( name, value ) { +/// +/// 1: Get the value of a property for the first element in the set of matched elements. +/// 1.1 - prop(propertyName) +/// 2: Set one or more properties for the set of matched elements. +/// 2.1 - prop(propertyName, value) +/// 2.2 - prop(map) +/// 2.3 - prop(propertyName, function(index, oldPropertyValue)) +/// +/// +/// The name of the property to set. +/// +/// +/// A value to set for the property. +/// +/// + + return jQuery.access( this, name, value, true, jQuery.prop ); + }; +jQuery.prototype.pushStack = function( elems, name, selector ) { +/// +/// Add a collection of DOM elements onto the jQuery stack. +/// 1 - pushStack(elements) +/// 2 - pushStack(elements, name, arguments) +/// +/// +/// An array of elements to push onto the stack and make into a new jQuery object. +/// +/// +/// The name of a jQuery method that generated the array of elements. +/// +/// +/// The arguments that were passed in to the jQuery method (for serialization). +/// +/// + + // Build a new jQuery matched element set + var ret = this.constructor(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + ( this.selector ? " " : "" ) + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }; +jQuery.prototype.queue = function( type, data ) { +/// +/// 1: Show the queue of functions to be executed on the matched elements. +/// 1.1 - queue(queueName) +/// 2: Manipulate the queue of functions to be executed on the matched elements. +/// 2.1 - queue(queueName, newQueue) +/// 2.2 - queue(queueName, callback( next )) +/// +/// +/// A string containing the name of the queue. Defaults to fx, the standard effects queue. +/// +/// +/// An array of functions to replace the current queue contents. +/// +/// + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + } + + if ( data === undefined ) { + return jQuery.queue( this[0], type ); + } + return this.each(function() { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }; +jQuery.prototype.ready = function( fn ) { +/// +/// Specify a function to execute when the DOM is fully loaded. +/// +/// +/// A function to execute after the DOM is ready. +/// +/// + + // Attach the listeners + jQuery.bindReady(); + + // Add the callback + readyList.add( fn ); + + return this; + }; +jQuery.prototype.remove = function( selector, keepData ) { +/// +/// Remove the set of matched elements from the DOM. +/// +/// +/// A selector expression that filters the set of matched elements to be removed. +/// +/// + + for ( var i = 0, elem; (elem = this[i]) != null; i++ ) { + if ( !selector || jQuery.filter( selector, [ elem ] ).length ) { + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( elem.getElementsByTagName("*") ); + jQuery.cleanData( [ elem ] ); + } + + if ( elem.parentNode ) { + elem.parentNode.removeChild( elem ); + } + } + } + + return this; + }; +jQuery.prototype.removeAttr = function( name ) { +/// +/// Remove an attribute from each element in the set of matched elements. +/// +/// +/// An attribute to remove; as of version 1.7, it can be a space-separated list of attributes. +/// +/// + + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }; +jQuery.prototype.removeClass = function( value ) { +/// +/// Remove a single class, multiple classes, or all classes from each element in the set of matched elements. +/// 1 - removeClass(className) +/// 2 - removeClass(function(index, class)) +/// +/// +/// One or more space-separated classes to be removed from the class attribute of each matched element. +/// +/// + + var classNames, i, l, elem, className, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call(this, j, this.className) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + classNames = ( value || "" ).split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + className = (" " + elem.className + " ").replace( rclass, " " ); + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[ c ] + " ", " "); + } + elem.className = jQuery.trim( className ); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }; +jQuery.prototype.removeData = function( key ) { +/// +/// Remove a previously-stored piece of data. +/// 1 - removeData(name) +/// 2 - removeData(list) +/// +/// +/// A string naming the piece of data to delete. +/// +/// + + return this.each(function() { + jQuery.removeData( this, key ); + }); + }; +jQuery.prototype.removeProp = function( name ) { +/// +/// Remove a property for the set of matched elements. +/// +/// +/// The name of the property to set. +/// +/// + + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }; +jQuery.prototype.replaceAll = function( selector ) { +/// +/// Replace each target element with the set of matched elements. +/// +/// +/// A selector expression indicating which element(s) to replace. +/// +/// + + var ret = [], + insert = jQuery( selector ), + parent = this.length === 1 && this[0].parentNode; + + if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) { + insert[ original ]( this[0] ); + return this; + + } else { + for ( var i = 0, l = insert.length; i < l; i++ ) { + var elems = ( i > 0 ? this.clone(true) : this ).get(); + jQuery( insert[i] )[ original ]( elems ); + ret = ret.concat( elems ); + } + + return this.pushStack( ret, name, insert.selector ); + } + }; +jQuery.prototype.replaceWith = function( value ) { +/// +/// Replace each element in the set of matched elements with the provided new content. +/// 1 - replaceWith(newContent) +/// 2 - replaceWith(function) +/// +/// +/// The content to insert. May be an HTML string, DOM element, or jQuery object. +/// +/// + + if ( this[0] && this[0].parentNode ) { + // Make sure that the elements are removed from the DOM before they are inserted + // this can help fix replacing a parent with child elements + if ( jQuery.isFunction( value ) ) { + return this.each(function(i) { + var self = jQuery(this), old = self.html(); + self.replaceWith( value.call( this, i, old ) ); + }); + } + + if ( typeof value !== "string" ) { + value = jQuery( value ).detach(); + } + + return this.each(function() { + var next = this.nextSibling, + parent = this.parentNode; + + jQuery( this ).remove(); + + if ( next ) { + jQuery(next).before( value ); + } else { + jQuery(parent).append( value ); + } + }); + } else { + return this.length ? + this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) : + this; + } + }; +jQuery.prototype.resize = function( data, fn ) { +/// +/// Bind an event handler to the "resize" JavaScript event, or trigger that event on an element. +/// 1 - resize(handler(eventObject)) +/// 2 - resize(eventData, handler(eventObject)) +/// 3 - resize() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.scroll = function( data, fn ) { +/// +/// Bind an event handler to the "scroll" JavaScript event, or trigger that event on an element. +/// 1 - scroll(handler(eventObject)) +/// 2 - scroll(eventData, handler(eventObject)) +/// 3 - scroll() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.scrollLeft = function( val ) { +/// +/// 1: Get the current horizontal position of the scroll bar for the first element in the set of matched elements. +/// 1.1 - scrollLeft() +/// 2: Set the current horizontal position of the scroll bar for each of the set of matched elements. +/// 2.1 - scrollLeft(value) +/// +/// +/// An integer indicating the new position to set the scroll bar to. +/// +/// + + var elem, win; + + if ( val === undefined ) { + elem = this[ 0 ]; + + if ( !elem ) { + return null; + } + + win = getWindow( elem ); + + // Return the scroll offset + return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] : + jQuery.support.boxModel && win.document.documentElement[ method ] || + win.document.body[ method ] : + elem[ method ]; + } + + // Set the scroll offset + return this.each(function() { + win = getWindow( this ); + + if ( win ) { + win.scrollTo( + !i ? val : jQuery( win ).scrollLeft(), + i ? val : jQuery( win ).scrollTop() + ); + + } else { + this[ method ] = val; + } + }); + }; +jQuery.prototype.scrollTop = function( val ) { +/// +/// 1: Get the current vertical position of the scroll bar for the first element in the set of matched elements. +/// 1.1 - scrollTop() +/// 2: Set the current vertical position of the scroll bar for each of the set of matched elements. +/// 2.1 - scrollTop(value) +/// +/// +/// An integer indicating the new position to set the scroll bar to. +/// +/// + + var elem, win; + + if ( val === undefined ) { + elem = this[ 0 ]; + + if ( !elem ) { + return null; + } + + win = getWindow( elem ); + + // Return the scroll offset + return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] : + jQuery.support.boxModel && win.document.documentElement[ method ] || + win.document.body[ method ] : + elem[ method ]; + } + + // Set the scroll offset + return this.each(function() { + win = getWindow( this ); + + if ( win ) { + win.scrollTo( + !i ? val : jQuery( win ).scrollLeft(), + i ? val : jQuery( win ).scrollTop() + ); + + } else { + this[ method ] = val; + } + }); + }; +jQuery.prototype.select = function( data, fn ) { +/// +/// Bind an event handler to the "select" JavaScript event, or trigger that event on an element. +/// 1 - select(handler(eventObject)) +/// 2 - select(eventData, handler(eventObject)) +/// 3 - select() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.serialize = function() { +/// +/// Encode a set of form elements as a string for submission. +/// +/// + + return jQuery.param( this.serializeArray() ); + }; +jQuery.prototype.serializeArray = function() { +/// +/// Encode a set of form elements as an array of names and values. +/// +/// + + return this.map(function(){ + return this.elements ? jQuery.makeArray( this.elements ) : this; + }) + .filter(function(){ + return this.name && !this.disabled && + ( this.checked || rselectTextarea.test( this.nodeName ) || + rinput.test( this.type ) ); + }) + .map(function( i, elem ){ + var val = jQuery( this ).val(); + + return val == null ? + null : + jQuery.isArray( val ) ? + jQuery.map( val, function( val, i ){ + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + }) : + { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + }).get(); + }; +jQuery.prototype.show = function( speed, easing, callback ) { +/// +/// Display the matched elements. +/// 1 - show() +/// 2 - show(duration, callback) +/// 3 - show(duration, easing, callback) +/// +/// +/// A string or number determining how long the animation will run. +/// +/// +/// A string indicating which easing function to use for the transition. +/// +/// +/// A function to call once the animation is complete. +/// +/// + + var elem, display; + + if ( speed || speed === 0 ) { + return this.animate( genFx("show", 3), speed, easing, callback ); + + } else { + for ( var i = 0, j = this.length; i < j; i++ ) { + elem = this[ i ]; + + if ( elem.style ) { + display = elem.style.display; + + // Reset the inline display of this element to learn if it is + // being hidden by cascaded rules or not + if ( !jQuery._data(elem, "olddisplay") && display === "none" ) { + display = elem.style.display = ""; + } + + // Set elements which have been overridden with display: none + // in a stylesheet to whatever the default browser style is + // for such an element + if ( display === "" && jQuery.css(elem, "display") === "none" ) { + jQuery._data( elem, "olddisplay", defaultDisplay(elem.nodeName) ); + } + } + } + + // Set the display of most of the elements in a second loop + // to avoid the constant reflow + for ( i = 0; i < j; i++ ) { + elem = this[ i ]; + + if ( elem.style ) { + display = elem.style.display; + + if ( display === "" || display === "none" ) { + elem.style.display = jQuery._data( elem, "olddisplay" ) || ""; + } + } + } + + return this; + } + }; +jQuery.prototype.siblings = function( until, selector ) { +/// +/// Get the siblings of each element in the set of matched elements, optionally filtered by a selector. +/// +/// +/// A string containing a selector expression to match elements against. +/// +/// + + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, slice.call( arguments ).join(",") ); + }; +jQuery.prototype.size = function() { +/// +/// Return the number of elements in the jQuery object. +/// +/// + + return this.length; + }; +jQuery.prototype.slice = function() { +/// +/// Reduce the set of matched elements to a subset specified by a range of indices. +/// +/// +/// An integer indicating the 0-based position at which the elements begin to be selected. If negative, it indicates an offset from the end of the set. +/// +/// +/// An integer indicating the 0-based position at which the elements stop being selected. If negative, it indicates an offset from the end of the set. If omitted, the range continues until the end of the set. +/// +/// + + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }; +jQuery.prototype.slideDown = function( speed, easing, callback ) { +/// +/// Display the matched elements with a sliding motion. +/// 1 - slideDown(duration, callback) +/// 2 - slideDown(duration, easing, callback) +/// +/// +/// A string or number determining how long the animation will run. +/// +/// +/// A string indicating which easing function to use for the transition. +/// +/// +/// A function to call once the animation is complete. +/// +/// + + return this.animate( props, speed, easing, callback ); + }; +jQuery.prototype.slideToggle = function( speed, easing, callback ) { +/// +/// Display or hide the matched elements with a sliding motion. +/// 1 - slideToggle(duration, callback) +/// 2 - slideToggle(duration, easing, callback) +/// +/// +/// A string or number determining how long the animation will run. +/// +/// +/// A string indicating which easing function to use for the transition. +/// +/// +/// A function to call once the animation is complete. +/// +/// + + return this.animate( props, speed, easing, callback ); + }; +jQuery.prototype.slideUp = function( speed, easing, callback ) { +/// +/// Hide the matched elements with a sliding motion. +/// 1 - slideUp(duration, callback) +/// 2 - slideUp(duration, easing, callback) +/// +/// +/// A string or number determining how long the animation will run. +/// +/// +/// A string indicating which easing function to use for the transition. +/// +/// +/// A function to call once the animation is complete. +/// +/// + + return this.animate( props, speed, easing, callback ); + }; +jQuery.prototype.stop = function( type, clearQueue, gotoEnd ) { +/// +/// Stop the currently-running animation on the matched elements. +/// 1 - stop(clearQueue, jumpToEnd) +/// 2 - stop(queue, clearQueue, jumpToEnd) +/// +/// +/// The name of the queue in which to stop animations. +/// +/// +/// A Boolean indicating whether to remove queued animation as well. Defaults to false. +/// +/// +/// A Boolean indicating whether to complete the current animation immediately. Defaults to false. +/// +/// + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue && type !== false ) { + this.queue( type || "fx", [] ); + } + + return this.each(function() { + var index, + hadTimers = false, + timers = jQuery.timers, + data = jQuery._data( this ); + + // clear marker counters if we know they won't be + if ( !gotoEnd ) { + jQuery._unmark( true, this ); + } + + function stopQueue( elem, data, index ) { + var hooks = data[ index ]; + jQuery.removeData( elem, index, true ); + hooks.stop( gotoEnd ); + } + + if ( type == null ) { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && index.indexOf(".run") === index.length - 4 ) { + stopQueue( this, data, index ); + } + } + } else if ( data[ index = type + ".run" ] && data[ index ].stop ){ + stopQueue( this, data, index ); + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) { + if ( gotoEnd ) { + + // force the next step to be the last + timers[ index ]( true ); + } else { + timers[ index ].saveState(); + } + hadTimers = true; + timers.splice( index, 1 ); + } + } + + // start the next in the queue if the last step wasn't forced + // timers currently will call their complete callbacks, which will dequeue + // but only if they were gotoEnd + if ( !( gotoEnd && hadTimers ) ) { + jQuery.dequeue( this, type ); + } + }); + }; +jQuery.prototype.submit = function( data, fn ) { +/// +/// Bind an event handler to the "submit" JavaScript event, or trigger that event on an element. +/// 1 - submit(handler(eventObject)) +/// 2 - submit(eventData, handler(eventObject)) +/// 3 - submit() +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.text = function( text ) { +/// +/// 1: Get the combined text contents of each element in the set of matched elements, including their descendants. +/// 1.1 - text() +/// 2: Set the content of each element in the set of matched elements to the specified text. +/// 2.1 - text(textString) +/// 2.2 - text(function(index, text)) +/// +/// +/// A string of text to set as the content of each matched element. +/// +/// + + if ( jQuery.isFunction(text) ) { + return this.each(function(i) { + var self = jQuery( this ); + + self.text( text.call(this, i, self.text()) ); + }); + } + + if ( typeof text !== "object" && text !== undefined ) { + return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) ); + } + + return jQuery.text( this ); + }; +jQuery.prototype.toArray = function() { +/// +/// Retrieve all the DOM elements contained in the jQuery set, as an array. +/// +/// + + return slice.call( this, 0 ); + }; +jQuery.prototype.toggle = function( fn, fn2, callback ) { +/// +/// 1: Bind two or more handlers to the matched elements, to be executed on alternate clicks. +/// 1.1 - toggle(handler(eventObject), handler(eventObject), handler(eventObject)) +/// 2: Display or hide the matched elements. +/// 2.1 - toggle(duration, callback) +/// 2.2 - toggle(duration, easing, callback) +/// 2.3 - toggle(showOrHide) +/// +/// +/// A function to execute every even time the element is clicked. +/// +/// +/// A function to execute every odd time the element is clicked. +/// +/// +/// Additional handlers to cycle through after clicks. +/// +/// + + var bool = typeof fn === "boolean"; + + if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) { + this._toggle.apply( this, arguments ); + + } else if ( fn == null || bool ) { + this.each(function() { + var state = bool ? fn : jQuery(this).is(":hidden"); + jQuery(this)[ state ? "show" : "hide" ](); + }); + + } else { + this.animate(genFx("toggle", 3), fn, fn2, callback); + } + + return this; + }; +jQuery.prototype.toggleClass = function( value, stateVal ) { +/// +/// Add or remove one or more classes from each element in the set of matched elements, depending on either the class's presence or the value of the switch argument. +/// 1 - toggleClass(className) +/// 2 - toggleClass(className, switch) +/// 3 - toggleClass(switch) +/// 4 - toggleClass(function(index, class, switch), switch) +/// +/// +/// One or more class names (separated by spaces) to be toggled for each element in the matched set. +/// +/// +/// A Boolean (not just truthy/falsy) value to determine whether the class should be added or removed. +/// +/// + + var type = typeof value, + isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + state = stateVal, + classNames = value.split( rspace ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }; +jQuery.prototype.trigger = function( type, data ) { +/// +/// Execute all handlers and behaviors attached to the matched elements for the given event type. +/// 1 - trigger(eventType, extraParameters) +/// 2 - trigger(event) +/// +/// +/// A string containing a JavaScript event type, such as click or submit. +/// +/// +/// Additional parameters to pass along to the event handler. +/// +/// + + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }; +jQuery.prototype.triggerHandler = function( type, data ) { +/// +/// Execute all handlers attached to an element for an event. +/// +/// +/// A string containing a JavaScript event type, such as click or submit. +/// +/// +/// An array of additional parameters to pass along to the event handler. +/// +/// + + if ( this[0] ) { + return jQuery.event.trigger( type, data, this[0], true ); + } + }; +jQuery.prototype.unbind = function( types, fn ) { +/// +/// Remove a previously-attached event handler from the elements. +/// 1 - unbind(eventType, handler(eventObject)) +/// 2 - unbind(eventType, false) +/// 3 - unbind(event) +/// +/// +/// A string containing a JavaScript event type, such as click or submit. +/// +/// +/// The function that is to be no longer executed. +/// +/// + + return this.off( types, null, fn ); + }; +jQuery.prototype.undelegate = function( selector, types, fn ) { +/// +/// Remove a handler from the event for all elements which match the current selector, based upon a specific set of root elements. +/// 1 - undelegate() +/// 2 - undelegate(selector, eventType) +/// 3 - undelegate(selector, eventType, handler) +/// 4 - undelegate(selector, events) +/// 5 - undelegate(namespace) +/// +/// +/// A selector which will be used to filter the event results. +/// +/// +/// A string containing a JavaScript event type, such as "click" or "keydown" +/// +/// +/// A function to execute at the time the event is triggered. +/// +/// + + // ( namespace ) or ( selector, types [, fn] ) + return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn ); + }; +jQuery.prototype.unload = function( data, fn ) { +/// +/// Bind an event handler to the "unload" JavaScript event. +/// 1 - unload(handler(eventObject)) +/// 2 - unload(eventData, handler(eventObject)) +/// +/// +/// A map of data that will be passed to the event handler. +/// +/// +/// A function to execute each time the event is triggered. +/// +/// + + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; +jQuery.prototype.unwrap = function() { +/// +/// Remove the parents of the set of matched elements from the DOM, leaving the matched elements in their place. +/// +/// + + return this.parent().each(function() { + if ( !jQuery.nodeName( this, "body" ) ) { + jQuery( this ).replaceWith( this.childNodes ); + } + }).end(); + }; +jQuery.prototype.val = function( value ) { +/// +/// 1: Get the current value of the first element in the set of matched elements. +/// 1.1 - val() +/// 2: Set the value of each element in the set of matched elements. +/// 2.1 - val(value) +/// 2.2 - val(function(index, value)) +/// +/// +/// A string of text or an array of strings corresponding to the value of each matched element to set as selected/checked. +/// +/// + + var hooks, ret, isFunction, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return; + } + + isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var self = jQuery(this), val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, self.val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + }; +jQuery.prototype.width = function( size ) { +/// +/// 1: Get the current computed width for the first element in the set of matched elements. +/// 1.1 - width() +/// 2: Set the CSS width of each element in the set of matched elements. +/// 2.1 - width(value) +/// 2.2 - width(function(index, width)) +/// +/// +/// An integer representing the number of pixels, or an integer along with an optional unit of measure appended (as a string). +/// +/// + + // Get window width or height + var elem = this[0]; + if ( !elem ) { + return size == null ? null : this; + } + + if ( jQuery.isFunction( size ) ) { + return this.each(function( i ) { + var self = jQuery( this ); + self[ type ]( size.call( this, i, self[ type ]() ) ); + }); + } + + if ( jQuery.isWindow( elem ) ) { + // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode + // 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat + var docElemProp = elem.document.documentElement[ "client" + name ], + body = elem.document.body; + return elem.document.compatMode === "CSS1Compat" && docElemProp || + body && body[ "client" + name ] || docElemProp; + + // Get document width or height + } else if ( elem.nodeType === 9 ) { + // Either scroll[Width/Height] or offset[Width/Height], whichever is greater + return Math.max( + elem.documentElement["client" + name], + elem.body["scroll" + name], elem.documentElement["scroll" + name], + elem.body["offset" + name], elem.documentElement["offset" + name] + ); + + // Get or set width or height on the element + } else if ( size === undefined ) { + var orig = jQuery.css( elem, type ), + ret = parseFloat( orig ); + + return jQuery.isNumeric( ret ) ? ret : orig; + + // Set the width or height on the element (default to pixels if value is unitless) + } else { + return this.css( type, typeof size === "string" ? size : size + "px" ); + } + }; +jQuery.prototype.wrap = function( html ) { +/// +/// Wrap an HTML structure around each element in the set of matched elements. +/// 1 - wrap(wrappingElement) +/// 2 - wrap(function(index)) +/// +/// +/// An HTML snippet, selector expression, jQuery object, or DOM element specifying the structure to wrap around the matched elements. +/// +/// + + var isFunction = jQuery.isFunction( html ); + + return this.each(function(i) { + jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); + }); + }; +jQuery.prototype.wrapAll = function( html ) { +/// +/// Wrap an HTML structure around all elements in the set of matched elements. +/// +/// +/// An HTML snippet, selector expression, jQuery object, or DOM element specifying the structure to wrap around the matched elements. +/// +/// + + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapAll( html.call(this, i) ); + }); + } + + if ( this[0] ) { + // The elements to wrap the target around + var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); + + if ( this[0].parentNode ) { + wrap.insertBefore( this[0] ); + } + + wrap.map(function() { + var elem = this; + + while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { + elem = elem.firstChild; + } + + return elem; + }).append( this ); + } + + return this; + }; +jQuery.prototype.wrapInner = function( html ) { +/// +/// Wrap an HTML structure around the content of each element in the set of matched elements. +/// 1 - wrapInner(wrappingElement) +/// 2 - wrapInner(function(index)) +/// +/// +/// An HTML snippet, selector expression, jQuery object, or DOM element specifying the structure to wrap around the content of the matched elements. +/// +/// + + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapInner( html.call(this, i) ); + }); + } + + return this.each(function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + }); + }; +jQuery.fn = jQuery.prototype; +jQuery.fn.init.prototype = jQuery.fn; +window.jQuery = window.$ = jQuery; +})(window); \ No newline at end of file diff --git a/OnPremise/WebSite/Scripts/jquery-1.7.1.js b/OnPremise/WebSite/Scripts/jquery-1.7.1.js new file mode 100644 index 0000000..8ccd0ea --- /dev/null +++ b/OnPremise/WebSite/Scripts/jquery-1.7.1.js @@ -0,0 +1,9266 @@ +/*! + * jQuery JavaScript Library v1.7.1 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Mon Nov 21 21:11:03 2011 -0500 + */ +(function( window, undefined ) { + +// Use the correct document accordingly with window argument (sandbox) +var document = window.document, + navigator = window.navigator, + location = window.location; +var jQuery = (function() { + +// Define a local copy of jQuery +var jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // A central reference to the root jQuery(document) + rootjQuery, + + // A simple way to check for HTML strings or ID strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + + // Used for trimming whitespace + trimLeft = /^\s+/, + trimRight = /\s+$/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, + rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + + // Useragent RegExp + rwebkit = /(webkit)[ \/]([\w.]+)/, + ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, + rmsie = /(msie) ([\w.]+)/, + rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, + + // Matches dashed string for camelizing + rdashAlpha = /-([a-z]|[0-9])/ig, + rmsPrefix = /^-ms-/, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return ( letter + "" ).toUpperCase(); + }, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // The deferred used on DOM ready + readyList, + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + trim = String.prototype.trim, + indexOf = Array.prototype.indexOf, + + // [[Class]] -> type pairs + class2type = {}; + +jQuery.fn = jQuery.prototype = { + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context && document.body ) { + this.context = document; + this[0] = document.body; + this.selector = selector; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = quickExpr.exec( selector ); + } + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + doc = ( context ? context.ownerDocument || context : document ); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.7.1", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = this.constructor(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + ( this.selector ? " " : "" ) + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // Add the callback + readyList.add( fn ); + + return this; + }, + + eq: function( i ) { + i = +i; + return i === -1 ? + this.slice( i ) : + this.slice( i, i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + // Either a released hold or an DOMready/load event and not yet ready + if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 1 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.fireWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger( "ready" ).off( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyList ) { + return; + } + + readyList = jQuery.Callbacks( "once memory" ); + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + return setTimeout( jQuery.ready, 1 ); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", DOMContentLoaded ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + // A crude way of determining if an object is a window + isWindow: function( obj ) { + return obj && typeof obj === "object" && "setInterval" in obj; + }, + + isNumeric: function( obj ) { + return !isNaN( parseFloat(obj) ) && isFinite( obj ); + }, + + type: function( obj ) { + return obj == null ? + String( obj ) : + class2type[ toString.call(obj) ] || "object"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw new Error( msg ); + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return ( new Function( "return " + data ) )(); + + } + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + parseXML: function( data ) { + var xml, tmp; + try { + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + } catch( e ) { + xml = undefined; + } + if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && rnotwhite.test( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction( object ); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { + break; + } + } + } + } + + return object; + }, + + // Use native String.trim function wherever possible + trim: trim ? + function( text ) { + return text == null ? + "" : + trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 + var type = jQuery.type( array ); + + if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array, i ) { + var len; + + if ( array ) { + if ( indexOf ) { + return indexOf.call( array, elem, i ); + } + + len = array.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + // Skip accessing in sparse arrays + if ( i in array && array[ i ] === elem ) { + return i; + } + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, + j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = [], retVal; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, key, ret = [], + i = 0, + length = elems.length, + // jquery objects are treated as arrays + isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( key in elems ) { + value = callback( elems[ key ], key, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + if ( typeof context === "string" ) { + var tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + var args = slice.call( arguments, 2 ), + proxy = function() { + return fn.apply( context, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + + return proxy; + }, + + // Mutifunctional method to get and set values to a collection + // The value/s can optionally be executed if it's a function + access: function( elems, key, value, exec, fn, pass ) { + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + jQuery.access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : undefined; + }, + + now: function() { + return ( new Date() ).getTime(); + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = rwebkit.exec( ua ) || + ropera.exec( ua ) || + rmsie.exec( ua ) || + ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + sub: function() { + function jQuerySub( selector, context ) { + return new jQuerySub.fn.init( selector, context ); + } + jQuery.extend( true, jQuerySub, this ); + jQuerySub.superclass = this; + jQuerySub.fn = jQuerySub.prototype = this(); + jQuerySub.fn.constructor = jQuerySub; + jQuerySub.sub = this.sub; + jQuerySub.fn.init = function init( selector, context ) { + if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { + context = jQuerySub( context ); + } + + return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); + }; + jQuerySub.fn.init.prototype = jQuerySub.fn; + var rootjQuerySub = jQuerySub(document); + return jQuerySub; + }, + + browser: {} +}); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +// IE doesn't match non-breaking spaces with \s +if ( rnotwhite.test( "\xA0" ) ) { + trimLeft = /^[\s\xA0]+/; + trimRight = /[\s\xA0]+$/; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch(e) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +return jQuery; + +})(); + + +// String to Object flags format cache +var flagsCache = {}; + +// Convert String-formatted flags into Object-formatted ones and store in cache +function createFlags( flags ) { + var object = flagsCache[ flags ] = {}, + i, length; + flags = flags.split( /\s+/ ); + for ( i = 0, length = flags.length; i < length; i++ ) { + object[ flags[i] ] = true; + } + return object; +} + +/* + * Create a callback list using the following parameters: + * + * flags: an optional list of space-separated flags that will change how + * the callback list behaves + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible flags: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( flags ) { + + // Convert flags from String-formatted to Object-formatted + // (we check in cache first) + flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {}; + + var // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = [], + // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list is currently firing + firing, + // First callback to fire (used internally by add and fireWith) + firingStart, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // Add one or several callbacks to the list + add = function( args ) { + var i, + length, + elem, + type, + actual; + for ( i = 0, length = args.length; i < length; i++ ) { + elem = args[ i ]; + type = jQuery.type( elem ); + if ( type === "array" ) { + // Inspect recursively + add( elem ); + } else if ( type === "function" ) { + // Add if not in unique mode and callback is not in + if ( !flags.unique || !self.has( elem ) ) { + list.push( elem ); + } + } + } + }, + // Fire callbacks + fire = function( context, args ) { + args = args || []; + memory = !flags.memory || [ context, args ]; + firing = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) { + memory = true; // Mark as halted + break; + } + } + firing = false; + if ( list ) { + if ( !flags.once ) { + if ( stack && stack.length ) { + memory = stack.shift(); + self.fireWith( memory[ 0 ], memory[ 1 ] ); + } + } else if ( memory === true ) { + self.disable(); + } else { + list = []; + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + var length = list.length; + add( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away, unless previous + // firing was halted (stopOnFalse) + } else if ( memory && memory !== true ) { + firingStart = length; + fire( memory[ 0 ], memory[ 1 ] ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + var args = arguments, + argIndex = 0, + argLength = args.length; + for ( ; argIndex < argLength ; argIndex++ ) { + for ( var i = 0; i < list.length; i++ ) { + if ( args[ argIndex ] === list[ i ] ) { + // Handle firingIndex and firingLength + if ( firing ) { + if ( i <= firingLength ) { + firingLength--; + if ( i <= firingIndex ) { + firingIndex--; + } + } + } + // Remove the element + list.splice( i--, 1 ); + // If we have some unicity property then + // we only need to do this once + if ( flags.unique ) { + break; + } + } + } + } + } + return this; + }, + // Control if a given callback is in the list + has: function( fn ) { + if ( list ) { + var i = 0, + length = list.length; + for ( ; i < length; i++ ) { + if ( fn === list[ i ] ) { + return true; + } + } + } + return false; + }, + // Remove all callbacks from the list + empty: function() { + list = []; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory || memory === true ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( stack ) { + if ( firing ) { + if ( !flags.once ) { + stack.push( [ context, args ] ); + } + } else if ( !( flags.once && memory ) ) { + fire( context, args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!memory; + } + }; + + return self; +}; + + + + +var // Static reference to slice + sliceDeferred = [].slice; + +jQuery.extend({ + + Deferred: function( func ) { + var doneList = jQuery.Callbacks( "once memory" ), + failList = jQuery.Callbacks( "once memory" ), + progressList = jQuery.Callbacks( "memory" ), + state = "pending", + lists = { + resolve: doneList, + reject: failList, + notify: progressList + }, + promise = { + done: doneList.add, + fail: failList.add, + progress: progressList.add, + + state: function() { + return state; + }, + + // Deprecated + isResolved: doneList.fired, + isRejected: failList.fired, + + then: function( doneCallbacks, failCallbacks, progressCallbacks ) { + deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks ); + return this; + }, + always: function() { + deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments ); + return this; + }, + pipe: function( fnDone, fnFail, fnProgress ) { + return jQuery.Deferred(function( newDefer ) { + jQuery.each( { + done: [ fnDone, "resolve" ], + fail: [ fnFail, "reject" ], + progress: [ fnProgress, "notify" ] + }, function( handler, data ) { + var fn = data[ 0 ], + action = data[ 1 ], + returned; + if ( jQuery.isFunction( fn ) ) { + deferred[ handler ](function() { + returned = fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify ); + } else { + newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] ); + } + }); + } else { + deferred[ handler ]( newDefer[ action ] ); + } + }); + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + if ( obj == null ) { + obj = promise; + } else { + for ( var key in promise ) { + obj[ key ] = promise[ key ]; + } + } + return obj; + } + }, + deferred = promise.promise({}), + key; + + for ( key in lists ) { + deferred[ key ] = lists[ key ].fire; + deferred[ key + "With" ] = lists[ key ].fireWith; + } + + // Handle state + deferred.done( function() { + state = "resolved"; + }, failList.disable, progressList.lock ).fail( function() { + state = "rejected"; + }, doneList.disable, progressList.lock ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( firstParam ) { + var args = sliceDeferred.call( arguments, 0 ), + i = 0, + length = args.length, + pValues = new Array( length ), + count = length, + pCount = length, + deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? + firstParam : + jQuery.Deferred(), + promise = deferred.promise(); + function resolveFunc( i ) { + return function( value ) { + args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + if ( !( --count ) ) { + deferred.resolveWith( deferred, args ); + } + }; + } + function progressFunc( i ) { + return function( value ) { + pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + deferred.notifyWith( promise, pValues ); + }; + } + if ( length > 1 ) { + for ( ; i < length; i++ ) { + if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) { + args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) ); + } else { + --count; + } + } + if ( !count ) { + deferred.resolveWith( deferred, args ); + } + } else if ( deferred !== firstParam ) { + deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); + } + return promise; + } +}); + + + + +jQuery.support = (function() { + + var support, + all, + a, + select, + opt, + input, + marginDiv, + fragment, + tds, + events, + eventName, + i, + isSupported, + div = document.createElement( "div" ), + documentElement = document.documentElement; + + // Preliminary tests + div.setAttribute("className", "t"); + div.innerHTML = "
a"; + + all = div.getElementsByTagName( "*" ); + a = div.getElementsByTagName( "a" )[ 0 ]; + + // Can't get basic test support + if ( !all || !all.length || !a ) { + return {}; + } + + // First batch of supports tests + select = document.createElement( "select" ); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName( "input" )[ 0 ]; + + support = { + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: ( div.firstChild.nodeType === 3 ), + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName("tbody").length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName("link").length, + + // Get the style information from getAttribute + // (IE uses .cssText instead) + style: /top/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: ( a.getAttribute("href") === "/a" ), + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.55/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Make sure that if no value is specified for a checkbox + // that it defaults to "on". + // (WebKit defaults to "" instead) + checkOn: ( input.value === "on" ), + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: opt.selected, + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + getSetAttribute: div.className !== "t", + + // Tests for enctype support on a form(#6743) + enctype: !!document.createElement("form").enctype, + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>", + + // Will be defined later + submitBubbles: true, + changeBubbles: true, + focusinBubbles: false, + deleteExpando: true, + noCloneEvent: true, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableMarginRight: true + }; + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Test to see if it's possible to delete an expando from an element + // Fails in Internet Explorer + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { + div.attachEvent( "onclick", function() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + support.noCloneEvent = false; + }); + div.cloneNode( true ).fireEvent( "onclick" ); + } + + // Check if a radio maintains its value + // after being appended to the DOM + input = document.createElement("input"); + input.value = "t"; + input.setAttribute("type", "radio"); + support.radioValue = input.value === "t"; + + input.setAttribute("checked", "checked"); + div.appendChild( input ); + fragment = document.createDocumentFragment(); + fragment.appendChild( div.lastChild ); + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + fragment.removeChild( input ); + fragment.appendChild( div ); + + div.innerHTML = ""; + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. For more + // info see bug #3333 + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + if ( window.getComputedStyle ) { + marginDiv = document.createElement( "div" ); + marginDiv.style.width = "0"; + marginDiv.style.marginRight = "0"; + div.style.width = "2px"; + div.appendChild( marginDiv ); + support.reliableMarginRight = + ( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; + } + + // Technique from Juriy Zaytsev + // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/ + // We only care about the case where non-standard event systems + // are used, namely in IE. Short-circuiting here helps us to + // avoid an eval call (in setAttribute) which can cause CSP + // to go haywire. See: https://developer.mozilla.org/en/Security/CSP + if ( div.attachEvent ) { + for( i in { + submit: 1, + change: 1, + focusin: 1 + }) { + eventName = "on" + i; + isSupported = ( eventName in div ); + if ( !isSupported ) { + div.setAttribute( eventName, "return;" ); + isSupported = ( typeof div[ eventName ] === "function" ); + } + support[ i + "Bubbles" ] = isSupported; + } + } + + fragment.removeChild( div ); + + // Null elements to avoid leaks in IE + fragment = select = opt = marginDiv = div = input = null; + + // Run tests that need a body at doc ready + jQuery(function() { + var container, outer, inner, table, td, offsetSupport, + conMarginTop, ptlm, vb, style, html, + body = document.getElementsByTagName("body")[0]; + + if ( !body ) { + // Return for frameset docs that don't have a body + return; + } + + conMarginTop = 1; + ptlm = "position:absolute;top:0;left:0;width:1px;height:1px;margin:0;"; + vb = "visibility:hidden;border:0;"; + style = "style='" + ptlm + "border:5px solid #000;padding:0;'"; + html = "
" + + "" + + "
"; + + container = document.createElement("div"); + container.style.cssText = vb + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px"; + body.insertBefore( container, body.firstChild ); + + // Construct the test element + div = document.createElement("div"); + container.appendChild( div ); + + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + // (only IE 8 fails this test) + div.innerHTML = "
t
"; + tds = div.getElementsByTagName( "td" ); + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Check if empty table cells still have offsetWidth/Height + // (IE <= 8 fail this test) + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + + // Figure out if the W3C box model works as expected + div.innerHTML = ""; + div.style.width = div.style.paddingLeft = "1px"; + jQuery.boxModel = support.boxModel = div.offsetWidth === 2; + + if ( typeof div.style.zoom !== "undefined" ) { + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + // (IE < 8 does this) + div.style.display = "inline"; + div.style.zoom = 1; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 ); + + // Check if elements with layout shrink-wrap their children + // (IE 6 does this) + div.style.display = ""; + div.innerHTML = "
"; + support.shrinkWrapBlocks = ( div.offsetWidth !== 2 ); + } + + div.style.cssText = ptlm + vb; + div.innerHTML = html; + + outer = div.firstChild; + inner = outer.firstChild; + td = outer.nextSibling.firstChild.firstChild; + + offsetSupport = { + doesNotAddBorder: ( inner.offsetTop !== 5 ), + doesAddBorderForTableAndCells: ( td.offsetTop === 5 ) + }; + + inner.style.position = "fixed"; + inner.style.top = "20px"; + + // safari subtracts parent border width here which is 5px + offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 ); + inner.style.position = inner.style.top = ""; + + outer.style.overflow = "hidden"; + outer.style.position = "relative"; + + offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 ); + offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop ); + + body.removeChild( container ); + div = container = null; + + jQuery.extend( support, offsetSupport ); + }); + + return support; +})(); + + + + +var rbrace = /^(?:\{.*\}|\[.*\])$/, + rmultiDash = /([A-Z])/g; + +jQuery.extend({ + cache: {}, + + // Please use with caution + uuid: 0, + + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", + "applet": true + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var privateCache, thisCache, ret, + internalKey = jQuery.expando, + getByName = typeof name === "string", + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey, + isEvents = name === "events"; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + elem[ internalKey ] = id = ++jQuery.uuid; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + cache[ id ] = {}; + + // Avoids exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + privateCache = thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Users should not attempt to inspect the internal events object using jQuery.data, + // it is undocumented and subject to change. But does anyone listen? No. + if ( isEvents && !thisCache[ name ] ) { + return privateCache.events; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( getByName ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; + }, + + removeData: function( elem, name, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, i, l, + + // Reference to internal data cache key + internalKey = jQuery.expando, + + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + + // See jQuery.data for more information + id = isNode ? elem[ internalKey ] : internalKey; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split( " " ); + } + } + } + + for ( i = 0, l = name.length; i < l; i++ ) { + delete thisCache[ name[i] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject(cache[ id ]) ) { + return; + } + } + + // Browsers that fail expando deletion also refuse to delete expandos on + // the window, but it will allow it on all other JS objects; other browsers + // don't care + // Ensure that `cache` is not a window object #10080 + if ( jQuery.support.deleteExpando || !cache.setInterval ) { + delete cache[ id ]; + } else { + cache[ id ] = null; + } + + // We destroyed the cache and need to eliminate the expando on the node to avoid + // false lookups in the cache for entries that no longer exist + if ( isNode ) { + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( jQuery.support.deleteExpando ) { + delete elem[ internalKey ]; + } else if ( elem.removeAttribute ) { + elem.removeAttribute( internalKey ); + } else { + elem[ internalKey ] = null; + } + } + }, + + // For internal use only. + _data: function( elem, name, data ) { + return jQuery.data( elem, name, data, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + if ( elem.nodeName ) { + var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; + + if ( match ) { + return !(match === true || elem.getAttribute("classid") !== match); + } + } + + return true; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var parts, attr, name, + data = null; + + if ( typeof key === "undefined" ) { + if ( this.length ) { + data = jQuery.data( this[0] ); + + if ( this[0].nodeType === 1 && !jQuery._data( this[0], "parsedAttrs" ) ) { + attr = this[0].attributes; + for ( var i = 0, l = attr.length; i < l; i++ ) { + name = attr[i].name; + + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.substring(5) ); + + dataAttr( this[0], name, data[ name ] ); + } + } + jQuery._data( this[0], "parsedAttrs", true ); + } + } + + return data; + + } else if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value === undefined ) { + data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + // Try to fetch any internally stored data first + if ( data === undefined && this.length ) { + data = jQuery.data( this[0], key ); + data = dataAttr( this[0], key, data ); + } + + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + + } else { + return this.each(function() { + var self = jQuery( this ), + args = [ parts[0], value ]; + + self.triggerHandler( "setData" + parts[1] + "!", args ); + jQuery.data( this, key, value ); + self.triggerHandler( "changeData" + parts[1] + "!", args ); + }); + } + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + + var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + jQuery.isNumeric( data ) ? parseFloat( data ) : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// checks a cache object for emptiness +function isEmptyDataObject( obj ) { + for ( var name in obj ) { + + // if the public data object is empty, the private is still empty + if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { + continue; + } + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} + + + + +function handleQueueMarkDefer( elem, type, src ) { + var deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + defer = jQuery._data( elem, deferDataKey ); + if ( defer && + ( src === "queue" || !jQuery._data(elem, queueDataKey) ) && + ( src === "mark" || !jQuery._data(elem, markDataKey) ) ) { + // Give room for hard-coded callbacks to fire first + // and eventually mark/queue something else on the element + setTimeout( function() { + if ( !jQuery._data( elem, queueDataKey ) && + !jQuery._data( elem, markDataKey ) ) { + jQuery.removeData( elem, deferDataKey, true ); + defer.fire(); + } + }, 0 ); + } +} + +jQuery.extend({ + + _mark: function( elem, type ) { + if ( elem ) { + type = ( type || "fx" ) + "mark"; + jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 ); + } + }, + + _unmark: function( force, elem, type ) { + if ( force !== true ) { + type = elem; + elem = force; + force = false; + } + if ( elem ) { + type = type || "fx"; + var key = type + "mark", + count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 ); + if ( count ) { + jQuery._data( elem, key, count ); + } else { + jQuery.removeData( elem, key, true ); + handleQueueMarkDefer( elem, type, "mark" ); + } + } + }, + + queue: function( elem, type, data ) { + var q; + if ( elem ) { + type = ( type || "fx" ) + "queue"; + q = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !q || jQuery.isArray(data) ) { + q = jQuery._data( elem, type, jQuery.makeArray(data) ); + } else { + q.push( data ); + } + } + return q || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + fn = queue.shift(), + hooks = {}; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + jQuery._data( elem, type + ".run", hooks ); + fn.call( elem, function() { + jQuery.dequeue( elem, type ); + }, hooks ); + } + + if ( !queue.length ) { + jQuery.removeData( elem, type + "queue " + type + ".run", true ); + handleQueueMarkDefer( elem, type, "queue" ); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + } + + if ( data === undefined ) { + return jQuery.queue( this[0], type ); + } + return this.each(function() { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = setTimeout( next, time ); + hooks.stop = function() { + clearTimeout( timeout ); + }; + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, object ) { + if ( typeof type !== "string" ) { + object = type; + type = undefined; + } + type = type || "fx"; + var defer = jQuery.Deferred(), + elements = this, + i = elements.length, + count = 1, + deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + tmp; + function resolve() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + } + while( i-- ) { + if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || + ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || + jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && + jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) { + count++; + tmp.add( resolve ); + } + } + resolve(); + return defer.promise(); + } +}); + + + + +var rclass = /[\n\t\r]/g, + rspace = /\s+/, + rreturn = /\r/g, + rtype = /^(?:button|input)$/i, + rfocusable = /^(?:button|input|object|select|textarea)$/i, + rclickable = /^a(?:rea)?$/i, + rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, + getSetAttribute = jQuery.support.getSetAttribute, + nodeHook, boolHook, fixSpecified; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.attr ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.prop ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + var classNames, i, l, elem, + setClass, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call(this, j, this.className) ); + }); + } + + if ( value && typeof value === "string" ) { + classNames = value.split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className && classNames.length === 1 ) { + elem.className = value; + + } else { + setClass = " " + elem.className + " "; + + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { + setClass += classNames[ c ] + " "; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classNames, i, l, elem, className, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call(this, j, this.className) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + classNames = ( value || "" ).split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + className = (" " + elem.className + " ").replace( rclass, " " ); + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[ c ] + " ", " "); + } + elem.className = jQuery.trim( className ); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + state = stateVal, + classNames = value.split( rspace ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " ", + i = 0, + l = this.length; + for ( ; i < l; i++ ) { + if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var hooks, ret, isFunction, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return; + } + + isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var self = jQuery(this), val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, self.val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // attributes.value is undefined in Blackberry 4.7 but + // uses .value. See #6932 + var val = elem.attributes.value; + return !val || val.specified ? elem.value : elem.text; + } + }, + select: { + get: function( elem ) { + var value, i, max, option, + index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type === "select-one"; + + // Nothing was selected + if ( index < 0 ) { + return null; + } + + // Loop through all the selected options + i = one ? index : 0; + max = one ? index + 1 : options.length; + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Don't return options that are disabled or in a disabled optgroup + if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && + (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + // Fixes Bug #2551 -- select.val() broken in IE after form.reset() + if ( one && !values.length && options.length ) { + return jQuery( options[ index ] ).val(); + } + + return values; + }, + + set: function( elem, value ) { + var values = jQuery.makeArray( value ); + + jQuery(elem).find("option").each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attrFn: { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true + }, + + attr: function( elem, name, value, pass ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery( elem )[ name ]( value ); + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + // All attributes are lowercase + // Grab necessary hook if one is defined + if ( notxml ) { + name = name.toLowerCase(); + hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook ); + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + + } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, "" + value ); + return value; + } + + } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + + ret = elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return ret === null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, value ) { + var propName, attrNames, name, l, + i = 0; + + if ( value && elem.nodeType === 1 ) { + attrNames = value.toLowerCase().split( rspace ); + l = attrNames.length; + + for ( ; i < l; i++ ) { + name = attrNames[ i ]; + + if ( name ) { + propName = jQuery.propFix[ name ] || name; + + // See #9699 for explanation of this approach (setting first, then removal) + jQuery.attr( elem, name, "" ); + elem.removeAttribute( getSetAttribute ? name : propName ); + + // Set corresponding property to false for boolean attributes + if ( rboolean.test( name ) && propName in elem ) { + elem[ propName ] = false; + } + } + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( rtype.test( elem.nodeName ) && elem.parentNode ) { + jQuery.error( "type property can't be changed" ); + } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to it's default in case type is set after value + // This is for element creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + }, + // Use the value property for back compat + // Use the nodeHook for button elements in IE6/7 (#1954) + value: { + get: function( elem, name ) { + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.get( elem, name ); + } + return name in elem ? + elem.value : + null; + }, + set: function( elem, value, name ) { + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.set( elem, value, name ); + } + // Does not return so that setAttribute is also used + elem.value = value; + } + } + }, + + propFix: { + tabindex: "tabIndex", + readonly: "readOnly", + "for": "htmlFor", + "class": "className", + maxlength: "maxLength", + cellspacing: "cellSpacing", + cellpadding: "cellPadding", + rowspan: "rowSpan", + colspan: "colSpan", + usemap: "useMap", + frameborder: "frameBorder", + contenteditable: "contentEditable" + }, + + prop: function( elem, name, value ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + return ( elem[ name ] = value ); + } + + } else { + if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + return elem[ name ]; + } + } + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + var attributeNode = elem.getAttributeNode("tabindex"); + + return attributeNode && attributeNode.specified ? + parseInt( attributeNode.value, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + } + } +}); + +// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional) +jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex; + +// Hook for boolean attributes +boolHook = { + get: function( elem, name ) { + // Align boolean attributes with corresponding properties + // Fall back to attribute presence where some booleans are not supported + var attrNode, + property = jQuery.prop( elem, name ); + return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ? + name.toLowerCase() : + undefined; + }, + set: function( elem, value, name ) { + var propName; + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + // value is true since we know at this point it's type boolean and not false + // Set boolean attributes to the same name and set the DOM property + propName = jQuery.propFix[ name ] || name; + if ( propName in elem ) { + // Only set the IDL specifically if it already exists on the element + elem[ propName ] = true; + } + + elem.setAttribute( name, name.toLowerCase() ); + } + return name; + } +}; + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !getSetAttribute ) { + + fixSpecified = { + name: true, + id: true + }; + + // Use this for any attribute in IE6/7 + // This fixes almost every IE6/7 issue + nodeHook = jQuery.valHooks.button = { + get: function( elem, name ) { + var ret; + ret = elem.getAttributeNode( name ); + return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ? + ret.nodeValue : + undefined; + }, + set: function( elem, value, name ) { + // Set the existing or create a new attribute node + var ret = elem.getAttributeNode( name ); + if ( !ret ) { + ret = document.createAttribute( name ); + elem.setAttributeNode( ret ); + } + return ( ret.nodeValue = value + "" ); + } + }; + + // Apply the nodeHook to tabindex + jQuery.attrHooks.tabindex.set = nodeHook.set; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }); + }); + + // Set contenteditable to false on removals(#10429) + // Setting to empty string throws an error as an invalid value + jQuery.attrHooks.contenteditable = { + get: nodeHook.get, + set: function( elem, value, name ) { + if ( value === "" ) { + value = "false"; + } + nodeHook.set( elem, value, name ); + } + }; +} + + +// Some attributes require a special call on IE +if ( !jQuery.support.hrefNormalized ) { + jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + get: function( elem ) { + var ret = elem.getAttribute( name, 2 ); + return ret === null ? undefined : ret; + } + }); + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Normalize to lowercase since IE uppercases css property names + return elem.style.cssText.toLowerCase() || undefined; + }, + set: function( elem, value ) { + return ( elem.style.cssText = "" + value ); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + return null; + } + }); +} + +// IE6/7 call enctype encoding +if ( !jQuery.support.enctype ) { + jQuery.propFix.enctype = "encoding"; +} + +// Radios and checkboxes getter/setter +if ( !jQuery.support.checkOn ) { + jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + get: function( elem ) { + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + } + }; + }); +} +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); + } + } + }); +}); + + + + +var rformElems = /^(?:textarea|input|select)$/i, + rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/, + rhoverHack = /\bhover(\.\S+)?\b/, + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/, + quickParse = function( selector ) { + var quick = rquickIs.exec( selector ); + if ( quick ) { + // 0 1 2 3 + // [ _, tag, id, class ] + quick[1] = ( quick[1] || "" ).toLowerCase(); + quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" ); + } + return quick; + }, + quickIs = function( elem, m ) { + var attrs = elem.attributes || {}; + return ( + (!m[1] || elem.nodeName.toLowerCase() === m[1]) && + (!m[2] || (attrs.id || {}).value === m[2]) && + (!m[3] || m[3].test( (attrs[ "class" ] || {}).value )) + ); + }, + hoverHack = function( events ) { + return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" ); + }; + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + add: function( elem, types, handler, data, selector ) { + + var elemData, eventHandle, events, + t, tns, type, namespaces, handleObj, + handleObjIn, quick, handlers, special; + + // Don't attach events to noData or text/comment nodes (allow plain objects tho) + if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + events = elemData.events; + if ( !events ) { + elemData.events = events = {}; + } + eventHandle = elemData.handle; + if ( !eventHandle ) { + elemData.handle = eventHandle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = jQuery.trim( hoverHack(types) ).split( " " ); + for ( t = 0; t < types.length; t++ ) { + + tns = rtypenamespace.exec( types[t] ) || []; + type = tns[1]; + namespaces = ( tns[2] || "" ).split( "." ).sort(); + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: tns[1], + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + quick: quickParse( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + handlers = events[ type ]; + if ( !handlers ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener/attachEvent if the special events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + global: {}, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var elemData = jQuery.hasData( elem ) && jQuery._data( elem ), + t, tns, type, origType, namespaces, origCount, + j, events, special, handle, eventType, handleObj; + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = jQuery.trim( hoverHack( types || "" ) ).split(" "); + for ( t = 0; t < types.length; t++ ) { + tns = rtypenamespace.exec( types[t] ) || []; + type = origType = tns[1]; + namespaces = tns[2]; + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector? special.delegateType : special.bindType ) || type; + eventType = events[ type ] || []; + origCount = eventType.length; + namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null; + + // Remove matching events + for ( j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !namespaces || namespaces.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + eventType.splice( j--, 1 ); + + if ( handleObj.selector ) { + eventType.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( eventType.length === 0 && origCount !== eventType.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery.removeData( elem, [ "events", "handle" ], true ); + } + }, + + // Events that are safe to short-circuit if no handlers are attached. + // Native DOM events should not be added, they may have inline handlers. + customEvent: { + "getData": true, + "setData": true, + "changeData": true + }, + + trigger: function( event, data, elem, onlyHandlers ) { + // Don't do events on text and comment nodes + if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) { + return; + } + + // Event object or event type + var type = event.type || event, + namespaces = [], + cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType; + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "!" ) >= 0 ) { + // Exclusive events trigger only for the exact event (no namespaces) + type = type.slice(0, -1); + exclusive = true; + } + + if ( type.indexOf( "." ) >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + + if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { + // No jQuery handlers for this event type, and it can't have inline handlers + return; + } + + // Caller can pass in an Event, Object, or just an event type string + event = typeof event === "object" ? + // jQuery.Event object + event[ jQuery.expando ] ? event : + // Object literal + new jQuery.Event( type, event ) : + // Just the event type (string) + new jQuery.Event( type ); + + event.type = type; + event.isTrigger = true; + event.exclusive = exclusive; + event.namespace = namespaces.join( "." ); + event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null; + ontype = type.indexOf( ":" ) < 0 ? "on" + type : ""; + + // Handle a global trigger + if ( !elem ) { + + // TODO: Stop taunting the data cache; remove global events and always attach to document + cache = jQuery.cache; + for ( i in cache ) { + if ( cache[ i ].events && cache[ i ].events[ type ] ) { + jQuery.event.trigger( event, data, cache[ i ].handle.elem, true ); + } + } + return; + } + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data != null ? jQuery.makeArray( data ) : []; + data.unshift( event ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + eventPath = [[ elem, special.bindType || type ]]; + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode; + old = null; + for ( ; cur; cur = cur.parentNode ) { + eventPath.push([ cur, bubbleType ]); + old = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( old && old === elem.ownerDocument ) { + eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]); + } + } + + // Fire handlers on the event path + for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) { + + cur = eventPath[i][0]; + event.type = eventPath[i][1]; + + handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + // Note that this is a bare JS function and not a jQuery handler + handle = ontype && cur[ ontype ]; + if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) { + event.preventDefault(); + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) && + !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction() check here because IE6/7 fails that test. + // Don't do default actions on window, that's where global variables be (#6170) + // IE<9 dies on focus/blur to hidden element (#1486) + if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + old = elem[ ontype ]; + + if ( old ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + elem[ type ](); + jQuery.event.triggered = undefined; + + if ( old ) { + elem[ ontype ] = old; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event || window.event ); + + var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []), + delegateCount = handlers.delegateCount, + args = [].slice.call( arguments, 0 ), + run_all = !event.exclusive && !event.namespace, + handlerQueue = [], + i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Determine handlers that should run if there are delegated events + // Avoid disabled elements in IE (#6911) and non-left-click bubbling in Firefox (#3861) + if ( delegateCount && !event.target.disabled && !(event.button && event.type === "click") ) { + + // Pregenerate a single jQuery object for reuse with .is() + jqcur = jQuery(this); + jqcur.context = this.ownerDocument || this; + + for ( cur = event.target; cur != this; cur = cur.parentNode || this ) { + selMatch = {}; + matches = []; + jqcur[0] = cur; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + sel = handleObj.selector; + + if ( selMatch[ sel ] === undefined ) { + selMatch[ sel ] = ( + handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel ) + ); + } + if ( selMatch[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ elem: cur, matches: matches }); + } + } + } + + // Add the remaining (directly-bound) handlers + if ( handlers.length > delegateCount ) { + handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) }); + } + + // Run delegates first; they may want to stop propagation beneath us + for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) { + matched = handlerQueue[ i ]; + event.currentTarget = matched.elem; + + for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) { + handleObj = matched.matches[ j ]; + + // Triggered event must either 1) be non-exclusive and have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) { + + event.data = handleObj.data; + event.handleObj = handleObj; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + return event.result; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 *** + props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split(" "), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var eventDoc, doc, body, + button = original.button, + fromElement = original.fromElement; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && fromElement ) { + event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, + originalEvent = event, + fixHook = jQuery.event.fixHooks[ event.type ] || {}, + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = jQuery.Event( originalEvent ); + + for ( i = copy.length; i; ) { + prop = copy[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Target should not be a text node (#504, Safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8) + if ( event.metaKey === undefined ) { + event.metaKey = event.ctrlKey; + } + + return fixHook.filter? fixHook.filter( event, originalEvent ) : event; + }, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady + }, + + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + + focus: { + delegateType: "focusin" + }, + blur: { + delegateType: "focusout" + }, + + beforeunload: { + setup: function( data, namespaces, eventHandle ) { + // We only want to do this special case on windows + if ( jQuery.isWindow( this ) ) { + this.onbeforeunload = eventHandle; + } + }, + + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { + this.onbeforeunload = null; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + var e = jQuery.extend( + new jQuery.Event(), + event, + { type: type, + isSimulated: true, + originalEvent: {} + } + ); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +// Some plugins are using, but it's undocumented/deprecated and will be removed. +// The 1.7 special event interface should provide all the hooks needed now. +jQuery.event.handle = jQuery.event.dispatch; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + if ( elem.detachEvent ) { + elem.detachEvent( "on" + type, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +function returnFalse() { + return false; +} +function returnTrue() { + return true; +} + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + preventDefault: function() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // otherwise set the returnValue property of the original event to false (IE) + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var target = this, + related = event.relatedTarget, + handleObj = event.handleObj, + selector = handleObj.selector, + ret; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +}); + +// IE submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Lazy-add a submit handler when a descendant form may potentially be submitted + jQuery.event.add( this, "click._submit keypress._submit", function( e ) { + // Node name check avoids a VML-related crash in IE (#9807) + var elem = e.target, + form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; + if ( form && !form._submit_attached ) { + jQuery.event.add( form, "submit._submit", function( event ) { + // If form was submitted by the user, bubble the event up the tree + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event, true ); + } + }); + form._submit_attached = true; + } + }); + // return undefined since we don't need an event listener + }, + + teardown: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Remove delegated handlers; cleanData eventually reaps submit handlers attached above + jQuery.event.remove( this, "._submit" ); + } + }; +} + +// IE change delegation and checkbox/radio fix +if ( !jQuery.support.changeBubbles ) { + + jQuery.event.special.change = { + + setup: function() { + + if ( rformElems.test( this.nodeName ) ) { + // IE doesn't fire change on a check/radio until blur; trigger it on click + // after a propertychange. Eat the blur-change in special.change.handle. + // This still fires onchange a second time for check/radio after blur. + if ( this.type === "checkbox" || this.type === "radio" ) { + jQuery.event.add( this, "propertychange._change", function( event ) { + if ( event.originalEvent.propertyName === "checked" ) { + this._just_changed = true; + } + }); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._just_changed && !event.isTrigger ) { + this._just_changed = false; + jQuery.event.simulate( "change", this, event, true ); + } + }); + } + return false; + } + // Delegated event; lazy-add a change handler on descendant inputs + jQuery.event.add( this, "beforeactivate._change", function( e ) { + var elem = e.target; + + if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event, true ); + } + }); + elem._change_attached = true; + } + }); + }, + + handle: function( event ) { + var elem = event.target; + + // Swallow native change events from checkbox/radio, we already triggered them above + if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { + return event.handleObj.handler.apply( this, arguments ); + } + }, + + teardown: function() { + jQuery.event.remove( this, "._change" ); + + return rformElems.test( this.nodeName ); + } + }; +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0, + handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + }); +} + +jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + // ( types-Object, data ) + data = selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on.call( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + var handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace? handleObj.type + "." + handleObj.namespace : handleObj.type, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( var type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + bind: function( types, data, fn ) { + return this.on( types, null, data, fn ); + }, + unbind: function( types, fn ) { + return this.off( types, null, fn ); + }, + + live: function( types, data, fn ) { + jQuery( this.context ).on( types, this.selector, data, fn ); + return this; + }, + die: function( types, fn ) { + jQuery( this.context ).off( types, this.selector || "**", fn ); + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.on( types, selector, data, fn ); + }, + undelegate: function( selector, types, fn ) { + // ( namespace ) or ( selector, types [, fn] ) + return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn ); + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + triggerHandler: function( type, data ) { + if ( this[0] ) { + return jQuery.event.trigger( type, data, this[0], true ); + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, + guid = fn.guid || jQuery.guid++, + i = 0, + toggler = function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + }; + + // link all the functions, so any of them can unbind this click handler + toggler.guid = guid; + while ( i < args.length ) { + args[ i++ ].guid = guid; + } + + return this.click( toggler ); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } + + if ( rkeyEvent.test( name ) ) { + jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks; + } + + if ( rmouseEvent.test( name ) ) { + jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks; + } +}); + + + +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + expando = "sizcache" + (Math.random() + '').replace('.', ''), + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true, + rBackslash = /\\/g, + rReturn = /\r\n/g, + rNonWord = /\W/; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function() { + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function( selector, context, results, seed ) { + results = results || []; + context = context || document; + + var origContext = context; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var m, set, checkSet, extra, ret, cur, pop, i, + prune = true, + contextXML = Sizzle.isXML( context ), + parts = [], + soFar = selector; + + // Reset the position of the chunker regexp (start from head) + do { + chunker.exec( "" ); + m = chunker.exec( soFar ); + + if ( m ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + } while ( m ); + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context, seed ); + + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set, seed ); + } + } + + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + + ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? + Sizzle.filter( ret.expr, ret.set )[0] : + ret.set[0]; + } + + if ( context ) { + ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + + set = ret.expr ? + Sizzle.filter( ret.expr, ret.set ) : + ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray( set ); + + } else { + prune = false; + } + + while ( parts.length ) { + cur = parts.pop(); + pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + Sizzle.error( cur || selector ); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + + } else if ( context && context.nodeType === 1 ) { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + + } else { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function( results ) { + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[ i - 1 ] ) { + results.splice( i--, 1 ); + } + } + } + } + + return results; +}; + +Sizzle.matches = function( expr, set ) { + return Sizzle( expr, null, null, set ); +}; + +Sizzle.matchesSelector = function( node, expr ) { + return Sizzle( expr, null, null, [node] ).length > 0; +}; + +Sizzle.find = function( expr, context, isXML ) { + var set, i, len, match, type, left; + + if ( !expr ) { + return []; + } + + for ( i = 0, len = Expr.order.length; i < len; i++ ) { + type = Expr.order[i]; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + left = match[1]; + match.splice( 1, 1 ); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace( rBackslash, "" ); + set = Expr.find[ type ]( match, context, isXML ); + + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = typeof context.getElementsByTagName !== "undefined" ? + context.getElementsByTagName( "*" ) : + []; + } + + return { set: set, expr: expr }; +}; + +Sizzle.filter = function( expr, set, inplace, not ) { + var match, anyFound, + type, found, item, filter, left, + i, pass, + old = expr, + result = [], + curLoop = set, + isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); + + while ( expr && set.length ) { + for ( type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + filter = Expr.filter[ type ]; + left = match[1]; + + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + pass = not ^ found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + + } else { + curLoop[i] = false; + } + + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Utility function for retreiving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +var getText = Sizzle.getText = function( elem ) { + var i, node, + nodeType = elem.nodeType, + ret = ""; + + if ( nodeType ) { + if ( nodeType === 1 || nodeType === 9 ) { + // Use textContent || innerText for elements + if ( typeof elem.textContent === 'string' ) { + return elem.textContent; + } else if ( typeof elem.innerText === 'string' ) { + // Replace IE's carriage returns + return elem.innerText.replace( rReturn, '' ); + } else { + // Traverse it's children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + } else { + + // If no nodeType, this is expected to be an array + for ( i = 0; (node = elem[i]); i++ ) { + // Do not traverse comment nodes + if ( node.nodeType !== 8 ) { + ret += getText( node ); + } + } + } + return ret; +}; + +var Expr = Sizzle.selectors = { + order: [ "ID", "NAME", "TAG" ], + + match: { + ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, + ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, + TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, + CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, + POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, + PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ + }, + + leftMatch: {}, + + attrMap: { + "class": "className", + "for": "htmlFor" + }, + + attrHandle: { + href: function( elem ) { + return elem.getAttribute( "href" ); + }, + type: function( elem ) { + return elem.getAttribute( "type" ); + } + }, + + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !rNonWord.test( part ), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + + ">": function( checkSet, part ) { + var elem, + isPartStr = typeof part === "string", + i = 0, + l = checkSet.length; + + if ( isPartStr && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + + } else { + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + + "": function(checkSet, part, isXML){ + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); + }, + + "~": function( checkSet, part, isXML ) { + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); + } + }, + + find: { + ID: function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }, + + NAME: function( match, context ) { + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], + results = context.getElementsByName( match[1] ); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + + TAG: function( match, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( match[1] ); + } + } + }, + preFilter: { + CLASS: function( match, curLoop, inplace, result, not, isXML ) { + match = " " + match[1].replace( rBackslash, "" ) + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + + ID: function( match ) { + return match[1].replace( rBackslash, "" ); + }, + + TAG: function( match, curLoop ) { + return match[1].replace( rBackslash, "" ).toLowerCase(); + }, + + CHILD: function( match ) { + if ( match[1] === "nth" ) { + if ( !match[2] ) { + Sizzle.error( match[0] ); + } + + match[2] = match[2].replace(/^\+|\s*/g, ''); + + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + else if ( match[2] ) { + Sizzle.error( match[0] ); + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + + ATTR: function( match, curLoop, inplace, result, not, isXML ) { + var name = match[1] = match[1].replace( rBackslash, "" ); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + // Handle if an un-quoted value was used + match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + + PSEUDO: function( match, curLoop, inplace, result, not ) { + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + + if ( !inplace ) { + result.push.apply( result, ret ); + } + + return false; + } + + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + + POS: function( match ) { + match.unshift( true ); + + return match; + } + }, + + filters: { + enabled: function( elem ) { + return elem.disabled === false && elem.type !== "hidden"; + }, + + disabled: function( elem ) { + return elem.disabled === true; + }, + + checked: function( elem ) { + return elem.checked === true; + }, + + selected: function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + parent: function( elem ) { + return !!elem.firstChild; + }, + + empty: function( elem ) { + return !elem.firstChild; + }, + + has: function( elem, i, match ) { + return !!Sizzle( match[3], elem ).length; + }, + + header: function( elem ) { + return (/h\d/i).test( elem.nodeName ); + }, + + text: function( elem ) { + var attr = elem.getAttribute( "type" ), type = elem.type; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); + }, + + radio: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; + }, + + checkbox: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; + }, + + file: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; + }, + + password: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; + }, + + submit: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "submit" === elem.type; + }, + + image: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; + }, + + reset: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "reset" === elem.type; + }, + + button: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && "button" === elem.type || name === "button"; + }, + + input: function( elem ) { + return (/input|select|textarea|button/i).test( elem.nodeName ); + }, + + focus: function( elem ) { + return elem === elem.ownerDocument.activeElement; + } + }, + setFilters: { + first: function( elem, i ) { + return i === 0; + }, + + last: function( elem, i, match, array ) { + return i === array.length - 1; + }, + + even: function( elem, i ) { + return i % 2 === 0; + }, + + odd: function( elem, i ) { + return i % 2 === 1; + }, + + lt: function( elem, i, match ) { + return i < match[3] - 0; + }, + + gt: function( elem, i, match ) { + return i > match[3] - 0; + }, + + nth: function( elem, i, match ) { + return match[3] - 0 === i; + }, + + eq: function( elem, i, match ) { + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function( elem, match, i, array ) { + var name = match[1], + filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0; + + } else if ( name === "not" ) { + var not = match[3]; + + for ( var j = 0, l = not.length; j < l; j++ ) { + if ( not[j] === elem ) { + return false; + } + } + + return true; + + } else { + Sizzle.error( name ); + } + }, + + CHILD: function( elem, match ) { + var first, last, + doneName, parent, cache, + count, diff, + type = match[1], + node = elem; + + switch ( type ) { + case "only": + case "first": + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + if ( type === "first" ) { + return true; + } + + node = elem; + + case "last": + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + return true; + + case "nth": + first = match[2]; + last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + doneName = match[0]; + parent = elem.parentNode; + + if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) { + count = 0; + + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + + parent[ expando ] = doneName; + } + + diff = elem.nodeIndex - last; + + if ( first === 0 ) { + return diff === 0; + + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + + ID: function( elem, match ) { + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + + TAG: function( elem, match ) { + return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match; + }, + + CLASS: function( elem, match ) { + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + + ATTR: function( elem, match ) { + var name = match[1], + result = Sizzle.attr ? + Sizzle.attr( elem, name ) : + Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + !type && Sizzle.attr ? + result != null : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + + POS: function( elem, match, i, array ) { + var name = match[2], + filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS, + fescape = function(all, num){ + return "\\" + (num - 0 + 1); + }; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); +} + +var makeArray = function( array, results ) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; + +// Provide a fallback method if it does not work +} catch( e ) { + makeArray = function( array, results ) { + var i = 0, + ret = results || []; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + + } else { + if ( typeof array.length === "number" ) { + for ( var l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + + } else { + for ( ; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder, siblingCheck; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + return a.compareDocumentPosition ? -1 : 1; + } + + return a.compareDocumentPosition(b) & 4 ? -1 : 1; + }; + +} else { + sortOrder = function( a, b ) { + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Fallback to using sourceIndex (in IE) if it's available on both nodes + } else if ( a.sourceIndex && b.sourceIndex ) { + return a.sourceIndex - b.sourceIndex; + } + + var al, bl, + ap = [], + bp = [], + aup = a.parentNode, + bup = b.parentNode, + cur = aup; + + // If the nodes are siblings (or identical) we can do a quick check + if ( aup === bup ) { + return siblingCheck( a, b ); + + // If no parents were found then the nodes are disconnected + } else if ( !aup ) { + return -1; + + } else if ( !bup ) { + return 1; + } + + // Otherwise they're somewhere else in the tree so we need + // to build up a full list of the parentNodes for comparison + while ( cur ) { + ap.unshift( cur ); + cur = cur.parentNode; + } + + cur = bup; + + while ( cur ) { + bp.unshift( cur ); + cur = cur.parentNode; + } + + al = ap.length; + bl = bp.length; + + // Start walking down the tree looking for a discrepancy + for ( var i = 0; i < al && i < bl; i++ ) { + if ( ap[i] !== bp[i] ) { + return siblingCheck( ap[i], bp[i] ); + } + } + + // We ended someplace up the tree so do a sibling check + return i === al ? + siblingCheck( a, bp[i], -1 ) : + siblingCheck( ap[i], b, 1 ); + }; + + siblingCheck = function( a, b, ret ) { + if ( a === b ) { + return ret; + } + + var cur = a.nextSibling; + + while ( cur ) { + if ( cur === b ) { + return -1; + } + + cur = cur.nextSibling; + } + + return 1; + }; +} + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date()).getTime(), + root = document.documentElement; + + form.innerHTML = ""; + + // Inject it into the root element, check its status, and remove it quickly + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + + return m ? + m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? + [m] : + undefined : + []; + } + }; + + Expr.filter.ID = function( elem, match ) { + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + + // release memory in IE + root = form = null; +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function( match, context ) { + var results = context.getElementsByTagName( match[1] ); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = ""; + + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + + Expr.attrHandle.href = function( elem ) { + return elem.getAttribute( "href", 2 ); + }; + } + + // release memory in IE + div = null; +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, + div = document.createElement("div"), + id = "__sizzle__"; + + div.innerHTML = "

"; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function( query, context, extra, seed ) { + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && !Sizzle.isXML(context) ) { + // See if we find a selector to speed up + var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); + + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { + // Speed-up: Sizzle("TAG") + if ( match[1] ) { + return makeArray( context.getElementsByTagName( query ), extra ); + + // Speed-up: Sizzle(".CLASS") + } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { + return makeArray( context.getElementsByClassName( match[2] ), extra ); + } + } + + if ( context.nodeType === 9 ) { + // Speed-up: Sizzle("body") + // The body element only exists once, optimize finding it + if ( query === "body" && context.body ) { + return makeArray( [ context.body ], extra ); + + // Speed-up: Sizzle("#ID") + } else if ( match && match[3] ) { + var elem = context.getElementById( match[3] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id === match[3] ) { + return makeArray( [ elem ], extra ); + } + + } else { + return makeArray( [], extra ); + } + } + + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(qsaError) {} + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + var oldContext = context, + old = context.getAttribute( "id" ), + nid = old || id, + hasParent = context.parentNode, + relativeHierarchySelector = /^\s*[+~]/.test( query ); + + if ( !old ) { + context.setAttribute( "id", nid ); + } else { + nid = nid.replace( /'/g, "\\$&" ); + } + if ( relativeHierarchySelector && hasParent ) { + context = context.parentNode; + } + + try { + if ( !relativeHierarchySelector || hasParent ) { + return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); + } + + } catch(pseudoError) { + } finally { + if ( !old ) { + oldContext.removeAttribute( "id" ); + } + } + } + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + // release memory in IE + div = null; + })(); +} + +(function(){ + var html = document.documentElement, + matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; + + if ( matches ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9 fails this) + var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), + pseudoWorks = false; + + try { + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( document.documentElement, "[test!='']:sizzle" ); + + } catch( pseudoError ) { + pseudoWorks = true; + } + + Sizzle.matchesSelector = function( node, expr ) { + // Make sure that attribute selectors are quoted + expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); + + if ( !Sizzle.isXML( node ) ) { + try { + if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { + var ret = matches.call( node, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || !disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9, so check for that + node.document && node.document.nodeType !== 11 ) { + return ret; + } + } + } catch(e) {} + } + + return Sizzle(expr, null, null, [node]).length > 0; + }; + } +})(); + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "
"; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function( match, context, isXML ) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + // release memory in IE + div = null; +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem[ expando ] === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem[ expando ] = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem[ expando ] === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem[ expando ] = doneName; + elem.sizset = i; + } + + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +if ( document.documentElement.contains ) { + Sizzle.contains = function( a, b ) { + return a !== b && (a.contains ? a.contains(b) : true); + }; + +} else if ( document.documentElement.compareDocumentPosition ) { + Sizzle.contains = function( a, b ) { + return !!(a.compareDocumentPosition(b) & 16); + }; + +} else { + Sizzle.contains = function() { + return false; + }; +} + +Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function( selector, context, seed ) { + var match, + tmpSet = [], + later = "", + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet, seed ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +// Override sizzle attribute retrieval +Sizzle.attr = jQuery.attr; +Sizzle.selectors.attrMap = {}; +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.filters; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})(); + + +var runtil = /Until$/, + rparentsprev = /^(?:parents|prevUntil|prevAll)/, + // Note: This RegExp should be improved, or likely pulled from Sizzle + rmultiselector = /,/, + isSimple = /^.[^:#\[\.,]*$/, + slice = Array.prototype.slice, + POS = jQuery.expr.match.POS, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var self = this, + i, l; + + if ( typeof selector !== "string" ) { + return jQuery( selector ).filter(function() { + for ( i = 0, l = self.length; i < l; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }); + } + + var ret = this.pushStack( "", "find", selector ), + length, n, r; + + for ( i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( n = length; n < ret.length; n++ ) { + for ( r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + has: function( target ) { + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false), "not", selector); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && ( + typeof selector === "string" ? + // If this is a positional selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + POS.test( selector ) ? + jQuery( selector, this.context ).index( this[0] ) >= 0 : + jQuery.filter( selector, this ).length > 0 : + this.filter( selector ).length > 0 ); + }, + + closest: function( selectors, context ) { + var ret = [], i, l, cur = this[0]; + + // Array (deprecated as of jQuery 1.7) + if ( jQuery.isArray( selectors ) ) { + var level = 1; + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( i = 0; i < selectors.length; i++ ) { + + if ( jQuery( cur ).is( selectors[ i ] ) ) { + ret.push({ selector: selectors[ i ], elem: cur, level: level }); + } + } + + cur = cur.parentNode; + level++; + } + + return ret; + } + + // String + var pos = POS.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( i = 0, l = this.length; i < l; i++ ) { + cur = this[i]; + + while ( cur ) { + if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + + } else { + cur = cur.parentNode; + if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { + break; + } + } + } + } + + ret = ret.length > 1 ? jQuery.unique( ret ) : ret; + + return this.pushStack( ret, "closest", selectors ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + andSelf: function() { + return this.add( this.prevObject ); + } +}); + +// A painfully simple check to see if an element is disconnected +// from a document (should be improved, where feasible). +function isDisconnected( node ) { + return !node || !node.parentNode || node.parentNode.nodeType === 11; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return jQuery.nth( elem, 2, "nextSibling" ); + }, + prev: function( elem ) { + return jQuery.nth( elem, 2, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( elem.parentNode.firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.makeArray( elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, slice.call( arguments ).join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + nth: function( cur, result, dir, elem ) { + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, keep ) { + + // Can't pass null or undefined to indexOf in Firefox 4 + // Set to 0 to skip string check + qualifier = qualifier || 0; + + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + var retVal = !!qualifier.call( elem, i, elem ); + return retVal === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return ( elem === qualifier ) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep; + }); +} + + + + +function createSafeFragment( document ) { + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; +} + +var nodeNames = "abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|" + + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", + rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, + rtagName = /<([\w:]+)/, + rtbody = /", "" ], + legend: [ 1, "
", "
" ], + thead: [ 1, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + col: [ 2, "", "
" ], + area: [ 1, "", "" ], + _default: [ 0, "", "" ] + }, + safeFragment = createSafeFragment( document ); + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize and \ No newline at end of file diff --git a/OnPremise/WebSite/Views/Admin/Certificates.cshtml b/OnPremise/WebSite/Views/Admin/Certificates.cshtml new file mode 100644 index 0000000..e6e446f --- /dev/null +++ b/OnPremise/WebSite/Views/Admin/Certificates.cshtml @@ -0,0 +1,85 @@ +@model Thinktecture.IdentityServer.Web.ViewModels.Administration.EditCertificatesModel + +@{ + ViewBag.Title = "Certificates Configuration"; +} + +

+ Certificates Configuration + (help) +

+ + + + +@using (Html.BeginForm()) { + @Html.ValidationSummary(true) + @Html.AntiForgeryToken() + +
+ Configuration + +
+ @Html.LabelFor(model => model.SslCertificate) +
+
+ @Model.SslCertificate + @Html.ValidationMessageFor(model => model.SslCertificate) +
+ +
+ @Html.EditorFor(model => model.UpdateSslCertificate) + @Html.LabelFor(model => model.UpdateSslCertificate) + @Html.ValidationMessageFor(model => model.UpdateSslCertificate) + + @Html.DropDownList("UpdatedSslCertificate", Model.AvailableCertificatesList) +
+ +
+ @Html.LabelFor(model => model.SigningCertificate) +
+
+ @Model.SigningCertificate + @Html.ValidationMessageFor(model => model.SigningCertificate) +
+ +
+ @Html.EditorFor(model => model.UpdateSigningCertificate) + @Html.LabelFor(model => model.UpdateSigningCertificate) + @Html.ValidationMessageFor(model => model.UpdateSigningCertificate) + + @Html.DropDownList("UpdatedSigningCertificate", Model.AvailableCertificatesList) +
+ + @if (ViewBag.SaveEnabled) + { +

+ +

+ } +
+} + +
+ @Html.ActionLink("Back", "Index") +
+ +@if (false) +{ + \ No newline at end of file diff --git a/OnPremise/WebSite/Views/Admin/Configuration.cshtml b/OnPremise/WebSite/Views/Admin/Configuration.cshtml new file mode 100644 index 0000000..ef63ef5 --- /dev/null +++ b/OnPremise/WebSite/Views/Admin/Configuration.cshtml @@ -0,0 +1,37 @@ +@model Thinktecture.IdentityServer.Web.ViewModels.Administration.GlobalConfigurationModel + +@{ + ViewBag.Title = "Global Token Service Configuration"; +} + +

+ Global Token Service Configuration + (help) +

+ + + + +@using (Html.BeginForm()) +{ + @Html.ValidationSummary(true) + @Html.AntiForgeryToken() + +
+ Configuration + + @Html.EditorForModel() + + @if (ViewBag.SaveEnabled) + { +

+ +

+ } +
+} + +
+ @Html.ActionLink("Back", "Index") +
+ diff --git a/OnPremise/WebSite/Views/Admin/Endpoints.cshtml b/OnPremise/WebSite/Views/Admin/Endpoints.cshtml new file mode 100644 index 0000000..ff19298 --- /dev/null +++ b/OnPremise/WebSite/Views/Admin/Endpoints.cshtml @@ -0,0 +1,37 @@ +@model Thinktecture.IdentityServer.Web.ViewModels.Administration.EndpointConfigurationModel + +@{ + ViewBag.Title = "Endpoint Configuration"; +} + +

+ Endpoint Configuration + (help) +

+ + + + +@using (Html.BeginForm()) +{ + @Html.ValidationSummary(true) + @Html.AntiForgeryToken() + +
+ Configuration + + @Html.EditorForModel() + + @if (ViewBag.SaveEnabled) + { +

+ +

+ } +
+} + +
+ @Html.ActionLink("Back", "Index") +
+ diff --git a/OnPremise/WebSite/Views/Admin/Index.cshtml b/OnPremise/WebSite/Views/Admin/Index.cshtml new file mode 100644 index 0000000..ee527d1 --- /dev/null +++ b/OnPremise/WebSite/Views/Admin/Index.cshtml @@ -0,0 +1,41 @@ +@{ + ViewBag.Title = "Administration"; +} + +

Administration

+ +

+ @Html.ActionLink("My Claims", "myclaims") +

+ +

+ @Html.ActionLink("My Token", "mytoken") +

+ +

+ @Html.ActionLink("Global Configuration", "configuration") +

+ +

+ @Html.ActionLink("Endpoint Configuration", "endpoints") +

+ +

+ @Html.ActionLink("Service Certificates", "certificates") +

+ +

+ @Html.ActionLink("Relying Parties", "index", "RelyingPartiesAdmin") +

+ +

+ @Html.ActionLink("Client Certificates", "index", "ClientCertificatesAdmin") +

+ +

+ @Html.ActionLink("Delegation", "index", "DelegationAdmin") +

+ +

+ @Html.ActionLink("Recycle IdentityServer", "restart") +

diff --git a/OnPremise/WebSite/Views/Admin/MyClaims.cshtml b/OnPremise/WebSite/Views/Admin/MyClaims.cshtml new file mode 100644 index 0000000..a3a2dab --- /dev/null +++ b/OnPremise/WebSite/Views/Admin/MyClaims.cshtml @@ -0,0 +1,16 @@ +@model Thinktecture.IdentityServer.Web.ViewModels.Administration.MyModel + +@{ + ViewBag.Title = "My Claims"; +} + +

My Claims

+ +@foreach (var claim in Model.Claims) +{ +

+ @claim.ClaimType +
+ @claim.Value +

+} diff --git a/OnPremise/WebSite/Views/ClientCertificatesAdmin/Add.cshtml b/OnPremise/WebSite/Views/ClientCertificatesAdmin/Add.cshtml new file mode 100644 index 0000000..fee399f --- /dev/null +++ b/OnPremise/WebSite/Views/ClientCertificatesAdmin/Add.cshtml @@ -0,0 +1,60 @@ +@model Thinktecture.IdentityServer.Web.ViewModels.Administration.AddClientCertificateModel + +@{ + ViewBag.Title = "Add"; +} + +

+ Add + (help) +

+ + + + +@using (Html.BeginForm("add", "ClientCertificatesAdmin", FormMethod.Post, new { enctype = "multipart/form-data" })) +{ + @Html.AntiForgeryToken() + @Html.ValidationSummary(true) + +
+ Client Certificate + +
+ @Html.LabelFor(model => model.UserName) +
+
+ @Html.EditorFor(model => model.UserName) + @Html.ValidationMessageFor(model => model.UserName) +
+ +
+ @Html.LabelFor(model => model.Description) +
+
+ @Html.EditorFor(model => model.Description) + @Html.ValidationMessageFor(model => model.Description) +
+ +
+ @Html.LabelFor(model => model.Thumbprint) +
+
+ @Html.EditorFor(model => model.Thumbprint) + @Html.ValidationMessageFor(model => model.Thumbprint) +
+ +
+ +
+ +

+ +

+
+} + +
+ @Html.ActionLink("Back", "Index") +
+ diff --git a/OnPremise/WebSite/Views/ClientCertificatesAdmin/Delete.cshtml b/OnPremise/WebSite/Views/ClientCertificatesAdmin/Delete.cshtml new file mode 100644 index 0000000..a4497ad --- /dev/null +++ b/OnPremise/WebSite/Views/ClientCertificatesAdmin/Delete.cshtml @@ -0,0 +1,16 @@ +@{ + ViewBag.Title = "Delete"; +} + +

Delete

+ +@using (Html.BeginForm()) +{ + @Html.AntiForgeryToken() + @Html.ValidationSummary() + + +
+
+ +} diff --git a/OnPremise/WebSite/Views/ClientCertificatesAdmin/Edit.cshtml b/OnPremise/WebSite/Views/ClientCertificatesAdmin/Edit.cshtml new file mode 100644 index 0000000..8afff9b --- /dev/null +++ b/OnPremise/WebSite/Views/ClientCertificatesAdmin/Edit.cshtml @@ -0,0 +1,32 @@ +@model Thinktecture.IdentityServer.Web.ViewModels.Administration.EditClientCertificatesModel + +@{ + ViewBag.Title = "Edit"; +} + +

+ Edit Client Certificates for @Model.UserName + (help) +

+ +

+ @Html.ActionLink("Add New", "Add") +

+ +
    + @foreach (var cert in Model.ClientCertificates) + { +
  • + @cert.Description +
    + @cert.Thumbprint + @Html.ActionLink("(delete)", "delete", new { userName = Model.UserName, thumbprint = cert.Thumbprint }) +
    +
    +
  • + } +
+ +

+ @Html.ActionLink("Back", "Index") +

diff --git a/OnPremise/WebSite/Views/ClientCertificatesAdmin/Index.cshtml b/OnPremise/WebSite/Views/ClientCertificatesAdmin/Index.cshtml new file mode 100644 index 0000000..1eddd39 --- /dev/null +++ b/OnPremise/WebSite/Views/ClientCertificatesAdmin/Index.cshtml @@ -0,0 +1,28 @@ +@model List + +@{ + ViewBag.Title = "Client Certificates"; +} + +

Client Certificates

+ +

+ @Html.ActionLink("Add New", "add") +

+ +
    + @foreach (var user in Model) + { +
  • + @user + @Html.ActionLink("(edit)", "edit", new { username = user }) + @Html.ActionLink("(delete)", "deleteall", new { username = user }) +
  • + } +
+ +

+ @Html.ActionLink("Back", "index", "admin") +

+ + diff --git a/OnPremise/WebSite/Views/DelegationAdmin/Add.cshtml b/OnPremise/WebSite/Views/DelegationAdmin/Add.cshtml new file mode 100644 index 0000000..6a93fbb --- /dev/null +++ b/OnPremise/WebSite/Views/DelegationAdmin/Add.cshtml @@ -0,0 +1,56 @@ +@model Thinktecture.IdentityServer.Web.ViewModels.Administration.AddDelegationModel + +@{ + ViewBag.Title = "Add"; +} + +

+ Add + (help) +

+ + + + +@using (Html.BeginForm()) +{ + @Html.AntiForgeryToken() + @Html.ValidationSummary(true) + +
+ Delegation + +
+ @Html.LabelFor(model => model.UserName) +
+
+ @Html.EditorFor(model => model.UserName) + @Html.ValidationMessageFor(model => model.UserName) +
+ +
+ @Html.LabelFor(model => model.Description) +
+
+ @Html.EditorFor(model => model.Description) + @Html.ValidationMessageFor(model => model.Description) +
+ +
+ @Html.LabelFor(model => model.Realm) +
+
+ @Html.EditorFor(model => model.Realm) + @Html.ValidationMessageFor(model => model.Realm) +
+ +

+ +

+
+} + +
+ @Html.ActionLink("Back", "Index") +
+ diff --git a/OnPremise/WebSite/Views/DelegationAdmin/Delete.cshtml b/OnPremise/WebSite/Views/DelegationAdmin/Delete.cshtml new file mode 100644 index 0000000..a4497ad --- /dev/null +++ b/OnPremise/WebSite/Views/DelegationAdmin/Delete.cshtml @@ -0,0 +1,16 @@ +@{ + ViewBag.Title = "Delete"; +} + +

Delete

+ +@using (Html.BeginForm()) +{ + @Html.AntiForgeryToken() + @Html.ValidationSummary() + + +
+
+ +} diff --git a/OnPremise/WebSite/Views/DelegationAdmin/Edit.cshtml b/OnPremise/WebSite/Views/DelegationAdmin/Edit.cshtml new file mode 100644 index 0000000..983ecab --- /dev/null +++ b/OnPremise/WebSite/Views/DelegationAdmin/Edit.cshtml @@ -0,0 +1,32 @@ +@model Thinktecture.IdentityServer.Web.ViewModels.Administration.EditDelegationModel + +@{ + ViewBag.Title = "Edit"; +} + +

+ Edit Delegation Settings for @Model.UserName + (help) +

+ +

+ @Html.ActionLink("Add New", "Add") +

+ +
    + @foreach (var setting in Model.Settings) + { +
  • + @setting.Description +
    + @setting.Realm.AbsoluteUri + @Html.ActionLink("(delete)", "delete", new { userName = Model.UserName, realm = setting.Realm.AbsoluteUri }) +
    +
    +
  • + } +
+ +

+ @Html.ActionLink("Back", "Index") +

diff --git a/OnPremise/WebSite/Views/DelegationAdmin/Index.cshtml b/OnPremise/WebSite/Views/DelegationAdmin/Index.cshtml new file mode 100644 index 0000000..c669315 --- /dev/null +++ b/OnPremise/WebSite/Views/DelegationAdmin/Index.cshtml @@ -0,0 +1,28 @@ +@model IEnumerable + +@{ + ViewBag.Title = "Delegation"; +} + +

Delegation

+ +

+ @Html.ActionLink("Add New", "add") +

+ +
    + @foreach (var user in Model) + { +
  • + @user + @Html.ActionLink("(edit)", "edit", new { username = user }) + @Html.ActionLink("(delete)", "deleteall", new { username = user }) +
  • + } +
+ +

+ @Html.ActionLink("Back", "index", "admin") +

+ + diff --git a/OnPremise/WebSite/Views/Home/AppIntegration.cshtml b/OnPremise/WebSite/Views/Home/AppIntegration.cshtml new file mode 100644 index 0000000..3123dfe --- /dev/null +++ b/OnPremise/WebSite/Views/Home/AppIntegration.cshtml @@ -0,0 +1,16 @@ +@model Dictionary + +@{ + ViewBag.Title = "Application Integration"; +} + +

Application Integration

+ +@foreach (var pair in Model) +{ +

+ @pair.Key +
+ @pair.Value +

+} \ No newline at end of file diff --git a/OnPremise/WebSite/Views/Home/Index.cshtml b/OnPremise/WebSite/Views/Home/Index.cshtml new file mode 100644 index 0000000..44a2992 --- /dev/null +++ b/OnPremise/WebSite/Views/Home/Index.cshtml @@ -0,0 +1,13 @@ +@{ + ViewBag.Title = ViewBag.SiteName; +} + +

Welcome to thinktecture Identity Server

+ +

+ @Html.ActionLink("View WS-Federation Metadata", "Generate", "FederationMetadata") +

+ +

+ @Html.ActionLink("Application integration", "appintegration", "home") +

\ No newline at end of file diff --git a/OnPremise/WebSite/Views/InitialConfiguration/Index.cshtml b/OnPremise/WebSite/Views/InitialConfiguration/Index.cshtml new file mode 100644 index 0000000..e22fed0 --- /dev/null +++ b/OnPremise/WebSite/Views/InitialConfiguration/Index.cshtml @@ -0,0 +1,49 @@ +@model Thinktecture.IdentityServer.Web.ViewModels.InitialConfigurationModel + +@{ + ViewBag.Title = "Initial Configuration"; +} + +

+ Initial Configuration + (help) +

+ + +@using (Html.BeginForm()) +{ + @Html.ValidationSummary(true) + +
+ Settings + +
+ @Html.LabelFor(model => model.SiteName) +
+
+ @Html.EditorFor(model => model.SiteName) + @Html.ValidationMessageFor(model => model.SiteName) +
+ +
+ @Html.LabelFor(model => model.IssuerUri) +
+
+ @Html.EditorFor(model => model.IssuerUri) + @Html.ValidationMessageFor(model => model.IssuerUri) +
+ +
+ @Html.LabelFor(model => model.SigningCertificate) +
+ +
+ @Html.DropDownList("SigningCertificate", Model.AvailableCertificatesList) +
+ +

+ +

+
+ +} \ No newline at end of file diff --git a/OnPremise/WebSite/Views/RelyingPartiesAdmin/Add.cshtml b/OnPremise/WebSite/Views/RelyingPartiesAdmin/Add.cshtml new file mode 100644 index 0000000..36748c1 --- /dev/null +++ b/OnPremise/WebSite/Views/RelyingPartiesAdmin/Add.cshtml @@ -0,0 +1,116 @@ +@model Thinktecture.IdentityServer.Web.ViewModels.Administration.RelyingPartyModel + +@{ + ViewBag.Title = "Add new Relying Party"; +} + +

+ Add new Relying Party + (help) +

+ + + + +@using (Html.BeginForm("Add", "RelyingPartiesAdmin", FormMethod.Post, new { enctype = "multipart/form-data" })) +{ + @Html.AntiForgeryToken() + @Html.ValidationSummary(true) + +
+ Relying Party Details + +
+ @Html.LabelFor(model => model.Name) +
+
+ @Html.EditorFor(model => model.Name) + @Html.ValidationMessageFor(model => model.Name) +
+ +
+ @Html.LabelFor(model => model.Realm) +
+
+ @Html.EditorFor(model => model.Realm) + @Html.ValidationMessageFor(model => model.Realm) +
+ +
+ @Html.LabelFor(model => model.ReplyTo) +
+
+ @Html.EditorFor(model => model.ReplyTo) + @Html.ValidationMessageFor(model => model.ReplyTo) +
+ +
+ @Html.LabelFor(model => model.ExtraData1) +
+
+ @Html.EditorFor(model => model.ExtraData1) + @Html.ValidationMessageFor(model => model.ExtraData1) +
+ +
+ @Html.LabelFor(model => model.ExtraData2) +
+
+ @Html.EditorFor(model => model.ExtraData2) + @Html.ValidationMessageFor(model => model.ExtraData2) +
+ +
+ @Html.LabelFor(model => model.ExtraData3) +
+
+ @Html.EditorFor(model => model.ExtraData3) + @Html.ValidationMessageFor(model => model.ExtraData3) +
+ +
+ @Html.LabelFor(model => model.EncryptingCertificate) +
+
+ @Html.EditorFor(model => model.EncryptingCertificate) + @Html.ValidationMessageFor(model => model.EncryptingCertificate) +
+ +
+ +
+ @Html.LabelFor(model => model.SymmetricSigningKey) +
+
+ @Html.EditorFor(model => model.SymmetricSigningKey) + @Html.ValidationMessageFor(model => model.SymmetricSigningKey) + +
+ +
+ +

+ +

+
+} + +
+ @Html.ActionLink("Back", "Index") +
+ +@if (false) +{ + \ No newline at end of file diff --git a/OnPremise/WebSite/Views/RelyingPartiesAdmin/Delete.cshtml b/OnPremise/WebSite/Views/RelyingPartiesAdmin/Delete.cshtml new file mode 100644 index 0000000..4e61782 --- /dev/null +++ b/OnPremise/WebSite/Views/RelyingPartiesAdmin/Delete.cshtml @@ -0,0 +1,19 @@ +@{ + ViewBag.Title = "Delete"; +} + +

Delete

+ +@using (Html.BeginForm()) +{ + @Html.AntiForgeryToken() + @Html.ValidationSummary() + + +
+
+ +} + + + diff --git a/OnPremise/WebSite/Views/RelyingPartiesAdmin/Edit.cshtml b/OnPremise/WebSite/Views/RelyingPartiesAdmin/Edit.cshtml new file mode 100644 index 0000000..7648bff --- /dev/null +++ b/OnPremise/WebSite/Views/RelyingPartiesAdmin/Edit.cshtml @@ -0,0 +1,123 @@ +@model Thinktecture.IdentityServer.Web.ViewModels.Administration.RelyingPartyModel + +@{ + ViewBag.Title = "Edit " + Model.Name; +} + +

+ Edit @Model.Name + (help) +

+ + + + +@using (Html.BeginForm("Edit", "RelyingPartiesAdmin", FormMethod.Post, new { enctype = "multipart/form-data" })) +{ + @Html.AntiForgeryToken() + @Html.ValidationSummary(true) + @Html.HiddenFor(model => model.Id) + +
+ Relying Party + +
+ @Html.LabelFor(model => model.Name) +
+
+ @Html.EditorFor(model => model.Name) + @Html.ValidationMessageFor(model => model.Name) +
+ +
+ @Html.LabelFor(model => model.Realm) +
+
+ @Html.EditorFor(model => model.Realm) + @Html.ValidationMessageFor(model => model.Realm) +
+ +
+ @Html.LabelFor(model => model.ReplyTo) +
+
+ @Html.EditorFor(model => model.ReplyTo) + @Html.ValidationMessageFor(model => model.ReplyTo) +
+ +
+ @Html.LabelFor(model => model.ExtraData1) +
+
+ @Html.EditorFor(model => model.ExtraData1) + @Html.ValidationMessageFor(model => model.ExtraData1) +
+ +
+ @Html.LabelFor(model => model.ExtraData2) +
+
+ @Html.EditorFor(model => model.ExtraData2) + @Html.ValidationMessageFor(model => model.ExtraData2) +
+ +
+ @Html.LabelFor(model => model.ExtraData3) +
+
+ @Html.EditorFor(model => model.ExtraData3) + @Html.ValidationMessageFor(model => model.ExtraData3) +
+ +
+ @Html.LabelFor(model => model.EncryptingCertificate) +
+
+ @Html.EditorFor(model => model.EncryptingCertificate) + @Html.ValidationMessageFor(model => model.EncryptingCertificate) +
+ (@Model.EncryptingCertificateName) + +
+
+ +
+ + +
+ +
+ @Html.LabelFor(model => model.SymmetricSigningKey) +
+
+ @Html.EditorFor(model => model.SymmetricSigningKey) + @Html.ValidationMessageFor(model => model.SymmetricSigningKey) +
+ +
+ +

+ +

+
+} + +
+ @Html.ActionLink("Back", "Index") +
+ +@if (false) +{ + \ No newline at end of file diff --git a/OnPremise/WebSite/Views/RelyingPartiesAdmin/Index.cshtml b/OnPremise/WebSite/Views/RelyingPartiesAdmin/Index.cshtml new file mode 100644 index 0000000..300b8d4 --- /dev/null +++ b/OnPremise/WebSite/Views/RelyingPartiesAdmin/Index.cshtml @@ -0,0 +1,22 @@ +@model Thinktecture.IdentityServer.Web.ViewModels.Administration.RelyingPartiesModel +@{ + ViewBag.Title = "Relying Parties"; +} +

Relying Parties

+ +

+ @Html.ActionLink("Add New", "add") +

+ +
    + @foreach (var item in Model.RelyingParties) + { +
  • + @item.Name + @Html.ActionLink("(edit)", "edit", new { id = item.Id }) + @Html.ActionLink("(delete)", "delete", new { id = item.Id }) +
    + (@item.Realm) +
  • + } +
\ No newline at end of file diff --git a/OnPremise/WebSite/Views/Shared/Confirm.cshtml b/OnPremise/WebSite/Views/Shared/Confirm.cshtml new file mode 100644 index 0000000..e9d96c2 --- /dev/null +++ b/OnPremise/WebSite/Views/Shared/Confirm.cshtml @@ -0,0 +1,16 @@ +@{ + ViewBag.Title = "Confirm"; +} + +

Confirm

+ +@using (Html.BeginForm()) +{ + @Html.AntiForgeryToken() + @Html.ValidationSummary() + + +
+
+ +} diff --git a/OnPremise/WebSite/Views/Shared/Error.cshtml b/OnPremise/WebSite/Views/Shared/Error.cshtml new file mode 100644 index 0000000..7618dc4 --- /dev/null +++ b/OnPremise/WebSite/Views/Shared/Error.cshtml @@ -0,0 +1,15 @@ +@{ + Layout = null; +} + + + + + Error + + +

+ Sorry, an error occurred while processing your request. +

+ + \ No newline at end of file diff --git a/OnPremise/WebSite/Views/Shared/SignedOut.cshtml b/OnPremise/WebSite/Views/Shared/SignedOut.cshtml new file mode 100644 index 0000000..bf38dce --- /dev/null +++ b/OnPremise/WebSite/Views/Shared/SignedOut.cshtml @@ -0,0 +1,15 @@ +@{ + Layout = null; +} + + + + + Error + + +

+ You have been signed out of Identity Server. It might be possible that you still have active sessions with other applications. +

+ + \ No newline at end of file diff --git a/OnPremise/WebSite/Views/Shared/_Layout.cshtml b/OnPremise/WebSite/Views/Shared/_Layout.cshtml new file mode 100644 index 0000000..6450548 --- /dev/null +++ b/OnPremise/WebSite/Views/Shared/_Layout.cshtml @@ -0,0 +1,48 @@ + + + + @ViewBag.Title + + + @Html.Raw(ViewBag.Meta) + + + + +
+
+ Logo + +

@ViewBag.SiteName

+
+ + + +
+ + @RenderBody() + + diff --git a/OnPremise/WebSite/Views/WSFederation/SignOut.cshtml b/OnPremise/WebSite/Views/WSFederation/SignOut.cshtml new file mode 100644 index 0000000..baa5a2a --- /dev/null +++ b/OnPremise/WebSite/Views/WSFederation/SignOut.cshtml @@ -0,0 +1,24 @@ +@model IEnumerable + +@{ + ViewBag.Title = "Federated Sign Out"; +} + +

Federated Sign Out

+ +@foreach (var link in Model) +{ +

+ @link +   + Signout Request +

+} + + +@if (!string.IsNullOrWhiteSpace(ViewBag.ReturnUrl)) +{ +

+ Return to application +

+} \ No newline at end of file diff --git a/OnPremise/WebSite/Views/Web.config b/OnPremise/WebSite/Views/Web.config new file mode 100644 index 0000000..41c7be1 --- /dev/null +++ b/OnPremise/WebSite/Views/Web.config @@ -0,0 +1,60 @@ + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/OnPremise/WebSite/Views/_ViewStart.cshtml b/OnPremise/WebSite/Views/_ViewStart.cshtml new file mode 100644 index 0000000..efda124 --- /dev/null +++ b/OnPremise/WebSite/Views/_ViewStart.cshtml @@ -0,0 +1,3 @@ +@{ + Layout = "~/Views/Shared/_Layout.cshtml"; +} \ No newline at end of file diff --git a/OnPremise/WebSite/Web.Debug.config b/OnPremise/WebSite/Web.Debug.config new file mode 100644 index 0000000..2c6dd51 --- /dev/null +++ b/OnPremise/WebSite/Web.Debug.config @@ -0,0 +1,30 @@ + + + + + + + + + + \ No newline at end of file diff --git a/OnPremise/WebSite/Web.Release.config b/OnPremise/WebSite/Web.Release.config new file mode 100644 index 0000000..4122d79 --- /dev/null +++ b/OnPremise/WebSite/Web.Release.config @@ -0,0 +1,31 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/OnPremise/WebSite/Web.config b/OnPremise/WebSite/Web.config new file mode 100644 index 0000000..3631920 --- /dev/null +++ b/OnPremise/WebSite/Web.config @@ -0,0 +1,136 @@ + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OnPremise/WebSite/WebSite.Publish.xml b/OnPremise/WebSite/WebSite.Publish.xml new file mode 100644 index 0000000..86ffbe2 --- /dev/null +++ b/OnPremise/WebSite/WebSite.Publish.xml @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OnPremise/WebSite/WebSite.csproj b/OnPremise/WebSite/WebSite.csproj new file mode 100644 index 0000000..aad122b --- /dev/null +++ b/OnPremise/WebSite/WebSite.csproj @@ -0,0 +1,338 @@ + + + + Debug + AnyCPU + + + 2.0 + {B9C90A36-86C0-4974-B0B4-3524F508D847} + {E53F8FEA-EAE0-44A6-8774-FFD645390401};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + Thinktecture.IdentityServer.Web + Thinktecture.IdentityServer.Web + v4.0 + false + false + + + + + + + + + ..\ + true + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + true + + + pdbonly + true + bin\ + TRACE + prompt + 4 + + + + False + ..\packages\AutoMapper.2.1.265\lib\net40\AutoMapper.dll + + + False + ..\packages\EntityFramework.4.3.1\lib\net40\EntityFramework.dll + + + True + + + True + ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll + + + False + ..\packages\routedebugger.2.1.1\lib\net40\RouteDebugger.dll + + + + + False + ..\packages\SqlServerCompact.4.0.8852.1\lib\net40\System.Data.SqlServerCe.dll + + + False + ..\packages\SqlServerCompact.4.0.8852.1\lib\net40\System.Data.SqlServerCe.Entity.dll + + + + + + + + + + ..\packages\System.Web.Providers.1.0.1\lib\Net40\System.Web.Providers.dll + + + + + + + + + + + + + + + + + + + + + + + + False + ..\packages\Thinktecture.IdentityModel.1.3.0.0\lib\Thinktecture.IdentityModel.dll + + + ..\packages\WebActivator.1.5\lib\net40\WebActivator.dll + + + + + + + + + + + + + + + + + + + Global.asax + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Designer + + + Web.config + + + Web.config + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {9658F86F-3059-4731-9EB0-5F67A4FF1A8A} + Thinktecture.IdentityServer.Core.Repositories + + + {38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A} + Thinktecture.IdentityServer.Core + + + {FC2D7E2A-65A2-480F-AAE8-855FD026AF85} + Thinktecture.IdentityServer.Web.Library + + + + + + + + + + + + + True + + + + + + + if not exist "$(TargetDir)x86" md "$(TargetDir)x86" + xcopy /s /y "$(SolutionDir)packages\SqlServerCompact.4.0.8852.1\NativeBinaries\x86\*.*" "$(TargetDir)x86" + if not exist "$(TargetDir)amd64" md "$(TargetDir)amd64" + xcopy /s /y "$(SolutionDir)packages\SqlServerCompact.4.0.8852.1\NativeBinaries\amd64\*.*" "$(TargetDir)amd64" + + + \ No newline at end of file diff --git a/OnPremise/WebSite/WebSite.csproj.vspscc b/OnPremise/WebSite/WebSite.csproj.vspscc new file mode 100644 index 0000000..b6d3289 --- /dev/null +++ b/OnPremise/WebSite/WebSite.csproj.vspscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "" +"NUMBER_OF_EXCLUDED_FILES" = "0" +"ORIGINAL_PROJECT_FILE_PATH" = "" +"NUMBER_OF_NESTED_PROJECTS" = "0" +"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER" +} diff --git a/OnPremise/WebSite/license.txt b/OnPremise/WebSite/license.txt new file mode 100644 index 0000000..f7700e0 --- /dev/null +++ b/OnPremise/WebSite/license.txt @@ -0,0 +1,24 @@ +Copyright 2011 - Dominick Baier + +Microsoft Public License (Ms-PL) + +This license governs use of the accompanying software. If you use the software, you +accept this license. If you do not accept the license, do not use the software. + +1. Definitions +The terms "reproduce," "reproduction," "derivative works," and "distribution" have the +same meaning here as under U.S. copyright law. +A "contribution" is the original software, or any additions or changes to the software. +A "contributor" is any person that distributes its contribution under this license. +"Licensed patents" are a contributor's patent claims that read directly on its contribution. + +2. Grant of Rights +(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. +(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. + +3. Conditions and Limitations +(A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. +(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. +(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. +(D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license. +(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. \ No newline at end of file diff --git a/OnPremise/WebSite/packages.config b/OnPremise/WebSite/packages.config new file mode 100644 index 0000000..2a05e41 --- /dev/null +++ b/OnPremise/WebSite/packages.config @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OnPremise/WebSite/readme.txt b/OnPremise/WebSite/readme.txt new file mode 100644 index 0000000..8525551 --- /dev/null +++ b/OnPremise/WebSite/readme.txt @@ -0,0 +1,41 @@ +Before installing and using IdSrv there are some system/environment prerequisites. + +General + - IIS 7.x with support for .NET 4.0, MVC3 is required (for development Visual Studio 2010 SP1). + - IdSrv needs to be added to an IIS site with a working SSL configuration. + - IdSrv needs an X509 certificate to sign outgoing security tokens. This can be the same as the SSL certificate. Make sure the application pool account has read access to the signature certificate's private key. + - IdSrv requires SSL client certificates for certain pages. To be able to configure this inside IdSrv, configuration delegation for SSL must be enabled in IIS. + - The IIS application pool account needs read access to the IdSrv web files and modify access to the App_Data sub-directory that contains the configuration database. + +User Management + - IdSrv uses the standard ASP.NET provider system by default. If you have an existing provider database you can adjust the connection string in configuration/connectionStrings.config. + - You can also use the aspnet_regsql.exe tool from the .NET SDK to create a new provider database. + - The IIS application pool account needs access to the provider database. + - By default all users of IdSrv must be in the IdentityServerUsers role. This can be changed in Global Configuration. + - All administrators of IdSrv must be in the 'IdentityServerAdministrators' role. + +Walkthrough for setting up IdSrv + - http://claudioasanchez.blogspot.com/2011/12/walk-though-of-provisioning-identity.html + +Resources + - Private Key Access + http://msmvps.com/blogs/luisabreu/archive/2010/09/13/grant-access-to-certificate-s-private-key-in-iis-7-5.aspx + - Setup SSL + http://learn.iis.net/page.aspx/144/how-to-set-up-ssl-on-iis/ + - IIS Configuration Delegation + http://learn.iis.net/page.aspx/159/configuring-remote-administration-and-feature-delegation-in-iis-7/ + + + +Changelog + +post 1.0 + - Added a "Recycle IdSrv" link to the admin area + - Added a "UseSqlServerForConfiguration" AppSetting to make migration to SQL Server easier. + - Minor UI bug fixes + +Version 1.0a + - fixed a bug in federation metadata generation that broke fedutil. + +Version 1.0 + - release \ No newline at end of file diff --git a/Tests/Extensions.cs b/Tests/Extensions.cs new file mode 100644 index 0000000..540f833 --- /dev/null +++ b/Tests/Extensions.cs @@ -0,0 +1,48 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text; + +namespace Thinktecture.IdentityServer.Tests +{ + internal static class Extensions + { + public static void SetBasicAuthenticationHeader(this HttpClient client, string userName, string password) + { + Encoding encoding = Encoding.GetEncoding("iso-8859-1"); + string credential = String.Format("{0}:{1}", userName, password); + + var encoded = Convert.ToBase64String(encoding.GetBytes(credential)); + + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", encoded); + } + + public static void SetAccessToken(this HttpClient client, string token, string tokenType) + { + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(tokenType, token); + } + + public static string ToQueryString(this Dictionary dictionary) + { + var sb = new StringBuilder(128); + sb.Append("?"); + + foreach (var entry in dictionary) + { + sb.AppendFormat("{0}={1}&", entry.Key, entry.Value); + } + + return sb.ToString().TrimEnd('&'); + } + } +} diff --git a/Tests/Factories/ConfigurationFactory.cs b/Tests/Factories/ConfigurationFactory.cs new file mode 100644 index 0000000..c8bf523 --- /dev/null +++ b/Tests/Factories/ConfigurationFactory.cs @@ -0,0 +1,78 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using Thinktecture.IdentityServer.Models; + +namespace Thinktecture.IdentityServer.Tests +{ + internal static class ConfigurationFactory + { + public static GlobalConfiguration Create(string mode) + { + switch (mode) + { + case Constants.ConfigurationModes.LockedDown: + return CreateLockedDownConfiguration(); + case Constants.ConfigurationModes.LockedDownAllowReplyTo: + return CreateLockedDownAllowReplyToConfiguration(); + default: + throw new ArgumentException("mode"); + } + } + + public static GlobalConfiguration CreateLockedDownConfiguration() + { + return new GlobalConfiguration + { + SiteName = "Unit Test", + IssuerUri = "http://test.identityserver.thinktecture.com", + + DefaultTokenLifetime = 10, + MaximumTokenLifetime = 24, + DefaultTokenType = "urn:oasis:names:tc:SAML:2.0:assertion", + + EnableClientCertificates = true, + EnableDelegation = false, + + AllowKnownRealmsOnly = true, + AllowReplyTo = false, + RequireReplyToWithinRealm = true, + + RequireEncryption = true, + RequireSsl = true, + RequireSignInConfirmation = false + }; + } + + private static GlobalConfiguration CreateLockedDownAllowReplyToConfiguration() + { + return new GlobalConfiguration + { + SiteName = "Unit Test", + IssuerUri = "http://test.identityserver.thinktecture.com", + + DefaultTokenLifetime = 10, + MaximumTokenLifetime = 24, + DefaultTokenType = "urn:oasis:names:tc:SAML:2.0:assertion", + + EnableClientCertificates = true, + EnableDelegation = false, + + AllowKnownRealmsOnly = true, + AllowReplyTo = true, + RequireReplyToWithinRealm = true, + + RequireEncryption = true, + RequireSsl = true, + RequireSignInConfirmation = false + }; + } + } +} diff --git a/Tests/Factories/Constants.cs b/Tests/Factories/Constants.cs new file mode 100644 index 0000000..fa44b1a --- /dev/null +++ b/Tests/Factories/Constants.cs @@ -0,0 +1,83 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Security.Cryptography.X509Certificates; + +namespace Thinktecture.IdentityServer.Tests +{ + internal static class Constants + { + public static class Http + { + public static string LocalBaseAddress = "https://roadie/idsrv/issue/simple"; + public static string CloudBaseAddress = "https://idp.thinktecture.com/issue/simple"; + } + + public static class Wrap + { + public static string LocalBaseAddress = "https://roadie/idsrv/issue/wrap"; + public static string CloudBaseAddress = "https://idp.thinktecture.com/issue/wrap"; + } + + public static class OAuth2 + { + public static string LocalBaseAddress = "https://roadie/idsrv/issue/oauth2"; + public static string CloudBaseAddress = "https://idp.thinktecture.com/issue/oauth2"; + } + + public static class WSTrust + { + public static string LocalMixedUserName = "https://roadie/idsrv/issue/wstrust/mixed/username"; + public static string CloudMixedUserName = "https://idp.thinktecture.com/issue/wstrust/mixed/username"; + + public static string LocalMixedCertificate = "https://roadie/idsrv/issue/wstrust/mixed/certificate"; + public static string CloudMixedCertificate = "https://idp.thinktecture.com/issue/wstrust/mixed/certificate"; + } + + public static class Realms + { + public const string LocalRP = "https://roadie/rp/"; + public const string UnknownRealm = "http://unknown/"; + public const string PlainTextNoEncryption = "http://server/noEncryption/"; + public const string SslNoEncryption = "https://server/noEncryption/"; + public const string PlainTextEncryption = "http://server/encryption/"; + public const string SslEncryption = "https://server/encryption/"; + public const string ExplicitReplyTo = "https://server/explicitreplyto/"; + } + + public static class Principals + { + public const string AliceUserName = "AliceUserName"; + public const string Anonymous = "Anoynmous"; + } + + public static class ConfigurationModes + { + public const string LockedDown = "LockedDown"; + public const string LockedDownAllowReplyTo = "LockedDownAllowReplyTo"; + } + + public static class Certificates + { + public const string DefaultEncryptionCertificateString = @"IAAAAAEAAADOBAAAMIIEyjCCArKgAwIBAgIKYQWg2wAAAAAAGDANBgkqhkiG9w0BAQUFADAbMRkwFwYDVQQDExBMZWFzdFByaXZpbGVnZUNBMB4XDTA4MDUxOTA1MzcxMFoXDTEzMDUxOTA1NDcxMFowEjEQMA4GA1UEAxMHU2VydmljZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAn4obl6lUFqeEw2pCgVWFmPGnRf7mChAXqH5lmfKOPRC6hh7V1MK/3d86TwHWpg8FKUS4PGICquqQwubI7E047QtTZEzXcebZCRQE9HZNhLROtiMPQB3XeljSRJKqhbiEhnMpFsPBBahHd0NEDmcPq+UCG++giXf36e9el6inw2UCAwEAAaOCAZswggGXMA4GA1UdDwEB/wQEAwIE8DATBgNVHSUEDDAKBggrBgEFBQcDATAdBgNVHQ4EFgQU7FMpPcpVwxRefnfwVnqDDELzpPswHwYDVR0jBBgwFoAUcIXV36QCEM2E4PAXL02aoLMnHU0wgaIGA1UdHwSBmjCBlzCBlKCBkaCBjoYraHR0cDovL2hvbWUvQ2VydEVucm9sbC9MZWFzdFByaXZpbGVnZUNBLmNybIYrZmlsZTovL2hvbWUvQ2VydEVucm9sbC9MZWFzdFByaXZpbGVnZUNBLmNybIYyaHR0cDovL3d3dy5sZWFzdHByaXZpbGVnZS5jb20vTGVhc3RQcml2aWxlZ2VDQS5jcmwwgYoGCCsGAQUFBwEBBH4wfDA8BggrBgEFBQcwAoYwaHR0cDovL2hvbWUvQ2VydEVucm9sbC9ob21lX0xlYXN0UHJpdmlsZWdlQ0EuY3J0MDwGCCsGAQUFBzAChjBmaWxlOi8vaG9tZS9DZXJ0RW5yb2xsL2hvbWVfTGVhc3RQcml2aWxlZ2VDQS5jcnQwDQYJKoZIhvcNAQEFBQADggIBADqlncvFFvHL5viU6sftGwsWD0u82Yh4nAmcLPt8MuExtB2oTYRNyQak8NJUp8NxtpTp1F7HqcG84bGJBRkRYX/JVZzrsf9EC9/dbovSxqtho4gz0Zo/+i/Bjo+52RRWu3GGCCEv4Dz0diH5tPO6Ma89A/bjpEI/oUjD92j0g9X3gZqPyw8XIXjaFurTd1HcuqAOTPC7XosYg1NH31ODhSaMiMfCYbvnUD1xB6PyzFQ8IaOvr54mguFOxMtz1c/1k5SgtkiXHoq9HLkY8xN3R8Yuk/0h2l60yu2yqrK87Zlo+Jx7+o1sxkHwI2cVleVFTI+5XKWW0u6yVGzqAEtY7P7SkuGSpN/qVDPM3rDqBf7WIeGmxwfKDkvAyYwBfyDR018tDf+MI/wDr+Xia72siGaZSIV9HilNxR2+KLy7AQVs0rQvc8xbUlcn9UXZZMtv3pItHRN/Y4XncTWDjNfwipec6oxBrW5MbzFZKzxJPnmC6365MKn152B8W4zQB6LxF6ZEwT2ZJ3Ln0bbQc1SEwZ4SIC3ROkw6Z1WVVGKxD6vukrwhOiRy7rhFoOowVXmVINWhRrvBA+h6FGBi/ciWhEQPzmhygXpd8+LVOwJGD8zWqmxHCY1+swizc3aStZSCDTJkjghn52DLbTqZbofbFY7keZi6XV92uBn1Z96nuLkM"; + public const string ValidClientCertificateName = "CN=Client"; + + public static X509Certificate2 DefaultEncryptionCertificate = new X509Certificate2(Convert.FromBase64String(DefaultEncryptionCertificateString)); + } + + public static class Credentials + { + public const string ValidUserName = "dominick"; + public const string UnauthorizedUserName = "internal"; + + public const string ValidPassword = "abc!123"; + } + } +} diff --git a/Tests/Factories/HttpClientFactory.cs b/Tests/Factories/HttpClientFactory.cs new file mode 100644 index 0000000..19b293a --- /dev/null +++ b/Tests/Factories/HttpClientFactory.cs @@ -0,0 +1,33 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Net.Http; +using System.Security.Cryptography.X509Certificates; +using Thinktecture.IdentityServer.Helper; + +namespace Thinktecture.IdentityServer.Tests +{ + internal static class HttpClientFactory + { + public static HttpClient Create(string baseAddress) + { + return new HttpClient { BaseAddress = new Uri(baseAddress) }; + } + + public static X509Certificate2 GetValidClientCertificate() + { + return X509Certificates.GetCertificateFromStore( + StoreLocation.CurrentUser, + StoreName.My, + X509FindType.FindBySubjectDistinguishedName, + Constants.Certificates.ValidClientCertificateName); + } + } +} diff --git a/Tests/Factories/PrincipalFactory.cs b/Tests/Factories/PrincipalFactory.cs new file mode 100644 index 0000000..2af9057 --- /dev/null +++ b/Tests/Factories/PrincipalFactory.cs @@ -0,0 +1,47 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Collections.Generic; +using Microsoft.IdentityModel.Claims; + +namespace Thinktecture.IdentityServer.Tests +{ + internal static class PrincipalFactory + { + public static IClaimsPrincipal Create(string type) + { + switch (type) + { + case Constants.Principals.AliceUserName: + return Create("Alice", AuthenticationMethods.Password); + case Constants.Principals.Anonymous: + return CreateAnonymous(); + default: + throw new ArgumentException("type"); + } + } + + public static IClaimsPrincipal Create(string userName, string authenticationMethod) + { + var claims = new List + { + new Claim(ClaimTypes.Name, userName), + new Claim(ClaimTypes.AuthenticationMethod, authenticationMethod) + }; + + return ClaimsPrincipal.CreateFromIdentity(new ClaimsIdentity(claims)); + } + + public static IClaimsPrincipal CreateAnonymous() + { + return ClaimsPrincipal.AnonymousPrincipal; + } + } +} diff --git a/Tests/Factories/RstFactory.cs b/Tests/Factories/RstFactory.cs new file mode 100644 index 0000000..7cf278d --- /dev/null +++ b/Tests/Factories/RstFactory.cs @@ -0,0 +1,27 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.ServiceModel; +using Microsoft.IdentityModel.Protocols.WSTrust; +using Microsoft.IdentityModel.SecurityTokenService; + +namespace Thinktecture.IdentityServer.Tests +{ + internal static class RstFactory + { + public static RequestSecurityToken Create(string realm) + { + return new RequestSecurityToken + { + RequestType = RequestTypes.Issue, + AppliesTo = new EndpointAddress(realm) + }; + } + } +} diff --git a/Tests/Factories/WSTrustClientFactory.cs b/Tests/Factories/WSTrustClientFactory.cs new file mode 100644 index 0000000..81fa1bc --- /dev/null +++ b/Tests/Factories/WSTrustClientFactory.cs @@ -0,0 +1,49 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.Security.Cryptography.X509Certificates; +using System.ServiceModel; +using System.ServiceModel.Security; +using Microsoft.IdentityModel.Protocols.WSTrust; +using Microsoft.IdentityModel.Protocols.WSTrust.Bindings; + +namespace Thinktecture.IdentityServer.Tests +{ + internal static class WSTrustClientFactory + { + public static IWSTrustChannelContract CreateMixedUserNameClient(string userName, string password, string endpointAddress) + { + var factory = new WSTrustChannelFactory( + new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential), + new EndpointAddress(endpointAddress)); + factory.TrustVersion = TrustVersion.WSTrust13; + + factory.Credentials.UserName.UserName = userName; + factory.Credentials.UserName.Password = password; + + return factory.CreateChannel(); + } + + public static IWSTrustChannelContract CreateMixedCertificateClient(string subjectName, string endpointAddress) + { + var factory = new WSTrustChannelFactory( + new CertificateWSTrustBinding(SecurityMode.TransportWithMessageCredential), + new EndpointAddress(endpointAddress)); + factory.TrustVersion = TrustVersion.WSTrust13; + + factory.Credentials.ClientCertificate.SetCertificate( + StoreLocation.CurrentUser, + StoreName.My, + X509FindType.FindBySubjectDistinguishedName, + subjectName); + + return factory.CreateChannel(); + } + } +} diff --git a/Tests/Integration Tests/OAuth2Tests.cs b/Tests/Integration Tests/OAuth2Tests.cs new file mode 100644 index 0000000..57e8dd8 --- /dev/null +++ b/Tests/Integration Tests/OAuth2Tests.cs @@ -0,0 +1,144 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Net; +using System.Net.Http; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Thinktecture.IdentityServer.OAuth; + +namespace Thinktecture.IdentityServer.Tests +{ + [TestClass] + public class OAuth2Tests + { + string baseAddress = Constants.OAuth2.LocalBaseAddress; + //string baseAddress = Constants.OAuth2.CloudBaseAddress; + + string scope = Constants.Realms.LocalRP; + + [TestMethod] + public void ValidUserNameCredential() + { + var client = new OAuth2Client(new Uri(baseAddress)); + + var response = client.RequestAccessTokenUserName( + Constants.Credentials.ValidUserName, + Constants.Credentials.ValidPassword, + scope); + + Assert.IsTrue(response != null, "response is null"); + Assert.IsTrue(!string.IsNullOrWhiteSpace(response.AccessToken), "access token is null"); + Assert.IsTrue(!string.IsNullOrWhiteSpace(response.TokenType), "token type is null"); + Assert.IsTrue(response.ExpiresIn > 0, "expiresIn is 0"); + + Trace.WriteLine(response.AccessToken); + } + + [TestMethod] + public void ValidClientCertificateCredential() + { + var client = new OAuth2Client(new Uri(baseAddress)); + + var response = client.RequestAccessTokenCertificate( + HttpClientFactory.GetValidClientCertificate(), + scope); + + Assert.IsTrue(response != null, "response is null"); + Assert.IsTrue(!string.IsNullOrWhiteSpace(response.AccessToken), "access token is null"); + Assert.IsTrue(!string.IsNullOrWhiteSpace(response.TokenType), "token type is null"); + Assert.IsTrue(response.ExpiresIn > 0, "expiresIn is 0"); + + Trace.WriteLine(response.AccessToken); + } + + [TestMethod] + public void InvalidUserNameCredential() + { + var form = new FormUrlEncodedContent(new Dictionary + { + { OAuth2Constants.GrantType, OAuth2Constants.Password }, + { OAuth2Constants.UserName, Constants.Credentials.ValidUserName }, + { OAuth2Constants.Password, "invalid" }, + { OAuth2Constants.scope, scope } + }); + + var client = new HttpClient(); + var result = client.PostAsync(new Uri(baseAddress), form).Result; + + Assert.AreEqual(HttpStatusCode.Unauthorized, result.StatusCode); + } + + [TestMethod] + public void UnauthorizedUser() + { + var form = new FormUrlEncodedContent(new Dictionary + { + { OAuth2Constants.GrantType, OAuth2Constants.Password }, + { OAuth2Constants.UserName, Constants.Credentials.UnauthorizedUserName }, + { OAuth2Constants.Password, Constants.Credentials.ValidUserName }, + { OAuth2Constants.scope, scope } + }); + + var client = new HttpClient(); + var result = client.PostAsync(new Uri(baseAddress), form).Result; + + Assert.AreEqual(HttpStatusCode.Unauthorized, result.StatusCode); + } + + [TestMethod] + public void NoRealm() + { + var form = new FormUrlEncodedContent(new Dictionary + { + { OAuth2Constants.GrantType, OAuth2Constants.Password }, + { OAuth2Constants.UserName, Constants.Credentials.ValidUserName }, + { OAuth2Constants.Password, Constants.Credentials.ValidUserName } + }); + + var client = new HttpClient(); + var result = client.PostAsync(new Uri(baseAddress), form).Result; + + Assert.AreEqual(HttpStatusCode.BadRequest, result.StatusCode); + } + + [TestMethod] + public void MalformedRealm() + { + var form = new FormUrlEncodedContent(new Dictionary + { + { OAuth2Constants.GrantType, OAuth2Constants.Password }, + { OAuth2Constants.UserName, Constants.Credentials.ValidUserName }, + { OAuth2Constants.Password, Constants.Credentials.ValidUserName }, + { OAuth2Constants.scope, "invalid" } + }); + + var client = new HttpClient(); + var result = client.PostAsync(new Uri(baseAddress), form).Result; + + Assert.AreEqual(HttpStatusCode.BadRequest, result.StatusCode); + } + + [TestMethod] + public void NoCredentials() + { + var form = new FormUrlEncodedContent(new Dictionary + { + { OAuth2Constants.scope, scope } + }); + + var client = new HttpClient(); + var result = client.PostAsync(new Uri(baseAddress), form).Result; + + Assert.AreEqual(HttpStatusCode.BadRequest, result.StatusCode); + } + } +} \ No newline at end of file diff --git a/Tests/Integration Tests/SimpleHttpTests.cs b/Tests/Integration Tests/SimpleHttpTests.cs new file mode 100644 index 0000000..80565c7 --- /dev/null +++ b/Tests/Integration Tests/SimpleHttpTests.cs @@ -0,0 +1,196 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Net; +using System.Net.Http; +using System.Net.Mime; +using System.Web; +using System.Xml.Linq; +using Microsoft.IdentityModel.Tokens; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Thinktecture.IdentityServer.Core.Swt; + +namespace Thinktecture.IdentityServer.Tests +{ + [TestClass] + public class SimpleHttp + { + string baseAddress = Constants.Http.LocalBaseAddress; + //string baseAddress = Constants.Http.CloudBaseAddress; + + string rp = Constants.Realms.LocalRP; + + [TestMethod] + public void NoRealm() + { + var client = new HttpClient(); + + var result = client.GetAsync(new Uri(baseAddress)).Result; + Assert.AreEqual(HttpStatusCode.BadRequest, result.StatusCode); + } + + [TestMethod] + public void MalformedRealm() + { + var values = new Dictionary + { + { "realm", "malformed" } + }; + + var client = new HttpClient(); + + var result = client.GetAsync(baseAddress + values.ToQueryString()).Result; + Assert.AreEqual(HttpStatusCode.BadRequest, result.StatusCode); + } + + [TestMethod] + public void NoCredentials() + { + var values = new Dictionary + { + { "realm", rp } + }; + + var client = new HttpClient(); + + var result = client.GetAsync(baseAddress + values.ToQueryString()).Result; + Assert.AreEqual(HttpStatusCode.Unauthorized, result.StatusCode); + } + + [TestMethod] + public void ValidUserNameCredential() + { + var values = new Dictionary + { + { "realm", rp } + }; + + var client = new HttpClient(); + client.SetBasicAuthenticationHeader(Constants.Credentials.ValidUserName, Constants.Credentials.ValidPassword); + + var result = client.GetAsync(baseAddress + values.ToQueryString()).Result; + + Assert.AreEqual(HttpStatusCode.OK, result.StatusCode); + Assert.AreEqual(MediaTypeNames.Text.Xml, result.Content.Headers.ContentType.MediaType); + } + + [TestMethod] + public void ValidClientCertificateCredential() + { + var values = new Dictionary + { + { "realm", rp } + }; + + var handler = new WebRequestHandler(); + handler.ClientCertificates.Add(HttpClientFactory.GetValidClientCertificate()); + + var client = new HttpClient(handler); + + var result = client.GetAsync(baseAddress + values.ToQueryString()).Result; + + Assert.AreEqual(HttpStatusCode.OK, result.StatusCode); + Assert.AreEqual(MediaTypeNames.Text.Xml, result.Content.Headers.ContentType.MediaType); + } + + [TestMethod] + public void UnAuthorizedUser() + { + var values = new Dictionary + { + { "realm", rp } + }; + + var client = new HttpClient(); + client.SetBasicAuthenticationHeader(Constants.Credentials.UnauthorizedUserName, Constants.Credentials.ValidPassword); + + var result = client.GetAsync(baseAddress + values.ToQueryString()).Result; + Assert.AreEqual(HttpStatusCode.Unauthorized, result.StatusCode); + } + + [TestMethod] + public void ValidUserNameCredentialSaml11() + { + var values = new Dictionary + { + { "realm", rp }, + { "tokentype", SecurityTokenTypes.Saml11TokenProfile11 } + }; + + var client = new HttpClient(); + client.SetBasicAuthenticationHeader(Constants.Credentials.ValidUserName, Constants.Credentials.ValidPassword); + + var result = client.GetAsync(baseAddress + values.ToQueryString()).Result; + + Assert.AreEqual(HttpStatusCode.OK, result.StatusCode); + Assert.AreEqual(MediaTypeNames.Text.Xml, result.Content.Headers.ContentType.MediaType); + + Trace.Write(XElement.Parse(result.Content.ReadAsStringAsync().Result).ToString()); + } + + [TestMethod] + public void ValidUserNameCredentialSaml2() + { + var values = new Dictionary + { + { "realm", rp }, + { "tokentype", SecurityTokenTypes.Saml2TokenProfile11 } + }; + + var client = new HttpClient(); + client.SetBasicAuthenticationHeader(Constants.Credentials.ValidUserName, Constants.Credentials.ValidPassword); + + var result = client.GetAsync(baseAddress + values.ToQueryString()).Result; + + Assert.AreEqual(HttpStatusCode.OK, result.StatusCode); + Assert.AreEqual(MediaTypeNames.Text.Xml, result.Content.Headers.ContentType.MediaType); + + Trace.Write(XElement.Parse(result.Content.ReadAsStringAsync().Result).ToString()); + } + + + [TestMethod] + public void ValidUserNameCredentialSwt() + { + var values = new Dictionary + { + { "realm", rp }, + { "tokentype", SimpleWebToken.OasisTokenProfile } + }; + + var client = new HttpClient(); + client.SetBasicAuthenticationHeader(Constants.Credentials.ValidUserName, Constants.Credentials.ValidPassword); + + var result = client.GetAsync(baseAddress + values.ToQueryString()).Result; + + Assert.AreEqual(HttpStatusCode.OK, result.StatusCode); + Assert.AreEqual(MediaTypeNames.Text.Plain, result.Content.Headers.ContentType.MediaType); + + Trace.WriteLine(HttpUtility.UrlDecode(result.Content.ReadAsStringAsync().Result)); + } + + [TestMethod] + public void InvalidUserNameCredential() + { + var values = new Dictionary + { + { "realm", rp } + }; + + var client = new HttpClient(); + client.SetBasicAuthenticationHeader(Constants.Credentials.ValidUserName, "invalid"); + + var result = client.GetAsync(baseAddress + values.ToQueryString()).Result; + Assert.AreEqual(HttpStatusCode.Unauthorized, result.StatusCode); + } + } +} diff --git a/Tests/Integration Tests/WSTrustTests.cs b/Tests/Integration Tests/WSTrustTests.cs new file mode 100644 index 0000000..46c0907 --- /dev/null +++ b/Tests/Integration Tests/WSTrustTests.cs @@ -0,0 +1,235 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System.IdentityModel.Tokens; +using System.ServiceModel; +using System.ServiceModel.Security; +using Microsoft.IdentityModel.Protocols.WSTrust; +using Microsoft.IdentityModel.SecurityTokenService; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Thinktecture.IdentityServer.Core.Swt; + +namespace Thinktecture.IdentityServer.Tests +{ + [TestClass] + public class WSTrust + { + IWSTrustChannelContract _mixedUserNameClient; + IWSTrustChannelContract _mixedCertificateClient; + + RequestSecurityToken _rst; + + string baseAddressUserName = Constants.WSTrust.LocalMixedUserName; + //string baseAddressUserName = Constants.WSTrust.CloudMixedUserName; + + string baseAddressCertificate = Constants.WSTrust.LocalMixedCertificate; + + string rp = Constants.Realms.LocalRP; + + [TestInitialize] + public void Setup() + { + _mixedUserNameClient = WSTrustClientFactory.CreateMixedUserNameClient( + Constants.Credentials.ValidUserName, + Constants.Credentials.ValidPassword, + baseAddressUserName); + + _mixedCertificateClient = WSTrustClientFactory.CreateMixedCertificateClient( + Constants.Certificates.ValidClientCertificateName, + baseAddressCertificate); + + _rst = new RequestSecurityToken + { + AppliesTo = new EndpointAddress(rp), + RequestType = RequestTypes.Issue, + KeyType = KeyTypes.Symmetric + }; + + } + + [TestMethod] + public void ValidUserNameCredential() + { + RequestSecurityTokenResponse rstr; + var token = _mixedUserNameClient.Issue(_rst, out rstr); + + Assert.IsTrue(token != null); + } + + [TestMethod] + public void ValidClientCertificateCredential() + { + RequestSecurityTokenResponse rstr; + var token = _mixedCertificateClient.Issue(_rst, out rstr); + + Assert.IsTrue(token != null); + } + + [TestMethod] + public void ValidUserNameCredentialSaml11() + { + var rst = new RequestSecurityToken + { + AppliesTo = new EndpointAddress(rp), + RequestType = RequestTypes.Issue, + KeyType = KeyTypes.Symmetric, + + TokenType = Microsoft.IdentityModel.Tokens.SecurityTokenTypes.Saml11TokenProfile11 + }; + + RequestSecurityTokenResponse rstr; + var token = _mixedUserNameClient.Issue(rst, out rstr) as GenericXmlSecurityToken; + + Assert.IsTrue(token != null); + Assert.IsTrue(token.ProofToken != null); + Assert.AreEqual(Microsoft.IdentityModel.Tokens.SecurityTokenTypes.Saml11TokenProfile11, rstr.TokenType); + } + + [TestMethod] + public void ValidUserNameCredentialSaml11Bearer() + { + var rst = new RequestSecurityToken + { + AppliesTo = new EndpointAddress(rp), + RequestType = RequestTypes.Issue, + KeyType = KeyTypes.Bearer, + + TokenType = Microsoft.IdentityModel.Tokens.SecurityTokenTypes.Saml11TokenProfile11 + }; + + RequestSecurityTokenResponse rstr; + var token = _mixedUserNameClient.Issue(rst, out rstr) as GenericXmlSecurityToken; + + Assert.IsTrue(token != null); + Assert.IsTrue(token.ProofToken == null); + Assert.AreEqual(Microsoft.IdentityModel.Tokens.SecurityTokenTypes.Saml11TokenProfile11, rstr.TokenType); + } + + [TestMethod] + public void ValidUserNameCredentialSaml2Bearer() + { + var rst = new RequestSecurityToken + { + AppliesTo = new EndpointAddress(rp), + RequestType = RequestTypes.Issue, + KeyType = KeyTypes.Bearer, + + TokenType = Microsoft.IdentityModel.Tokens.SecurityTokenTypes.Saml2TokenProfile11 + }; + + RequestSecurityTokenResponse rstr; + var token = _mixedUserNameClient.Issue(rst, out rstr) as GenericXmlSecurityToken; + + Assert.IsTrue(token != null); + Assert.IsTrue(token.ProofToken == null); + Assert.AreEqual(Microsoft.IdentityModel.Tokens.SecurityTokenTypes.Saml2TokenProfile11, rstr.TokenType); + } + + [TestMethod] + public void ValidUserNameCredentialSaml2() + { + var rst = new RequestSecurityToken + { + AppliesTo = new EndpointAddress(rp), + RequestType = RequestTypes.Issue, + KeyType = KeyTypes.Symmetric, + + TokenType = Microsoft.IdentityModel.Tokens.SecurityTokenTypes.Saml2TokenProfile11 + }; + + RequestSecurityTokenResponse rstr; + var token = _mixedUserNameClient.Issue(rst, out rstr) as GenericXmlSecurityToken; + + Assert.IsTrue(token != null); + Assert.IsTrue(token.ProofToken != null); + Assert.AreEqual(Microsoft.IdentityModel.Tokens.SecurityTokenTypes.Saml2TokenProfile11, rstr.TokenType); + } + + [TestMethod] + public void ValidUserNameCredentialSwtSymmetric() + { + var rst = new RequestSecurityToken + { + AppliesTo = new EndpointAddress(rp), + RequestType = RequestTypes.Issue, + KeyType = KeyTypes.Symmetric, + + TokenType = SimpleWebToken.OasisTokenProfile + }; + + RequestSecurityTokenResponse rstr; + var token = _mixedUserNameClient.Issue(rst, out rstr) as GenericXmlSecurityToken; + + Assert.IsTrue(token != null); + Assert.IsTrue(token.ProofToken != null); + Assert.AreEqual(SimpleWebToken.OasisTokenProfile, rstr.TokenType); + } + + [TestMethod] + public void ValidUserNameCredentialSwtBearer() + { + var rst = new RequestSecurityToken + { + AppliesTo = new EndpointAddress(rp), + RequestType = RequestTypes.Issue, + KeyType = KeyTypes.Bearer, + + TokenType = SimpleWebToken.OasisTokenProfile + }; + + RequestSecurityTokenResponse rstr; + var token = _mixedUserNameClient.Issue(rst, out rstr) as GenericXmlSecurityToken; + + Assert.IsTrue(token != null); + Assert.IsTrue(token.ProofToken == null); + Assert.AreEqual(SimpleWebToken.OasisTokenProfile, rstr.TokenType); + } + + + [TestMethod] + [ExpectedException(typeof(MessageSecurityException))] + public void InvalidUserNameCredential() + { + var client = WSTrustClientFactory.CreateMixedUserNameClient( + Constants.Credentials.ValidUserName, + "invalid", + baseAddressUserName); + + RequestSecurityTokenResponse rstr; + var token = client.Issue(_rst, out rstr); + } + + [TestMethod] + [ExpectedException(typeof(FaultException))] + public void UnauthorizedUser() + { + var client = WSTrustClientFactory.CreateMixedUserNameClient( + Constants.Credentials.UnauthorizedUserName, + Constants.Credentials.ValidPassword, + baseAddressUserName); + + RequestSecurityTokenResponse rstr; + var token = client.Issue(_rst, out rstr); + } + + [TestMethod] + [ExpectedException(typeof(FaultException))] + public void NoRealm() + { + var rst = new RequestSecurityToken + { + RequestType = RequestTypes.Issue, + KeyType = KeyTypes.Symmetric + }; + + RequestSecurityTokenResponse rstr; + var token = _mixedUserNameClient.Issue(rst, out rstr); + } + } +} diff --git a/Tests/Integration Tests/WrapTests.cs b/Tests/Integration Tests/WrapTests.cs new file mode 100644 index 0000000..590d2e3 --- /dev/null +++ b/Tests/Integration Tests/WrapTests.cs @@ -0,0 +1,127 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Net; +using System.Net.Http; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Thinktecture.IdentityServer.OAuth; + +namespace Thinktecture.IdentityServer.Tests +{ + [TestClass] + public class WrapTests + { + WrapClient _client; + string baseAddress = Constants.Wrap.LocalBaseAddress; + string scope = Constants.Realms.LocalRP; + + [TestInitialize] + public void Setup() + { + _client = new WrapClient(new Uri(baseAddress)); + } + + [TestMethod] + public void ValidUserNameCredential() + { + var swt = _client.Issue(Constants.Credentials.ValidUserName, Constants.Credentials.ValidPassword, new Uri(scope)); + + Assert.IsTrue(swt != null); + + var id = swt.ToClaimsIdentity(); + + Assert.IsTrue(id.Claims.Count > 0); + + foreach (var claim in id.Claims) + { + Trace.WriteLine(string.Format("{0} ::: {1}", claim.ClaimType, claim.Value)); + } + } + + [TestMethod] + public void InvalidUserNameCredential() + { + var form = new FormUrlEncodedContent(new Dictionary + { + { "wrap_name", Constants.Credentials.ValidUserName }, + { "wrap_password", "invalid" }, + { "wrap_scope", scope } + }); + + var client = new HttpClient(); + var result = client.PostAsync(new Uri(baseAddress), form).Result; + + Assert.AreEqual(HttpStatusCode.Unauthorized, result.StatusCode); + } + + [TestMethod] + public void UnauthorizedUser() + { + var form = new FormUrlEncodedContent(new Dictionary + { + { "wrap_name", Constants.Credentials.UnauthorizedUserName }, + { "wrap_password", Constants.Credentials.ValidPassword }, + { "wrap_scope", scope } + }); + + var client = new HttpClient(); + var result = client.PostAsync(new Uri(baseAddress), form).Result; + + Assert.AreEqual(HttpStatusCode.Unauthorized, result.StatusCode); + } + + [TestMethod] + public void NoRealm() + { + var form = new FormUrlEncodedContent(new Dictionary + { + { "wrap_name", Constants.Credentials.ValidUserName }, + { "wrap_password", Constants.Credentials.ValidPassword } + }); + + var client = new HttpClient(); + var result = client.PostAsync(new Uri(baseAddress), form).Result; + + Assert.AreEqual(HttpStatusCode.BadRequest, result.StatusCode); + } + + [TestMethod] + public void MalformedRealm() + { + var form = new FormUrlEncodedContent(new Dictionary + { + { "wrap_name", Constants.Credentials.ValidUserName }, + { "wrap_password", Constants.Credentials.ValidPassword }, + { "wrap_scope", "invalid" } + }); + + var client = new HttpClient(); + var result = client.PostAsync(new Uri(baseAddress), form).Result; + + Assert.AreEqual(HttpStatusCode.BadRequest, result.StatusCode); + } + + [TestMethod] + public void NoCredentials() + { + var form = new FormUrlEncodedContent(new Dictionary + { + { "wrap_scope", scope } + }); + + var client = new HttpClient(); + var result = client.PostAsync(new Uri(baseAddress), form).Result; + + Assert.AreEqual(HttpStatusCode.Unauthorized, result.StatusCode); + } + } +} diff --git a/Tests/Properties/AssemblyInfo.cs b/Tests/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..fa1cca7 --- /dev/null +++ b/Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,34 @@ +using System.Reflection; +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("Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("Tests")] +[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("a3c3928a-bad2-440d-bab1-90aebfbdf19f")] + +// 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 Build and Revision Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Tests/Repositories/TestRelyingPartyRepository.cs b/Tests/Repositories/TestRelyingPartyRepository.cs new file mode 100644 index 0000000..e98c8bc --- /dev/null +++ b/Tests/Repositories/TestRelyingPartyRepository.cs @@ -0,0 +1,101 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using Thinktecture.IdentityServer.Models; +using Thinktecture.IdentityServer.Repositories; + +namespace Thinktecture.IdentityServer.Tests +{ + class TestRelyingPartyRepository : IRelyingPartyRepository + { + List _rps = new List + { + new RelyingParty + { + Id = "1", + Name = "Plain text, no encryption", + Realm = new Uri(Constants.Realms.PlainTextNoEncryption) + }, + new RelyingParty + { + Id = "2", + Name = "SSL, no encryption", + Realm = new Uri(Constants.Realms.SslNoEncryption) + }, + new RelyingParty + { + Id = "3", + Name = "Plain text, encryption", + Realm = new Uri(Constants.Realms.PlainTextEncryption), + EncryptingCertificate = Constants.Certificates.DefaultEncryptionCertificate + }, + new RelyingParty + { + Id = "4", + Name = "SSL, encryption", + Realm = new Uri(Constants.Realms.SslEncryption), + EncryptingCertificate = Constants.Certificates.DefaultEncryptionCertificate + }, + new RelyingParty + { + Id = "4", + Name = "Explicit replyTo", + Realm = new Uri(Constants.Realms.ExplicitReplyTo), + ReplyTo = new Uri(Constants.Realms.ExplicitReplyTo), + EncryptingCertificate = Constants.Certificates.DefaultEncryptionCertificate + } + }; + + public bool TryGet(string realm, out RelyingParty relyingParty) + { + relyingParty = + (from rp in _rps + where rp.Realm.AbsoluteUri.Equals(realm, StringComparison.OrdinalIgnoreCase) + select rp) + .FirstOrDefault(); + + return (relyingParty != null); + } + + #region Management - not implemented + public bool SupportsWriteAccess + { + get { throw new NotImplementedException(); } + } + + public IEnumerable List(int pageIndex, int pageSize) + { + throw new NotImplementedException(); + } + + public Models.RelyingParty Get(string id) + { + throw new NotImplementedException(); + } + + public void Add(Models.RelyingParty relyingParty) + { + throw new NotImplementedException(); + } + + public void Update(Models.RelyingParty relyingParty) + { + throw new NotImplementedException(); + } + + public void Delete(string id) + { + throw new NotImplementedException(); + } + #endregion + } +} diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj new file mode 100644 index 0000000..a40cb37 --- /dev/null +++ b/Tests/Tests.csproj @@ -0,0 +1,120 @@ + + + + Debug + AnyCPU + + + 2.0 + {7392F6F9-9723-4E1F-A0C4-7F6340E5CAAF} + Library + Properties + Thinktecture.IdentityServer.Tests + Thinktecture.IdentityServer.Tests + v4.0 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + + + + + + + + ..\ + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + 3.5 + + + + True + ..\OnPremise\packages\System.Json.4.0.20126.16343\lib\net40\System.Json.dll + + + True + ..\OnPremise\packages\System.Net.Http.2.0.20126.16343\lib\net40\System.Net.Http.dll + + + True + ..\OnPremise\packages\System.Net.Http.Formatting.4.0.20126.16343\lib\net40\System.Net.Http.Formatting.dll + + + True + ..\OnPremise\packages\System.Net.Http.2.0.20126.16343\lib\net40\System.Net.Http.WebRequest.dll + + + + + + + + + False + + + + + + + + + + + + + + + + + + + + + + + + + + {38CE5C59-909E-4DA6-8E1D-7EEE7312CA9A} + Thinktecture.IdentityServer.Core + + + + + + + + + \ No newline at end of file diff --git a/Tests/Tests.csproj.vspscc b/Tests/Tests.csproj.vspscc new file mode 100644 index 0000000..b6d3289 --- /dev/null +++ b/Tests/Tests.csproj.vspscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "" +"NUMBER_OF_EXCLUDED_FILES" = "0" +"ORIGINAL_PROJECT_FILE_PATH" = "" +"NUMBER_OF_NESTED_PROJECTS" = "0" +"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER" +} diff --git a/Tests/Tools/AccessTokenResponse.cs b/Tests/Tools/AccessTokenResponse.cs new file mode 100644 index 0000000..03c760f --- /dev/null +++ b/Tests/Tools/AccessTokenResponse.cs @@ -0,0 +1,19 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +namespace Thinktecture.IdentityServer.OAuth +{ + public class AccessTokenResponse + { + public string AccessToken { get; set; } + public string RefreshToken { get; set; } + public string TokenType { get; set; } + public int ExpiresIn { get; set; } + } +} diff --git a/Tests/Tools/OAuth2Client.cs b/Tests/Tools/OAuth2Client.cs new file mode 100644 index 0000000..6d351ee --- /dev/null +++ b/Tests/Tools/OAuth2Client.cs @@ -0,0 +1,106 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Collections.Generic; +using System.Json; +using System.Net.Http; +using System.Security.Cryptography.X509Certificates; + +namespace Thinktecture.IdentityServer.OAuth +{ + public class OAuth2Client + { + HttpClient _client; + + public OAuth2Client(Uri address) + { + _client = new HttpClient { BaseAddress = address }; + } + + public AccessTokenResponse RequestAccessTokenCertificate(X509Certificate2 certificate, string scope) + { + var handler = new WebRequestHandler(); + handler.ClientCertificates.Add(certificate); + + var client = new HttpClient(handler) { BaseAddress = _client.BaseAddress }; + var response = client.PostAsync("", CreateFormCertificate(scope)).Result; + response.EnsureSuccessStatusCode(); + + var json = JsonValue.Parse(response.Content.ReadAsStringAsync().Result).AsDynamic(); + return CreateResponseFromJson(json); + } + + public AccessTokenResponse RequestAccessTokenUserName(string userName, string password, string scope) + { + var response = _client.PostAsync("", CreateFormUserName(userName, password, scope)).Result; + response.EnsureSuccessStatusCode(); + + var json = JsonValue.Parse(response.Content.ReadAsStringAsync().Result).AsDynamic(); + return CreateResponseFromJson(json); + } + + public AccessTokenResponse RequestAccessTokenAssertion(string assertion, string assertionType, string scope) + { + var response = _client.PostAsync("", CreateFormAssertion(assertion, assertionType, scope)).Result; + response.EnsureSuccessStatusCode(); + + var json = JsonValue.Parse(response.Content.ReadAsStringAsync().Result).AsDynamic(); + return CreateResponseFromJson(json); + } + + protected virtual FormUrlEncodedContent CreateFormCertificate(string scope) + { + var values = new Dictionary + { + { OAuth2Constants.GrantType, OAuth2Constants.ClientCredentials }, + { OAuth2Constants.scope, scope } + }; + + return new FormUrlEncodedContent(values); + } + + protected virtual FormUrlEncodedContent CreateFormUserName(string userName, string password, string scope) + { + var values = new Dictionary + { + { OAuth2Constants.GrantType, OAuth2Constants.Password }, + { OAuth2Constants.UserName, userName }, + { OAuth2Constants.Password, password }, + { OAuth2Constants.scope, scope } + }; + + return new FormUrlEncodedContent(values); + } + + protected virtual FormUrlEncodedContent CreateFormAssertion(string assertion, string assertionType, string scope) + { + var values = new Dictionary + { + { OAuth2Constants.GrantType, assertionType }, + { OAuth2Constants.Assertion, assertion }, + { OAuth2Constants.scope, scope } + }; + + return new FormUrlEncodedContent(values); + } + + private AccessTokenResponse CreateResponseFromJson(dynamic json) + { + return new AccessTokenResponse + { + AccessToken = json.access_token, + RefreshToken = json.refresh_token, + TokenType = json.token_type, + ExpiresIn = json.expires_in + }; + } + + } +} diff --git a/Tests/Tools/OAuth2Constants.cs b/Tests/Tools/OAuth2Constants.cs new file mode 100644 index 0000000..41f3dc7 --- /dev/null +++ b/Tests/Tools/OAuth2Constants.cs @@ -0,0 +1,21 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +namespace Thinktecture.IdentityServer.OAuth +{ + public static class OAuth2Constants + { + public const string GrantType = "grant_type"; + public const string Password = "password"; + public const string UserName = "username"; + public const string scope = "scope"; + public const string Assertion = "assertion"; + public const string ClientCredentials = "client_credentials"; + } +} diff --git a/Tests/Tools/WrapClient.cs b/Tests/Tools/WrapClient.cs new file mode 100644 index 0000000..5d3eb33 --- /dev/null +++ b/Tests/Tools/WrapClient.cs @@ -0,0 +1,147 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using System.Collections.Specialized; +using System.IdentityModel.Tokens; +using System.IO; +using System.Linq; +using System.Net; +using System.Text; +using System.Web; +using System.Xml; +using Microsoft.IdentityModel.Tokens.Saml11; +using Thinktecture.IdentityServer.Core.Swt; + +namespace Thinktecture.IdentityServer.OAuth +{ + /// + /// Implements the OAuth WRAP protocol to request tokens from an issuer. + /// + public class WrapClient + { + Uri _issuerAddress; + + /// + /// Initializes a new instance of the class. + /// + /// The issuer address. + public WrapClient(Uri issuerAddress) + { + _issuerAddress = issuerAddress; + } + + /// + /// Requests an SWT Token using username/password credentials. + /// + /// Name of the user. + /// The password. + /// The requested scope. + /// The requested SWT token + public SimpleWebToken Issue(string userName, string password, Uri scope) + { + var values = new NameValueCollection + { + { "wrap_name", userName }, + { "wrap_password", password }, + { "wrap_scope", scope.AbsoluteUri } + }; + + return ResponseToSimpleWebToken(RequestToken(values)); + } + + /// + /// Requests an SWT Token using an input SWT token. + /// + /// The input SWT token. + /// The requested scope. + /// The requested SWT token + public SimpleWebToken Issue(SimpleWebToken token, Uri scope) + { + return IssueAssertion(token.ToString(), "SWT", scope); + } + + /// + /// Requests an SWT Token using an input SAML token. + /// + /// The input SAML token. + /// The requested scope. + /// The requested SWT token + public SimpleWebToken Issue(SamlSecurityToken token, Uri scope) + { + var handler = new Saml11SecurityTokenHandler(); + + var sb = new StringBuilder(128); + handler.WriteToken(XmlWriter.Create(new StringWriter(sb)), token); + + return IssueAssertion(sb.ToString(), "SAML", scope); + } + + /// + /// Requests an SWT Token using an input GenericXml SAML token. + /// + /// The input GenericXml SAML token. + /// The requested scope. + /// The requested SWT token + public SimpleWebToken Issue(GenericXmlSecurityToken token, Uri scope) + { + return IssueAssertion(token.TokenXml.OuterXml, "SAML", scope); + } + + /// + /// Requests an SWT Token using an input assertion. + /// + /// The assertion. + /// The assertion format. + /// The requested scope. + /// The requested SWT token + public SimpleWebToken IssueAssertion(string token, string assertionFormat, Uri scope) + { + var values = new NameValueCollection + { + { "wrap_assertion_format", assertionFormat}, + { "wrap_assertion", token }, + { "wrap_scope", scope.AbsoluteUri } + }; + + return ResponseToSimpleWebToken(RequestToken(values)); + } + + private SimpleWebToken ResponseToSimpleWebToken(string response) + { + //string prefix = "wrap_access_token="; + + //if (!response.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) + //{ + // throw new ArgumentException("response"); + //} + + //var tokenString = response.Substring(prefix.Length); + //return new SimpleWebToken(tokenString); + + return new SimpleWebToken( + HttpUtility.HtmlDecode( + Uri.UnescapeDataString( + response.Split('&') + .Single(value => value.StartsWith("wrap_access_token=", StringComparison.OrdinalIgnoreCase)) + .Split('=')[1]))); + } + + private string RequestToken(NameValueCollection values) + { + using (var client = new WebClient()) + { + client.BaseAddress = _issuerAddress.AbsoluteUri; + + byte[] responseBytes = client.UploadValues("", "POST", values); + return Encoding.UTF8.GetString(responseBytes); + } + } + } +} diff --git a/Tests/Unit Tests/PolicyEnforcementTest.cs b/Tests/Unit Tests/PolicyEnforcementTest.cs new file mode 100644 index 0000000..b488651 --- /dev/null +++ b/Tests/Unit Tests/PolicyEnforcementTest.cs @@ -0,0 +1,226 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using System; +using Microsoft.IdentityModel.Claims; +using Microsoft.IdentityModel.Protocols.WSTrust; +using Microsoft.IdentityModel.SecurityTokenService; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Thinktecture.IdentityServer.Core.Swt; +using Thinktecture.IdentityServer.Models; +using Thinktecture.IdentityServer.TokenService; + +namespace Thinktecture.IdentityServer.Tests +{ + [TestClass] + public class PolicyEnforcementTest + { + GlobalConfiguration config; + Request request; + IClaimsPrincipal _alice; + + [TestInitialize] + public void Setup() + { + config = ConfigurationFactory.Create(Constants.ConfigurationModes.LockedDown); + request = new Request(config, new TestRelyingPartyRepository(), null); + _alice = PrincipalFactory.Create(Constants.Principals.AliceUserName); + } + + [TestMethod] + [ExpectedException(typeof(MissingAppliesToException))] + public void Validate_NoRealm() + { + var rst = new RequestSecurityToken { RequestType = RequestTypes.Issue }; + var details = request.Analyze(rst, _alice); + + // unknown realm + request.Validate(); + } + + [TestMethod] + public void Analyze_UnknownRealm() + { + var rst = RstFactory.Create(Constants.Realms.UnknownRealm); + var details = request.Analyze(rst, _alice); + + // unknown realm + Assert.IsFalse(details.IsKnownRealm); + } + + [TestMethod] + [ExpectedException(typeof(InvalidScopeException))] + public void Validate_UnknownRealm() + { + var rst = RstFactory.Create(Constants.Realms.UnknownRealm); + var details = request.Analyze(rst, _alice); + + // unknown realm + request.Validate(); + } + + [TestMethod] + public void Analyze_PlainTextNoEncryption() + { + var rst = RstFactory.Create(Constants.Realms.PlainTextNoEncryption); + var details = request.Analyze(rst, _alice); + + // known realm, registered + Assert.IsTrue(details.IsKnownRealm); + Assert.AreEqual(rst.AppliesTo.Uri.AbsoluteUri, details.RelyingPartyRegistration.Realm.AbsoluteUri); + + // reply to + Assert.IsTrue(details.ReplyToAddressIsWithinRealm); + Assert.AreEqual(rst.AppliesTo.Uri.AbsoluteUri, details.ReplyToAddress.AbsoluteUri); + + // security settings + Assert.IsFalse(details.UsesSsl); + Assert.IsFalse(details.UsesEncryption); + } + + [TestMethod] + [ExpectedException(typeof(InvalidRequestException))] + public void Validate_PlainTextNoEncryption() + { + var rst = RstFactory.Create(Constants.Realms.PlainTextNoEncryption); + var details = request.Analyze(rst, _alice); + + request.Validate(); + } + + [TestMethod] + public void Analyze_SslNoEncryption() + { + var rst = RstFactory.Create(Constants.Realms.SslNoEncryption); + var details = request.Analyze(rst, _alice); + + // known realm, registered + Assert.IsTrue(details.IsKnownRealm); + Assert.AreEqual(rst.AppliesTo.Uri.AbsoluteUri, details.RelyingPartyRegistration.Realm.AbsoluteUri); + + // reply to + Assert.IsTrue(details.ReplyToAddressIsWithinRealm); + Assert.AreEqual(rst.AppliesTo.Uri.AbsoluteUri, details.ReplyToAddress.AbsoluteUri); + + // security settings + Assert.IsTrue(details.UsesSsl); + Assert.IsFalse(details.UsesEncryption); + } + + [TestMethod] + [ExpectedException(typeof(InvalidRequestException))] + public void Validate_SslNoEncryption() + { + var rst = RstFactory.Create(Constants.Realms.SslNoEncryption); + var details = request.Analyze(rst, _alice); + + request.Validate(); + } + + [TestMethod] + public void Analyze_PlainTextEncryption() + { + var rst = RstFactory.Create(Constants.Realms.PlainTextEncryption); + var details = request.Analyze(rst, _alice); + + // known realm, registered + Assert.IsTrue(details.IsKnownRealm); + Assert.AreEqual(rst.AppliesTo.Uri.AbsoluteUri, details.RelyingPartyRegistration.Realm.AbsoluteUri); + + // reply to + Assert.IsTrue(details.ReplyToAddressIsWithinRealm); + Assert.AreEqual(rst.AppliesTo.Uri.AbsoluteUri, details.ReplyToAddress.AbsoluteUri); + + // security settings + Assert.IsFalse(details.UsesSsl); + Assert.IsTrue(details.UsesEncryption); + } + + [TestMethod] + [ExpectedException(typeof(InvalidRequestException))] + public void Validate_PlainTextEncryption() + { + var rst = RstFactory.Create(Constants.Realms.PlainTextEncryption); + var details = request.Analyze(rst, _alice); + + request.Validate(); + } + + [TestMethod] + public void Analyze_SslEncryption() + { + var rst = RstFactory.Create(Constants.Realms.SslEncryption); + var details = request.Analyze(rst, _alice); + + // known realm, registered + Assert.IsTrue(details.IsKnownRealm); + Assert.AreEqual(rst.AppliesTo.Uri.AbsoluteUri, details.RelyingPartyRegistration.Realm.AbsoluteUri); + + // reply to + Assert.IsTrue(details.ReplyToAddressIsWithinRealm); + Assert.AreEqual(rst.AppliesTo.Uri.AbsoluteUri, details.ReplyToAddress.AbsoluteUri); + + // security settings + Assert.IsTrue(details.UsesSsl); + Assert.IsTrue(details.UsesEncryption); + } + + [TestMethod] + public void Validate_SslEncryption() + { + var rst = RstFactory.Create(Constants.Realms.SslEncryption); + var details = request.Analyze(rst, _alice); + + request.Validate(); + } + + [TestMethod] + [ExpectedException(typeof(InvalidRequestException))] + public void Validate_SymmetricSignatureNoSigningKey() + { + var rst = RstFactory.Create(Constants.Realms.PlainTextNoEncryption); + rst.TokenType = SimpleWebToken.OasisTokenProfile; + + var details = request.Analyze(rst, _alice); + + request.Validate(); + } + + [TestMethod] + public void Analyze_ReplyToShouldBeIgnored() + { + var rst = RstFactory.Create(Constants.Realms.SslEncryption); + rst.ReplyTo = "http://foo"; + var details = request.Analyze(rst, _alice); + + // known realm, registered + Assert.IsTrue(details.IsKnownRealm); + Assert.AreEqual(rst.AppliesTo.Uri.AbsoluteUri, details.RelyingPartyRegistration.Realm.AbsoluteUri); + + // reply to + Assert.IsTrue(details.ReplyToAddressIsWithinRealm); + Assert.AreEqual(rst.AppliesTo.Uri.AbsoluteUri, details.ReplyToAddress.AbsoluteUri); + + // security settings + Assert.IsTrue(details.UsesSsl); + Assert.IsTrue(details.UsesEncryption); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void Analyze_AnonymousClientIdentity() + { + var rst = RstFactory.Create(Constants.Realms.UnknownRealm); + var details = request.Analyze(rst, PrincipalFactory.Create(Constants.Principals.Anonymous)); + + // unknown realm + Assert.IsFalse(details.IsKnownRealm); + } + } +} diff --git a/Tests/Unit Tests/ReplyToHandlingTest.cs b/Tests/Unit Tests/ReplyToHandlingTest.cs new file mode 100644 index 0000000..a7b2a59 --- /dev/null +++ b/Tests/Unit Tests/ReplyToHandlingTest.cs @@ -0,0 +1,77 @@ +/* + * Copyright (c) Dominick Baier. All rights reserved. + * + * This code is licensed under the Microsoft Permissive License (Ms-PL) + * + * SEE: http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx + * + */ + +using Microsoft.IdentityModel.Claims; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Thinktecture.IdentityServer.Models; +using Thinktecture.IdentityServer.TokenService; + +namespace Thinktecture.IdentityServer.Tests +{ + [TestClass] + public class ReplyToHandlingTest + { + GlobalConfiguration config; + Request request; + IClaimsPrincipal _alice; + + [TestInitialize] + public void Setup() + { + config = ConfigurationFactory.Create(Constants.ConfigurationModes.LockedDownAllowReplyTo); + request = new Request(config, new TestRelyingPartyRepository(), null); + _alice = PrincipalFactory.Create(Constants.Principals.AliceUserName); + } + + [TestMethod] + public void IgnoreReplyToForRegisteredRPwithReplyTo() + { + var rst = RstFactory.Create(Constants.Realms.ExplicitReplyTo); + rst.ReplyTo = "http://foo"; + var details = request.Analyze(rst, _alice); + + // make sure reply to is from configuration + Assert.IsTrue(details.IsReplyToFromConfiguration); + + // reply to + Assert.IsTrue(details.ReplyToAddressIsWithinRealm); + Assert.AreEqual(rst.AppliesTo.Uri.AbsoluteUri, details.ReplyToAddress.AbsoluteUri); + } + + [TestMethod] + public void HonourReplyToForRegisteredRPwithoutReplyTo() + { + var rst = RstFactory.Create(Constants.Realms.SslEncryption); + rst.ReplyTo = Constants.Realms.SslEncryption + "subrealm/"; + var details = request.Analyze(rst, _alice); + + // make sure reply to is from configuration + Assert.IsFalse(details.IsReplyToFromConfiguration); + + // reply to + Assert.IsTrue(details.ReplyToAddressIsWithinRealm); + Assert.AreEqual(rst.ReplyTo, details.ReplyToAddress.AbsoluteUri); + } + + [TestMethod] + public void DetectCrossRealmRedirect() + { + var rst = RstFactory.Create(Constants.Realms.SslEncryption); + rst.ReplyTo = "http://foo/"; + var details = request.Analyze(rst, _alice); + + // make sure reply to is from configuration + Assert.IsFalse(details.IsReplyToFromConfiguration); + + // reply to + Assert.IsFalse(details.ReplyToAddressIsWithinRealm); + Assert.AreEqual(rst.ReplyTo, details.ReplyToAddress.AbsoluteUri); + } + } +} diff --git a/Tests/packages.config b/Tests/packages.config new file mode 100644 index 0000000..15487d4 --- /dev/null +++ b/Tests/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/readme b/readme new file mode 100644 index 0000000..7d98036 --- /dev/null +++ b/readme @@ -0,0 +1 @@ +Thinktecture IdentityServer is an open source security token service based on Microsoft .NET, ASP.NET MVC, WCF and WIF. \ No newline at end of file