├── .gitattributes ├── .gitignore ├── License.txt ├── ModularVNext.sln ├── global.json ├── readme.md └── src ├── ModularVNext ├── Compiler │ └── Preprocess │ │ └── RazorPreCompilation.cs ├── Controllers │ └── HomeController.cs ├── Extensions │ └── EnumerableExtensions.cs ├── Infrastructure │ ├── CompositeFileProvider.cs │ ├── DirectoryLoader.cs │ ├── ModuleAssemblyLocator.cs │ ├── ModuleAwareAssemblyProvider.cs │ └── SafeEmbeddedFileProvider.cs ├── ModularVNext.kproj ├── Startup.cs ├── Views │ ├── Home │ │ ├── About.cshtml │ │ ├── Contact.cshtml │ │ └── Index.cshtml │ ├── Shared │ │ ├── Error.cshtml │ │ └── _Layout.cshtml │ └── _ViewStart.cshtml ├── bower.json ├── config.json ├── gruntfile.js ├── package.json ├── project.json └── wwwroot │ ├── _references.js │ ├── css │ └── site.css │ ├── images │ ├── ASP-NET-Banners-01.png │ ├── ASP-NET-Banners-02.png │ ├── Banner-01-Azure.png │ └── Banner-02-VS.png │ └── lib │ ├── bootstrap-touch-carousel │ ├── css │ │ └── bootstrap-touch-carousel.css │ └── js │ │ └── bootstrap-touch-carousel.js │ ├── bootstrap │ ├── css │ │ ├── bootstrap-theme.css │ │ ├── bootstrap-theme.min.css │ │ ├── bootstrap.css │ │ └── bootstrap.min.css │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ └── glyphicons-halflings-regular.woff │ └── js │ │ ├── bootstrap.js │ │ └── bootstrap.min.js │ ├── hammer.js │ └── hammer.js │ ├── jquery-validation-unobtrusive │ ├── jquery.validate.unobtrusive.js │ └── jquery.validate.unobtrusive.min.js │ ├── jquery-validation │ └── jquery.validate.js │ └── jquery │ ├── jquery.js │ ├── jquery.min.js │ └── jquery.min.map ├── Module1 ├── Controllers │ └── Module1Controller.cs ├── Module1.kproj ├── Views │ └── Module1 │ │ └── Index.cshtml └── project.json └── Module2 ├── Areas └── Module2 │ ├── Content │ └── module2.css │ ├── Controllers │ └── WeatherController.cs │ └── Views │ └── Weather │ └── Index.cshtml ├── Module2.kproj └── project.json /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Build results 10 | [Dd]ebug/ 11 | [Dd]ebugPublic/ 12 | [Rr]elease/ 13 | x64/ 14 | build/ 15 | bld/ 16 | [Bb]in/ 17 | [Oo]bj/ 18 | 19 | # Roslyn cache directories 20 | *.ide/ 21 | 22 | # MSTest test Results 23 | [Tt]est[Rr]esult*/ 24 | [Bb]uild[Ll]og.* 25 | 26 | #NUNIT 27 | *.VisualState.xml 28 | TestResult.xml 29 | 30 | # Build Results of an ATL Project 31 | [Dd]ebugPS/ 32 | [Rr]eleasePS/ 33 | dlldata.c 34 | 35 | *_i.c 36 | *_p.c 37 | *_i.h 38 | *.ilk 39 | *.meta 40 | *.obj 41 | *.pch 42 | *.pdb 43 | *.pgc 44 | *.pgd 45 | *.rsp 46 | *.sbr 47 | *.tlb 48 | *.tli 49 | *.tlh 50 | *.tmp 51 | *.tmp_proj 52 | *.log 53 | *.vspscc 54 | *.vssscc 55 | .builds 56 | *.pidb 57 | *.svclog 58 | *.scc 59 | 60 | # Chutzpah Test files 61 | _Chutzpah* 62 | 63 | # Visual C++ cache files 64 | ipch/ 65 | *.aps 66 | *.ncb 67 | *.opensdf 68 | *.sdf 69 | *.cachefile 70 | 71 | # Visual Studio profiler 72 | *.psess 73 | *.vsp 74 | *.vspx 75 | 76 | # TFS 2012 Local Workspace 77 | $tf/ 78 | 79 | # Guidance Automation Toolkit 80 | *.gpState 81 | 82 | # ReSharper is a .NET coding add-in 83 | _ReSharper*/ 84 | *.[Rr]e[Ss]harper 85 | *.DotSettings.user 86 | 87 | # JustCode is a .NET coding addin-in 88 | .JustCode 89 | 90 | # TeamCity is a build add-in 91 | _TeamCity* 92 | 93 | # DotCover is a Code Coverage Tool 94 | *.dotCover 95 | 96 | # NCrunch 97 | _NCrunch_* 98 | .*crunch*.local.xml 99 | 100 | # MightyMoose 101 | *.mm.* 102 | AutoTest.Net/ 103 | 104 | # Web workbench (sass) 105 | .sass-cache/ 106 | 107 | # Installshield output folder 108 | [Ee]xpress/ 109 | 110 | # DocProject is a documentation generator add-in 111 | DocProject/buildhelp/ 112 | DocProject/Help/*.HxT 113 | DocProject/Help/*.HxC 114 | DocProject/Help/*.hhc 115 | DocProject/Help/*.hhk 116 | DocProject/Help/*.hhp 117 | DocProject/Help/Html2 118 | DocProject/Help/html 119 | 120 | # Click-Once directory 121 | publish/ 122 | 123 | # Publish Web Output 124 | *.[Pp]ublish.xml 125 | *.azurePubxml 126 | ## TODO: Comment the next line if you want to checkin your 127 | ## web deploy settings but do note that will include unencrypted 128 | ## passwords 129 | #*.pubxml 130 | 131 | # NuGet Packages Directory 132 | packages/* 133 | ## TODO: If the tool you use requires repositories.config 134 | ## uncomment the next line 135 | #!packages/repositories.config 136 | 137 | # Enable "build/" folder in the NuGet Packages folder since 138 | # NuGet packages use it for MSBuild targets. 139 | # This line needs to be after the ignore of the build folder 140 | # (and the packages folder if the line above has been uncommented) 141 | !packages/build/ 142 | 143 | # Windows Azure Build Output 144 | csx/ 145 | *.build.csdef 146 | 147 | # Windows Store app package directory 148 | AppPackages/ 149 | 150 | # Others 151 | sql/ 152 | *.Cache 153 | ClientBin/ 154 | [Ss]tyle[Cc]op.* 155 | ~$* 156 | *~ 157 | *.dbmdl 158 | *.dbproj.schemaview 159 | *.pfx 160 | *.publishsettings 161 | node_modules/ 162 | bower_components/ 163 | 164 | # RIA/Silverlight projects 165 | Generated_Code/ 166 | 167 | # Backup & report files from converting an old project file 168 | # to a newer Visual Studio version. Backup files are not needed, 169 | # because we have git ;-) 170 | _UpgradeReport_Files/ 171 | Backup*/ 172 | UpgradeLog*.XML 173 | UpgradeLog*.htm 174 | 175 | # SQL Server files 176 | *.mdf 177 | *.ldf 178 | 179 | # Business Intelligence projects 180 | *.rdl.data 181 | *.bim.layout 182 | *.bim_*.settings 183 | 184 | # Microsoft Fakes 185 | FakesAssemblies/ 186 | 187 | # LightSwitch generated files 188 | GeneratedArtifacts/ 189 | _Pvt_Extensions/ 190 | ModelManifest.xml -------------------------------------------------------------------------------- /License.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Stuart Leeks 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | 24 | 25 | 26 | Portions of this software are taken from https://github.com/aspnet/Entropy and 27 | subject to the license below. 28 | 29 | Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. 30 | 31 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use 32 | these files except in compliance with the License. You may obtain a copy of the 33 | License at 34 | 35 | http://www.apache.org/licenses/LICENSE-2.0 36 | 37 | Unless required by applicable law or agreed to in writing, software distributed 38 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 39 | CONDITIONS OF ANY KIND, either express or implied. See the License for the 40 | specific language governing permissions and limitations under the License. -------------------------------------------------------------------------------- /ModularVNext.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.22609.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{69F59749-2521-4847-9A22-F2D38569C638}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C87FB3F6-0C21-4AEC-96A8-BD185A3AD732}" 9 | ProjectSection(SolutionItems) = preProject 10 | global.json = global.json 11 | License.txt = License.txt 12 | readme.md = readme.md 13 | EndProjectSection 14 | EndProject 15 | Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ModularVNext", "src\ModularVNext\ModularVNext.kproj", "{EF4E488C-46AF-48E2-9797-DA08D3A0D01C}" 16 | ProjectSection(ProjectDependencies) = postProject 17 | {54E8903B-D80D-4448-A81D-EDCA38E3EE8C} = {54E8903B-D80D-4448-A81D-EDCA38E3EE8C} 18 | {C9F291B3-CA16-427D-A64A-1013A2C97F5C} = {C9F291B3-CA16-427D-A64A-1013A2C97F5C} 19 | EndProjectSection 20 | EndProject 21 | Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Module1", "src\Module1\Module1.kproj", "{54E8903B-D80D-4448-A81D-EDCA38E3EE8C}" 22 | EndProject 23 | Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Module2", "src\Module2\Module2.kproj", "{C9F291B3-CA16-427D-A64A-1013A2C97F5C}" 24 | EndProject 25 | Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.FileProviders", "..\_LibsEtc\aspnetvnext\FileSystem\src\Microsoft.AspNet.FileProviders\Microsoft.AspNet.FileProviders.kproj", "{A830B046-595A-4992-B9E1-3C28C6440707}" 26 | EndProject 27 | Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.FileProviders.Interfaces", "..\_LibsEtc\aspnetvnext\FileSystem\src\Microsoft.AspNet.FileProviders.Interfaces\Microsoft.AspNet.FileProviders.Interfaces.kproj", "{DD94B7E8-3A59-4F84-98A0-8139BE259A87}" 28 | EndProject 29 | Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.StaticFiles", "..\_LibsEtc\aspnetvnext\StaticFiles\src\Microsoft.AspNet.StaticFiles\Microsoft.AspNet.StaticFiles.kproj", "{8D7BC5A4-F19C-4184-8338-A6B42997218C}" 30 | EndProject 31 | Global 32 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 33 | Debug|Any CPU = Debug|Any CPU 34 | Release|Any CPU = Release|Any CPU 35 | EndGlobalSection 36 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 37 | {EF4E488C-46AF-48E2-9797-DA08D3A0D01C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 38 | {EF4E488C-46AF-48E2-9797-DA08D3A0D01C}.Debug|Any CPU.Build.0 = Debug|Any CPU 39 | {EF4E488C-46AF-48E2-9797-DA08D3A0D01C}.Release|Any CPU.ActiveCfg = Release|Any CPU 40 | {EF4E488C-46AF-48E2-9797-DA08D3A0D01C}.Release|Any CPU.Build.0 = Release|Any CPU 41 | {54E8903B-D80D-4448-A81D-EDCA38E3EE8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 42 | {54E8903B-D80D-4448-A81D-EDCA38E3EE8C}.Debug|Any CPU.Build.0 = Debug|Any CPU 43 | {54E8903B-D80D-4448-A81D-EDCA38E3EE8C}.Release|Any CPU.ActiveCfg = Release|Any CPU 44 | {54E8903B-D80D-4448-A81D-EDCA38E3EE8C}.Release|Any CPU.Build.0 = Release|Any CPU 45 | {C9F291B3-CA16-427D-A64A-1013A2C97F5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 46 | {C9F291B3-CA16-427D-A64A-1013A2C97F5C}.Debug|Any CPU.Build.0 = Debug|Any CPU 47 | {C9F291B3-CA16-427D-A64A-1013A2C97F5C}.Release|Any CPU.ActiveCfg = Release|Any CPU 48 | {C9F291B3-CA16-427D-A64A-1013A2C97F5C}.Release|Any CPU.Build.0 = Release|Any CPU 49 | {A830B046-595A-4992-B9E1-3C28C6440707}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 50 | {A830B046-595A-4992-B9E1-3C28C6440707}.Debug|Any CPU.Build.0 = Debug|Any CPU 51 | {A830B046-595A-4992-B9E1-3C28C6440707}.Release|Any CPU.ActiveCfg = Release|Any CPU 52 | {A830B046-595A-4992-B9E1-3C28C6440707}.Release|Any CPU.Build.0 = Release|Any CPU 53 | {DD94B7E8-3A59-4F84-98A0-8139BE259A87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 54 | {DD94B7E8-3A59-4F84-98A0-8139BE259A87}.Debug|Any CPU.Build.0 = Debug|Any CPU 55 | {DD94B7E8-3A59-4F84-98A0-8139BE259A87}.Release|Any CPU.ActiveCfg = Release|Any CPU 56 | {DD94B7E8-3A59-4F84-98A0-8139BE259A87}.Release|Any CPU.Build.0 = Release|Any CPU 57 | {8D7BC5A4-F19C-4184-8338-A6B42997218C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 58 | {8D7BC5A4-F19C-4184-8338-A6B42997218C}.Debug|Any CPU.Build.0 = Debug|Any CPU 59 | {8D7BC5A4-F19C-4184-8338-A6B42997218C}.Release|Any CPU.ActiveCfg = Release|Any CPU 60 | {8D7BC5A4-F19C-4184-8338-A6B42997218C}.Release|Any CPU.Build.0 = Release|Any CPU 61 | EndGlobalSection 62 | GlobalSection(SolutionProperties) = preSolution 63 | HideSolutionNode = FALSE 64 | EndGlobalSection 65 | GlobalSection(NestedProjects) = preSolution 66 | {EF4E488C-46AF-48E2-9797-DA08D3A0D01C} = {69F59749-2521-4847-9A22-F2D38569C638} 67 | {54E8903B-D80D-4448-A81D-EDCA38E3EE8C} = {69F59749-2521-4847-9A22-F2D38569C638} 68 | {C9F291B3-CA16-427D-A64A-1013A2C97F5C} = {69F59749-2521-4847-9A22-F2D38569C638} 69 | EndGlobalSection 70 | EndGlobal 71 | -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sources": [ 3 | "src", 4 | "test" 5 | ], 6 | "sdk": { 7 | "version": "1.0.0-beta3" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Readme # 2 | This project demonstrates a couple of ways to encapsulate packages of functionality in an ASP.NET MVC 6 project. I.e. to allow modules of ASP.NET MVC 6 functionality to be written in separate projects from the main application. 3 | 4 | 5 | The goals for this sample are to reduce friction at development and deployment time. At development time, it is desirable to work with files on disk for rapid development cycles. It is also key to avoid copying files from modules into the main application folder. At deployment time, it is beneficial to minimise the amount 6 | 7 | 8 | This sample covers the packaging modules and module discovery & loading. 9 | 10 | This sample was written against MVC 6.0.0-beta3 11 | 12 | ## Solution structure ## 13 | The solution contains two projects 14 | - ModularVNext 15 | - Module1 16 | - Module2 17 | 18 | ModularVNext is the main web application. 19 | 20 | Module1 is a class library project with Controllers and Views. The Views are packaged as resources. 21 | 22 | Module2 is a class library project that puts the Controllers and Views inside an MVC Area. 23 | This is probably a good route to take as it will help isolate module contents. 24 | This module also includes a CSS file to demonstrate static content (again bundled as a resource). 25 | 26 | When you run the application you can click on the link to render the content from Module1's view. 27 | 28 | ## Module discovery ## 29 | Modules are discovered by being placed in the modules folder under the bin folder. 30 | The "moduleLoadPath" configuration value determines the path (which allows it to vary between dev and deployment). 31 | There is some code scan this directory and load the assemblies in the Startup class. 32 | 33 | ## Serving module content ## 34 | The serving of module content is enabled through a CompositeFileProvider. Out of the box, MVC only allows a single provider. 35 | The composite provider allows multiple file providers to be chained together. This is registered in Startup. 36 | 37 | There are multiple PhysicalFileProviders included in the composite provider. 38 | These are determined by the configuration value "additionalFileProviderBasePaths". 39 | Adding paths here for modules that you are developing allows MVC to locate and serve content from those paths. 40 | (As noted in the code, this is not recommended for production). 41 | 42 | The second mechanism that is used is to add EmbeddedFileProviders that serve views from compiled resources. 43 | In the project.json for Module1, the Views folder is marked for being compiled in as a resource. 44 | Module2 marks the Content and Views folders for being included as resources. 45 | 46 | To allow MVC to discover the controllers, there is a ModuleAwareAssemblyProvider that includes the loaded assemblies into 47 | the set of assemblies that MVC scans for controllers. 48 | 49 | ## Dev time experience ## 50 | In order to include the modules, they need to produce build output i.e. an assembly (a project option). 51 | Beyond this, the assembly needs to be in the modules folder. 52 | The project uses a grunt task that is bound to the After Build event to copy the modules over to that directory. -------------------------------------------------------------------------------- /src/ModularVNext/Compiler/Preprocess/RazorPreCompilation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNet.Mvc; 3 | 4 | namespace ModularVNext.Compiler.Preprocess 5 | { 6 | public class RazorPreCompilation : RazorPreCompileModule 7 | { 8 | public RazorPreCompilation(IServiceProvider provider) : base(provider) 9 | { 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/ModularVNext/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Microsoft.AspNet.Mvc; 5 | 6 | namespace ModularVNext.Controllers 7 | { 8 | public class HomeController : Controller 9 | { 10 | public IActionResult Index() 11 | { 12 | return View(); 13 | } 14 | 15 | public IActionResult About() 16 | { 17 | ViewBag.Message = "Your application description page."; 18 | 19 | return View(); 20 | } 21 | 22 | public IActionResult Contact() 23 | { 24 | ViewBag.Message = "Your contact page."; 25 | 26 | return View(); 27 | } 28 | 29 | public IActionResult Error() 30 | { 31 | return View("~/Views/Shared/Error.cshtml"); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/ModularVNext/Extensions/EnumerableExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace ModularVNext.Extensions 5 | { 6 | public static class EnumerableExtensions 7 | { 8 | public static IEnumerable Concat(this IEnumerable source, T item) 9 | { 10 | foreach (var sourceItem in source) 11 | { 12 | yield return sourceItem; 13 | } 14 | yield return item; 15 | } 16 | public static IEnumerable Concat(this T source, IEnumerable items) 17 | { 18 | yield return source; 19 | foreach (var item in items) 20 | { 21 | yield return item; 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/ModularVNext/Infrastructure/CompositeFileProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Microsoft.AspNet.FileProviders; 5 | using Microsoft.Framework.Expiration.Interfaces; 6 | 7 | namespace ModularVNext.Infrastructure 8 | { 9 | public class CompositeFileProvider : IFileProvider 10 | { 11 | private List _fileProviders; 12 | 13 | public CompositeFileProvider(IEnumerable fileProviders) 14 | { 15 | _fileProviders = fileProviders.ToList(); 16 | } 17 | 18 | public IDirectoryContents GetDirectoryContents(string subpath) 19 | { 20 | foreach (var fileProvider in _fileProviders) 21 | { 22 | var contents = fileProvider.GetDirectoryContents(subpath); 23 | if (contents != null && contents.Exists) 24 | { 25 | return contents; 26 | } 27 | } 28 | return new NotFoundDirectoryContents(); 29 | } 30 | 31 | public IFileInfo GetFileInfo(string subpath) 32 | { 33 | foreach (var fileProvider in _fileProviders) 34 | { 35 | var fileInfo = fileProvider.GetFileInfo(subpath); 36 | if (fileInfo != null && fileInfo.Exists) 37 | { 38 | return fileInfo; 39 | } 40 | } 41 | return new NotFoundFileInfo(subpath); 42 | } 43 | 44 | public IExpirationTrigger Watch(string filter) 45 | { 46 | // TODO - need a composite expiration trigger! 47 | throw new NotImplementedException(); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /src/ModularVNext/Infrastructure/DirectoryLoader.cs: -------------------------------------------------------------------------------- 1 | // Copyright(c) Microsoft Open Technologies, Inc.All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use 4 | // these files except in compliance with the License.You may obtain a copy of the 5 | // License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software distributed 10 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 11 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 12 | // specific language governing permissions and limitations under the License. 13 | 14 | using System.IO; 15 | using System.Reflection; 16 | using Microsoft.Framework.Runtime; 17 | 18 | namespace ModularVNext.Infrastructure 19 | { 20 | // 21 | // This class is based on code from https://raw.githubusercontent.com/aspnet/Entropy/ 22 | // 23 | public class DirectoryLoader : IAssemblyLoader 24 | { 25 | private readonly IAssemblyLoadContext _context; 26 | private readonly string _path; 27 | 28 | public DirectoryLoader(string path, IAssemblyLoadContext context) 29 | { 30 | _path = path; 31 | _context = context; 32 | } 33 | 34 | public Assembly Load(string name) 35 | { 36 | return _context.LoadFile(Path.Combine(_path, name + ".dll")); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /src/ModularVNext/Infrastructure/ModuleAssemblyLocator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | 5 | namespace ModularVNext.Infrastructure 6 | { 7 | public class ModuleAssemblyLocator 8 | { 9 | public ModuleAssemblyLocator(IEnumerable moduleAssemblies) 10 | { 11 | ModuleAssemblies = moduleAssemblies; 12 | } 13 | 14 | public IEnumerable ModuleAssemblies { get; private set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/ModularVNext/Infrastructure/ModuleAwareAssemblyProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using Microsoft.AspNet.Mvc; 6 | using Microsoft.Framework.Runtime; 7 | using ModularVNext.Extensions; 8 | 9 | namespace ModularVNext.Infrastructure 10 | { 11 | /// 12 | /// Provides the module assemblies back to MVC to search for controllers 13 | /// 14 | public class ModuleAwareAssemblyProvider : IAssemblyProvider 15 | { 16 | private readonly DefaultAssemblyProvider _defaultProvider; 17 | 18 | // TODO - update this post beta3: http://www.strathweb.com/2015/04/asp-net-mvc-6-discovers-controllers/ 19 | private readonly IEnumerable _moduleAssemblies; 20 | 21 | public ModuleAwareAssemblyProvider(DefaultAssemblyProvider defaultProvider, 22 | ModuleAssemblyLocator moduleAssemblyProvider) 23 | { 24 | _defaultProvider = defaultProvider; 25 | _moduleAssemblies = moduleAssemblyProvider.ModuleAssemblies; 26 | } 27 | 28 | public IEnumerable CandidateAssemblies 29 | { 30 | get 31 | { 32 | return _defaultProvider.CandidateAssemblies.Concat(_moduleAssemblies); 33 | } 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /src/ModularVNext/Infrastructure/SafeEmbeddedFileProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using Microsoft.AspNet.FileProviders; 4 | using Microsoft.Framework.Expiration.Interfaces; 5 | 6 | namespace ModularVNext.Infrastructure 7 | { 8 | public class SafeEmbeddedFileProvider : IFileProvider 9 | { 10 | // unfortunately (as of beta3) the EmbeddedFileProvider throws an ArgumentException (from Assembly.GetManifestResourceInfo) when: 11 | // - baseNamespace is "" 12 | // - subpath is "" or "/" 13 | // This class works around that for now :-) 14 | 15 | private readonly string _baseNamespace; 16 | private readonly EmbeddedFileProvider _inner; 17 | 18 | public SafeEmbeddedFileProvider(Assembly assembly) 19 | { 20 | _baseNamespace = ""; 21 | _inner = new EmbeddedFileProvider(assembly); 22 | } 23 | public SafeEmbeddedFileProvider(Assembly assembly, string baseNamespace) 24 | { 25 | } 26 | 27 | public IFileInfo GetFileInfo(string subpath) 28 | { 29 | if(_baseNamespace == "" 30 | && (subpath=="" || subpath == "/")) 31 | { 32 | return new NotFoundFileInfo(subpath); 33 | } 34 | return _inner.GetFileInfo(subpath); 35 | } 36 | public IDirectoryContents GetDirectoryContents(string subpath) 37 | { 38 | return _inner.GetDirectoryContents(subpath); 39 | } 40 | public IExpirationTrigger Watch(string pattern) 41 | { 42 | return _inner.Watch(pattern); 43 | } 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/ModularVNext/ModularVNext.kproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 14.0 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | 9 | ef4e488c-46af-48e2-9797-da08d3a0d01c 10 | ModularVNext 11 | ..\..\artifacts\obj\$(MSBuildProjectName) 12 | ..\..\artifacts\bin\$(MSBuildProjectName)\ 13 | 14 | 15 | ModularVNext 16 | 17 | 18 | 2.0 19 | 56978 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/ModularVNext/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Reflection; 6 | using Microsoft.AspNet.Builder; 7 | using Microsoft.AspNet.Diagnostics; 8 | using Microsoft.AspNet.FileProviders; 9 | using Microsoft.AspNet.Hosting; 10 | using Microsoft.AspNet.Mvc; 11 | using Microsoft.AspNet.Mvc.Razor; 12 | using Microsoft.AspNet.StaticFiles; 13 | using Microsoft.Framework.ConfigurationModel; 14 | using Microsoft.Framework.DependencyInjection; 15 | using Microsoft.Framework.DependencyInjection.Fallback; 16 | using Microsoft.Framework.Logging; 17 | using Microsoft.Framework.Logging.Console; 18 | using Microsoft.Framework.Runtime; 19 | using ModularVNext.Extensions; 20 | using ModularVNext.Infrastructure; 21 | 22 | namespace ModularVNext 23 | { 24 | public class Startup 25 | { 26 | private IFileProvider _modulesFileProvider; 27 | private readonly string ApplicationBasePath; 28 | private readonly IAssemblyLoadContextAccessor _assemblyLoadContextAccessor; 29 | private readonly IAssemblyLoaderContainer _assemblyLoaderContainer; 30 | 31 | public Startup(IHostingEnvironment hostingEnvironment, 32 | IApplicationEnvironment applicationEnvironment, 33 | IAssemblyLoaderContainer assemblyLoaderContainer, 34 | IAssemblyLoadContextAccessor assemblyLoadContextAccessor) 35 | { 36 | _assemblyLoadContextAccessor = assemblyLoadContextAccessor; 37 | _assemblyLoaderContainer = assemblyLoaderContainer; 38 | ApplicationBasePath = applicationEnvironment.ApplicationBasePath; 39 | Configuration = new Configuration() 40 | .AddJsonFile("config.json") 41 | .AddEnvironmentVariables(); 42 | } 43 | 44 | public IConfiguration Configuration { get; set; } 45 | 46 | public void ConfigureServices(IServiceCollection services) 47 | { 48 | var basePaths = Configuration.Get("additionalFileProviderBasePaths")?.Split(';') ?? new string[] { }; 49 | var modulesPath = Path.Combine(ApplicationBasePath, Configuration.Get("moduleLoadPath")); 50 | 51 | var moduleAssemblies = LoadAssembliesFrom(modulesPath, _assemblyLoaderContainer, _assemblyLoadContextAccessor); 52 | 53 | _modulesFileProvider = GetModulesFileProvider(basePaths, moduleAssemblies); 54 | 55 | 56 | services.AddInstance(Configuration); 57 | 58 | services.AddMvc(); 59 | 60 | services.Configure(o => 61 | { 62 | o.FileProvider = _modulesFileProvider; 63 | }); 64 | 65 | services.AddInstance(new ModuleAssemblyLocator(moduleAssemblies)); 66 | services.AddTransient(); 67 | services.AddTransient(); 68 | } 69 | 70 | public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerfactory) 71 | { 72 | loggerfactory.AddConsole(); 73 | 74 | if (string.Equals(env.EnvironmentName, "Development", StringComparison.OrdinalIgnoreCase)) 75 | { 76 | app.UseBrowserLink(); 77 | app.UseErrorPage(ErrorPageOptions.ShowAll); 78 | } 79 | else 80 | { 81 | app.UseErrorHandler("/Home/Error"); 82 | } 83 | 84 | app.UseStaticFiles(new StaticFileOptions 85 | { 86 | FileProvider = _modulesFileProvider 87 | }); 88 | 89 | app.UseMvc(routes => 90 | { 91 | routes.MapRoute( 92 | name: "areaRoute", 93 | template: "{area:exists}/{controller}/{action}", 94 | defaults: new { controller = "Home", action = "Index" } 95 | ); 96 | routes.MapRoute( 97 | name: "default", 98 | template: "{controller}/{action}/{id?}", 99 | defaults: new { controller = "Home", action = "Index" }); 100 | }); 101 | } 102 | 103 | private List LoadAssembliesFrom(string modulesDirectory, 104 | IAssemblyLoaderContainer assemblyLoaderContainer, 105 | IAssemblyLoadContextAccessor loadContextAccessor) 106 | { 107 | var assemblies = new List(); 108 | var loadContext = _assemblyLoadContextAccessor.GetLoadContext(typeof(Startup).GetTypeInfo().Assembly); 109 | using (assemblyLoaderContainer.AddLoader(new DirectoryLoader(modulesDirectory, loadContext))) 110 | { 111 | foreach (var modulePath in Directory.EnumerateFiles(modulesDirectory, "*.dll")) 112 | { 113 | var name = Path.GetFileNameWithoutExtension(modulePath); 114 | assemblies.Add(loadContext.Load(name)); 115 | } 116 | } 117 | return assemblies; 118 | } 119 | private IFileProvider GetModulesFileProvider(string[] basePaths, List moduleAssemblies) 120 | { 121 | // TODO - probably want to set this to be debug only as it allows serving content outside the root directory 122 | var redirectedFileProviders = basePaths 123 | .Select(path => Path.IsPathRooted(path) ? path : Path.Combine(ApplicationBasePath, path)) 124 | .Select(root => new PhysicalFileProvider(root)); 125 | 126 | var resourceFileProviders = moduleAssemblies.Select(a => new SafeEmbeddedFileProvider(a)); 127 | 128 | IFileProvider rootProvider = new PhysicalFileProvider(ApplicationBasePath); 129 | return new CompositeFileProvider( 130 | rootProvider 131 | .Concat(redirectedFileProviders) 132 | .Concat(resourceFileProviders) 133 | ); 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/ModularVNext/Views/Home/About.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "About"; 3 | } 4 |

@ViewBag.Title.

5 |

@ViewBag.Message

6 | 7 |

Use this area to provide additional information.

-------------------------------------------------------------------------------- /src/ModularVNext/Views/Home/Contact.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Contact"; 3 | } 4 |

@ViewBag.Title.

5 |

@ViewBag.Message

6 | 7 |
8 | One Microsoft Way
9 | Redmond, WA 98052-6399
10 | P: 11 | 425.555.0100 12 |
13 | 14 |
15 | Support: Support@example.com
16 | Marketing: Marketing@example.com 17 |
-------------------------------------------------------------------------------- /src/ModularVNext/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Home Page"; 3 | } 4 | 5 |
6 |

This is the home page!

7 | This page is rendered from Views/Home/Index.cshtml in the main web app project 8 |
9 |
10 | Try the @Html.ActionLink("Module1", "Index", "Module1") controller. 11 |
12 |
13 | Try the @Html.ActionLink("Module2", "Index", "Weather", new { area = "Module2" }, null) controller. 14 |
15 |
16 | Depending on the configuration, the Module1 content is either rendered from disk (which is great for development time work), or from 17 | an embedded resource (which could work well for deployed modules). See the readme.md in the solution. 18 |
-------------------------------------------------------------------------------- /src/ModularVNext/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Error"; 3 | } 4 | 5 |

Error.

6 |

An error occurred while processing your request.

-------------------------------------------------------------------------------- /src/ModularVNext/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | @ViewBag.Title - My ASP.NET Application 7 | 8 | 9 | 10 | 11 | @RenderSection("head", required:false) 12 | 13 | 14 | 33 |
34 | @RenderBody() 35 |
36 |
37 |

© @DateTime.Now.Year - My ASP.NET Application

38 |
39 |
40 | 41 | 42 | 43 | 44 | @RenderSection("scripts", required: false) 45 | 46 | -------------------------------------------------------------------------------- /src/ModularVNext/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @using ModularVNext; 2 | @{ 3 | Layout = "/Views/Shared/_Layout.cshtml"; 4 | } 5 | -------------------------------------------------------------------------------- /src/ModularVNext/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "WebApplication", 3 | "private": true, 4 | "dependencies": { 5 | "bootstrap": "3.0.0", 6 | "jquery": "1.10.2", 7 | "jquery-validation": "1.11.1", 8 | "jquery-validation-unobtrusive": "3.2.2", 9 | "hammer.js": "2.0.4", 10 | "bootstrap-touch-carousel": "0.8.0" 11 | }, 12 | "exportsOverride": { 13 | "bootstrap": { 14 | "js": "dist/js/*.*", 15 | "css": "dist/css/*.*", 16 | "fonts": "dist/fonts/*.*" 17 | }, 18 | "bootstrap-touch-carousel": { 19 | "js": "dist/js/*.*", 20 | "css": "dist/css/*.*" 21 | }, 22 | "jquery": { 23 | "": "jquery.{js,min.js,min.map}" 24 | }, 25 | "jquery-validation": { 26 | "": "jquery.validate.js" 27 | }, 28 | "jquery-validation-unobtrusive": { 29 | "": "jquery.validate.unobtrusive.{js,min.js}" 30 | }, 31 | "hammer": { 32 | "": "hammer.{js,min.js}" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/ModularVNext/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "additionalFileProviderBasePaths": "..\\Module1;..\\Module2", 3 | "moduleLoadPath" : "artifacts\\bin\\modules" 4 | } -------------------------------------------------------------------------------- /src/ModularVNext/gruntfile.js: -------------------------------------------------------------------------------- 1 | /// 2 | // This file in the main entry point for defining grunt tasks and using grunt plugins. 3 | // Click here to learn more. http://go.microsoft.com/fwlink/?LinkID=513275&clcid=0x409 4 | 5 | module.exports = function (grunt) { 6 | grunt.initConfig({ 7 | bower: { 8 | install: { 9 | options: { 10 | targetDir: "wwwroot/lib", 11 | layout: "byComponent", 12 | cleanTargetDir: false 13 | } 14 | } 15 | }, 16 | copy: { 17 | module1: { 18 | expand: true, 19 | cwd: "../../artifacts/bin/Module1/Debug/aspnet50/", 20 | src: ["Module1.dll"], 21 | dest: "./artifacts/bin/modules/" 22 | }, 23 | module2: { 24 | expand: true, 25 | cwd: "../../artifacts/bin/Module2/Debug/aspnet50/", 26 | src: ["Module2.dll"], 27 | dest: "./artifacts/bin/modules/" 28 | } 29 | } 30 | }); 31 | 32 | // This command registers the default task which will install bower packages into wwwroot/lib 33 | grunt.registerTask("default", ["bower:install"]); 34 | 35 | // The following line loads the grunt plugins. 36 | // This line needs to be at the end of this this file. 37 | grunt.loadNpmTasks("grunt-bower-task"); 38 | grunt.loadNpmTasks("grunt-contrib-copy"); 39 | }; -------------------------------------------------------------------------------- /src/ModularVNext/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.0.0", 3 | "name": "", 4 | "devDependencies": { 5 | "grunt": "0.4.5", 6 | "grunt-bower-task": "0.4.0", 7 | "grunt-contrib-copy": "0.8.0" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/ModularVNext/project.json: -------------------------------------------------------------------------------- 1 | { 2 | /* Click to learn more about project.json http://go.microsoft.com/fwlink/?LinkID=517074 */ 3 | "webroot": "wwwroot", 4 | "version": "1.0.0-*", 5 | "dependencies": { 6 | "Microsoft.AspNet.Mvc": "6.0.0-beta3", 7 | "Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-beta3", 8 | "Microsoft.AspNet.Diagnostics": "1.0.0-beta3", 9 | "Microsoft.AspNet.Server.IIS": "1.0.0-beta3", 10 | "Microsoft.AspNet.Server.WebListener": "1.0.0-beta3", 11 | "Microsoft.AspNet.StaticFiles": "1.0.0-beta3", 12 | "Microsoft.Framework.ConfigurationModel.Json": "1.0.0-beta3", 13 | "Microsoft.Framework.CodeGenerators.Mvc": "1.0.0-beta3", 14 | "Microsoft.Framework.Logging": "1.0.0-beta3", 15 | "Microsoft.Framework.Logging.Console": "1.0.0-beta3", 16 | "Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0-beta3", 17 | "Microsoft.Framework.Runtime.Interfaces": "1.0.0-beta3" 18 | //,"Module1": "" 19 | //,"Module2": "" 20 | }, 21 | "commands": { 22 | /* Change the port number when you are self hosting this application */ 23 | "web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5000", 24 | "gen": "Microsoft.Framework.CodeGeneration", 25 | "ef": "EntityFramework.Commands" 26 | }, 27 | "frameworks": { 28 | "aspnet50": { }, 29 | "aspnetcore50": {} 30 | }, 31 | "exclude": [ 32 | "wwwroot", 33 | "node_modules", 34 | "bower_components" 35 | ], 36 | "bundleExclude": [ 37 | "node_modules", 38 | "bower_components", 39 | "**.kproj", 40 | "**.user", 41 | "**.vspscc" 42 | ], 43 | "scripts": { 44 | "postrestore": [ "npm install" ], 45 | "prepare": [ "grunt bower:install" ] 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/ModularVNext/wwwroot/_references.js: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | /// 5 | /// 6 | /// 7 | /// 8 | /// 9 | -------------------------------------------------------------------------------- /src/ModularVNext/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 50px; 3 | padding-bottom: 20px; 4 | } 5 | 6 | 7 | /* Wrapping element */ 8 | /* Set some basic padding to keep content from hitting the edges */ 9 | .body-content { 10 | padding-left: 15px; 11 | padding-right: 15px; 12 | } 13 | 14 | /* Set widths on the form inputs since otherwise they're 100% wide */ 15 | input, 16 | select, 17 | textarea { 18 | max-width: 280px; 19 | } 20 | 21 | 22 | /* CAROUSEL 23 | -------------------------------------------------- */ 24 | 25 | .carousel-caption { 26 | z-index: 10 !important; 27 | } 28 | 29 | .carousel-caption p { 30 | font-size: 20px; 31 | line-height: 1.4; 32 | } 33 | 34 | @media (min-width: 768px) { 35 | 36 | .carousel-caption { 37 | z-index: 10 !important; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/ModularVNext/wwwroot/images/ASP-NET-Banners-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stuartleeks/ModularVNext/effd3731e827faf5c8f4e44aa1bb7eeb758970f0/src/ModularVNext/wwwroot/images/ASP-NET-Banners-01.png -------------------------------------------------------------------------------- /src/ModularVNext/wwwroot/images/ASP-NET-Banners-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stuartleeks/ModularVNext/effd3731e827faf5c8f4e44aa1bb7eeb758970f0/src/ModularVNext/wwwroot/images/ASP-NET-Banners-02.png -------------------------------------------------------------------------------- /src/ModularVNext/wwwroot/images/Banner-01-Azure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stuartleeks/ModularVNext/effd3731e827faf5c8f4e44aa1bb7eeb758970f0/src/ModularVNext/wwwroot/images/Banner-01-Azure.png -------------------------------------------------------------------------------- /src/ModularVNext/wwwroot/images/Banner-02-VS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stuartleeks/ModularVNext/effd3731e827faf5c8f4e44aa1bb7eeb758970f0/src/ModularVNext/wwwroot/images/Banner-02-VS.png -------------------------------------------------------------------------------- /src/ModularVNext/wwwroot/lib/bootstrap-touch-carousel/css/bootstrap-touch-carousel.css: -------------------------------------------------------------------------------- 1 | /* bootstrap-touch-carousel v0.7.1, (c) 2014 (ixisio) Andreas Klein */ 2 | .touch-carousel{position:relative;overflow:hidden;width:100%;-webkit-transform:translate3d(0,0,0) scale3d(1,1,1);-webkit-backface-visibility:hidden;-webkit-transform-style:preserve-3d;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.touch-carousel .carousel-control{display:none!important}.touch-carousel .carousel-indicators{bottom:10px}.touch-carousel .carousel-indicators li{width:16px;height:16px;margin:1px 5px}.touch-carousel .carousel-indicators li.active{margin:0 5px;width:18px;height:18px}.touch-carousel .carousel-inner{overflow:hidden;-webkit-transform:translate3d(0%,0,0) scale3d(1,1,1);-moz-transform:translate3d(0%,0,0) scale3d(1,1,1);-ms-transform:translate3d(0%,0,0) scale3d(1,1,1);transform:translate3d(0%,0,0) scale3d(1,1,1);-webkit-backface-visibility:hidden;-webkit-transform-style:preserve-3d;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.touch-carousel .carousel-inner>.item{position:relative;float:left;display:block;-webkit-transition:none;-moz-transition:none;transition:none;-webkit-backface-visibility:hidden;-webkit-transform-style:preserve-3d}.touch-carousel .carousel-inner>.item *{-webkit-transition:none;-moz-transition:none;transition:none}.touch-carousel .carousel-inner.animate{-webkit-transition:all .3s linear;-moz-transition:all .3s linear;transition:all .3s linear}@media screen and (max-width:767px){.carousel-caption{display:none}} -------------------------------------------------------------------------------- /src/ModularVNext/wwwroot/lib/bootstrap-touch-carousel/js/bootstrap-touch-carousel.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * bootstrap-touch-carousel v0.7.1 3 | * https://github.com/ixisio/bootstrap-touch-carousel.git 4 | * 5 | * Copyright (c) 2014 (ixisio) Andreas Klein 6 | * Licensed under the MIT license 7 | * 8 | * 9 | * Including Hammer.js@1.0.6dev, http://eightmedia.github.com/hammer.js 10 | */ 11 | +function(a){"use strict";function b(a,b){var c=document.createElement("div").style;for(var d in a)if(void 0!==c[a[d]])return"pfx"==b?a[d]:!0;return!1}function c(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]}}function d(){var a=["transformProperty","WebkitTransform","MozTransform","msTransform"];return!!b(a)}function e(){return"WebKitCSSMatrix"in window&&"m11"in new WebKitCSSMatrix}if(!("ontouchstart"in window||navigator.msMaxTouchPoints))return!1;a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=c(),a.support.csstransforms=d(),a.support.csstransforms3d=e()});var f="touch-carousel",g=function(b,c){return this.$element=a(b),this.$itemsWrapper=this.$element.find(".carousel-inner"),this.$items=this.$element.find(".item"),this.$indicators=this.$element.find(".carousel-indicators"),this.pane_width=this.pane_count=this.current_pane=0,this.onGesture=!1,this.options=c,this._setPaneDimensions(),this.$items.length<=1?this.disable():(this._regTouchGestures(),a(window).on("orientationchange resize",a.proxy(this._setPaneDimensions,this)),void 0)};g.DEFAULTS={interval:!1,toughness:.25},g.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},g.prototype.to=function(a){return a>this.$items.length-1||0>a?void 0:this._showPane(a)},g.prototype.pause=function(a){return a||(this.paused=!0),clearInterval(this.interval),this.interval=null,this},g.prototype._regTouchGestures=function(){this.$itemsWrapper.add(this.$indicators).hammer({drag_lock_to_axis:!0}).on("release dragleft dragright swipeleft swiperight",a.proxy(this._handleGestures,this))},g.prototype._setPaneDimensions=function(){this.pane_width=this.$element.width(),this.pane_count=this.$items.length,this.$itemsWrapper.width(this.pane_width*this.pane_count),this.$items.width(this.pane_width)},g.prototype._showPane=function(a){this.$items.eq(this.current_pane).toggleClass("active"),a>=this.pane_count&&this.pause(),a=Math.max(0,Math.min(a,this.pane_count-1)),this.$items.eq(a).toggleClass("active"),this.current_pane=a;var b=-(100/this.pane_count*this.current_pane);return this._setContainerOffset(b,!0,a),this},g.prototype._setContainerOffset=function(b,c,d){var e=this;if(this.$itemsWrapper.removeClass("animate"),c&&this.$itemsWrapper.addClass("animate"),a.support.csstransforms3d)this.onGesture=!0,this.$itemsWrapper.css("transform","translate3d("+b+"%,0,0) scale3d(1,1,1)");else if(a.support.csstransforms)this.onGesture=!0,this.$itemsWrapper.css("transform","translate("+b+"%,0)");else{var f=this.pane_width*this.pane_count/100*b;this.$itemsWrapper.css("left",f+"px")}a.support.transition?this.$itemsWrapper.one(a.support.transition.end,function(){e.$itemsWrapper.removeClass("animate"),e.onGesture=!1,e._updateIndicators(d)}):(this.$itemsWrapper.removeClass("animate"),this.onGesture=!1,this._updateIndicators(d))},g.prototype.next=function(){return this._showPane(this.current_pane+1)},g.prototype.prev=function(){return this._showPane(this.current_pane-1)},g.prototype._handleGestures=function(a){if(a.gesture.preventDefault(),!this.sliding)switch(this.pause(),a.type){case"dragright":case"dragleft":var b=-(100/this.pane_count)*this.current_pane,c=100/this.pane_width*a.gesture.deltaX/this.pane_count;(0===this.current_pane&&a.gesture.direction==Hammer.DIRECTION_RIGHT||this.current_pane==this.pane_count-1&&a.gesture.direction==Hammer.DIRECTION_LEFT)&&(c*=this.options.toughness),this._setContainerOffset(c+b);break;case"swipeleft":this.next(),a.gesture.stopDetect();break;case"swiperight":this.prev(),a.gesture.stopDetect();break;case"release":Math.abs(a.gesture.deltaX)>this.pane_width/2?"right"==a.gesture.direction?this.prev():this.next():this._showPane(this.current_pane,!0)}},g.prototype.disable=function(){return this.$indicators.hide(),this.$element.removeData(f),!1},g.prototype._updateIndicators=function(a){return this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$indicators.children().eq(a).addClass("active")),this};var h=a.fn.carousel;a.fn.carousel=function(b){return this.each(function(){var c=a(this),d=c.data(f),e=a.extend({},g.DEFAULTS,c.data(),"object"==typeof b&&b),h="string"==typeof b?b:e.slide;d||c.data(f,d=new g(this,e)).addClass(f),"number"==typeof b?d.to(b):h?d[h]():e.interval&&d.pause().cycle()})},a.fn.carousel.Constructor=g,a.fn.carousel.noConflict=function(){return a.fn.carousel=h,this},a(document).off("click.bs.carousel").on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),g=a.extend({},e.data(),d.data()),h=d.attr("data-slide-to");h&&(g.interval=!1),e.carousel(g),(h=d.attr("data-slide-to"))&&e.data(f).to(h),b.preventDefault()})}(window.jQuery),function(a,b){"use strict";function c(){if(!d.READY){d.event.determineEventTypes();for(var a in d.gestures)d.gestures.hasOwnProperty(a)&&d.detection.register(d.gestures[a]);d.event.onTouch(d.DOCUMENT,d.EVENT_MOVE,d.detection.detect),d.event.onTouch(d.DOCUMENT,d.EVENT_END,d.detection.detect),d.READY=!0}}var d=function(a,b){return new d.Instance(a,b||{})};d.defaults={stop_browser_behavior:{userSelect:"none",touchAction:"none",touchCallout:"none",contentZooming:"none",userDrag:"none",tapHighlightColor:"rgba(0,0,0,0)"}},d.HAS_POINTEREVENTS=a.navigator.pointerEnabled||a.navigator.msPointerEnabled,d.HAS_TOUCHEVENTS="ontouchstart"in a,d.MOBILE_REGEX=/mobile|tablet|ip(ad|hone|od)|android|silk/i,d.NO_MOUSEEVENTS=d.HAS_TOUCHEVENTS&&a.navigator.userAgent.match(d.MOBILE_REGEX),d.EVENT_TYPES={},d.DIRECTION_DOWN="down",d.DIRECTION_LEFT="left",d.DIRECTION_UP="up",d.DIRECTION_RIGHT="right",d.POINTER_MOUSE="mouse",d.POINTER_TOUCH="touch",d.POINTER_PEN="pen",d.EVENT_START="start",d.EVENT_MOVE="move",d.EVENT_END="end",d.DOCUMENT=a.document,d.plugins={},d.READY=!1,d.Instance=function(a,b){var e=this;return c(),this.element=a,this.enabled=!0,this.options=d.utils.extend(d.utils.extend({},d.defaults),b||{}),this.options.stop_browser_behavior&&d.utils.stopDefaultBrowserBehavior(this.element,this.options.stop_browser_behavior),d.event.onTouch(a,d.EVENT_START,function(a){e.enabled&&d.detection.startDetect(e,a)}),this},d.Instance.prototype={on:function(a,b){for(var c=a.split(" "),d=0;d0&&b==d.EVENT_END?b=d.EVENT_MOVE:k||(b=d.EVENT_END),(k||null===e)&&(e=i),c.call(d.detection,h.collectEventData(a,b,h.getTouchList(e,b),i)),d.HAS_POINTEREVENTS&&b==d.EVENT_END&&(k=d.PointerEvent.updatePointer(b,i))),k||(e=null,f=!1,g=!1,d.PointerEvent.reset())}})},determineEventTypes:function(){var a;a=d.HAS_POINTEREVENTS?d.PointerEvent.getEvents():d.NO_MOUSEEVENTS?["touchstart","touchmove","touchend touchcancel"]:["touchstart mousedown","touchmove mousemove","touchend touchcancel mouseup"],d.EVENT_TYPES[d.EVENT_START]=a[0],d.EVENT_TYPES[d.EVENT_MOVE]=a[1],d.EVENT_TYPES[d.EVENT_END]=a[2]},getTouchList:function(a){return d.HAS_POINTEREVENTS?d.PointerEvent.getTouchList():a.touches?a.touches:(a.indentifier=1,[a])},collectEventData:function(a,b,c,e){var f=d.POINTER_TOUCH;return(e.type.match(/mouse/)||d.PointerEvent.matchType(d.POINTER_MOUSE,e))&&(f=d.POINTER_MOUSE),{center:d.utils.getCenter(c),timeStamp:(new Date).getTime(),target:e.target,touches:c,eventType:b,pointerType:f,srcEvent:e,preventDefault:function(){this.srcEvent.preventManipulation&&this.srcEvent.preventManipulation(),this.srcEvent.preventDefault&&this.srcEvent.preventDefault()},stopPropagation:function(){this.srcEvent.stopPropagation()},stopDetect:function(){return d.detection.stopDetect()}}}},d.PointerEvent={pointers:{},getTouchList:function(){var a=this,b=[];return Object.keys(a.pointers).sort().forEach(function(c){b.push(a.pointers[c])}),b},updatePointer:function(a,b){return a==d.EVENT_END?this.pointers={}:(b.identifier=b.pointerId,this.pointers[b.pointerId]=b),Object.keys(this.pointers).length},matchType:function(a,b){if(!b.pointerType)return!1;var c={};return c[d.POINTER_MOUSE]=b.pointerType==b.MSPOINTER_TYPE_MOUSE||b.pointerType==d.POINTER_MOUSE,c[d.POINTER_TOUCH]=b.pointerType==b.MSPOINTER_TYPE_TOUCH||b.pointerType==d.POINTER_TOUCH,c[d.POINTER_PEN]=b.pointerType==b.MSPOINTER_TYPE_PEN||b.pointerType==d.POINTER_PEN,c[a]},getEvents:function(){return["pointerdown MSPointerDown","pointermove MSPointerMove","pointerup pointercancel MSPointerUp MSPointerCancel"]},reset:function(){this.pointers={}}},d.utils={extend:function(a,c,d){for(var e in c)a[e]!==b&&d||(a[e]=c[e]);return a},hasParent:function(a,b){for(;a;){if(a==b)return!0;a=a.parentNode}return!1},getCenter:function(a){for(var b=[],c=[],d=0,e=a.length;e>d;d++)b.push(a[d].pageX),c.push(a[d].pageY);return{pageX:(Math.min.apply(Math,b)+Math.max.apply(Math,b))/2,pageY:(Math.min.apply(Math,c)+Math.max.apply(Math,c))/2}},getVelocity:function(a,b,c){return{x:Math.abs(b/a)||0,y:Math.abs(c/a)||0}},getAngle:function(a,b){var c=b.pageY-a.pageY,d=b.pageX-a.pageX;return 180*Math.atan2(c,d)/Math.PI},getDirection:function(a,b){var c=Math.abs(a.pageX-b.pageX),e=Math.abs(a.pageY-b.pageY);return c>=e?a.pageX-b.pageX>0?d.DIRECTION_LEFT:d.DIRECTION_RIGHT:a.pageY-b.pageY>0?d.DIRECTION_UP:d.DIRECTION_DOWN},getDistance:function(a,b){var c=b.pageX-a.pageX,d=b.pageY-a.pageY;return Math.sqrt(c*c+d*d)},getScale:function(a,b){return a.length>=2&&b.length>=2?this.getDistance(b[0],b[1])/this.getDistance(a[0],a[1]):1},getRotation:function(a,b){return a.length>=2&&b.length>=2?this.getAngle(b[1],b[0])-this.getAngle(a[1],a[0]):0},isVertical:function(a){return a==d.DIRECTION_UP||a==d.DIRECTION_DOWN},stopDefaultBrowserBehavior:function(a,b){var c,d=["webkit","khtml","moz","Moz","ms","o",""];if(b&&a.style){for(var e=0;ec;c++){var f=this.gestures[c];if(!this.stopped&&b[f.name]!==!1&&f.handler.call(f,a,this.current.inst)===!1){this.stopDetect();break}}return this.current&&(this.current.lastEvent=a),a.eventType==d.EVENT_END&&!a.touches.length-1&&this.stopDetect(),a}},stopDetect:function(){this.previous=d.utils.extend({},this.current),this.current=null,this.stopped=!0},extendEventData:function(a){var b=this.current.startEvent;if(b&&(a.touches.length!=b.touches.length||a.touches===b.touches)){b.touches=[];for(var c=0,e=a.touches.length;e>c;c++)b.touches.push(d.utils.extend({},a.touches[c]))}var f=a.timeStamp-b.timeStamp,g=a.center.pageX-b.center.pageX,h=a.center.pageY-b.center.pageY,i=d.utils.getVelocity(f,g,h);return d.utils.extend(a,{deltaTime:f,deltaX:g,deltaY:h,velocityX:i.x,velocityY:i.y,distance:d.utils.getDistance(b.center,a.center),angle:d.utils.getAngle(b.center,a.center),interimAngle:this.current.lastEvent&&d.utils.getAngle(this.current.lastEvent.center,a.center),direction:d.utils.getDirection(b.center,a.center),interimDirection:this.current.lastEvent&&d.utils.getDirection(this.current.lastEvent.center,a.center),scale:d.utils.getScale(b.touches,a.touches),rotation:d.utils.getRotation(b.touches,a.touches),startEvent:b}),a},register:function(a){var c=a.defaults||{};return c[a.name]===b&&(c[a.name]=!0),d.utils.extend(d.defaults,c,!0),a.index=a.index||1e3,this.gestures.push(a),this.gestures.sort(function(a,b){return a.indexb.index?1:0}),this.gestures}},d.gestures=d.gestures||{},d.gestures.Hold={name:"hold",index:10,defaults:{hold_timeout:500,hold_threshold:1},timer:null,handler:function(a,b){switch(a.eventType){case d.EVENT_START:clearTimeout(this.timer),d.detection.current.name=this.name,this.timer=setTimeout(function(){"hold"==d.detection.current.name&&b.trigger("hold",a)},b.options.hold_timeout);break;case d.EVENT_MOVE:a.distance>b.options.hold_threshold&&clearTimeout(this.timer);break;case d.EVENT_END:clearTimeout(this.timer)}}},d.gestures.Tap={name:"tap",index:100,defaults:{tap_max_touchtime:250,tap_max_distance:10,tap_always:!0,doubletap_distance:20,doubletap_interval:300},handler:function(a,b){if(a.eventType==d.EVENT_END&&"touchcancel"!=a.srcEvent.type){var c=d.detection.previous,e=!1;if(a.deltaTime>b.options.tap_max_touchtime||a.distance>b.options.tap_max_distance)return;c&&"tap"==c.name&&a.timeStamp-c.lastEvent.timeStamp0&&a.touches.length>b.options.swipe_max_touches)return;(a.velocityX>b.options.swipe_velocity||a.velocityY>b.options.swipe_velocity)&&(b.trigger(this.name,a),b.trigger(this.name+a.direction,a))}}},d.gestures.Drag={name:"drag",index:50,defaults:{drag_min_distance:10,correct_for_drag_min_distance:!0,drag_max_touches:1,drag_block_horizontal:!1,drag_block_vertical:!1,drag_lock_to_axis:!1,drag_lock_min_distance:25},triggered:!1,handler:function(a,b){if(d.detection.current.name!=this.name&&this.triggered)return b.trigger(this.name+"end",a),this.triggered=!1,void 0;if(!(b.options.drag_max_touches>0&&a.touches.length>b.options.drag_max_touches))switch(a.eventType){case d.EVENT_START:this.triggered=!1;break;case d.EVENT_MOVE:if(a.distanceb.options.transform_min_rotation&&b.trigger("rotate",a),c>b.options.transform_min_scale&&(b.trigger("pinch",a),b.trigger("pinch"+(a.scale<1?"in":"out"),a));break;case d.EVENT_END:this.triggered&&b.trigger(this.name+"end",a),this.triggered=!1}}},d.gestures.Touch={name:"touch",index:-1/0,defaults:{prevent_default:!1,prevent_mouseevents:!1},handler:function(a,b){return b.options.prevent_mouseevents&&a.pointerType==d.POINTER_MOUSE?(a.stopDetect(),void 0):(b.options.prevent_default&&a.preventDefault(),a.eventType==d.EVENT_START&&b.trigger(this.name,a),void 0)}},d.gestures.Release={name:"release",index:1/0,handler:function(a,b){a.eventType==d.EVENT_END&&b.trigger(this.name,a)}},"function"==typeof define&&"object"==typeof define.amd&&define.amd?define(function(){return d}):"object"==typeof module&&"object"==typeof module.exports?module.exports=d:a.Hammer=d}(this),function(a){"use strict";var b=function(b,c){return c===a?b:(b.event.bindDom=function(b,d,e){c(b).on(d,function(b){var c=b.originalEvent||b;c.pageX===a&&(c.pageX=b.pageX,c.pageY=b.pageY),c.target||(c.target=b.target),c.which===a&&(c.which=c.button),c.preventDefault||(c.preventDefault=b.preventDefault),c.stopPropagation||(c.stopPropagation=b.stopPropagation),e.call(this,c)})},b.Instance.prototype.on=function(a,b){return c(this.element).on(a,b)},b.Instance.prototype.off=function(a,b){return c(this.element).off(a,b)},b.Instance.prototype.trigger=function(a,b){var d=c(this.element);return d.has(b.target).length&&(d=c(b.target)),d.trigger({type:a,gesture:b})},c.fn.hammer=function(a){return this.each(function(){var d=c(this),e=d.data("hammer");e?e&&a&&b.utils.extend(e.options,a):d.data("hammer",new b(this,a||{}))})},b)};"function"==typeof define&&"object"==typeof define.amd&&define.amd?define("hammer-jquery",["hammer","jquery"],b):b(window.Hammer,window.jQuery||window.Zepto)}(); -------------------------------------------------------------------------------- /src/ModularVNext/wwwroot/lib/bootstrap/css/bootstrap-theme.css: -------------------------------------------------------------------------------- 1 | .btn-default, 2 | .btn-primary, 3 | .btn-success, 4 | .btn-info, 5 | .btn-warning, 6 | .btn-danger { 7 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); 8 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075); 9 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075); 10 | } 11 | 12 | .btn-default:active, 13 | .btn-primary:active, 14 | .btn-success:active, 15 | .btn-info:active, 16 | .btn-warning:active, 17 | .btn-danger:active, 18 | .btn-default.active, 19 | .btn-primary.active, 20 | .btn-success.active, 21 | .btn-info.active, 22 | .btn-warning.active, 23 | .btn-danger.active { 24 | -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); 25 | box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); 26 | } 27 | 28 | .btn:active, 29 | .btn.active { 30 | background-image: none; 31 | } 32 | 33 | .btn-default { 34 | text-shadow: 0 1px 0 #fff; 35 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ffffff), to(#e6e6e6)); 36 | background-image: -webkit-linear-gradient(top, #ffffff, 0%, #e6e6e6, 100%); 37 | background-image: -moz-linear-gradient(top, #ffffff 0%, #e6e6e6 100%); 38 | background-image: linear-gradient(to bottom, #ffffff 0%, #e6e6e6 100%); 39 | background-repeat: repeat-x; 40 | border-color: #e0e0e0; 41 | border-color: #ccc; 42 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0); 43 | } 44 | 45 | .btn-default:active, 46 | .btn-default.active { 47 | background-color: #e6e6e6; 48 | border-color: #e0e0e0; 49 | } 50 | 51 | .btn-primary { 52 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3071a9)); 53 | background-image: -webkit-linear-gradient(top, #428bca, 0%, #3071a9, 100%); 54 | background-image: -moz-linear-gradient(top, #428bca 0%, #3071a9 100%); 55 | background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); 56 | background-repeat: repeat-x; 57 | border-color: #2d6ca2; 58 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); 59 | } 60 | 61 | .btn-primary:active, 62 | .btn-primary.active { 63 | background-color: #3071a9; 64 | border-color: #2d6ca2; 65 | } 66 | 67 | .btn-success { 68 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5cb85c), to(#449d44)); 69 | background-image: -webkit-linear-gradient(top, #5cb85c, 0%, #449d44, 100%); 70 | background-image: -moz-linear-gradient(top, #5cb85c 0%, #449d44 100%); 71 | background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); 72 | background-repeat: repeat-x; 73 | border-color: #419641; 74 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); 75 | } 76 | 77 | .btn-success:active, 78 | .btn-success.active { 79 | background-color: #449d44; 80 | border-color: #419641; 81 | } 82 | 83 | .btn-warning { 84 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f0ad4e), to(#ec971f)); 85 | background-image: -webkit-linear-gradient(top, #f0ad4e, 0%, #ec971f, 100%); 86 | background-image: -moz-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); 87 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); 88 | background-repeat: repeat-x; 89 | border-color: #eb9316; 90 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); 91 | } 92 | 93 | .btn-warning:active, 94 | .btn-warning.active { 95 | background-color: #ec971f; 96 | border-color: #eb9316; 97 | } 98 | 99 | .btn-danger { 100 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9534f), to(#c9302c)); 101 | background-image: -webkit-linear-gradient(top, #d9534f, 0%, #c9302c, 100%); 102 | background-image: -moz-linear-gradient(top, #d9534f 0%, #c9302c 100%); 103 | background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); 104 | background-repeat: repeat-x; 105 | border-color: #c12e2a; 106 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); 107 | } 108 | 109 | .btn-danger:active, 110 | .btn-danger.active { 111 | background-color: #c9302c; 112 | border-color: #c12e2a; 113 | } 114 | 115 | .btn-info { 116 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5bc0de), to(#31b0d5)); 117 | background-image: -webkit-linear-gradient(top, #5bc0de, 0%, #31b0d5, 100%); 118 | background-image: -moz-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); 119 | background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); 120 | background-repeat: repeat-x; 121 | border-color: #2aabd2; 122 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); 123 | } 124 | 125 | .btn-info:active, 126 | .btn-info.active { 127 | background-color: #31b0d5; 128 | border-color: #2aabd2; 129 | } 130 | 131 | .thumbnail, 132 | .img-thumbnail { 133 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); 134 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); 135 | } 136 | 137 | .dropdown-menu > li > a:hover, 138 | .dropdown-menu > li > a:focus, 139 | .dropdown-menu > .active > a, 140 | .dropdown-menu > .active > a:hover, 141 | .dropdown-menu > .active > a:focus { 142 | background-color: #357ebd; 143 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd)); 144 | background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%); 145 | background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%); 146 | background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); 147 | background-repeat: repeat-x; 148 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); 149 | } 150 | 151 | .navbar { 152 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ffffff), to(#f8f8f8)); 153 | background-image: -webkit-linear-gradient(top, #ffffff, 0%, #f8f8f8, 100%); 154 | background-image: -moz-linear-gradient(top, #ffffff 0%, #f8f8f8 100%); 155 | background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%); 156 | background-repeat: repeat-x; 157 | border-radius: 4px; 158 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); 159 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075); 160 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075); 161 | } 162 | 163 | .navbar .navbar-nav > .active > a { 164 | background-color: #f8f8f8; 165 | } 166 | 167 | .navbar-brand, 168 | .navbar-nav > li > a { 169 | text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25); 170 | } 171 | 172 | .navbar-inverse { 173 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#3c3c3c), to(#222222)); 174 | background-image: -webkit-linear-gradient(top, #3c3c3c, 0%, #222222, 100%); 175 | background-image: -moz-linear-gradient(top, #3c3c3c 0%, #222222 100%); 176 | background-image: linear-gradient(to bottom, #3c3c3c 0%, #222222 100%); 177 | background-repeat: repeat-x; 178 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); 179 | } 180 | 181 | .navbar-inverse .navbar-nav > .active > a { 182 | background-color: #222222; 183 | } 184 | 185 | .navbar-inverse .navbar-brand, 186 | .navbar-inverse .navbar-nav > li > a { 187 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); 188 | } 189 | 190 | .navbar-static-top, 191 | .navbar-fixed-top, 192 | .navbar-fixed-bottom { 193 | border-radius: 0; 194 | } 195 | 196 | .alert { 197 | text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2); 198 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); 199 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); 200 | } 201 | 202 | .alert-success { 203 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#dff0d8), to(#c8e5bc)); 204 | background-image: -webkit-linear-gradient(top, #dff0d8, 0%, #c8e5bc, 100%); 205 | background-image: -moz-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); 206 | background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); 207 | background-repeat: repeat-x; 208 | border-color: #b2dba1; 209 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); 210 | } 211 | 212 | .alert-info { 213 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9edf7), to(#b9def0)); 214 | background-image: -webkit-linear-gradient(top, #d9edf7, 0%, #b9def0, 100%); 215 | background-image: -moz-linear-gradient(top, #d9edf7 0%, #b9def0 100%); 216 | background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); 217 | background-repeat: repeat-x; 218 | border-color: #9acfea; 219 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); 220 | } 221 | 222 | .alert-warning { 223 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#fcf8e3), to(#f8efc0)); 224 | background-image: -webkit-linear-gradient(top, #fcf8e3, 0%, #f8efc0, 100%); 225 | background-image: -moz-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); 226 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); 227 | background-repeat: repeat-x; 228 | border-color: #f5e79e; 229 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); 230 | } 231 | 232 | .alert-danger { 233 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f2dede), to(#e7c3c3)); 234 | background-image: -webkit-linear-gradient(top, #f2dede, 0%, #e7c3c3, 100%); 235 | background-image: -moz-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); 236 | background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); 237 | background-repeat: repeat-x; 238 | border-color: #dca7a7; 239 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); 240 | } 241 | 242 | .progress { 243 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ebebeb), to(#f5f5f5)); 244 | background-image: -webkit-linear-gradient(top, #ebebeb, 0%, #f5f5f5, 100%); 245 | background-image: -moz-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); 246 | background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); 247 | background-repeat: repeat-x; 248 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); 249 | } 250 | 251 | .progress-bar { 252 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3071a9)); 253 | background-image: -webkit-linear-gradient(top, #428bca, 0%, #3071a9, 100%); 254 | background-image: -moz-linear-gradient(top, #428bca 0%, #3071a9 100%); 255 | background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); 256 | background-repeat: repeat-x; 257 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); 258 | } 259 | 260 | .progress-bar-success { 261 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5cb85c), to(#449d44)); 262 | background-image: -webkit-linear-gradient(top, #5cb85c, 0%, #449d44, 100%); 263 | background-image: -moz-linear-gradient(top, #5cb85c 0%, #449d44 100%); 264 | background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); 265 | background-repeat: repeat-x; 266 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); 267 | } 268 | 269 | .progress-bar-info { 270 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5bc0de), to(#31b0d5)); 271 | background-image: -webkit-linear-gradient(top, #5bc0de, 0%, #31b0d5, 100%); 272 | background-image: -moz-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); 273 | background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); 274 | background-repeat: repeat-x; 275 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); 276 | } 277 | 278 | .progress-bar-warning { 279 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f0ad4e), to(#ec971f)); 280 | background-image: -webkit-linear-gradient(top, #f0ad4e, 0%, #ec971f, 100%); 281 | background-image: -moz-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); 282 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); 283 | background-repeat: repeat-x; 284 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); 285 | } 286 | 287 | .progress-bar-danger { 288 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9534f), to(#c9302c)); 289 | background-image: -webkit-linear-gradient(top, #d9534f, 0%, #c9302c, 100%); 290 | background-image: -moz-linear-gradient(top, #d9534f 0%, #c9302c 100%); 291 | background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); 292 | background-repeat: repeat-x; 293 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); 294 | } 295 | 296 | .list-group { 297 | border-radius: 4px; 298 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); 299 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); 300 | } 301 | 302 | .list-group-item.active, 303 | .list-group-item.active:hover, 304 | .list-group-item.active:focus { 305 | text-shadow: 0 -1px 0 #3071a9; 306 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3278b3)); 307 | background-image: -webkit-linear-gradient(top, #428bca, 0%, #3278b3, 100%); 308 | background-image: -moz-linear-gradient(top, #428bca 0%, #3278b3 100%); 309 | background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%); 310 | background-repeat: repeat-x; 311 | border-color: #3278b3; 312 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0); 313 | } 314 | 315 | .panel { 316 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 317 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 318 | } 319 | 320 | .panel-default > .panel-heading { 321 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f5f5f5), to(#e8e8e8)); 322 | background-image: -webkit-linear-gradient(top, #f5f5f5, 0%, #e8e8e8, 100%); 323 | background-image: -moz-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 324 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); 325 | background-repeat: repeat-x; 326 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); 327 | } 328 | 329 | .panel-primary > .panel-heading { 330 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd)); 331 | background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%); 332 | background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%); 333 | background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); 334 | background-repeat: repeat-x; 335 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); 336 | } 337 | 338 | .panel-success > .panel-heading { 339 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#dff0d8), to(#d0e9c6)); 340 | background-image: -webkit-linear-gradient(top, #dff0d8, 0%, #d0e9c6, 100%); 341 | background-image: -moz-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); 342 | background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); 343 | background-repeat: repeat-x; 344 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); 345 | } 346 | 347 | .panel-info > .panel-heading { 348 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9edf7), to(#c4e3f3)); 349 | background-image: -webkit-linear-gradient(top, #d9edf7, 0%, #c4e3f3, 100%); 350 | background-image: -moz-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); 351 | background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); 352 | background-repeat: repeat-x; 353 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); 354 | } 355 | 356 | .panel-warning > .panel-heading { 357 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#fcf8e3), to(#faf2cc)); 358 | background-image: -webkit-linear-gradient(top, #fcf8e3, 0%, #faf2cc, 100%); 359 | background-image: -moz-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); 360 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); 361 | background-repeat: repeat-x; 362 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); 363 | } 364 | 365 | .panel-danger > .panel-heading { 366 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f2dede), to(#ebcccc)); 367 | background-image: -webkit-linear-gradient(top, #f2dede, 0%, #ebcccc, 100%); 368 | background-image: -moz-linear-gradient(top, #f2dede 0%, #ebcccc 100%); 369 | background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); 370 | background-repeat: repeat-x; 371 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); 372 | } 373 | 374 | .well { 375 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#e8e8e8), to(#f5f5f5)); 376 | background-image: -webkit-linear-gradient(top, #e8e8e8, 0%, #f5f5f5, 100%); 377 | background-image: -moz-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); 378 | background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); 379 | background-repeat: repeat-x; 380 | border-color: #dcdcdc; 381 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); 382 | -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1); 383 | box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1); 384 | } -------------------------------------------------------------------------------- /src/ModularVNext/wwwroot/lib/bootstrap/css/bootstrap-theme.min.css: -------------------------------------------------------------------------------- 1 | .btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn:active,.btn.active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left 0,left 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,0%,#e6e6e6,100%);background-image:-moz-linear-gradient(top,#fff 0,#e6e6e6 100%);background-image:linear-gradient(to bottom,#fff 0,#e6e6e6 100%);background-repeat:repeat-x;border-color:#e0e0e0;border-color:#ccc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe6e6e6',GradientType=0)}.btn-default:active,.btn-default.active{background-color:#e6e6e6;border-color:#e0e0e0}.btn-primary{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3071a9));background-image:-webkit-linear-gradient(top,#428bca,0%,#3071a9,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;border-color:#2d6ca2;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3071a9',GradientType=0)}.btn-primary:active,.btn-primary.active{background-color:#3071a9;border-color:#2d6ca2}.btn-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5cb85c),to(#449d44));background-image:-webkit-linear-gradient(top,#5cb85c,0%,#449d44,100%);background-image:-moz-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;border-color:#419641;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c',endColorstr='#ff449d44',GradientType=0)}.btn-success:active,.btn-success.active{background-color:#449d44;border-color:#419641}.btn-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f0ad4e),to(#ec971f));background-image:-webkit-linear-gradient(top,#f0ad4e,0%,#ec971f,100%);background-image:-moz-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;border-color:#eb9316;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e',endColorstr='#ffec971f',GradientType=0)}.btn-warning:active,.btn-warning.active{background-color:#ec971f;border-color:#eb9316}.btn-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9534f),to(#c9302c));background-image:-webkit-linear-gradient(top,#d9534f,0%,#c9302c,100%);background-image:-moz-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;border-color:#c12e2a;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f',endColorstr='#ffc9302c',GradientType=0)}.btn-danger:active,.btn-danger.active{background-color:#c9302c;border-color:#c12e2a}.btn-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5bc0de),to(#31b0d5));background-image:-webkit-linear-gradient(top,#5bc0de,0%,#31b0d5,100%);background-image:-moz-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;border-color:#2aabd2;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff31b0d5',GradientType=0)}.btn-info:active,.btn-info.active{background-color:#31b0d5;border-color:#2aabd2}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus,.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-color:#357ebd;background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#357ebd));background-image:-webkit-linear-gradient(top,#428bca,0%,#357ebd,100%);background-image:-moz-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff357ebd',GradientType=0)}.navbar{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fff),to(#f8f8f8));background-image:-webkit-linear-gradient(top,#fff,0%,#f8f8f8,100%);background-image:-moz-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);background-repeat:repeat-x;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff8f8f8',GradientType=0);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075)}.navbar .navbar-nav>.active>a{background-color:#f8f8f8}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,0.25)}.navbar-inverse{background-image:-webkit-gradient(linear,left 0,left 100%,from(#3c3c3c),to(#222));background-image:-webkit-linear-gradient(top,#3c3c3c,0%,#222,100%);background-image:-moz-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c',endColorstr='#ff222222',GradientType=0)}.navbar-inverse .navbar-nav>.active>a{background-color:#222}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05)}.alert-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#dff0d8),to(#c8e5bc));background-image:-webkit-linear-gradient(top,#dff0d8,0%,#c8e5bc,100%);background-image:-moz-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);background-repeat:repeat-x;border-color:#b2dba1;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8',endColorstr='#ffc8e5bc',GradientType=0)}.alert-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9edf7),to(#b9def0));background-image:-webkit-linear-gradient(top,#d9edf7,0%,#b9def0,100%);background-image:-moz-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);background-repeat:repeat-x;border-color:#9acfea;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7',endColorstr='#ffb9def0',GradientType=0)}.alert-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fcf8e3),to(#f8efc0));background-image:-webkit-linear-gradient(top,#fcf8e3,0%,#f8efc0,100%);background-image:-moz-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);background-repeat:repeat-x;border-color:#f5e79e;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3',endColorstr='#fff8efc0',GradientType=0)}.alert-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f2dede),to(#e7c3c3));background-image:-webkit-linear-gradient(top,#f2dede,0%,#e7c3c3,100%);background-image:-moz-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);background-repeat:repeat-x;border-color:#dca7a7;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede',endColorstr='#ffe7c3c3',GradientType=0)}.progress{background-image:-webkit-gradient(linear,left 0,left 100%,from(#ebebeb),to(#f5f5f5));background-image:-webkit-linear-gradient(top,#ebebeb,0%,#f5f5f5,100%);background-image:-moz-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb',endColorstr='#fff5f5f5',GradientType=0)}.progress-bar{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3071a9));background-image:-webkit-linear-gradient(top,#428bca,0%,#3071a9,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3071a9',GradientType=0)}.progress-bar-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5cb85c),to(#449d44));background-image:-webkit-linear-gradient(top,#5cb85c,0%,#449d44,100%);background-image:-moz-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c',endColorstr='#ff449d44',GradientType=0)}.progress-bar-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5bc0de),to(#31b0d5));background-image:-webkit-linear-gradient(top,#5bc0de,0%,#31b0d5,100%);background-image:-moz-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff31b0d5',GradientType=0)}.progress-bar-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f0ad4e),to(#ec971f));background-image:-webkit-linear-gradient(top,#f0ad4e,0%,#ec971f,100%);background-image:-moz-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e',endColorstr='#ffec971f',GradientType=0)}.progress-bar-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9534f),to(#c9302c));background-image:-webkit-linear-gradient(top,#d9534f,0%,#c9302c,100%);background-image:-moz-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f',endColorstr='#ffc9302c',GradientType=0)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3278b3));background-image:-webkit-linear-gradient(top,#428bca,0%,#3278b3,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);background-repeat:repeat-x;border-color:#3278b3;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3278b3',GradientType=0)}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.panel-default>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f5f5f5),to(#e8e8e8));background-image:-webkit-linear-gradient(top,#f5f5f5,0%,#e8e8e8,100%);background-image:-moz-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#ffe8e8e8',GradientType=0)}.panel-primary>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#357ebd));background-image:-webkit-linear-gradient(top,#428bca,0%,#357ebd,100%);background-image:-moz-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff357ebd',GradientType=0)}.panel-success>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#dff0d8),to(#d0e9c6));background-image:-webkit-linear-gradient(top,#dff0d8,0%,#d0e9c6,100%);background-image:-moz-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8',endColorstr='#ffd0e9c6',GradientType=0)}.panel-info>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9edf7),to(#c4e3f3));background-image:-webkit-linear-gradient(top,#d9edf7,0%,#c4e3f3,100%);background-image:-moz-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7',endColorstr='#ffc4e3f3',GradientType=0)}.panel-warning>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fcf8e3),to(#faf2cc));background-image:-webkit-linear-gradient(top,#fcf8e3,0%,#faf2cc,100%);background-image:-moz-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3',endColorstr='#fffaf2cc',GradientType=0)}.panel-danger>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f2dede),to(#ebcccc));background-image:-webkit-linear-gradient(top,#f2dede,0%,#ebcccc,100%);background-image:-moz-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede',endColorstr='#ffebcccc',GradientType=0)}.well{background-image:-webkit-gradient(linear,left 0,left 100%,from(#e8e8e8),to(#f5f5f5));background-image:-webkit-linear-gradient(top,#e8e8e8,0%,#f5f5f5,100%);background-image:-moz-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);background-repeat:repeat-x;border-color:#dcdcdc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8',endColorstr='#fff5f5f5',GradientType=0);-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1)} -------------------------------------------------------------------------------- /src/ModularVNext/wwwroot/lib/bootstrap/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stuartleeks/ModularVNext/effd3731e827faf5c8f4e44aa1bb7eeb758970f0/src/ModularVNext/wwwroot/lib/bootstrap/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /src/ModularVNext/wwwroot/lib/bootstrap/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stuartleeks/ModularVNext/effd3731e827faf5c8f4e44aa1bb7eeb758970f0/src/ModularVNext/wwwroot/lib/bootstrap/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /src/ModularVNext/wwwroot/lib/bootstrap/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stuartleeks/ModularVNext/effd3731e827faf5c8f4e44aa1bb7eeb758970f0/src/ModularVNext/wwwroot/lib/bootstrap/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /src/ModularVNext/wwwroot/lib/bootstrap/js/bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * bootstrap.js v3.0.0 by @fat and @mdo 3 | * Copyright 2013 Twitter Inc. 4 | * http://www.apache.org/licenses/LICENSE-2.0 5 | */ 6 | if(!jQuery)throw new Error("Bootstrap requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]}}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(window.jQuery),+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function c(){f.trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one(a.support.transition.end,c).emulateTransitionEnd(150):c())};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),"string"==typeof b&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d)};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.is("input")?"val":"html",e=c.data();a+="Text",e.resetText||c.data("resetText",c[d]()),c[d](e[a]||this.options[a]),setTimeout(function(){"loadingText"==a?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.closest('[data-toggle="buttons"]');if(a.length){var b=this.$element.find("input").prop("checked",!this.$element.hasClass("active")).trigger("change");"radio"===b.prop("type")&&a.find(".active").removeClass("active")}this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof c&&c;e||d.data("bs.button",e=new b(this,f)),"toggle"==c?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(window.jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition.end&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){return this.sliding?void 0:this.slide("next")},b.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}this.sliding=!0,f&&this.pause();var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});if(!e.hasClass("active")){if(this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")){if(this.$element.trigger(j),j.isDefaultPrevented())return;e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid")},0)}).emulateTransitionEnd(600)}else{if(this.$element.trigger(j),j.isDefaultPrevented())return;d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return f&&this.cycle(),this}};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c),g="string"==typeof c?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),"number"==typeof c?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),d.data()),g=d.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=d.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b=a.Event("show.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])}}},b.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?(this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350),void 0):d.call(this)}}},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);e||d.data("bs.collapse",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":d.data(),i=d.attr("data-parent"),j=i&&a(i);g&&g.transitioning||(j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(d).addClass("collapsed"),d[f.hasClass("in")?"addClass":"removeClass"]("collapsed")),f.collapse(h)})}(window.jQuery),+function(a){"use strict";function b(){a(d).remove(),a(e).each(function(b){var d=c(a(this));d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown")),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown"))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){if("ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(''}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"html":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof c&&c;e||d.data("bs.popover",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(window.jQuery),+function(a){"use strict";function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(c).is("body")?a(window):a(c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";this.offsets=a([]),this.targets=a([]);var c=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#\w/.test(e)&&a(e);return f&&f.length&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,d=c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(b>=d)return g!=(a=f.last()[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parents(".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(window.jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.attr("data-target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},b.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),f.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),"string"==typeof c&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(this.$element.is(":visible")){var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top()),"function"==typeof h&&(h=f.bottom());var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=c-h?"bottom":null!=g&&g>=d?"top":!1;this.affixed!==i&&(this.unpin&&this.$element.css("top",""),this.affixed=i,this.unpin="bottom"==i?e.top-d:null,this.$element.removeClass(b.RESET).addClass("affix"+(i?"-"+i:"")),"bottom"==i&&this.$element.offset({top:document.body.offsetHeight-h-this.$element.height()}))}};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof c&&c;e||d.data("bs.affix",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(window.jQuery); -------------------------------------------------------------------------------- /src/ModularVNext/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js: -------------------------------------------------------------------------------- 1 | /*! 2 | ** Unobtrusive validation support library for jQuery and jQuery Validate 3 | ** Copyright (C) Microsoft Corporation. All rights reserved. 4 | */ 5 | 6 | /*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */ 7 | /*global document: false, jQuery: false */ 8 | 9 | (function ($) { 10 | var $jQval = $.validator, 11 | adapters, 12 | data_validation = "unobtrusiveValidation"; 13 | 14 | function setValidationValues(options, ruleName, value) { 15 | options.rules[ruleName] = value; 16 | if (options.message) { 17 | options.messages[ruleName] = options.message; 18 | } 19 | } 20 | 21 | function splitAndTrim(value) { 22 | return value.replace(/^\s+|\s+$/g, "").split(/\s*,\s*/g); 23 | } 24 | 25 | function escapeAttributeValue(value) { 26 | // As mentioned on http://api.jquery.com/category/selectors/ 27 | return value.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g, "\\$1"); 28 | } 29 | 30 | function getModelPrefix(fieldName) { 31 | return fieldName.substr(0, fieldName.lastIndexOf(".") + 1); 32 | } 33 | 34 | function appendModelPrefix(value, prefix) { 35 | if (value.indexOf("*.") === 0) { 36 | value = value.replace("*.", prefix); 37 | } 38 | return value; 39 | } 40 | 41 | function onError(error, inputElement) { // 'this' is the form element 42 | var container = $(this).find("[data-valmsg-for='" + escapeAttributeValue(inputElement[0].name) + "']"), 43 | replaceAttrValue = container.attr("data-valmsg-replace"), 44 | replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) !== false : null; 45 | 46 | container.removeClass("field-validation-valid").addClass("field-validation-error"); 47 | error.data("unobtrusiveContainer", container); 48 | 49 | if (replace) { 50 | container.empty(); 51 | error.removeClass("input-validation-error").appendTo(container); 52 | } 53 | else { 54 | error.hide(); 55 | } 56 | } 57 | 58 | function onErrors(event, validator) { // 'this' is the form element 59 | var container = $(this).find("[data-valmsg-summary=true]"), 60 | list = container.find("ul"); 61 | 62 | if (list && list.length && validator.errorList.length) { 63 | list.empty(); 64 | container.addClass("validation-summary-errors").removeClass("validation-summary-valid"); 65 | 66 | $.each(validator.errorList, function () { 67 | $("
  • ").html(this.message).appendTo(list); 68 | }); 69 | } 70 | } 71 | 72 | function onSuccess(error) { // 'this' is the form element 73 | var container = error.data("unobtrusiveContainer"), 74 | replaceAttrValue = container.attr("data-valmsg-replace"), 75 | replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) : null; 76 | 77 | if (container) { 78 | container.addClass("field-validation-valid").removeClass("field-validation-error"); 79 | error.removeData("unobtrusiveContainer"); 80 | 81 | if (replace) { 82 | container.empty(); 83 | } 84 | } 85 | } 86 | 87 | function onReset(event) { // 'this' is the form element 88 | var $form = $(this); 89 | $form.data("validator").resetForm(); 90 | $form.find(".validation-summary-errors") 91 | .addClass("validation-summary-valid") 92 | .removeClass("validation-summary-errors"); 93 | $form.find(".field-validation-error") 94 | .addClass("field-validation-valid") 95 | .removeClass("field-validation-error") 96 | .removeData("unobtrusiveContainer") 97 | .find(">*") // If we were using valmsg-replace, get the underlying error 98 | .removeData("unobtrusiveContainer"); 99 | } 100 | 101 | function validationInfo(form) { 102 | var $form = $(form), 103 | result = $form.data(data_validation), 104 | onResetProxy = $.proxy(onReset, form), 105 | defaultOptions = $jQval.unobtrusive.options || {}, 106 | execInContext = function (name, args) { 107 | var func = defaultOptions[name]; 108 | func && $.isFunction(func) && func.apply(form, args); 109 | } 110 | 111 | if (!result) { 112 | result = { 113 | options: { // options structure passed to jQuery Validate's validate() method 114 | errorClass: defaultOptions.errorClass || "input-validation-error", 115 | errorElement: defaultOptions.errorElement || "span", 116 | errorPlacement: function () { 117 | onError.apply(form, arguments); 118 | execInContext("errorPlacement", arguments); 119 | }, 120 | invalidHandler: function () { 121 | onErrors.apply(form, arguments); 122 | execInContext("invalidHandler", arguments); 123 | }, 124 | messages: {}, 125 | rules: {}, 126 | success: function () { 127 | onSuccess.apply(form, arguments); 128 | execInContext("success", arguments); 129 | } 130 | }, 131 | attachValidation: function () { 132 | $form 133 | .off("reset." + data_validation, onResetProxy) 134 | .on("reset." + data_validation, onResetProxy) 135 | .validate(this.options); 136 | }, 137 | validate: function () { // a validation function that is called by unobtrusive Ajax 138 | $form.validate(); 139 | return $form.valid(); 140 | } 141 | }; 142 | $form.data(data_validation, result); 143 | } 144 | 145 | return result; 146 | } 147 | 148 | $jQval.unobtrusive = { 149 | adapters: [], 150 | 151 | parseElement: function (element, skipAttach) { 152 | /// 153 | /// Parses a single HTML element for unobtrusive validation attributes. 154 | /// 155 | /// The HTML element to be parsed. 156 | /// [Optional] true to skip attaching the 157 | /// validation to the form. If parsing just this single element, you should specify true. 158 | /// If parsing several elements, you should specify false, and manually attach the validation 159 | /// to the form when you are finished. The default is false. 160 | var $element = $(element), 161 | form = $element.parents("form")[0], 162 | valInfo, rules, messages; 163 | 164 | if (!form) { // Cannot do client-side validation without a form 165 | return; 166 | } 167 | 168 | valInfo = validationInfo(form); 169 | valInfo.options.rules[element.name] = rules = {}; 170 | valInfo.options.messages[element.name] = messages = {}; 171 | 172 | $.each(this.adapters, function () { 173 | var prefix = "data-val-" + this.name, 174 | message = $element.attr(prefix), 175 | paramValues = {}; 176 | 177 | if (message !== undefined) { // Compare against undefined, because an empty message is legal (and falsy) 178 | prefix += "-"; 179 | 180 | $.each(this.params, function () { 181 | paramValues[this] = $element.attr(prefix + this); 182 | }); 183 | 184 | this.adapt({ 185 | element: element, 186 | form: form, 187 | message: message, 188 | params: paramValues, 189 | rules: rules, 190 | messages: messages 191 | }); 192 | } 193 | }); 194 | 195 | $.extend(rules, { "__dummy__": true }); 196 | 197 | if (!skipAttach) { 198 | valInfo.attachValidation(); 199 | } 200 | }, 201 | 202 | parse: function (selector) { 203 | /// 204 | /// Parses all the HTML elements in the specified selector. It looks for input elements decorated 205 | /// with the [data-val=true] attribute value and enables validation according to the data-val-* 206 | /// attribute values. 207 | /// 208 | /// Any valid jQuery selector. 209 | 210 | // $forms includes all forms in selector's DOM hierarchy (parent, children and self) that have at least one 211 | // element with data-val=true 212 | var $selector = $(selector), 213 | $forms = $selector.parents() 214 | .addBack() 215 | .filter("form") 216 | .add($selector.find("form")) 217 | .has("[data-val=true]"); 218 | 219 | $selector.find("[data-val=true]").each(function () { 220 | $jQval.unobtrusive.parseElement(this, true); 221 | }); 222 | 223 | $forms.each(function () { 224 | var info = validationInfo(this); 225 | if (info) { 226 | info.attachValidation(); 227 | } 228 | }); 229 | } 230 | }; 231 | 232 | adapters = $jQval.unobtrusive.adapters; 233 | 234 | adapters.add = function (adapterName, params, fn) { 235 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation. 236 | /// The name of the adapter to be added. This matches the name used 237 | /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). 238 | /// [Optional] An array of parameter names (strings) that will 239 | /// be extracted from the data-val-nnnn-mmmm HTML attributes (where nnnn is the adapter name, and 240 | /// mmmm is the parameter name). 241 | /// The function to call, which adapts the values from the HTML 242 | /// attributes into jQuery Validate rules and/or messages. 243 | /// 244 | if (!fn) { // Called with no params, just a function 245 | fn = params; 246 | params = []; 247 | } 248 | this.push({ name: adapterName, params: params, adapt: fn }); 249 | return this; 250 | }; 251 | 252 | adapters.addBool = function (adapterName, ruleName) { 253 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where 254 | /// the jQuery Validate validation rule has no parameter values. 255 | /// The name of the adapter to be added. This matches the name used 256 | /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). 257 | /// [Optional] The name of the jQuery Validate rule. If not provided, the value 258 | /// of adapterName will be used instead. 259 | /// 260 | return this.add(adapterName, function (options) { 261 | setValidationValues(options, ruleName || adapterName, true); 262 | }); 263 | }; 264 | 265 | adapters.addMinMax = function (adapterName, minRuleName, maxRuleName, minMaxRuleName, minAttribute, maxAttribute) { 266 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where 267 | /// the jQuery Validate validation has three potential rules (one for min-only, one for max-only, and 268 | /// one for min-and-max). The HTML parameters are expected to be named -min and -max. 269 | /// The name of the adapter to be added. This matches the name used 270 | /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). 271 | /// The name of the jQuery Validate rule to be used when you only 272 | /// have a minimum value. 273 | /// The name of the jQuery Validate rule to be used when you only 274 | /// have a maximum value. 275 | /// The name of the jQuery Validate rule to be used when you 276 | /// have both a minimum and maximum value. 277 | /// [Optional] The name of the HTML attribute that 278 | /// contains the minimum value. The default is "min". 279 | /// [Optional] The name of the HTML attribute that 280 | /// contains the maximum value. The default is "max". 281 | /// 282 | return this.add(adapterName, [minAttribute || "min", maxAttribute || "max"], function (options) { 283 | var min = options.params.min, 284 | max = options.params.max; 285 | 286 | if (min && max) { 287 | setValidationValues(options, minMaxRuleName, [min, max]); 288 | } 289 | else if (min) { 290 | setValidationValues(options, minRuleName, min); 291 | } 292 | else if (max) { 293 | setValidationValues(options, maxRuleName, max); 294 | } 295 | }); 296 | }; 297 | 298 | adapters.addSingleVal = function (adapterName, attribute, ruleName) { 299 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where 300 | /// the jQuery Validate validation rule has a single value. 301 | /// The name of the adapter to be added. This matches the name used 302 | /// in the data-val-nnnn HTML attribute(where nnnn is the adapter name). 303 | /// [Optional] The name of the HTML attribute that contains the value. 304 | /// The default is "val". 305 | /// [Optional] The name of the jQuery Validate rule. If not provided, the value 306 | /// of adapterName will be used instead. 307 | /// 308 | return this.add(adapterName, [attribute || "val"], function (options) { 309 | setValidationValues(options, ruleName || adapterName, options.params[attribute]); 310 | }); 311 | }; 312 | 313 | $jQval.addMethod("__dummy__", function (value, element, params) { 314 | return true; 315 | }); 316 | 317 | $jQval.addMethod("regex", function (value, element, params) { 318 | var match; 319 | if (this.optional(element)) { 320 | return true; 321 | } 322 | 323 | match = new RegExp(params).exec(value); 324 | return (match && (match.index === 0) && (match[0].length === value.length)); 325 | }); 326 | 327 | $jQval.addMethod("nonalphamin", function (value, element, nonalphamin) { 328 | var match; 329 | if (nonalphamin) { 330 | match = value.match(/\W/g); 331 | match = match && match.length >= nonalphamin; 332 | } 333 | return match; 334 | }); 335 | 336 | if ($jQval.methods.extension) { 337 | adapters.addSingleVal("accept", "mimtype"); 338 | adapters.addSingleVal("extension", "extension"); 339 | } else { 340 | // for backward compatibility, when the 'extension' validation method does not exist, such as with versions 341 | // of JQuery Validation plugin prior to 1.10, we should use the 'accept' method for 342 | // validating the extension, and ignore mime-type validations as they are not supported. 343 | adapters.addSingleVal("extension", "extension", "accept"); 344 | } 345 | 346 | adapters.addSingleVal("regex", "pattern"); 347 | adapters.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"); 348 | adapters.addMinMax("length", "minlength", "maxlength", "rangelength").addMinMax("range", "min", "max", "range"); 349 | adapters.addMinMax("minlength", "minlength").addMinMax("maxlength", "minlength", "maxlength"); 350 | adapters.add("equalto", ["other"], function (options) { 351 | var prefix = getModelPrefix(options.element.name), 352 | other = options.params.other, 353 | fullOtherName = appendModelPrefix(other, prefix), 354 | element = $(options.form).find(":input").filter("[name='" + escapeAttributeValue(fullOtherName) + "']")[0]; 355 | 356 | setValidationValues(options, "equalTo", element); 357 | }); 358 | adapters.add("required", function (options) { 359 | // jQuery Validate equates "required" with "mandatory" for checkbox elements 360 | if (options.element.tagName.toUpperCase() !== "INPUT" || options.element.type.toUpperCase() !== "CHECKBOX") { 361 | setValidationValues(options, "required", true); 362 | } 363 | }); 364 | adapters.add("remote", ["url", "type", "additionalfields"], function (options) { 365 | var value = { 366 | url: options.params.url, 367 | type: options.params.type || "GET", 368 | data: {} 369 | }, 370 | prefix = getModelPrefix(options.element.name); 371 | 372 | $.each(splitAndTrim(options.params.additionalfields || options.element.name), function (i, fieldName) { 373 | var paramName = appendModelPrefix(fieldName, prefix); 374 | value.data[paramName] = function () { 375 | return $(options.form).find(":input").filter("[name='" + escapeAttributeValue(paramName) + "']").val(); 376 | }; 377 | }); 378 | 379 | setValidationValues(options, "remote", value); 380 | }); 381 | adapters.add("password", ["min", "nonalphamin", "regex"], function (options) { 382 | if (options.params.min) { 383 | setValidationValues(options, "minlength", options.params.min); 384 | } 385 | if (options.params.nonalphamin) { 386 | setValidationValues(options, "nonalphamin", options.params.nonalphamin); 387 | } 388 | if (options.params.regex) { 389 | setValidationValues(options, "regex", options.params.regex); 390 | } 391 | }); 392 | 393 | $(function () { 394 | $jQval.unobtrusive.parse(document); 395 | }); 396 | }(jQuery)); -------------------------------------------------------------------------------- /src/ModularVNext/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | ** Unobtrusive validation support library for jQuery and jQuery Validate 3 | ** Copyright (C) Microsoft Corporation. All rights reserved. 4 | */ 5 | (function(a){var d=a.validator,b,e="unobtrusiveValidation";function c(a,b,c){a.rules[b]=c;if(a.message)a.messages[b]=a.message}function j(a){return a.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/g)}function f(a){return a.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g,"\\$1")}function h(a){return a.substr(0,a.lastIndexOf(".")+1)}function g(a,b){if(a.indexOf("*.")===0)a=a.replace("*.",b);return a}function m(c,e){var b=a(this).find("[data-valmsg-for='"+f(e[0].name)+"']"),d=b.attr("data-valmsg-replace"),g=d?a.parseJSON(d)!==false:null;b.removeClass("field-validation-valid").addClass("field-validation-error");c.data("unobtrusiveContainer",b);if(g){b.empty();c.removeClass("input-validation-error").appendTo(b)}else c.hide()}function l(e,d){var c=a(this).find("[data-valmsg-summary=true]"),b=c.find("ul");if(b&&b.length&&d.errorList.length){b.empty();c.addClass("validation-summary-errors").removeClass("validation-summary-valid");a.each(d.errorList,function(){a("
  • ").html(this.message).appendTo(b)})}}function k(d){var b=d.data("unobtrusiveContainer"),c=b.attr("data-valmsg-replace"),e=c?a.parseJSON(c):null;if(b){b.addClass("field-validation-valid").removeClass("field-validation-error");d.removeData("unobtrusiveContainer");e&&b.empty()}}function n(){var b=a(this);b.data("validator").resetForm();b.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors");b.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")}function i(b){var c=a(b),f=c.data(e),i=a.proxy(n,b),g=d.unobtrusive.options||{},h=function(e,d){var c=g[e];c&&a.isFunction(c)&&c.apply(b,d)};if(!f){f={options:{errorClass:g.errorClass||"input-validation-error",errorElement:g.errorElement||"span",errorPlacement:function(){m.apply(b,arguments);h("errorPlacement",arguments)},invalidHandler:function(){l.apply(b,arguments);h("invalidHandler",arguments)},messages:{},rules:{},success:function(){k.apply(b,arguments);h("success",arguments)}},attachValidation:function(){c.off("reset."+e,i).on("reset."+e,i).validate(this.options)},validate:function(){c.validate();return c.valid()}};c.data(e,f)}return f}d.unobtrusive={adapters:[],parseElement:function(b,h){var d=a(b),f=d.parents("form")[0],c,e,g;if(!f)return;c=i(f);c.options.rules[b.name]=e={};c.options.messages[b.name]=g={};a.each(this.adapters,function(){var c="data-val-"+this.name,i=d.attr(c),h={};if(i!==undefined){c+="-";a.each(this.params,function(){h[this]=d.attr(c+this)});this.adapt({element:b,form:f,message:i,params:h,rules:e,messages:g})}});a.extend(e,{__dummy__:true});!h&&c.attachValidation()},parse:function(c){var b=a(c),e=b.parents().addBack().filter("form").add(b.find("form")).has("[data-val=true]");b.find("[data-val=true]").each(function(){d.unobtrusive.parseElement(this,true)});e.each(function(){var a=i(this);a&&a.attachValidation()})}};b=d.unobtrusive.adapters;b.add=function(c,a,b){if(!b){b=a;a=[]}this.push({name:c,params:a,adapt:b});return this};b.addBool=function(a,b){return this.add(a,function(d){c(d,b||a,true)})};b.addMinMax=function(e,g,f,a,d,b){return this.add(e,[d||"min",b||"max"],function(b){var e=b.params.min,d=b.params.max;if(e&&d)c(b,a,[e,d]);else if(e)c(b,g,e);else d&&c(b,f,d)})};b.addSingleVal=function(a,b,d){return this.add(a,[b||"val"],function(e){c(e,d||a,e.params[b])})};d.addMethod("__dummy__",function(){return true});d.addMethod("regex",function(b,c,d){var a;if(this.optional(c))return true;a=(new RegExp(d)).exec(b);return a&&a.index===0&&a[0].length===b.length});d.addMethod("nonalphamin",function(c,d,b){var a;if(b){a=c.match(/\W/g);a=a&&a.length>=b}return a});if(d.methods.extension){b.addSingleVal("accept","mimtype");b.addSingleVal("extension","extension")}else b.addSingleVal("extension","extension","accept");b.addSingleVal("regex","pattern");b.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url");b.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range");b.addMinMax("minlength","minlength").addMinMax("maxlength","minlength","maxlength");b.add("equalto",["other"],function(b){var i=h(b.element.name),j=b.params.other,d=g(j,i),e=a(b.form).find(":input").filter("[name='"+f(d)+"']")[0];c(b,"equalTo",e)});b.add("required",function(a){(a.element.tagName.toUpperCase()!=="INPUT"||a.element.type.toUpperCase()!=="CHECKBOX")&&c(a,"required",true)});b.add("remote",["url","type","additionalfields"],function(b){var d={url:b.params.url,type:b.params.type||"GET",data:{}},e=h(b.element.name);a.each(j(b.params.additionalfields||b.element.name),function(i,h){var c=g(h,e);d.data[c]=function(){return a(b.form).find(":input").filter("[name='"+f(c)+"']").val()}});c(b,"remote",d)});b.add("password",["min","nonalphamin","regex"],function(a){a.params.min&&c(a,"minlength",a.params.min);a.params.nonalphamin&&c(a,"nonalphamin",a.params.nonalphamin);a.params.regex&&c(a,"regex",a.params.regex)});a(function(){d.unobtrusive.parse(document)})})(jQuery); -------------------------------------------------------------------------------- /src/ModularVNext/wwwroot/lib/jquery-validation/jquery.validate.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery Validation Plugin 1.11.1 3 | * 4 | * http://bassistance.de/jquery-plugins/jquery-plugin-validation/ 5 | * http://docs.jquery.com/Plugins/Validation 6 | * 7 | * Copyright 2013 Jörn Zaefferer 8 | * Released under the MIT license: 9 | * http://www.opensource.org/licenses/mit-license.php 10 | */ 11 | 12 | (function($) { 13 | 14 | $.extend($.fn, { 15 | // http://docs.jquery.com/Plugins/Validation/validate 16 | validate: function( options ) { 17 | 18 | // if nothing is selected, return nothing; can't chain anyway 19 | if ( !this.length ) { 20 | if ( options && options.debug && window.console ) { 21 | console.warn( "Nothing selected, can't validate, returning nothing." ); 22 | } 23 | return; 24 | } 25 | 26 | // check if a validator for this form was already created 27 | var validator = $.data( this[0], "validator" ); 28 | if ( validator ) { 29 | return validator; 30 | } 31 | 32 | // Add novalidate tag if HTML5. 33 | this.attr( "novalidate", "novalidate" ); 34 | 35 | validator = new $.validator( options, this[0] ); 36 | $.data( this[0], "validator", validator ); 37 | 38 | if ( validator.settings.onsubmit ) { 39 | 40 | this.validateDelegate( ":submit", "click", function( event ) { 41 | if ( validator.settings.submitHandler ) { 42 | validator.submitButton = event.target; 43 | } 44 | // allow suppressing validation by adding a cancel class to the submit button 45 | if ( $(event.target).hasClass("cancel") ) { 46 | validator.cancelSubmit = true; 47 | } 48 | 49 | // allow suppressing validation by adding the html5 formnovalidate attribute to the submit button 50 | if ( $(event.target).attr("formnovalidate") !== undefined ) { 51 | validator.cancelSubmit = true; 52 | } 53 | }); 54 | 55 | // validate the form on submit 56 | this.submit( function( event ) { 57 | if ( validator.settings.debug ) { 58 | // prevent form submit to be able to see console output 59 | event.preventDefault(); 60 | } 61 | function handle() { 62 | var hidden; 63 | if ( validator.settings.submitHandler ) { 64 | if ( validator.submitButton ) { 65 | // insert a hidden input as a replacement for the missing submit button 66 | hidden = $("").attr("name", validator.submitButton.name).val( $(validator.submitButton).val() ).appendTo(validator.currentForm); 67 | } 68 | validator.settings.submitHandler.call( validator, validator.currentForm, event ); 69 | if ( validator.submitButton ) { 70 | // and clean up afterwards; thanks to no-block-scope, hidden can be referenced 71 | hidden.remove(); 72 | } 73 | return false; 74 | } 75 | return true; 76 | } 77 | 78 | // prevent submit for invalid forms or custom submit handlers 79 | if ( validator.cancelSubmit ) { 80 | validator.cancelSubmit = false; 81 | return handle(); 82 | } 83 | if ( validator.form() ) { 84 | if ( validator.pendingRequest ) { 85 | validator.formSubmitted = true; 86 | return false; 87 | } 88 | return handle(); 89 | } else { 90 | validator.focusInvalid(); 91 | return false; 92 | } 93 | }); 94 | } 95 | 96 | return validator; 97 | }, 98 | // http://docs.jquery.com/Plugins/Validation/valid 99 | valid: function() { 100 | if ( $(this[0]).is("form")) { 101 | return this.validate().form(); 102 | } else { 103 | var valid = true; 104 | var validator = $(this[0].form).validate(); 105 | this.each(function() { 106 | valid = valid && validator.element(this); 107 | }); 108 | return valid; 109 | } 110 | }, 111 | // attributes: space seperated list of attributes to retrieve and remove 112 | removeAttrs: function( attributes ) { 113 | var result = {}, 114 | $element = this; 115 | $.each(attributes.split(/\s/), function( index, value ) { 116 | result[value] = $element.attr(value); 117 | $element.removeAttr(value); 118 | }); 119 | return result; 120 | }, 121 | // http://docs.jquery.com/Plugins/Validation/rules 122 | rules: function( command, argument ) { 123 | var element = this[0]; 124 | 125 | if ( command ) { 126 | var settings = $.data(element.form, "validator").settings; 127 | var staticRules = settings.rules; 128 | var existingRules = $.validator.staticRules(element); 129 | switch(command) { 130 | case "add": 131 | $.extend(existingRules, $.validator.normalizeRule(argument)); 132 | // remove messages from rules, but allow them to be set separetely 133 | delete existingRules.messages; 134 | staticRules[element.name] = existingRules; 135 | if ( argument.messages ) { 136 | settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages ); 137 | } 138 | break; 139 | case "remove": 140 | if ( !argument ) { 141 | delete staticRules[element.name]; 142 | return existingRules; 143 | } 144 | var filtered = {}; 145 | $.each(argument.split(/\s/), function( index, method ) { 146 | filtered[method] = existingRules[method]; 147 | delete existingRules[method]; 148 | }); 149 | return filtered; 150 | } 151 | } 152 | 153 | var data = $.validator.normalizeRules( 154 | $.extend( 155 | {}, 156 | $.validator.classRules(element), 157 | $.validator.attributeRules(element), 158 | $.validator.dataRules(element), 159 | $.validator.staticRules(element) 160 | ), element); 161 | 162 | // make sure required is at front 163 | if ( data.required ) { 164 | var param = data.required; 165 | delete data.required; 166 | data = $.extend({required: param}, data); 167 | } 168 | 169 | return data; 170 | } 171 | }); 172 | 173 | // Custom selectors 174 | $.extend($.expr[":"], { 175 | // http://docs.jquery.com/Plugins/Validation/blank 176 | blank: function( a ) { return !$.trim("" + $(a).val()); }, 177 | // http://docs.jquery.com/Plugins/Validation/filled 178 | filled: function( a ) { return !!$.trim("" + $(a).val()); }, 179 | // http://docs.jquery.com/Plugins/Validation/unchecked 180 | unchecked: function( a ) { return !$(a).prop("checked"); } 181 | }); 182 | 183 | // constructor for validator 184 | $.validator = function( options, form ) { 185 | this.settings = $.extend( true, {}, $.validator.defaults, options ); 186 | this.currentForm = form; 187 | this.init(); 188 | }; 189 | 190 | $.validator.format = function( source, params ) { 191 | if ( arguments.length === 1 ) { 192 | return function() { 193 | var args = $.makeArray(arguments); 194 | args.unshift(source); 195 | return $.validator.format.apply( this, args ); 196 | }; 197 | } 198 | if ( arguments.length > 2 && params.constructor !== Array ) { 199 | params = $.makeArray(arguments).slice(1); 200 | } 201 | if ( params.constructor !== Array ) { 202 | params = [ params ]; 203 | } 204 | $.each(params, function( i, n ) { 205 | source = source.replace( new RegExp("\\{" + i + "\\}", "g"), function() { 206 | return n; 207 | }); 208 | }); 209 | return source; 210 | }; 211 | 212 | $.extend($.validator, { 213 | 214 | defaults: { 215 | messages: {}, 216 | groups: {}, 217 | rules: {}, 218 | errorClass: "error", 219 | validClass: "valid", 220 | errorElement: "label", 221 | focusInvalid: true, 222 | errorContainer: $([]), 223 | errorLabelContainer: $([]), 224 | onsubmit: true, 225 | ignore: ":hidden", 226 | ignoreTitle: false, 227 | onfocusin: function( element, event ) { 228 | this.lastActive = element; 229 | 230 | // hide error label and remove error class on focus if enabled 231 | if ( this.settings.focusCleanup && !this.blockFocusCleanup ) { 232 | if ( this.settings.unhighlight ) { 233 | this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass ); 234 | } 235 | this.addWrapper(this.errorsFor(element)).hide(); 236 | } 237 | }, 238 | onfocusout: function( element, event ) { 239 | if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) { 240 | this.element(element); 241 | } 242 | }, 243 | onkeyup: function( element, event ) { 244 | if ( event.which === 9 && this.elementValue(element) === "" ) { 245 | return; 246 | } else if ( element.name in this.submitted || element === this.lastElement ) { 247 | this.element(element); 248 | } 249 | }, 250 | onclick: function( element, event ) { 251 | // click on selects, radiobuttons and checkboxes 252 | if ( element.name in this.submitted ) { 253 | this.element(element); 254 | } 255 | // or option elements, check parent select in that case 256 | else if ( element.parentNode.name in this.submitted ) { 257 | this.element(element.parentNode); 258 | } 259 | }, 260 | highlight: function( element, errorClass, validClass ) { 261 | if ( element.type === "radio" ) { 262 | this.findByName(element.name).addClass(errorClass).removeClass(validClass); 263 | } else { 264 | $(element).addClass(errorClass).removeClass(validClass); 265 | } 266 | }, 267 | unhighlight: function( element, errorClass, validClass ) { 268 | if ( element.type === "radio" ) { 269 | this.findByName(element.name).removeClass(errorClass).addClass(validClass); 270 | } else { 271 | $(element).removeClass(errorClass).addClass(validClass); 272 | } 273 | } 274 | }, 275 | 276 | // http://docs.jquery.com/Plugins/Validation/Validator/setDefaults 277 | setDefaults: function( settings ) { 278 | $.extend( $.validator.defaults, settings ); 279 | }, 280 | 281 | messages: { 282 | required: "This field is required.", 283 | remote: "Please fix this field.", 284 | email: "Please enter a valid email address.", 285 | url: "Please enter a valid URL.", 286 | date: "Please enter a valid date.", 287 | dateISO: "Please enter a valid date (ISO).", 288 | number: "Please enter a valid number.", 289 | digits: "Please enter only digits.", 290 | creditcard: "Please enter a valid credit card number.", 291 | equalTo: "Please enter the same value again.", 292 | maxlength: $.validator.format("Please enter no more than {0} characters."), 293 | minlength: $.validator.format("Please enter at least {0} characters."), 294 | rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."), 295 | range: $.validator.format("Please enter a value between {0} and {1}."), 296 | max: $.validator.format("Please enter a value less than or equal to {0}."), 297 | min: $.validator.format("Please enter a value greater than or equal to {0}.") 298 | }, 299 | 300 | autoCreateRanges: false, 301 | 302 | prototype: { 303 | 304 | init: function() { 305 | this.labelContainer = $(this.settings.errorLabelContainer); 306 | this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm); 307 | this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer ); 308 | this.submitted = {}; 309 | this.valueCache = {}; 310 | this.pendingRequest = 0; 311 | this.pending = {}; 312 | this.invalid = {}; 313 | this.reset(); 314 | 315 | var groups = (this.groups = {}); 316 | $.each(this.settings.groups, function( key, value ) { 317 | if ( typeof value === "string" ) { 318 | value = value.split(/\s/); 319 | } 320 | $.each(value, function( index, name ) { 321 | groups[name] = key; 322 | }); 323 | }); 324 | var rules = this.settings.rules; 325 | $.each(rules, function( key, value ) { 326 | rules[key] = $.validator.normalizeRule(value); 327 | }); 328 | 329 | function delegate(event) { 330 | var validator = $.data(this[0].form, "validator"), 331 | eventType = "on" + event.type.replace(/^validate/, ""); 332 | if ( validator.settings[eventType] ) { 333 | validator.settings[eventType].call(validator, this[0], event); 334 | } 335 | } 336 | $(this.currentForm) 337 | .validateDelegate(":text, [type='password'], [type='file'], select, textarea, " + 338 | "[type='number'], [type='search'] ,[type='tel'], [type='url'], " + 339 | "[type='email'], [type='datetime'], [type='date'], [type='month'], " + 340 | "[type='week'], [type='time'], [type='datetime-local'], " + 341 | "[type='range'], [type='color'] ", 342 | "focusin focusout keyup", delegate) 343 | .validateDelegate("[type='radio'], [type='checkbox'], select, option", "click", delegate); 344 | 345 | if ( this.settings.invalidHandler ) { 346 | $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler); 347 | } 348 | }, 349 | 350 | // http://docs.jquery.com/Plugins/Validation/Validator/form 351 | form: function() { 352 | this.checkForm(); 353 | $.extend(this.submitted, this.errorMap); 354 | this.invalid = $.extend({}, this.errorMap); 355 | if ( !this.valid() ) { 356 | $(this.currentForm).triggerHandler("invalid-form", [this]); 357 | } 358 | this.showErrors(); 359 | return this.valid(); 360 | }, 361 | 362 | checkForm: function() { 363 | this.prepareForm(); 364 | for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) { 365 | this.check( elements[i] ); 366 | } 367 | return this.valid(); 368 | }, 369 | 370 | // http://docs.jquery.com/Plugins/Validation/Validator/element 371 | element: function( element ) { 372 | element = this.validationTargetFor( this.clean( element ) ); 373 | this.lastElement = element; 374 | this.prepareElement( element ); 375 | this.currentElements = $(element); 376 | var result = this.check( element ) !== false; 377 | if ( result ) { 378 | delete this.invalid[element.name]; 379 | } else { 380 | this.invalid[element.name] = true; 381 | } 382 | if ( !this.numberOfInvalids() ) { 383 | // Hide error containers on last error 384 | this.toHide = this.toHide.add( this.containers ); 385 | } 386 | this.showErrors(); 387 | return result; 388 | }, 389 | 390 | // http://docs.jquery.com/Plugins/Validation/Validator/showErrors 391 | showErrors: function( errors ) { 392 | if ( errors ) { 393 | // add items to error list and map 394 | $.extend( this.errorMap, errors ); 395 | this.errorList = []; 396 | for ( var name in errors ) { 397 | this.errorList.push({ 398 | message: errors[name], 399 | element: this.findByName(name)[0] 400 | }); 401 | } 402 | // remove items from success list 403 | this.successList = $.grep( this.successList, function( element ) { 404 | return !(element.name in errors); 405 | }); 406 | } 407 | if ( this.settings.showErrors ) { 408 | this.settings.showErrors.call( this, this.errorMap, this.errorList ); 409 | } else { 410 | this.defaultShowErrors(); 411 | } 412 | }, 413 | 414 | // http://docs.jquery.com/Plugins/Validation/Validator/resetForm 415 | resetForm: function() { 416 | if ( $.fn.resetForm ) { 417 | $(this.currentForm).resetForm(); 418 | } 419 | this.submitted = {}; 420 | this.lastElement = null; 421 | this.prepareForm(); 422 | this.hideErrors(); 423 | this.elements().removeClass( this.settings.errorClass ).removeData( "previousValue" ); 424 | }, 425 | 426 | numberOfInvalids: function() { 427 | return this.objectLength(this.invalid); 428 | }, 429 | 430 | objectLength: function( obj ) { 431 | var count = 0; 432 | for ( var i in obj ) { 433 | count++; 434 | } 435 | return count; 436 | }, 437 | 438 | hideErrors: function() { 439 | this.addWrapper( this.toHide ).hide(); 440 | }, 441 | 442 | valid: function() { 443 | return this.size() === 0; 444 | }, 445 | 446 | size: function() { 447 | return this.errorList.length; 448 | }, 449 | 450 | focusInvalid: function() { 451 | if ( this.settings.focusInvalid ) { 452 | try { 453 | $(this.findLastActive() || this.errorList.length && this.errorList[0].element || []) 454 | .filter(":visible") 455 | .focus() 456 | // manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find 457 | .trigger("focusin"); 458 | } catch(e) { 459 | // ignore IE throwing errors when focusing hidden elements 460 | } 461 | } 462 | }, 463 | 464 | findLastActive: function() { 465 | var lastActive = this.lastActive; 466 | return lastActive && $.grep(this.errorList, function( n ) { 467 | return n.element.name === lastActive.name; 468 | }).length === 1 && lastActive; 469 | }, 470 | 471 | elements: function() { 472 | var validator = this, 473 | rulesCache = {}; 474 | 475 | // select all valid inputs inside the form (no submit or reset buttons) 476 | return $(this.currentForm) 477 | .find("input, select, textarea") 478 | .not(":submit, :reset, :image, [disabled]") 479 | .not( this.settings.ignore ) 480 | .filter(function() { 481 | if ( !this.name && validator.settings.debug && window.console ) { 482 | console.error( "%o has no name assigned", this); 483 | } 484 | 485 | // select only the first element for each name, and only those with rules specified 486 | if ( this.name in rulesCache || !validator.objectLength($(this).rules()) ) { 487 | return false; 488 | } 489 | 490 | rulesCache[this.name] = true; 491 | return true; 492 | }); 493 | }, 494 | 495 | clean: function( selector ) { 496 | return $(selector)[0]; 497 | }, 498 | 499 | errors: function() { 500 | var errorClass = this.settings.errorClass.replace(" ", "."); 501 | return $(this.settings.errorElement + "." + errorClass, this.errorContext); 502 | }, 503 | 504 | reset: function() { 505 | this.successList = []; 506 | this.errorList = []; 507 | this.errorMap = {}; 508 | this.toShow = $([]); 509 | this.toHide = $([]); 510 | this.currentElements = $([]); 511 | }, 512 | 513 | prepareForm: function() { 514 | this.reset(); 515 | this.toHide = this.errors().add( this.containers ); 516 | }, 517 | 518 | prepareElement: function( element ) { 519 | this.reset(); 520 | this.toHide = this.errorsFor(element); 521 | }, 522 | 523 | elementValue: function( element ) { 524 | var type = $(element).attr("type"), 525 | val = $(element).val(); 526 | 527 | if ( type === "radio" || type === "checkbox" ) { 528 | return $("input[name='" + $(element).attr("name") + "']:checked").val(); 529 | } 530 | 531 | if ( typeof val === "string" ) { 532 | return val.replace(/\r/g, ""); 533 | } 534 | return val; 535 | }, 536 | 537 | check: function( element ) { 538 | element = this.validationTargetFor( this.clean( element ) ); 539 | 540 | var rules = $(element).rules(); 541 | var dependencyMismatch = false; 542 | var val = this.elementValue(element); 543 | var result; 544 | 545 | for (var method in rules ) { 546 | var rule = { method: method, parameters: rules[method] }; 547 | try { 548 | 549 | result = $.validator.methods[method].call( this, val, element, rule.parameters ); 550 | 551 | // if a method indicates that the field is optional and therefore valid, 552 | // don't mark it as valid when there are no other rules 553 | if ( result === "dependency-mismatch" ) { 554 | dependencyMismatch = true; 555 | continue; 556 | } 557 | dependencyMismatch = false; 558 | 559 | if ( result === "pending" ) { 560 | this.toHide = this.toHide.not( this.errorsFor(element) ); 561 | return; 562 | } 563 | 564 | if ( !result ) { 565 | this.formatAndAdd( element, rule ); 566 | return false; 567 | } 568 | } catch(e) { 569 | if ( this.settings.debug && window.console ) { 570 | console.log( "Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method.", e ); 571 | } 572 | throw e; 573 | } 574 | } 575 | if ( dependencyMismatch ) { 576 | return; 577 | } 578 | if ( this.objectLength(rules) ) { 579 | this.successList.push(element); 580 | } 581 | return true; 582 | }, 583 | 584 | // return the custom message for the given element and validation method 585 | // specified in the element's HTML5 data attribute 586 | customDataMessage: function( element, method ) { 587 | return $(element).data("msg-" + method.toLowerCase()) || (element.attributes && $(element).attr("data-msg-" + method.toLowerCase())); 588 | }, 589 | 590 | // return the custom message for the given element name and validation method 591 | customMessage: function( name, method ) { 592 | var m = this.settings.messages[name]; 593 | return m && (m.constructor === String ? m : m[method]); 594 | }, 595 | 596 | // return the first defined argument, allowing empty strings 597 | findDefined: function() { 598 | for(var i = 0; i < arguments.length; i++) { 599 | if ( arguments[i] !== undefined ) { 600 | return arguments[i]; 601 | } 602 | } 603 | return undefined; 604 | }, 605 | 606 | defaultMessage: function( element, method ) { 607 | return this.findDefined( 608 | this.customMessage( element.name, method ), 609 | this.customDataMessage( element, method ), 610 | // title is never undefined, so handle empty string as undefined 611 | !this.settings.ignoreTitle && element.title || undefined, 612 | $.validator.messages[method], 613 | "Warning: No message defined for " + element.name + "" 614 | ); 615 | }, 616 | 617 | formatAndAdd: function( element, rule ) { 618 | var message = this.defaultMessage( element, rule.method ), 619 | theregex = /\$?\{(\d+)\}/g; 620 | if ( typeof message === "function" ) { 621 | message = message.call(this, rule.parameters, element); 622 | } else if (theregex.test(message)) { 623 | message = $.validator.format(message.replace(theregex, "{$1}"), rule.parameters); 624 | } 625 | this.errorList.push({ 626 | message: message, 627 | element: element 628 | }); 629 | 630 | this.errorMap[element.name] = message; 631 | this.submitted[element.name] = message; 632 | }, 633 | 634 | addWrapper: function( toToggle ) { 635 | if ( this.settings.wrapper ) { 636 | toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) ); 637 | } 638 | return toToggle; 639 | }, 640 | 641 | defaultShowErrors: function() { 642 | var i, elements; 643 | for ( i = 0; this.errorList[i]; i++ ) { 644 | var error = this.errorList[i]; 645 | if ( this.settings.highlight ) { 646 | this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass ); 647 | } 648 | this.showLabel( error.element, error.message ); 649 | } 650 | if ( this.errorList.length ) { 651 | this.toShow = this.toShow.add( this.containers ); 652 | } 653 | if ( this.settings.success ) { 654 | for ( i = 0; this.successList[i]; i++ ) { 655 | this.showLabel( this.successList[i] ); 656 | } 657 | } 658 | if ( this.settings.unhighlight ) { 659 | for ( i = 0, elements = this.validElements(); elements[i]; i++ ) { 660 | this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass ); 661 | } 662 | } 663 | this.toHide = this.toHide.not( this.toShow ); 664 | this.hideErrors(); 665 | this.addWrapper( this.toShow ).show(); 666 | }, 667 | 668 | validElements: function() { 669 | return this.currentElements.not(this.invalidElements()); 670 | }, 671 | 672 | invalidElements: function() { 673 | return $(this.errorList).map(function() { 674 | return this.element; 675 | }); 676 | }, 677 | 678 | showLabel: function( element, message ) { 679 | var label = this.errorsFor( element ); 680 | if ( label.length ) { 681 | // refresh error/success class 682 | label.removeClass( this.settings.validClass ).addClass( this.settings.errorClass ); 683 | // replace message on existing label 684 | label.html(message); 685 | } else { 686 | // create label 687 | label = $("<" + this.settings.errorElement + ">") 688 | .attr("for", this.idOrName(element)) 689 | .addClass(this.settings.errorClass) 690 | .html(message || ""); 691 | if ( this.settings.wrapper ) { 692 | // make sure the element is visible, even in IE 693 | // actually showing the wrapped element is handled elsewhere 694 | label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent(); 695 | } 696 | if ( !this.labelContainer.append(label).length ) { 697 | if ( this.settings.errorPlacement ) { 698 | this.settings.errorPlacement(label, $(element) ); 699 | } else { 700 | label.insertAfter(element); 701 | } 702 | } 703 | } 704 | if ( !message && this.settings.success ) { 705 | label.text(""); 706 | if ( typeof this.settings.success === "string" ) { 707 | label.addClass( this.settings.success ); 708 | } else { 709 | this.settings.success( label, element ); 710 | } 711 | } 712 | this.toShow = this.toShow.add(label); 713 | }, 714 | 715 | errorsFor: function( element ) { 716 | var name = this.idOrName(element); 717 | return this.errors().filter(function() { 718 | return $(this).attr("for") === name; 719 | }); 720 | }, 721 | 722 | idOrName: function( element ) { 723 | return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name); 724 | }, 725 | 726 | validationTargetFor: function( element ) { 727 | // if radio/checkbox, validate first element in group instead 728 | if ( this.checkable(element) ) { 729 | element = this.findByName( element.name ).not(this.settings.ignore)[0]; 730 | } 731 | return element; 732 | }, 733 | 734 | checkable: function( element ) { 735 | return (/radio|checkbox/i).test(element.type); 736 | }, 737 | 738 | findByName: function( name ) { 739 | return $(this.currentForm).find("[name='" + name + "']"); 740 | }, 741 | 742 | getLength: function( value, element ) { 743 | switch( element.nodeName.toLowerCase() ) { 744 | case "select": 745 | return $("option:selected", element).length; 746 | case "input": 747 | if ( this.checkable( element) ) { 748 | return this.findByName(element.name).filter(":checked").length; 749 | } 750 | } 751 | return value.length; 752 | }, 753 | 754 | depend: function( param, element ) { 755 | return this.dependTypes[typeof param] ? this.dependTypes[typeof param](param, element) : true; 756 | }, 757 | 758 | dependTypes: { 759 | "boolean": function( param, element ) { 760 | return param; 761 | }, 762 | "string": function( param, element ) { 763 | return !!$(param, element.form).length; 764 | }, 765 | "function": function( param, element ) { 766 | return param(element); 767 | } 768 | }, 769 | 770 | optional: function( element ) { 771 | var val = this.elementValue(element); 772 | return !$.validator.methods.required.call(this, val, element) && "dependency-mismatch"; 773 | }, 774 | 775 | startRequest: function( element ) { 776 | if ( !this.pending[element.name] ) { 777 | this.pendingRequest++; 778 | this.pending[element.name] = true; 779 | } 780 | }, 781 | 782 | stopRequest: function( element, valid ) { 783 | this.pendingRequest--; 784 | // sometimes synchronization fails, make sure pendingRequest is never < 0 785 | if ( this.pendingRequest < 0 ) { 786 | this.pendingRequest = 0; 787 | } 788 | delete this.pending[element.name]; 789 | if ( valid && this.pendingRequest === 0 && this.formSubmitted && this.form() ) { 790 | $(this.currentForm).submit(); 791 | this.formSubmitted = false; 792 | } else if (!valid && this.pendingRequest === 0 && this.formSubmitted) { 793 | $(this.currentForm).triggerHandler("invalid-form", [this]); 794 | this.formSubmitted = false; 795 | } 796 | }, 797 | 798 | previousValue: function( element ) { 799 | return $.data(element, "previousValue") || $.data(element, "previousValue", { 800 | old: null, 801 | valid: true, 802 | message: this.defaultMessage( element, "remote" ) 803 | }); 804 | } 805 | 806 | }, 807 | 808 | classRuleSettings: { 809 | required: {required: true}, 810 | email: {email: true}, 811 | url: {url: true}, 812 | date: {date: true}, 813 | dateISO: {dateISO: true}, 814 | number: {number: true}, 815 | digits: {digits: true}, 816 | creditcard: {creditcard: true} 817 | }, 818 | 819 | addClassRules: function( className, rules ) { 820 | if ( className.constructor === String ) { 821 | this.classRuleSettings[className] = rules; 822 | } else { 823 | $.extend(this.classRuleSettings, className); 824 | } 825 | }, 826 | 827 | classRules: function( element ) { 828 | var rules = {}; 829 | var classes = $(element).attr("class"); 830 | if ( classes ) { 831 | $.each(classes.split(" "), function() { 832 | if ( this in $.validator.classRuleSettings ) { 833 | $.extend(rules, $.validator.classRuleSettings[this]); 834 | } 835 | }); 836 | } 837 | return rules; 838 | }, 839 | 840 | attributeRules: function( element ) { 841 | var rules = {}; 842 | var $element = $(element); 843 | var type = $element[0].getAttribute("type"); 844 | 845 | for (var method in $.validator.methods) { 846 | var value; 847 | 848 | // support for in both html5 and older browsers 849 | if ( method === "required" ) { 850 | value = $element.get(0).getAttribute(method); 851 | // Some browsers return an empty string for the required attribute 852 | // and non-HTML5 browsers might have required="" markup 853 | if ( value === "" ) { 854 | value = true; 855 | } 856 | // force non-HTML5 browsers to return bool 857 | value = !!value; 858 | } else { 859 | value = $element.attr(method); 860 | } 861 | 862 | // convert the value to a number for number inputs, and for text for backwards compability 863 | // allows type="date" and others to be compared as strings 864 | if ( /min|max/.test( method ) && ( type === null || /number|range|text/.test( type ) ) ) { 865 | value = Number(value); 866 | } 867 | 868 | if ( value ) { 869 | rules[method] = value; 870 | } else if ( type === method && type !== 'range' ) { 871 | // exception: the jquery validate 'range' method 872 | // does not test for the html5 'range' type 873 | rules[method] = true; 874 | } 875 | } 876 | 877 | // maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs 878 | if ( rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength) ) { 879 | delete rules.maxlength; 880 | } 881 | 882 | return rules; 883 | }, 884 | 885 | dataRules: function( element ) { 886 | var method, value, 887 | rules = {}, $element = $(element); 888 | for (method in $.validator.methods) { 889 | value = $element.data("rule-" + method.toLowerCase()); 890 | if ( value !== undefined ) { 891 | rules[method] = value; 892 | } 893 | } 894 | return rules; 895 | }, 896 | 897 | staticRules: function( element ) { 898 | var rules = {}; 899 | var validator = $.data(element.form, "validator"); 900 | if ( validator.settings.rules ) { 901 | rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {}; 902 | } 903 | return rules; 904 | }, 905 | 906 | normalizeRules: function( rules, element ) { 907 | // handle dependency check 908 | $.each(rules, function( prop, val ) { 909 | // ignore rule when param is explicitly false, eg. required:false 910 | if ( val === false ) { 911 | delete rules[prop]; 912 | return; 913 | } 914 | if ( val.param || val.depends ) { 915 | var keepRule = true; 916 | switch (typeof val.depends) { 917 | case "string": 918 | keepRule = !!$(val.depends, element.form).length; 919 | break; 920 | case "function": 921 | keepRule = val.depends.call(element, element); 922 | break; 923 | } 924 | if ( keepRule ) { 925 | rules[prop] = val.param !== undefined ? val.param : true; 926 | } else { 927 | delete rules[prop]; 928 | } 929 | } 930 | }); 931 | 932 | // evaluate parameters 933 | $.each(rules, function( rule, parameter ) { 934 | rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter; 935 | }); 936 | 937 | // clean number parameters 938 | $.each(['minlength', 'maxlength'], function() { 939 | if ( rules[this] ) { 940 | rules[this] = Number(rules[this]); 941 | } 942 | }); 943 | $.each(['rangelength', 'range'], function() { 944 | var parts; 945 | if ( rules[this] ) { 946 | if ( $.isArray(rules[this]) ) { 947 | rules[this] = [Number(rules[this][0]), Number(rules[this][1])]; 948 | } else if ( typeof rules[this] === "string" ) { 949 | parts = rules[this].split(/[\s,]+/); 950 | rules[this] = [Number(parts[0]), Number(parts[1])]; 951 | } 952 | } 953 | }); 954 | 955 | if ( $.validator.autoCreateRanges ) { 956 | // auto-create ranges 957 | if ( rules.min && rules.max ) { 958 | rules.range = [rules.min, rules.max]; 959 | delete rules.min; 960 | delete rules.max; 961 | } 962 | if ( rules.minlength && rules.maxlength ) { 963 | rules.rangelength = [rules.minlength, rules.maxlength]; 964 | delete rules.minlength; 965 | delete rules.maxlength; 966 | } 967 | } 968 | 969 | return rules; 970 | }, 971 | 972 | // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true} 973 | normalizeRule: function( data ) { 974 | if ( typeof data === "string" ) { 975 | var transformed = {}; 976 | $.each(data.split(/\s/), function() { 977 | transformed[this] = true; 978 | }); 979 | data = transformed; 980 | } 981 | return data; 982 | }, 983 | 984 | // http://docs.jquery.com/Plugins/Validation/Validator/addMethod 985 | addMethod: function( name, method, message ) { 986 | $.validator.methods[name] = method; 987 | $.validator.messages[name] = message !== undefined ? message : $.validator.messages[name]; 988 | if ( method.length < 3 ) { 989 | $.validator.addClassRules(name, $.validator.normalizeRule(name)); 990 | } 991 | }, 992 | 993 | methods: { 994 | 995 | // http://docs.jquery.com/Plugins/Validation/Methods/required 996 | required: function( value, element, param ) { 997 | // check if dependency is met 998 | if ( !this.depend(param, element) ) { 999 | return "dependency-mismatch"; 1000 | } 1001 | if ( element.nodeName.toLowerCase() === "select" ) { 1002 | // could be an array for select-multiple or a string, both are fine this way 1003 | var val = $(element).val(); 1004 | return val && val.length > 0; 1005 | } 1006 | if ( this.checkable(element) ) { 1007 | return this.getLength(value, element) > 0; 1008 | } 1009 | return $.trim(value).length > 0; 1010 | }, 1011 | 1012 | // http://docs.jquery.com/Plugins/Validation/Methods/email 1013 | email: function( value, element ) { 1014 | // contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/ 1015 | return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i.test(value); 1016 | }, 1017 | 1018 | // http://docs.jquery.com/Plugins/Validation/Methods/url 1019 | url: function( value, element ) { 1020 | // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/ 1021 | return this.optional(element) || /^(https?|s?ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value); 1022 | }, 1023 | 1024 | // http://docs.jquery.com/Plugins/Validation/Methods/date 1025 | date: function( value, element ) { 1026 | return this.optional(element) || !/Invalid|NaN/.test(new Date(value).toString()); 1027 | }, 1028 | 1029 | // http://docs.jquery.com/Plugins/Validation/Methods/dateISO 1030 | dateISO: function( value, element ) { 1031 | return this.optional(element) || /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/.test(value); 1032 | }, 1033 | 1034 | // http://docs.jquery.com/Plugins/Validation/Methods/number 1035 | number: function( value, element ) { 1036 | return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(value); 1037 | }, 1038 | 1039 | // http://docs.jquery.com/Plugins/Validation/Methods/digits 1040 | digits: function( value, element ) { 1041 | return this.optional(element) || /^\d+$/.test(value); 1042 | }, 1043 | 1044 | // http://docs.jquery.com/Plugins/Validation/Methods/creditcard 1045 | // based on http://en.wikipedia.org/wiki/Luhn 1046 | creditcard: function( value, element ) { 1047 | if ( this.optional(element) ) { 1048 | return "dependency-mismatch"; 1049 | } 1050 | // accept only spaces, digits and dashes 1051 | if ( /[^0-9 \-]+/.test(value) ) { 1052 | return false; 1053 | } 1054 | var nCheck = 0, 1055 | nDigit = 0, 1056 | bEven = false; 1057 | 1058 | value = value.replace(/\D/g, ""); 1059 | 1060 | for (var n = value.length - 1; n >= 0; n--) { 1061 | var cDigit = value.charAt(n); 1062 | nDigit = parseInt(cDigit, 10); 1063 | if ( bEven ) { 1064 | if ( (nDigit *= 2) > 9 ) { 1065 | nDigit -= 9; 1066 | } 1067 | } 1068 | nCheck += nDigit; 1069 | bEven = !bEven; 1070 | } 1071 | 1072 | return (nCheck % 10) === 0; 1073 | }, 1074 | 1075 | // http://docs.jquery.com/Plugins/Validation/Methods/minlength 1076 | minlength: function( value, element, param ) { 1077 | var length = $.isArray( value ) ? value.length : this.getLength($.trim(value), element); 1078 | return this.optional(element) || length >= param; 1079 | }, 1080 | 1081 | // http://docs.jquery.com/Plugins/Validation/Methods/maxlength 1082 | maxlength: function( value, element, param ) { 1083 | var length = $.isArray( value ) ? value.length : this.getLength($.trim(value), element); 1084 | return this.optional(element) || length <= param; 1085 | }, 1086 | 1087 | // http://docs.jquery.com/Plugins/Validation/Methods/rangelength 1088 | rangelength: function( value, element, param ) { 1089 | var length = $.isArray( value ) ? value.length : this.getLength($.trim(value), element); 1090 | return this.optional(element) || ( length >= param[0] && length <= param[1] ); 1091 | }, 1092 | 1093 | // http://docs.jquery.com/Plugins/Validation/Methods/min 1094 | min: function( value, element, param ) { 1095 | return this.optional(element) || value >= param; 1096 | }, 1097 | 1098 | // http://docs.jquery.com/Plugins/Validation/Methods/max 1099 | max: function( value, element, param ) { 1100 | return this.optional(element) || value <= param; 1101 | }, 1102 | 1103 | // http://docs.jquery.com/Plugins/Validation/Methods/range 1104 | range: function( value, element, param ) { 1105 | return this.optional(element) || ( value >= param[0] && value <= param[1] ); 1106 | }, 1107 | 1108 | // http://docs.jquery.com/Plugins/Validation/Methods/equalTo 1109 | equalTo: function( value, element, param ) { 1110 | // bind to the blur event of the target in order to revalidate whenever the target field is updated 1111 | // TODO find a way to bind the event just once, avoiding the unbind-rebind overhead 1112 | var target = $(param); 1113 | if ( this.settings.onfocusout ) { 1114 | target.unbind(".validate-equalTo").bind("blur.validate-equalTo", function() { 1115 | $(element).valid(); 1116 | }); 1117 | } 1118 | return value === target.val(); 1119 | }, 1120 | 1121 | // http://docs.jquery.com/Plugins/Validation/Methods/remote 1122 | remote: function( value, element, param ) { 1123 | if ( this.optional(element) ) { 1124 | return "dependency-mismatch"; 1125 | } 1126 | 1127 | var previous = this.previousValue(element); 1128 | if (!this.settings.messages[element.name] ) { 1129 | this.settings.messages[element.name] = {}; 1130 | } 1131 | previous.originalMessage = this.settings.messages[element.name].remote; 1132 | this.settings.messages[element.name].remote = previous.message; 1133 | 1134 | param = typeof param === "string" && {url:param} || param; 1135 | 1136 | if ( previous.old === value ) { 1137 | return previous.valid; 1138 | } 1139 | 1140 | previous.old = value; 1141 | var validator = this; 1142 | this.startRequest(element); 1143 | var data = {}; 1144 | data[element.name] = value; 1145 | $.ajax($.extend(true, { 1146 | url: param, 1147 | mode: "abort", 1148 | port: "validate" + element.name, 1149 | dataType: "json", 1150 | data: data, 1151 | success: function( response ) { 1152 | validator.settings.messages[element.name].remote = previous.originalMessage; 1153 | var valid = response === true || response === "true"; 1154 | if ( valid ) { 1155 | var submitted = validator.formSubmitted; 1156 | validator.prepareElement(element); 1157 | validator.formSubmitted = submitted; 1158 | validator.successList.push(element); 1159 | delete validator.invalid[element.name]; 1160 | validator.showErrors(); 1161 | } else { 1162 | var errors = {}; 1163 | var message = response || validator.defaultMessage( element, "remote" ); 1164 | errors[element.name] = previous.message = $.isFunction(message) ? message(value) : message; 1165 | validator.invalid[element.name] = true; 1166 | validator.showErrors(errors); 1167 | } 1168 | previous.valid = valid; 1169 | validator.stopRequest(element, valid); 1170 | } 1171 | }, param)); 1172 | return "pending"; 1173 | } 1174 | 1175 | } 1176 | 1177 | }); 1178 | 1179 | // deprecated, use $.validator.format instead 1180 | $.format = $.validator.format; 1181 | 1182 | }(jQuery)); 1183 | 1184 | // ajax mode: abort 1185 | // usage: $.ajax({ mode: "abort"[, port: "uniqueport"]}); 1186 | // if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() 1187 | (function($) { 1188 | var pendingRequests = {}; 1189 | // Use a prefilter if available (1.5+) 1190 | if ( $.ajaxPrefilter ) { 1191 | $.ajaxPrefilter(function( settings, _, xhr ) { 1192 | var port = settings.port; 1193 | if ( settings.mode === "abort" ) { 1194 | if ( pendingRequests[port] ) { 1195 | pendingRequests[port].abort(); 1196 | } 1197 | pendingRequests[port] = xhr; 1198 | } 1199 | }); 1200 | } else { 1201 | // Proxy ajax 1202 | var ajax = $.ajax; 1203 | $.ajax = function( settings ) { 1204 | var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode, 1205 | port = ( "port" in settings ? settings : $.ajaxSettings ).port; 1206 | if ( mode === "abort" ) { 1207 | if ( pendingRequests[port] ) { 1208 | pendingRequests[port].abort(); 1209 | } 1210 | pendingRequests[port] = ajax.apply(this, arguments); 1211 | return pendingRequests[port]; 1212 | } 1213 | return ajax.apply(this, arguments); 1214 | }; 1215 | } 1216 | }(jQuery)); 1217 | 1218 | // provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation 1219 | // handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target 1220 | (function($) { 1221 | $.extend($.fn, { 1222 | validateDelegate: function( delegate, type, handler ) { 1223 | return this.bind(type, function( event ) { 1224 | var target = $(event.target); 1225 | if ( target.is(delegate) ) { 1226 | return handler.apply(target, arguments); 1227 | } 1228 | }); 1229 | } 1230 | }); 1231 | }(jQuery)); 1232 | -------------------------------------------------------------------------------- /src/Module1/Controllers/Module1Controller.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNet.Mvc; 3 | 4 | namespace Module1.Controllers 5 | { 6 | public class Module1Controller : Controller 7 | { 8 | public IActionResult Index() 9 | { 10 | //return Content("Hello from Module1!!!"); 11 | return View(); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/Module1/Module1.kproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 14.0 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | 9 | 54e8903b-d80d-4448-a81d-edca38e3ee8c 10 | Module1 11 | ..\..\artifacts\obj\$(MSBuildProjectName) 12 | ..\..\artifacts\bin\$(MSBuildProjectName)\ 13 | 14 | 15 | 2.0 16 | 17 | 18 | True 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/Module1/Views/Module1/Index.cshtml: -------------------------------------------------------------------------------- 1 | 

    Hello from Module1

    2 | @Html.ActionLink("Back home", "Index", "Home") -------------------------------------------------------------------------------- /src/Module1/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0-*", 3 | "dependencies": { 4 | "Microsoft.AspNet.Mvc": "6.0.0-beta3", 5 | }, 6 | "resources": "Views/**", 7 | "frameworks" : { 8 | "aspnet50" : { 9 | "dependencies": { 10 | } 11 | }, 12 | "aspnetcore50" : { 13 | "dependencies": { 14 | "System.Runtime": "4.0.20-beta-22523" 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Module2/Areas/Module2/Content/module2.css: -------------------------------------------------------------------------------- 1 | h1{ 2 | color:red; 3 | } -------------------------------------------------------------------------------- /src/Module2/Areas/Module2/Controllers/WeatherController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNet.Mvc; 3 | 4 | namespace Module2.Controllers 5 | { 6 | [Area("Module2")] 7 | public class WeatherController : Controller 8 | { 9 | public IActionResult Index() 10 | { 11 | return View(); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Module2/Areas/Module2/Views/Weather/Index.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 |

    The Module2 WeatherController says that today will be sunny

    7 |
    The above text should be red (if it isn't then the stylesheet hasn't been resolved!)
    8 | @Html.ActionLink("Back home", "Index", "Home") 9 | 10 | -------------------------------------------------------------------------------- /src/Module2/Module2.kproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 14.0 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | 9 | c9f291b3-ca16-427d-a64a-1013a2c97f5c 10 | Module2 11 | ..\..\artifacts\obj\$(MSBuildProjectName) 12 | ..\..\artifacts\bin\$(MSBuildProjectName)\ 13 | 14 | 15 | 2.0 16 | 17 | 18 | True 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/Module2/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0-*", 3 | "dependencies": { 4 | "Microsoft.AspNet.Mvc": "6.0.0-beta3" 5 | }, 6 | "resources": [ "Areas/Module2/Views/**", "Areas/Module2/Content/**" ], 7 | "frameworks": { 8 | "aspnet50": { 9 | "dependencies": { 10 | } 11 | }, 12 | "aspnetcore50": { 13 | "dependencies": { 14 | "System.Runtime": "4.0.20-beta-22523" 15 | } 16 | } 17 | } 18 | } 19 | --------------------------------------------------------------------------------