├── .gitattributes ├── .gitignore ├── .nuget ├── NuGet.Config ├── NuGet.exe └── NuGet.targets ├── LICENSE ├── README.md ├── htbox-website.sln ├── packages └── repositories.config └── src └── htbox ├── App_Code ├── Benthos.Web.cshtml └── CMS.cshtml ├── App_Data └── HTBox_Dev_Content.gz ├── App_Start ├── Benthos_N2CMS.cs ├── FilterConfig.cs ├── RouteConfig.cs └── WebApiConfig.cs ├── Controllers ├── CMS │ ├── BlogController.cs │ ├── BlogPostController.cs │ ├── ContentController.cs │ └── HomePageController.cs ├── MailingListController.cs └── SampleMVCController.cs ├── Global.asax ├── Global.asax.cs ├── N2 ├── N2.zip ├── n2cms.configuration.xsd └── web.config ├── Properties └── AssemblyInfo.cs ├── Scripts ├── jquery-1.10.2.intellisense.js ├── jquery-1.10.2.js ├── jquery-1.10.2.min.js ├── jquery-1.10.2.min.map ├── jquery.unobtrusive-ajax.js ├── jquery.unobtrusive-ajax.min.js ├── jquery.validate-vsdoc.js ├── jquery.validate.js ├── jquery.validate.min.js ├── jquery.validate.unobtrusive.js └── jquery.validate.unobtrusive.min.js ├── ViewModels ├── CMS │ ├── Blog.cs │ ├── BlogPost.cs │ ├── CMSBasePage.cs │ ├── CMSPage.cs │ ├── FakePart.cs │ ├── FakePartList.cs │ ├── HomePage.cs │ └── Redirect.cs └── MailingListSubscribeViewModel.cs ├── Views ├── Blog │ └── Index.cshtml ├── BlogPost │ └── Index.cshtml ├── CMS │ └── Index.cshtml ├── HomePage │ └── Index.cshtml ├── MailingList │ └── Subscribe.cshtml ├── SampleMVC │ └── Index.cshtml ├── Shared │ └── _Layout.cshtml ├── Web.config └── _ViewStart.cshtml ├── Web.Debug.config ├── Web.Release.config ├── Web.config ├── _ImportedCode └── Benthos.N2CMS │ ├── N2CMSAwareMvcController.cs │ └── N2CMSDelegatingControllerFactory.cs ├── htbox.csproj ├── packages.config ├── static ├── css │ ├── app │ │ └── htbox-website.css │ ├── bootstrap │ │ ├── bootstrap.css │ │ └── bootstrap.min.css │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ └── glyphicons-halflings-regular.woff │ └── wp8fix │ │ └── wp8fix.css ├── img │ ├── appbar.rss.hover.png │ └── appbar.rss.png └── js │ ├── bootstrap │ ├── bootstrap.js │ └── bootstrap.min.js │ ├── html5shiv │ └── html5shiv.js │ ├── jcarousel │ ├── jquery.jcarousel-autoscroll.js │ ├── jquery.jcarousel-autoscroll.min.js │ ├── jquery.jcarousel.js │ └── jquery.jcarousel.min.js │ ├── jquery │ ├── jquery-1.10.2.intellisense.js │ ├── jquery-1.10.2.js │ ├── jquery-1.10.2.min.js │ └── jquery-1.10.2.min.map │ ├── mvc-validate │ ├── jquery.unobtrusive-ajax.js │ ├── jquery.unobtrusive-ajax.min.js │ ├── jquery.validate-vsdoc.js │ ├── jquery.validate.js │ ├── jquery.validate.min.js │ ├── jquery.validate.unobtrusive.bootstrap.js │ ├── jquery.validate.unobtrusive.js │ └── jquery.validate.unobtrusive.min.js │ ├── respond │ ├── respond.min.js │ └── respond.src.js │ └── wp8fix │ └── wp8fix.js └── upload └── about └── Kenya 294.JPG.png /.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 | # N2 zip file - actually have to include for azure build 5 | #N2.zip 6 | src/*/upload 7 | 8 | 9 | src/*/App_Data/Temp 10 | src/*/Properties/PublishProfiles 11 | 12 | App_Data 13 | 14 | # User-specific files 15 | *.suo 16 | *.user 17 | *.sln.docstates 18 | 19 | # Build results 20 | 21 | [Dd]ebug/ 22 | [Rr]elease/ 23 | x64/ 24 | build/ 25 | [Bb]in/ 26 | [Oo]bj/ 27 | 28 | # MSTest test Results 29 | [Tt]est[Rr]esult*/ 30 | [Bb]uild[Ll]og.* 31 | 32 | *_i.c 33 | *_p.c 34 | *.ilk 35 | *.meta 36 | *.obj 37 | *.pch 38 | *.pdb 39 | *.pgc 40 | *.pgd 41 | *.rsp 42 | *.sbr 43 | *.tlb 44 | *.tli 45 | *.tlh 46 | *.tmp 47 | *.tmp_proj 48 | *.log 49 | *.vspscc 50 | *.vssscc 51 | .builds 52 | *.pidb 53 | *.log 54 | *.scc 55 | 56 | # Visual C++ cache files 57 | ipch/ 58 | *.aps 59 | *.ncb 60 | *.opensdf 61 | *.sdf 62 | *.cachefile 63 | 64 | # Visual Studio profiler 65 | *.psess 66 | *.vsp 67 | *.vspx 68 | 69 | # Guidance Automation Toolkit 70 | *.gpState 71 | 72 | # ReSharper is a .NET coding add-in 73 | _ReSharper*/ 74 | *.[Rr]e[Ss]harper 75 | 76 | # TeamCity is a build add-in 77 | _TeamCity* 78 | 79 | # DotCover is a Code Coverage Tool 80 | *.dotCover 81 | 82 | # NCrunch 83 | *.ncrunch* 84 | .*crunch*.local.xml 85 | 86 | # Installshield output folder 87 | [Ee]xpress/ 88 | 89 | # DocProject is a documentation generator add-in 90 | DocProject/buildhelp/ 91 | DocProject/Help/*.HxT 92 | DocProject/Help/*.HxC 93 | DocProject/Help/*.hhc 94 | DocProject/Help/*.hhk 95 | DocProject/Help/*.hhp 96 | DocProject/Help/Html2 97 | DocProject/Help/html 98 | 99 | # Click-Once directory 100 | publish/ 101 | 102 | # Publish Web Output 103 | *.Publish.xml 104 | 105 | # NuGet Packages Directory 106 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 107 | packages/* 108 | 109 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets 110 | !packages/*/build/ 111 | 112 | # don't lose the repositories.config for custom nuget feeds 113 | !packages/repositories.config 114 | 115 | # Windows Azure Build Output 116 | csx 117 | *.build.csdef 118 | 119 | # Windows Store app package directory 120 | AppPackages/ 121 | 122 | # Others 123 | sql/ 124 | *.Cache 125 | ClientBin/ 126 | [Ss]tyle[Cc]op.* 127 | ~$* 128 | *~ 129 | *.dbmdl 130 | *.[Pp]ublish.xml 131 | *.pfx 132 | *.publishsettings 133 | 134 | # RIA/Silverlight projects 135 | Generated_Code/ 136 | 137 | # Backup & report files from converting an old project file to a newer 138 | # Visual Studio version. Backup files are not needed, because we have git ;-) 139 | _UpgradeReport_Files/ 140 | Backup*/ 141 | UpgradeLog*.XML 142 | UpgradeLog*.htm 143 | 144 | # SQL Server files 145 | App_Data/*.mdf 146 | App_Data/*.ldf 147 | 148 | 149 | #LightSwitch generated files 150 | GeneratedArtifacts/ 151 | _Pvt_Extensions/ 152 | ModelManifest.xml 153 | 154 | # ========================= 155 | # Windows detritus 156 | # ========================= 157 | 158 | # Windows image file caches 159 | Thumbs.db 160 | ehthumbs.db 161 | 162 | # Folder config file 163 | Desktop.ini 164 | 165 | # Recycle Bin used on file shares 166 | $RECYCLE.BIN/ 167 | 168 | # Mac desktop service store files 169 | .DS_Store 170 | -------------------------------------------------------------------------------- /.nuget/NuGet.Config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.nuget/NuGet.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HTBox/htbox-website/69c0755249eccd5b360b32e85c143461c90851d8/.nuget/NuGet.exe -------------------------------------------------------------------------------- /.nuget/NuGet.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildProjectDirectory)\..\ 5 | 6 | 7 | false 8 | 9 | 10 | false 11 | 12 | 13 | true 14 | 15 | 16 | false 17 | 18 | 19 | 20 | 21 | 22 | 26 | 27 | 28 | 29 | 30 | $([System.IO.Path]::Combine($(SolutionDir), ".nuget")) 31 | $([System.IO.Path]::Combine($(ProjectDir), "packages.config")) 32 | 33 | 34 | 35 | 36 | $(SolutionDir).nuget 37 | packages.config 38 | 39 | 40 | 41 | 42 | $(NuGetToolsPath)\NuGet.exe 43 | @(PackageSource) 44 | 45 | "$(NuGetExePath)" 46 | mono --runtime=v4.0.30319 $(NuGetExePath) 47 | 48 | $(TargetDir.Trim('\\')) 49 | 50 | -RequireConsent 51 | -NonInteractive 52 | 53 | 54 | $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir "$(SolutionDir) " 55 | $(NuGetCommand) pack "$(ProjectPath)" -Properties Configuration=$(Configuration) $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols 56 | 57 | 58 | 59 | RestorePackages; 60 | $(BuildDependsOn); 61 | 62 | 63 | 64 | 65 | $(BuildDependsOn); 66 | BuildPackage; 67 | 68 | 69 | 70 | 71 | 72 | 73 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | 95 | 97 | 98 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, and 10 | distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by the copyright 13 | owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all other entities 16 | that control, are controlled by, or are under common control with that entity. 17 | For the purposes of this definition, "control" means (i) the power, direct or 18 | indirect, to cause the direction or management of such entity, whether by 19 | contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the 20 | outstanding shares, or (iii) beneficial ownership of such entity. 21 | 22 | "You" (or "Your") shall mean an individual or Legal Entity exercising 23 | permissions granted by this License. 24 | 25 | "Source" form shall mean the preferred form for making modifications, including 26 | but not limited to software source code, documentation source, and configuration 27 | files. 28 | 29 | "Object" form shall mean any form resulting from mechanical transformation or 30 | translation of a Source form, including but not limited to compiled object code, 31 | generated documentation, and conversions to other media types. 32 | 33 | "Work" shall mean the work of authorship, whether in Source or Object form, made 34 | available under the License, as indicated by a copyright notice that is included 35 | in or attached to the work (an example is provided in the Appendix below). 36 | 37 | "Derivative Works" shall mean any work, whether in Source or Object form, that 38 | is based on (or derived from) the Work and for which the editorial revisions, 39 | annotations, elaborations, or other modifications represent, as a whole, an 40 | original work of authorship. For the purposes of this License, Derivative Works 41 | shall not include works that remain separable from, or merely link (or bind by 42 | name) to the interfaces of, the Work and Derivative Works thereof. 43 | 44 | "Contribution" shall mean any work of authorship, including the original version 45 | of the Work and any modifications or additions to that Work or Derivative Works 46 | thereof, that is intentionally submitted to Licensor for inclusion in the Work 47 | by the copyright owner or by an individual or Legal Entity authorized to submit 48 | on behalf of the copyright owner. For the purposes of this definition, 49 | "submitted" means any form of electronic, verbal, or written communication sent 50 | to the Licensor or its representatives, including but not limited to 51 | communication on electronic mailing lists, source code control systems, and 52 | issue tracking systems that are managed by, or on behalf of, the Licensor for 53 | the purpose of discussing and improving the Work, but excluding communication 54 | that is conspicuously marked or otherwise designated in writing by the copyright 55 | owner as "Not a Contribution." 56 | 57 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf 58 | of whom a Contribution has been received by Licensor and subsequently 59 | incorporated within the Work. 60 | 61 | 2. Grant of Copyright License. 62 | 63 | Subject to the terms and conditions of this License, each Contributor hereby 64 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, 65 | irrevocable copyright license to reproduce, prepare Derivative Works of, 66 | publicly display, publicly perform, sublicense, and distribute the Work and such 67 | Derivative Works in Source or Object form. 68 | 69 | 3. Grant of Patent License. 70 | 71 | Subject to the terms and conditions of this License, each Contributor hereby 72 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, 73 | irrevocable (except as stated in this section) patent license to make, have 74 | made, use, offer to sell, sell, import, and otherwise transfer the Work, where 75 | such license applies only to those patent claims licensable by such Contributor 76 | that are necessarily infringed by their Contribution(s) alone or by combination 77 | of their Contribution(s) with the Work to which such Contribution(s) was 78 | submitted. If You institute patent litigation against any entity (including a 79 | cross-claim or counterclaim in a lawsuit) alleging that the Work or a 80 | Contribution incorporated within the Work constitutes direct or contributory 81 | patent infringement, then any patent licenses granted to You under this License 82 | for that Work shall terminate as of the date such litigation is filed. 83 | 84 | 4. Redistribution. 85 | 86 | You may reproduce and distribute copies of the Work or Derivative Works thereof 87 | in any medium, with or without modifications, and in Source or Object form, 88 | provided that You meet the following conditions: 89 | 90 | You must give any other recipients of the Work or Derivative Works a copy of 91 | this License; and 92 | You must cause any modified files to carry prominent notices stating that You 93 | changed the files; and 94 | You must retain, in the Source form of any Derivative Works that You distribute, 95 | all copyright, patent, trademark, and attribution notices from the Source form 96 | of the Work, excluding those notices that do not pertain to any part of the 97 | Derivative Works; and 98 | If the Work includes a "NOTICE" text file as part of its distribution, then any 99 | Derivative Works that You distribute must include a readable copy of the 100 | attribution notices contained within such NOTICE file, excluding those notices 101 | that do not pertain to any part of the Derivative Works, in at least one of the 102 | following places: within a NOTICE text file distributed as part of the 103 | Derivative Works; within the Source form or documentation, if provided along 104 | with the Derivative Works; or, within a display generated by the Derivative 105 | Works, if and wherever such third-party notices normally appear. The contents of 106 | the NOTICE file are for informational purposes only and do not modify the 107 | License. You may add Your own attribution notices within Derivative Works that 108 | You distribute, alongside or as an addendum to the NOTICE text from the Work, 109 | provided that such additional attribution notices cannot be construed as 110 | modifying the License. 111 | You may add Your own copyright statement to Your modifications and may provide 112 | additional or different license terms and conditions for use, reproduction, or 113 | distribution of Your modifications, or for any such Derivative Works as a whole, 114 | provided Your use, reproduction, and distribution of the Work otherwise complies 115 | with the conditions stated in this License. 116 | 117 | 5. Submission of Contributions. 118 | 119 | Unless You explicitly state otherwise, any Contribution intentionally submitted 120 | for inclusion in the Work by You to the Licensor shall be under the terms and 121 | conditions of this License, without any additional terms or conditions. 122 | Notwithstanding the above, nothing herein shall supersede or modify the terms of 123 | any separate license agreement you may have executed with Licensor regarding 124 | such Contributions. 125 | 126 | 6. Trademarks. 127 | 128 | This License does not grant permission to use the trade names, trademarks, 129 | service marks, or product names of the Licensor, except as required for 130 | reasonable and customary use in describing the origin of the Work and 131 | reproducing the content of the NOTICE file. 132 | 133 | 7. Disclaimer of Warranty. 134 | 135 | Unless required by applicable law or agreed to in writing, Licensor provides the 136 | Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, 137 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, 138 | including, without limitation, any warranties or conditions of TITLE, 139 | NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are 140 | solely responsible for determining the appropriateness of using or 141 | redistributing the Work and assume any risks associated with Your exercise of 142 | permissions under this License. 143 | 144 | 8. Limitation of Liability. 145 | 146 | In no event and under no legal theory, whether in tort (including negligence), 147 | contract, or otherwise, unless required by applicable law (such as deliberate 148 | and grossly negligent acts) or agreed to in writing, shall any Contributor be 149 | liable to You for damages, including any direct, indirect, special, incidental, 150 | or consequential damages of any character arising as a result of this License or 151 | out of the use or inability to use the Work (including but not limited to 152 | damages for loss of goodwill, work stoppage, computer failure or malfunction, or 153 | any and all other commercial damages or losses), even if such Contributor has 154 | been advised of the possibility of such damages. 155 | 156 | 9. Accepting Warranty or Additional Liability. 157 | 158 | While redistributing the Work or Derivative Works thereof, You may choose to 159 | offer, and charge a fee for, acceptance of support, warranty, indemnity, or 160 | other liability obligations and/or rights consistent with this License. However, 161 | in accepting such obligations, You may act only on Your own behalf and on Your 162 | sole responsibility, not on behalf of any other Contributor, and only if You 163 | agree to indemnify, defend, and hold each Contributor harmless for any liability 164 | incurred by, or claims asserted against, such Contributor by reason of your 165 | accepting any such warranty or additional liability. 166 | 167 | END OF TERMS AND CONDITIONS 168 | 169 | APPENDIX: How to apply the Apache License to your work 170 | 171 | To apply the Apache License to your work, attach the following boilerplate 172 | notice, with the fields enclosed by brackets "[]" replaced with your own 173 | identifying information. (Don't include the brackets!) The text should be 174 | enclosed in the appropriate comment syntax for the file format. We also 175 | recommend that a file or class name and description of purpose be included on 176 | the same "printed page" as the copyright notice for easier identification within 177 | third-party archives. 178 | 179 | Copyright [yyyy] [name of copyright owner] 180 | 181 | Licensed under the Apache License, Version 2.0 (the "License"); 182 | you may not use this file except in compliance with the License. 183 | You may obtain a copy of the License at 184 | 185 | http://www.apache.org/licenses/LICENSE-2.0 186 | 187 | Unless required by applicable law or agreed to in writing, software 188 | distributed under the License is distributed on an "AS IS" BASIS, 189 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 190 | See the License for the specific language governing permissions and 191 | limitations under the License. 192 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | htbox-website 2 | ============= 3 | 4 | code for htbox website 5 | 6 | #### Contributing to www.htbox.org 7 | 8 | As the site is built on a CMS, you will need an inital package of content to setup your local dev copy of the website project. 9 | 10 | The following [How To Guide](http://tsblog.azurewebsites.net/how-to-prepare-local-copy-of-www-htbox-org/) provides the steps you will need to follow the first time you setup a local clone of our repository to develop locally. 11 | 12 | Thanks in advance for contributing! 13 | -------------------------------------------------------------------------------- /htbox-website.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "htbox", "src\htbox\htbox.csproj", "{38F94502-9556-475D-94DA-FE679C887307}" 5 | EndProject 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{296492B4-8BEC-4522-8AE6-B604CBA46A8C}" 7 | ProjectSection(SolutionItems) = preProject 8 | .nuget\NuGet.Config = .nuget\NuGet.Config 9 | .nuget\NuGet.exe = .nuget\NuGet.exe 10 | .nuget\NuGet.targets = .nuget\NuGet.targets 11 | EndProjectSection 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug|Any CPU = Debug|Any CPU 16 | Release|Any CPU = Release|Any CPU 17 | EndGlobalSection 18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 19 | {38F94502-9556-475D-94DA-FE679C887307}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 20 | {38F94502-9556-475D-94DA-FE679C887307}.Debug|Any CPU.Build.0 = Debug|Any CPU 21 | {38F94502-9556-475D-94DA-FE679C887307}.Release|Any CPU.ActiveCfg = Release|Any CPU 22 | {38F94502-9556-475D-94DA-FE679C887307}.Release|Any CPU.Build.0 = Release|Any CPU 23 | EndGlobalSection 24 | GlobalSection(SolutionProperties) = preSolution 25 | HideSolutionNode = FALSE 26 | EndGlobalSection 27 | EndGlobal 28 | -------------------------------------------------------------------------------- /packages/repositories.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /src/htbox/App_Code/Benthos.Web.cshtml: -------------------------------------------------------------------------------- 1 | @using System.Web.Mvc 2 | 3 | @helper AlertBox(TempDataDictionary tempData) { 4 | var alertkey = tempData.Keys.FirstOrDefault(key => key.StartsWith("alert-")); 5 | if (alertkey == null) { 6 | return; 7 | } 8 | 9 |
10 | 11 | @AlertMessage(tempData[alertkey].ToString()) 12 |
13 | } 14 | 15 | @helper AlertMessage(string message) { 16 | 17 | var index = message.IndexOf("!"); 18 | if (index == -1) { 19 | @message 20 | } else { 21 | @message.Substring(0, index + 1) @message.Substring(index + 1) 22 | } 23 | } -------------------------------------------------------------------------------- /src/htbox/App_Code/CMS.cshtml: -------------------------------------------------------------------------------- 1 | @using N2 2 | @using N2.Collections 3 | @using htbox.ViewModels.CMS 4 | @using NHibernate.Dialect.Schema 5 | 6 | @functions { 7 | 8 | public static int NavId() { 9 | var start = N2.Find.StartPage; 10 | var current = N2.Find.CurrentPage; 11 | var ViewBag = ((System.Web.Mvc.WebViewPage)PageContext.Page).ViewBag; 12 | 13 | if (current != null) { 14 | if (start.ID == current.ID) { 15 | return start.ID; 16 | } else { 17 | var top = N2.Find.AtLevel(current, start, 2); 18 | return top.ID; 19 | } 20 | } else if (ViewBag.BackingContentId != null) { 21 | if (ViewBag.BackingContentId is int) { 22 | return (int)ViewBag.BackingContentId; 23 | } 24 | } 25 | 26 | return -1; 27 | } 28 | } 29 | 30 | @helper FooterText() { 31 | var start = N2.Find.StartPage as htbox.ViewModels.CMS.HomePage; 32 | @start.FooterText 33 | } 34 | 35 | @helper TopNavId() { 36 | var start = N2.Find.StartPage; 37 | var current = N2.Find.CurrentPage; 38 | var result = ""; 39 | 40 | if (current != null) { 41 | if (start.ID == current.ID) { 42 | result = start.Name; 43 | } else { 44 | var top = N2.Find.AtLevel(current, start, 2); 45 | result = top.Name; 46 | } 47 | } else { 48 | result = "NotFound"; 49 | } 50 | 51 | @result.ToLowerInvariant().Trim().Replace(" ", "-") 52 | } 53 | 54 | 55 | @helper SiteNav() { 56 | var start = N2.Find.StartPage; 57 | var navId = NavId(); 58 | foreach (var item in start.Children.FindNavigatablePages()) { 59 | if (item.ID == navId) { 60 |
  • @item.Title
  • 61 | } else { 62 |
  • @item.Title
  • 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /src/htbox/App_Data/HTBox_Dev_Content.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HTBox/htbox-website/69c0755249eccd5b360b32e85c143461c90851d8/src/htbox/App_Data/HTBox_Dev_Content.gz -------------------------------------------------------------------------------- /src/htbox/App_Start/Benthos_N2CMS.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | 8 | using Benthos.N2CMS; 9 | 10 | using N2.Web.Mvc; 11 | 12 | [assembly: WebActivatorEx.PreApplicationStartMethod(typeof(htbox.App_Start.Benthos_N2CMS), "PreStart")] 13 | [assembly: WebActivatorEx.PostApplicationStartMethod(typeof(htbox.App_Start.Benthos_N2CMS), "PostStart")] 14 | 15 | namespace htbox.App_Start { 16 | public class Benthos_N2CMS { 17 | static IControllerFactory _cmsFactory; 18 | static IControllerFactory _factory; 19 | 20 | public static void PreStart() { 21 | _factory = ControllerBuilder.Current.GetControllerFactory(); 22 | 23 | var engine = MvcEngine.Create(); 24 | _cmsFactory = ControllerBuilder.Current.GetControllerFactory(); 25 | 26 | RouteTable.Routes.MapContentRoute("Content", engine); 27 | } 28 | 29 | public static void PostStart() { 30 | ControllerBuilder.Current.SetControllerFactory(new N2CMSDelegatingControllerFactory(_cmsFactory, _factory)); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /src/htbox/App_Start/FilterConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Mvc; 3 | 4 | namespace htbox { 5 | public class FilterConfig { 6 | public static void RegisterGlobalFilters(GlobalFilterCollection filters) { 7 | filters.Add(new HandleErrorAttribute()); 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /src/htbox/App_Start/RouteConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | 8 | namespace htbox { 9 | public class RouteConfig { 10 | public static void RegisterRoutes(RouteCollection routes) { 11 | routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 12 | 13 | routes.MapRoute( 14 | name: "Default", 15 | url: "{controller}/{action}/{id}", 16 | defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 17 | ); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /src/htbox/App_Start/WebApiConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web.Http; 5 | 6 | namespace htbox { 7 | public static class WebApiConfig { 8 | public static void Register(HttpConfiguration config) { 9 | config.Routes.MapHttpRoute( 10 | name: "DefaultApi", 11 | routeTemplate: "api/{controller}/{id}", 12 | defaults: new { id = RouteParameter.Optional } 13 | ); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/htbox/Controllers/CMS/BlogController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Web.Mvc; 3 | using System.ServiceModel.Syndication; 4 | using System.Xml; 5 | 6 | using htbox.ViewModels.CMS; 7 | 8 | using N2.Web; 9 | using N2.Web.Mvc; 10 | using System.Collections.Generic; 11 | 12 | namespace htbox.Controllers.CMS { 13 | [Controls(typeof(Blog))] 14 | public class BlogController : ContentController { 15 | public override ActionResult Index() { 16 | return base.Index(); 17 | } 18 | 19 | public ActionResult Rss() { 20 | return new RssActionResult(GetFeed()); 21 | } 22 | 23 | public ActionResult Atom() { 24 | return new AtomActionResult(GetFeed()); 25 | } 26 | 27 | private SyndicationFeed GetFeed() { 28 | var blog = CurrentItem; 29 | 30 | var feed = new SyndicationFeed() { 31 | Title = new TextSyndicationContent(blog.PageTitle), 32 | Description = new TextSyndicationContent(blog.Text, TextSyndicationContentKind.Html), 33 | BaseUri = new Uri(Request.Url.Scheme + "://" + Request.Url.Authority + blog.Url), 34 | Items = GetItems(), 35 | }; 36 | 37 | return feed; 38 | } 39 | 40 | private IEnumerable GetItems() { 41 | foreach (var p in CurrentItem.RecentPosts) { 42 | var item = new SyndicationItem(p.Title, p.Text, new Uri(Request.Url.Scheme + "://" + Request.Url.Authority + p.Url), Request.Url.Scheme + "://" + Request.Url.Authority + p.Url, p.Published.Value); 43 | 44 | item.Authors.Add(new SyndicationPerson("", "Humanitarian Toolbox", "")); 45 | item.PublishDate = p.Published.Value; 46 | item.Content = new TextSyndicationContent(p.Text, TextSyndicationContentKind.Html); 47 | yield return item; 48 | } 49 | } 50 | } 51 | 52 | public class AtomActionResult : ActionResult { 53 | public AtomActionResult(SyndicationFeed feed) { 54 | Feed = feed; 55 | } 56 | 57 | public SyndicationFeed Feed { get; set; } 58 | public override void ExecuteResult(ControllerContext context) { 59 | context.HttpContext.Response.ContentType = "application/atom+xml"; 60 | var formatter = new Atom10FeedFormatter(Feed); 61 | using (var writer = XmlWriter.Create(context.HttpContext.Response.Output, new XmlWriterSettings { Indent = true })) 62 | formatter.WriteTo(writer); 63 | } 64 | } 65 | 66 | public class RssActionResult : ActionResult { 67 | public RssActionResult(SyndicationFeed feed) { 68 | Feed = feed; 69 | } 70 | 71 | public SyndicationFeed Feed { get; set; } 72 | public override void ExecuteResult(ControllerContext context) { 73 | context.HttpContext.Response.ContentType = "application/rss+xml"; 74 | var formatter = new Rss20FeedFormatter(Feed); 75 | using (var writer = XmlWriter.Create(context.HttpContext.Response.Output, new XmlWriterSettings { Indent = true })) 76 | formatter.WriteTo(writer); 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /src/htbox/Controllers/CMS/BlogPostController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Web.Mvc; 3 | 4 | using htbox.ViewModels.CMS; 5 | 6 | using N2.Web; 7 | using N2.Web.Mvc; 8 | 9 | namespace htbox.Controllers.CMS { 10 | [Controls(typeof(BlogPost))] 11 | public class BlogPostController : ContentController { 12 | public override ActionResult Index() { 13 | return base.Index(); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/htbox/Controllers/CMS/ContentController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Web.Mvc; 3 | 4 | using htbox.ViewModels.CMS; 5 | 6 | using N2.Web; 7 | using N2.Web.Mvc; 8 | 9 | namespace htbox.Controllers.CMS { 10 | [Controls(typeof(CMSPage))] 11 | public class CMSController : ContentController { 12 | public override ActionResult Index() { 13 | 14 | if (!string.IsNullOrWhiteSpace(CurrentItem.MvcSubstitueUrl)) { 15 | var url = CurrentItem.MvcSubstitueUrl + "?backingcontentid=" + CurrentItem.ID; 16 | return Redirect(url); 17 | } 18 | 19 | return base.Index(); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/htbox/Controllers/CMS/HomePageController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Web.Mvc; 3 | 4 | using htbox.ViewModels.CMS; 5 | 6 | using N2.Web; 7 | using N2.Web.Mvc; 8 | 9 | namespace htbox.Controllers.CMS { 10 | [Controls(typeof(HomePage))] 11 | public class HomePageController : ContentController { 12 | public override ActionResult Index() { 13 | return base.Index(); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/htbox/Controllers/MailingListController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using System.Web; 7 | using System.Web.Mvc; 8 | 9 | using MailChimp; 10 | using MailChimp.Net; 11 | 12 | using htbox.ViewModels; 13 | using htbox._ImportedCode.Benthos.N2CMS; 14 | using MailChimp.Net.Interfaces; 15 | using MailChimp.Net.Models; 16 | 17 | namespace htbox.Controllers 18 | { 19 | public class MailingListController : N2CMSAwareMvcController { 20 | 21 | public ActionResult Subscribe() { 22 | //TODO: Move this back to base class 23 | if (TempData["ViewData"] != null) 24 | ViewData = (ViewDataDictionary)TempData["ViewData"]; 25 | 26 | ViewBag.Content = BackingContentSource; 27 | 28 | var model = new MailingListSubscribeViewModel(); 29 | 30 | return View(model); 31 | } 32 | 33 | // 34 | // POST: /MailingList/Create 35 | [HttpPost] 36 | [ValidateAntiForgeryToken] 37 | public async Task Subscribe(MailingListSubscribeViewModel viewModel) { 38 | //TODO: Remove this as it is for fake processing to check that only ".com" addresses are valid 39 | if (!ModelState.IsValid) { 40 | //TODO: move to base class and need to pull in my tempdata cookieprovider so we are multi-server tolerant with tempdata 41 | TempData["ViewData"] = ViewData; 42 | return RedirectToAction("Subscribe"); 43 | } 44 | 45 | //TODO: do actual subscription processing 46 | 47 | string mailChimpApiKey = ConfigurationSettings.AppSettings["MailChimpApiKey"]; 48 | string mailChimpListId = ConfigurationSettings.AppSettings["MailChimpListId"]; 49 | 50 | IMailChimpManager manager = new MailChimpManager(mailChimpApiKey); 51 | 52 | // Use the Status property if updating an existing member 53 | var member = new Member { EmailAddress = viewModel.EmailAddress, StatusIfNew = Status.Subscribed }; 54 | member.MergeFields.Add("FNAME", viewModel.FirstName); 55 | member.MergeFields.Add("LNAME", viewModel.LastName); 56 | await manager.Members.AddOrUpdateAsync(mailChimpListId, member); 57 | 58 | //TODO: move to base class and need to pull in my tempdata cookieprovider so we are multi-server tolerant with tempdata 59 | TempData["alert-success"] = "Thank you! You are now signed up."; 60 | return RedirectToAction("Subscribe"); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/htbox/Controllers/SampleMVCController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | 7 | namespace htbox.Controllers 8 | { 9 | public class SampleMVCController : Controller 10 | { 11 | // 12 | // GET: /SampleMVC/ 13 | 14 | public ActionResult Index() 15 | { 16 | return View(); 17 | } 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/htbox/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="htbox.MvcApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /src/htbox/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Http; 6 | using System.Web.Mvc; 7 | using System.Web.Routing; 8 | 9 | using N2.Web.Mvc; 10 | 11 | namespace htbox { 12 | // Note: For instructions on enabling IIS6 or IIS7 classic mode, 13 | // visit http://go.microsoft.com/?LinkId=9394801 14 | public class MvcApplication : System.Web.HttpApplication { 15 | protected void Application_Start() { 16 | AreaRegistration.RegisterAllAreas(); 17 | 18 | WebApiConfig.Register(GlobalConfiguration.Configuration); 19 | FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 20 | RouteConfig.RegisterRoutes(RouteTable.Routes); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/htbox/N2/N2.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HTBox/htbox-website/69c0755249eccd5b360b32e85c143461c90851d8/src/htbox/N2/N2.zip -------------------------------------------------------------------------------- /src/htbox/N2/web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /src/htbox/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("htbox")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("htbox")] 13 | [assembly: AssemblyCopyright("Copyright © 2013")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("bb21859a-e2c4-4fb5-8dea-9101dea2e0d3")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /src/htbox/Scripts/jquery.unobtrusive-ajax.js: -------------------------------------------------------------------------------- 1 | /*! 2 | ** Unobtrusive Ajax support library for jQuery 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 window: false, jQuery: false */ 8 | 9 | (function ($) { 10 | var data_click = "unobtrusiveAjaxClick", 11 | data_validation = "unobtrusiveValidation"; 12 | 13 | function getFunction(code, argNames) { 14 | var fn = window, parts = (code || "").split("."); 15 | while (fn && parts.length) { 16 | fn = fn[parts.shift()]; 17 | } 18 | if (typeof (fn) === "function") { 19 | return fn; 20 | } 21 | argNames.push(code); 22 | return Function.constructor.apply(null, argNames); 23 | } 24 | 25 | function isMethodProxySafe(method) { 26 | return method === "GET" || method === "POST"; 27 | } 28 | 29 | function asyncOnBeforeSend(xhr, method) { 30 | if (!isMethodProxySafe(method)) { 31 | xhr.setRequestHeader("X-HTTP-Method-Override", method); 32 | } 33 | } 34 | 35 | function asyncOnSuccess(element, data, contentType) { 36 | var mode; 37 | 38 | if (contentType.indexOf("application/x-javascript") !== -1) { // jQuery already executes JavaScript for us 39 | return; 40 | } 41 | 42 | mode = (element.getAttribute("data-ajax-mode") || "").toUpperCase(); 43 | $(element.getAttribute("data-ajax-update")).each(function (i, update) { 44 | var top; 45 | 46 | switch (mode) { 47 | case "BEFORE": 48 | top = update.firstChild; 49 | $("
    ").html(data).contents().each(function () { 50 | update.insertBefore(this, top); 51 | }); 52 | break; 53 | case "AFTER": 54 | $("
    ").html(data).contents().each(function () { 55 | update.appendChild(this); 56 | }); 57 | break; 58 | default: 59 | $(update).html(data); 60 | break; 61 | } 62 | }); 63 | } 64 | 65 | function asyncRequest(element, options) { 66 | var confirm, loading, method, duration; 67 | 68 | confirm = element.getAttribute("data-ajax-confirm"); 69 | if (confirm && !window.confirm(confirm)) { 70 | return; 71 | } 72 | 73 | loading = $(element.getAttribute("data-ajax-loading")); 74 | duration = element.getAttribute("data-ajax-loading-duration") || 0; 75 | 76 | $.extend(options, { 77 | type: element.getAttribute("data-ajax-method") || undefined, 78 | url: element.getAttribute("data-ajax-url") || undefined, 79 | beforeSend: function (xhr) { 80 | var result; 81 | asyncOnBeforeSend(xhr, method); 82 | result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(this, arguments); 83 | if (result !== false) { 84 | loading.show(duration); 85 | } 86 | return result; 87 | }, 88 | complete: function () { 89 | loading.hide(duration); 90 | getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(this, arguments); 91 | }, 92 | success: function (data, status, xhr) { 93 | asyncOnSuccess(element, data, xhr.getResponseHeader("Content-Type") || "text/html"); 94 | getFunction(element.getAttribute("data-ajax-success"), ["data", "status", "xhr"]).apply(this, arguments); 95 | }, 96 | error: getFunction(element.getAttribute("data-ajax-failure"), ["xhr", "status", "error"]) 97 | }); 98 | 99 | options.data.push({ name: "X-Requested-With", value: "XMLHttpRequest" }); 100 | 101 | method = options.type.toUpperCase(); 102 | if (!isMethodProxySafe(method)) { 103 | options.type = "POST"; 104 | options.data.push({ name: "X-HTTP-Method-Override", value: method }); 105 | } 106 | 107 | $.ajax(options); 108 | } 109 | 110 | function validate(form) { 111 | var validationInfo = $(form).data(data_validation); 112 | return !validationInfo || !validationInfo.validate || validationInfo.validate(); 113 | } 114 | 115 | $(document).on("click", "a[data-ajax=true]", function (evt) { 116 | evt.preventDefault(); 117 | asyncRequest(this, { 118 | url: this.href, 119 | type: "GET", 120 | data: [] 121 | }); 122 | }); 123 | 124 | $(document).on("click", "form[data-ajax=true] input[type=image]", function (evt) { 125 | var name = evt.target.name, 126 | $target = $(evt.target), 127 | form = $target.parents("form")[0], 128 | offset = $target.offset(); 129 | 130 | $(form).data(data_click, [ 131 | { name: name + ".x", value: Math.round(evt.pageX - offset.left) }, 132 | { name: name + ".y", value: Math.round(evt.pageY - offset.top) } 133 | ]); 134 | 135 | setTimeout(function () { 136 | $(form).removeData(data_click); 137 | }, 0); 138 | }); 139 | 140 | $(document).on("click", "form[data-ajax=true] :submit", function (evt) { 141 | var name = evt.target.name, 142 | form = $(evt.target).parents("form")[0]; 143 | 144 | $(form).data(data_click, name ? [{ name: name, value: evt.target.value }] : []); 145 | 146 | setTimeout(function () { 147 | $(form).removeData(data_click); 148 | }, 0); 149 | }); 150 | 151 | $(document).on("submit", "form[data-ajax=true]", function (evt) { 152 | var clickInfo = $(this).data(data_click) || []; 153 | evt.preventDefault(); 154 | if (!validate(this)) { 155 | return; 156 | } 157 | asyncRequest(this, { 158 | url: this.action, 159 | type: this.method || "GET", 160 | data: clickInfo.concat($(this).serializeArray()) 161 | }); 162 | }); 163 | }(jQuery)); -------------------------------------------------------------------------------- /src/htbox/Scripts/jquery.unobtrusive-ajax.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | ** Unobtrusive Ajax support library for jQuery 3 | ** Copyright (C) Microsoft Corporation. All rights reserved. 4 | */ 5 | (function(a){var b="unobtrusiveAjaxClick",g="unobtrusiveValidation";function c(d,b){var a=window,c=(d||"").split(".");while(a&&c.length)a=a[c.shift()];if(typeof a==="function")return a;b.push(d);return Function.constructor.apply(null,b)}function d(a){return a==="GET"||a==="POST"}function f(b,a){!d(a)&&b.setRequestHeader("X-HTTP-Method-Override",a)}function h(c,b,e){var d;if(e.indexOf("application/x-javascript")!==-1)return;d=(c.getAttribute("data-ajax-mode")||"").toUpperCase();a(c.getAttribute("data-ajax-update")).each(function(f,c){var e;switch(d){case"BEFORE":e=c.firstChild;a("
    ").html(b).contents().each(function(){c.insertBefore(this,e)});break;case"AFTER":a("
    ").html(b).contents().each(function(){c.appendChild(this)});break;default:a(c).html(b)}})}function e(b,e){var j,k,g,i;j=b.getAttribute("data-ajax-confirm");if(j&&!window.confirm(j))return;k=a(b.getAttribute("data-ajax-loading"));i=b.getAttribute("data-ajax-loading-duration")||0;a.extend(e,{type:b.getAttribute("data-ajax-method")||undefined,url:b.getAttribute("data-ajax-url")||undefined,beforeSend:function(d){var a;f(d,g);a=c(b.getAttribute("data-ajax-begin"),["xhr"]).apply(this,arguments);a!==false&&k.show(i);return a},complete:function(){k.hide(i);c(b.getAttribute("data-ajax-complete"),["xhr","status"]).apply(this,arguments)},success:function(a,e,d){h(b,a,d.getResponseHeader("Content-Type")||"text/html");c(b.getAttribute("data-ajax-success"),["data","status","xhr"]).apply(this,arguments)},error:c(b.getAttribute("data-ajax-failure"),["xhr","status","error"])});e.data.push({name:"X-Requested-With",value:"XMLHttpRequest"});g=e.type.toUpperCase();if(!d(g)){e.type="POST";e.data.push({name:"X-HTTP-Method-Override",value:g})}a.ajax(e)}function i(c){var b=a(c).data(g);return!b||!b.validate||b.validate()}a(document).on("click","a[data-ajax=true]",function(a){a.preventDefault();e(this,{url:this.href,type:"GET",data:[]})});a(document).on("click","form[data-ajax=true] input[type=image]",function(c){var g=c.target.name,d=a(c.target),f=d.parents("form")[0],e=d.offset();a(f).data(b,[{name:g+".x",value:Math.round(c.pageX-e.left)},{name:g+".y",value:Math.round(c.pageY-e.top)}]);setTimeout(function(){a(f).removeData(b)},0)});a(document).on("click","form[data-ajax=true] :submit",function(c){var e=c.target.name,d=a(c.target).parents("form")[0];a(d).data(b,e?[{name:e,value:c.target.value}]:[]);setTimeout(function(){a(d).removeData(b)},0)});a(document).on("submit","form[data-ajax=true]",function(d){var c=a(this).data(b)||[];d.preventDefault();if(!i(this))return;e(this,{url:this.action,type:this.method||"GET",data:c.concat(a(this).serializeArray())})})})(jQuery); -------------------------------------------------------------------------------- /src/htbox/Scripts/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 | 106 | if (!result) { 107 | result = { 108 | options: { // options structure passed to jQuery Validate's validate() method 109 | errorClass: "input-validation-error", 110 | errorElement: "span", 111 | errorPlacement: $.proxy(onError, form), 112 | invalidHandler: $.proxy(onErrors, form), 113 | messages: {}, 114 | rules: {}, 115 | success: $.proxy(onSuccess, form) 116 | }, 117 | attachValidation: function () { 118 | $form 119 | .unbind("reset." + data_validation, onResetProxy) 120 | .bind("reset." + data_validation, onResetProxy) 121 | .validate(this.options); 122 | }, 123 | validate: function () { // a validation function that is called by unobtrusive Ajax 124 | $form.validate(); 125 | return $form.valid(); 126 | } 127 | }; 128 | $form.data(data_validation, result); 129 | } 130 | 131 | return result; 132 | } 133 | 134 | $jQval.unobtrusive = { 135 | adapters: [], 136 | 137 | parseElement: function (element, skipAttach) { 138 | /// 139 | /// Parses a single HTML element for unobtrusive validation attributes. 140 | /// 141 | /// The HTML element to be parsed. 142 | /// [Optional] true to skip attaching the 143 | /// validation to the form. If parsing just this single element, you should specify true. 144 | /// If parsing several elements, you should specify false, and manually attach the validation 145 | /// to the form when you are finished. The default is false. 146 | var $element = $(element), 147 | form = $element.parents("form")[0], 148 | valInfo, rules, messages; 149 | 150 | if (!form) { // Cannot do client-side validation without a form 151 | return; 152 | } 153 | 154 | valInfo = validationInfo(form); 155 | valInfo.options.rules[element.name] = rules = {}; 156 | valInfo.options.messages[element.name] = messages = {}; 157 | 158 | $.each(this.adapters, function () { 159 | var prefix = "data-val-" + this.name, 160 | message = $element.attr(prefix), 161 | paramValues = {}; 162 | 163 | if (message !== undefined) { // Compare against undefined, because an empty message is legal (and falsy) 164 | prefix += "-"; 165 | 166 | $.each(this.params, function () { 167 | paramValues[this] = $element.attr(prefix + this); 168 | }); 169 | 170 | this.adapt({ 171 | element: element, 172 | form: form, 173 | message: message, 174 | params: paramValues, 175 | rules: rules, 176 | messages: messages 177 | }); 178 | } 179 | }); 180 | 181 | $.extend(rules, { "__dummy__": true }); 182 | 183 | if (!skipAttach) { 184 | valInfo.attachValidation(); 185 | } 186 | }, 187 | 188 | parse: function (selector) { 189 | /// 190 | /// Parses all the HTML elements in the specified selector. It looks for input elements decorated 191 | /// with the [data-val=true] attribute value and enables validation according to the data-val-* 192 | /// attribute values. 193 | /// 194 | /// Any valid jQuery selector. 195 | var $forms = $(selector) 196 | .parents("form") 197 | .andSelf() 198 | .add($(selector).find("form")) 199 | .filter("form"); 200 | 201 | $(selector).find(":input[data-val=true]").each(function () { 202 | $jQval.unobtrusive.parseElement(this, true); 203 | }); 204 | 205 | $forms.each(function () { 206 | var info = validationInfo(this); 207 | if (info) { 208 | info.attachValidation(); 209 | } 210 | }); 211 | } 212 | }; 213 | 214 | adapters = $jQval.unobtrusive.adapters; 215 | 216 | adapters.add = function (adapterName, params, fn) { 217 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation. 218 | /// The name of the adapter to be added. This matches the name used 219 | /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). 220 | /// [Optional] An array of parameter names (strings) that will 221 | /// be extracted from the data-val-nnnn-mmmm HTML attributes (where nnnn is the adapter name, and 222 | /// mmmm is the parameter name). 223 | /// The function to call, which adapts the values from the HTML 224 | /// attributes into jQuery Validate rules and/or messages. 225 | /// 226 | if (!fn) { // Called with no params, just a function 227 | fn = params; 228 | params = []; 229 | } 230 | this.push({ name: adapterName, params: params, adapt: fn }); 231 | return this; 232 | }; 233 | 234 | adapters.addBool = function (adapterName, ruleName) { 235 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where 236 | /// the jQuery Validate validation rule has no parameter values. 237 | /// The name of the adapter to be added. This matches the name used 238 | /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). 239 | /// [Optional] The name of the jQuery Validate rule. If not provided, the value 240 | /// of adapterName will be used instead. 241 | /// 242 | return this.add(adapterName, function (options) { 243 | setValidationValues(options, ruleName || adapterName, true); 244 | }); 245 | }; 246 | 247 | adapters.addMinMax = function (adapterName, minRuleName, maxRuleName, minMaxRuleName, minAttribute, maxAttribute) { 248 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where 249 | /// the jQuery Validate validation has three potential rules (one for min-only, one for max-only, and 250 | /// one for min-and-max). The HTML parameters are expected to be named -min and -max. 251 | /// The name of the adapter to be added. This matches the name used 252 | /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). 253 | /// The name of the jQuery Validate rule to be used when you only 254 | /// have a minimum value. 255 | /// The name of the jQuery Validate rule to be used when you only 256 | /// have a maximum value. 257 | /// The name of the jQuery Validate rule to be used when you 258 | /// have both a minimum and maximum value. 259 | /// [Optional] The name of the HTML attribute that 260 | /// contains the minimum value. The default is "min". 261 | /// [Optional] The name of the HTML attribute that 262 | /// contains the maximum value. The default is "max". 263 | /// 264 | return this.add(adapterName, [minAttribute || "min", maxAttribute || "max"], function (options) { 265 | var min = options.params.min, 266 | max = options.params.max; 267 | 268 | if (min && max) { 269 | setValidationValues(options, minMaxRuleName, [min, max]); 270 | } 271 | else if (min) { 272 | setValidationValues(options, minRuleName, min); 273 | } 274 | else if (max) { 275 | setValidationValues(options, maxRuleName, max); 276 | } 277 | }); 278 | }; 279 | 280 | adapters.addSingleVal = function (adapterName, attribute, ruleName) { 281 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where 282 | /// the jQuery Validate validation rule has a single value. 283 | /// The name of the adapter to be added. This matches the name used 284 | /// in the data-val-nnnn HTML attribute(where nnnn is the adapter name). 285 | /// [Optional] The name of the HTML attribute that contains the value. 286 | /// The default is "val". 287 | /// [Optional] The name of the jQuery Validate rule. If not provided, the value 288 | /// of adapterName will be used instead. 289 | /// 290 | return this.add(adapterName, [attribute || "val"], function (options) { 291 | setValidationValues(options, ruleName || adapterName, options.params[attribute]); 292 | }); 293 | }; 294 | 295 | $jQval.addMethod("__dummy__", function (value, element, params) { 296 | return true; 297 | }); 298 | 299 | $jQval.addMethod("regex", function (value, element, params) { 300 | var match; 301 | if (this.optional(element)) { 302 | return true; 303 | } 304 | 305 | match = new RegExp(params).exec(value); 306 | return (match && (match.index === 0) && (match[0].length === value.length)); 307 | }); 308 | 309 | $jQval.addMethod("nonalphamin", function (value, element, nonalphamin) { 310 | var match; 311 | if (nonalphamin) { 312 | match = value.match(/\W/g); 313 | match = match && match.length >= nonalphamin; 314 | } 315 | return match; 316 | }); 317 | 318 | adapters.addSingleVal("accept", "exts").addSingleVal("regex", "pattern"); 319 | adapters.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"); 320 | adapters.addMinMax("length", "minlength", "maxlength", "rangelength").addMinMax("range", "min", "max", "range"); 321 | adapters.add("equalto", ["other"], function (options) { 322 | var prefix = getModelPrefix(options.element.name), 323 | other = options.params.other, 324 | fullOtherName = appendModelPrefix(other, prefix), 325 | element = $(options.form).find(":input[name='" + escapeAttributeValue(fullOtherName) + "']")[0]; 326 | 327 | setValidationValues(options, "equalTo", element); 328 | }); 329 | adapters.add("required", function (options) { 330 | // jQuery Validate equates "required" with "mandatory" for checkbox elements 331 | if (options.element.tagName.toUpperCase() !== "INPUT" || options.element.type.toUpperCase() !== "CHECKBOX") { 332 | setValidationValues(options, "required", true); 333 | } 334 | }); 335 | adapters.add("remote", ["url", "type", "additionalfields"], function (options) { 336 | var value = { 337 | url: options.params.url, 338 | type: options.params.type || "GET", 339 | data: {} 340 | }, 341 | prefix = getModelPrefix(options.element.name); 342 | 343 | $.each(splitAndTrim(options.params.additionalfields || options.element.name), function (i, fieldName) { 344 | var paramName = appendModelPrefix(fieldName, prefix); 345 | value.data[paramName] = function () { 346 | return $(options.form).find(":input[name='" + escapeAttributeValue(paramName) + "']").val(); 347 | }; 348 | }); 349 | 350 | setValidationValues(options, "remote", value); 351 | }); 352 | adapters.add("password", ["min", "nonalphamin", "regex"], function (options) { 353 | if (options.params.min) { 354 | setValidationValues(options, "minlength", options.params.min); 355 | } 356 | if (options.params.nonalphamin) { 357 | setValidationValues(options, "nonalphamin", options.params.nonalphamin); 358 | } 359 | if (options.params.regex) { 360 | setValidationValues(options, "regex", options.params.regex); 361 | } 362 | }); 363 | 364 | $(function () { 365 | $jQval.unobtrusive.parse(document); 366 | }); 367 | } (jQuery)); -------------------------------------------------------------------------------- /src/htbox/Scripts/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(c){var b=a(c),d=b.data(e),f=a.proxy(n,c);if(!d){d={options:{errorClass:"input-validation-error",errorElement:"span",errorPlacement:a.proxy(m,c),invalidHandler:a.proxy(l,c),messages:{},rules:{},success:a.proxy(k,c)},attachValidation:function(){b.unbind("reset."+e,f).bind("reset."+e,f).validate(this.options)},validate:function(){b.validate();return b.valid()}};b.data(e,d)}return d}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(b){var c=a(b).parents("form").andSelf().add(a(b).find("form")).filter("form");a(b).find(":input[data-val=true]").each(function(){d.unobtrusive.parseElement(this,true)});c.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});b.addSingleVal("accept","exts").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.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[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[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/htbox/ViewModels/CMS/Blog.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | 6 | using N2; 7 | using N2.Definitions; 8 | using N2.Integrity; 9 | 10 | namespace htbox.ViewModels.CMS { 11 | [PageDefinition("Blog")] 12 | [RestrictChildren(typeof(BlogPost))] 13 | [SortChildren(SortBy.Expression, SortExpression = "Published DESC")] 14 | public class Blog : CMSBasePage { 15 | 16 | public List Posts { 17 | get { 18 | return new List(Children.FindNavigatablePages().Cast()); 19 | } 20 | } 21 | 22 | public List RecentPosts { 23 | get { 24 | return new List(Posts.Where(p => p.IsPublished()).Take(10).OrderByDescending(p => p.Published)); 25 | } 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/htbox/ViewModels/CMS/BlogPost.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | 6 | using N2; 7 | using N2.Details; 8 | using N2.Integrity; 9 | 10 | namespace htbox.ViewModels.CMS { 11 | [PageDefinition("Blog Post")] 12 | [RestrictParents(typeof(Blog))] 13 | [WithEditableTitle, WithEditableName] 14 | public class BlogPost : ContentItem { 15 | 16 | [EditableText("Post Title", 90, HelpText = "Longer form title for the Post")] 17 | public virtual string PostTitle { get; set; } 18 | 19 | [EditableFreeTextArea("Post Content", 200)] 20 | public virtual string Text { get; set; } 21 | 22 | [EditableDate("Publish Date", 100)] 23 | public override DateTime? Published { 24 | get { 25 | return base.Published; 26 | } 27 | set { 28 | base.Published = value; 29 | } 30 | } 31 | 32 | [EditableImageUpload("Post Image", 300)] 33 | public virtual string Image { get; set; } 34 | 35 | public bool HasImage { 36 | get { return !string.IsNullOrWhiteSpace(Image); } 37 | } 38 | 39 | public Blog Blog { 40 | get { return Parent as Blog; } 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /src/htbox/ViewModels/CMS/CMSBasePage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using N2; 4 | using N2.Details; 5 | 6 | namespace htbox.ViewModels.CMS { 7 | [WithEditableName, WithEditableTitle] 8 | public abstract class CMSBasePage : ContentItem { 9 | [EditableText("Page Title", 90, HelpText = "Longer form title for display on the page")] 10 | public virtual string PageTitle { get; set; } 11 | 12 | [EditableFreeTextArea("Page Content", 100)] 13 | public virtual string Text { get; set; } 14 | 15 | [EditableCheckBox("Show In Menus", 110, DefaultValue = true)] 16 | public override bool Visible { 17 | get { return base.Visible; } 18 | set { base.Visible = value; } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /src/htbox/ViewModels/CMS/CMSPage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using N2; 4 | using N2.Details; 5 | using N2.Web.UI.WebControls; 6 | 7 | namespace htbox.ViewModels.CMS { 8 | [PageDefinition("Content Page")] 9 | [WithEditableName, WithEditableTitle] 10 | public class CMSPage : CMSBasePage { 11 | 12 | [EditableImageUpload("Template Image", 210, HelpText = "Per Design Guidelines, the image will be responsively resized by device size but shouldn't be larger than 570px wide")] 13 | public virtual string Image { get; set; } 14 | 15 | [EditableText("Template Image Alt Text", 220)] 16 | public virtual string ImageAltText { get; set; } 17 | 18 | [Editable("Substitue Mvc Url", typeof(UrlSelector), "Url", 400, Required = false, HelpText = "Enter a url here to have this page redirect to an mvc controller action but still provide content to that action.")] 19 | public virtual string MvcSubstitueUrl { get; set; } 20 | 21 | public bool HasImage { 22 | get { return !string.IsNullOrWhiteSpace(Image); } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/htbox/ViewModels/CMS/FakePart.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using N2; 4 | 5 | namespace htbox.ViewModels.CMS { 6 | public class FakePart : ContentItem { 7 | 8 | public override string Url { 9 | get { return Parent.Url + "/Item?Key=" + Name; } 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/htbox/ViewModels/CMS/FakePartList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using N2.Collections; 5 | 6 | namespace htbox.ViewModels.CMS { 7 | public class FakePartList : CMSBasePage where TFakePart : FakePart { 8 | public string RequestedName { get; set; } 9 | 10 | ItemList _items = null; 11 | 12 | ItemFilter[] BuildItemFilters() { 13 | var filters = new List {new TypeFilter(typeof (TFakePart)), new PublishedFilter()}; 14 | AdjustItemFilters(filters); 15 | return filters.ToArray(); 16 | } 17 | 18 | protected virtual void AdjustItemFilters(List filters) { 19 | } 20 | 21 | protected virtual string SortExpression { 22 | get { return null; } 23 | } 24 | 25 | public IList Items { 26 | get { 27 | if (_items == null) { 28 | _items = GetChildren(BuildItemFilters()).Cast(); 29 | if (!String.IsNullOrWhiteSpace(SortExpression)) { 30 | _items.Sort(SortExpression); 31 | } 32 | } 33 | return _items; 34 | } 35 | } 36 | 37 | TFakePart _requestedItem = null; 38 | 39 | public TFakePart RequestedItem { 40 | get { 41 | if (_requestedItem == null && !String.IsNullOrWhiteSpace(RequestedName)) { 42 | _requestedItem = ((ItemList) Items).FindNamed(RequestedName); 43 | } 44 | return _requestedItem; 45 | } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /src/htbox/ViewModels/CMS/HomePage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | 6 | using N2; 7 | using N2.Definitions; 8 | using N2.Details; 9 | using N2.Integrity; 10 | 11 | namespace htbox.ViewModels.CMS { 12 | [PageDefinition("Home Page")] 13 | [WithEditableName, WithEditableTitle] 14 | [RestrictParents(typeof(IRootPage))] 15 | public class HomePage : CMSBasePage { 16 | 17 | [EditableText("First Sub Heading", 200)] 18 | public virtual string SubHeading1 { get; set; } 19 | 20 | [EditableText("First Sub Body", 210)] 21 | public virtual string SubBody1 { get; set; } 22 | 23 | [EditableText("Second Sub Heading", 230)] 24 | public virtual string SubHeading2 { get; set; } 25 | 26 | [EditableText("Second Sub Body", 240)] 27 | public virtual string SubBody2 { get; set; } 28 | 29 | [EditableText("Third Sub Heading", 260)] 30 | public virtual string SubHeading3 { get; set; } 31 | 32 | [EditableText("Third Sub Body", 270)] 33 | public virtual string SubBody3 { get; set; } 34 | 35 | [EditableText("Footer Text (for every page)", 600)] 36 | public virtual string FooterText { get; set; } 37 | 38 | public IList RecentItems { 39 | get { return _recentItems ?? (_recentItems = GetRecentItems()); } 40 | } 41 | 42 | public BlogPost FeatureItem { 43 | get { return _featureItem ?? (_featureItem = GetFeatureItem()); } 44 | } 45 | 46 | private BlogPost _featureItem; 47 | private IList _recentItems; 48 | 49 | IList GetRecentItems() { 50 | var items = N2.Find.Items.Where.Type.Eq(typeof(Blog)).Select(); 51 | if (items.Count < 1) 52 | throw new Exception("EventList not found."); 53 | var blog1 = items[0] as Blog; 54 | var posts = blog1.RecentPosts.Take(5).ToList(); 55 | 56 | if (items.Count > 1) { 57 | var blog2 = items[1] as Blog; 58 | posts.AddRange(blog2.RecentPosts.Take(5)); 59 | } 60 | 61 | posts.OrderBy(p => p.Published); 62 | 63 | return posts.Take(5).ToList(); 64 | } 65 | 66 | private BlogPost GetFeatureItem() { 67 | var featureItem = RecentItems.FirstOrDefault(p => !string.IsNullOrWhiteSpace(p.Image)); 68 | 69 | if (featureItem == null) { 70 | featureItem = RecentItems[0]; 71 | } 72 | 73 | return featureItem; 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /src/htbox/ViewModels/CMS/Redirect.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using N2; 4 | using N2.Details; 5 | using N2.Web.UI.WebControls; 6 | 7 | namespace htbox.ViewModels.CMS 8 | { 9 | [PageDefinition("Redirect", 10 | Description = "Redirects to another page or external address", 11 | IconUrl = "~/n2/resources/icons/page_go.png")] 12 | [WithEditableTitle("Title", 10, Focus = true)] 13 | public class Redirect : ContentItem 14 | { 15 | public override string Url 16 | { 17 | get { return N2.Web.Url.ToAbsolute(RedirectUrl); } 18 | } 19 | 20 | [Editable("Redirect To", typeof(UrlSelector), "Url", 40, Required = true)] 21 | public virtual string RedirectUrl { get; set; } 22 | 23 | [EditableCheckBox("301 (Permanent) Redirect?", 100)] 24 | public virtual bool Redirect301 { get; set; } 25 | 26 | [EditableCheckBox("Visible", 100)] 27 | public override bool Visible { 28 | get { return base.Visible; } 29 | set { base.Visible = value; } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/htbox/ViewModels/MailingListSubscribeViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.ComponentModel.DataAnnotations; 5 | using System.Linq; 6 | using System.Web; 7 | 8 | namespace htbox.ViewModels { 9 | public class MailingListSubscribeViewModel { 10 | [Required, DisplayName("First Name")] 11 | public string FirstName { get; set; } 12 | [Required, DisplayName("Last Name")] 13 | public string LastName { get; set; } 14 | 15 | [Required, DisplayName("Email Address"), DataType(DataType.EmailAddress)] 16 | public string EmailAddress { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /src/htbox/Views/Blog/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model htbox.ViewModels.CMS.Blog 2 | 3 | @{ 4 | ViewBag.Title = Model.PageTitle; 5 | ViewBag.TitleSuffixHtml = ""; 6 | ViewBag.SubTitle = Model.Text; 7 | } 8 | 9 | @section Header { 10 | 11 | 12 | } 13 | 14 | @foreach (var post in Model.Posts) { 15 |
    16 |

    @post.PostTitle

    17 | @if (post.Published.HasValue) { 18 |

    @post.Published.Value.ToLongDateString()

    19 | } else { 20 |

     

    21 | } 22 |
    23 |
    24 | @Html.Raw(post.Text) 25 |
    26 |
    27 |
    28 | } -------------------------------------------------------------------------------- /src/htbox/Views/BlogPost/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model htbox.ViewModels.CMS.BlogPost 2 | 3 | @{ 4 | ViewBag.Title = Model.Title + " : " + Model.Blog.PageTitle; 5 | ViewBag.ShowTitleOnPage = false; 6 | ViewBag.BackPage = Model.Blog; 7 | ViewBag.BackPageSuffixHtml = ""; 8 | } 9 | 10 | @section Header { 11 | 12 | 13 | } 14 | 15 | @if (Model.HasImage) { 16 |
    17 |
    18 | 19 |
    20 |
    21 | } 22 |
    23 |

    @Model.Title

    24 | @if (Model.Published.HasValue) { 25 |

    @Model.Published.Value.ToLongDateString()

    26 | } else { 27 |

     

    28 | } 29 |

     

    30 |
    31 |
    32 |
    33 | @Html.Raw(Model.Text) 34 |
    35 |
    36 | 37 | 38 | -------------------------------------------------------------------------------- /src/htbox/Views/CMS/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model htbox.ViewModels.CMS.CMSPage 2 | 3 | @{ 4 | ViewBag.Title = Model.PageTitle; 5 | ViewBag.PageText = Model.Text.Replace("

    Paypal Button

    ", @"
    6 | 7 | 8 | 9 | 10 |
    "); 11 | } 12 | 13 |
    14 | @if (Model.HasImage) { 15 |
    16 | @Html.Raw(ViewBag.PageText) 17 |
    18 | 21 | } else { 22 |
    23 | @Html.Raw(ViewBag.PageText) 24 |
    25 | } 26 |
    -------------------------------------------------------------------------------- /src/htbox/Views/HomePage/Index.cshtml: -------------------------------------------------------------------------------- 1 | @using System.Web.UI.WebControls 2 | @model htbox.ViewModels.CMS.HomePage 3 | 4 | @{ 5 | ViewBag.Title = "Humanitarian Toolbox"; 6 | ViewBag.ShowTitleOnPage = false; 7 | } 8 | 9 | @section Header { 10 | 11 | 12 | } 13 | 14 | @section hero { 15 | 16 |
    17 |
    18 |
      19 |
    • 20 |
    • 21 |
    • 22 |
    • 23 |
    • 24 |
    • 25 |
    • 26 |
    • 27 |
    • 28 |
    • 29 |
    • 30 |
    • 31 |
    • 32 |
    • 33 |
    • 34 |
    35 |
    36 |
    37 |
    38 |
    39 | 40 | @Html.Raw(Model.Text) 41 |

    Sign Up Now »

    42 |
    43 |
    44 |
    45 | } 46 | 47 | 48 |
    49 |
    50 |

    Recent News

    51 |
    52 |
    53 |
    54 | 55 |

    @Model.FeatureItem.PostTitle [learn more]

    56 |

    @Model.FeatureItem.Published.Value.ToShortDateString()

    57 |
    58 |
    59 | @foreach (var item in Model.RecentItems) { 60 | if (item.ID != Model.FeatureItem.ID) { 61 |

    @item.PostTitle
    @item.Published.Value.ToShortDateString()

    62 | } 63 | } 64 |
    65 |
    66 | 67 |
    68 |
    69 |

    What We Do

    70 |
    71 |
    72 |
    73 |

    @Model.SubHeading1

    74 |

    @Model.SubBody1

    75 |
    76 |
    77 |

    @Model.SubHeading2

    78 |

    @Model.SubBody2

    79 |
    80 |
    81 |

    @Model.SubHeading3

    82 |

    @Model.SubBody3

    83 |
    84 |
    85 | 86 |
    87 |

    Humanitarian Toolbox is grateful for the support from these organizations:

    88 |
    NetHope
    89 |
    Geeks Without Borders
    90 |
    Crisis Commons
    91 |
    .NET Rocks!
    92 |
    Microsoft
    93 |
    Telerik
    94 |
    95 | 96 | 97 | @section scripts { 98 | 99 | 100 | 110 | } -------------------------------------------------------------------------------- /src/htbox/Views/MailingList/Subscribe.cshtml: -------------------------------------------------------------------------------- 1 | @model htbox.ViewModels.MailingListSubscribeViewModel 2 | 3 | @{ 4 | ViewBag.Title = "Sign Up"; 5 | 6 | if (ViewBag.Content != null) { 7 | ViewBag.Title = ViewBag.Content.PageTitle; 8 | ViewBag.SubTitle = ViewBag.Content.Text; 9 | } 10 | } 11 | 12 |
    13 | @Html.AntiForgeryToken() 14 | 15 |
    16 |
    17 | 18 | @Html.TextBoxFor(m => m.FirstName, new { @class="form-control", placeholder="First"}) 19 | @Html.ValidationMessageFor(m => m.FirstName, null, new { @class="help-block" }) 20 |
    21 |
    22 | 23 | @Html.TextBoxFor(m => m.LastName, new { @class="form-control", placeholder="Last"}) 24 | @Html.ValidationMessageFor(m => m.LastName, null, new { @class="help-block" }) 25 |
    26 |
    27 |
    28 |
    29 | @Html.LabelFor(m => m.EmailAddress) 30 | @Html.TextBoxFor(m => m.EmailAddress, new { @class="form-control", @type = "email", placeholder="Email address"}) 31 | @Html.ValidationMessageFor(m => m.EmailAddress, null, new { @class="help-block" }) 32 |
    33 |
    34 |
    35 |
    36 | 37 |
    38 | 39 |
    40 |
    41 | 42 |
    43 |
    44 | 45 |
    46 |
    47 |
    48 | 49 |
    50 | 51 |
    52 |
    53 | 54 |
    55 |
    56 | 57 |
    58 |
    59 |
    60 |
    61 |
    62 | 63 | 68 |
    69 |
    70 | 71 |
    72 | 73 | @section scripts { 74 | 75 | 76 | 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/htbox/Views/SampleMVC/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Index"; 3 | } 4 | 5 |

    @ViewBag.Title

    6 | 7 | MVC Page -------------------------------------------------------------------------------- /src/htbox/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | @ViewBag.Title 5 | 6 | @RenderSection("Header", false) 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 49 | 50 | @RenderSection("hero", required:false) 51 | 52 |
    53 | @if (((ViewBag.ShowTitleOnPage == null || ViewBag.ShowTitleOnPage == true) && ViewBag.Title != null) || ViewBag.BackPage != null) { 54 | 65 | } 66 | 67 | @Benthos_Web.AlertBox(TempData) 68 | 69 | @RenderBody() 70 | 71 | 81 |
    82 | 83 | 85 | 86 | 87 | 88 | 89 | @RenderSection("scripts", required:false) 90 | 91 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /src/htbox/Views/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 |
    7 |
    8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 39 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /src/htbox/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "~/Views/Shared/_Layout.cshtml"; 3 | } -------------------------------------------------------------------------------- /src/htbox/Web.Debug.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /src/htbox/Web.Release.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/htbox/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 6 | 7 | 8 | 9 | 10 |
    11 |
    12 |
    13 |
    14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /src/htbox/_ImportedCode/Benthos.N2CMS/N2CMSAwareMvcController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Web.Mvc; 4 | using System.Web.Routing; 5 | 6 | using htbox.ViewModels.CMS; 7 | 8 | namespace htbox._ImportedCode.Benthos.N2CMS { 9 | public abstract class N2CMSAwareMvcController : Controller { 10 | CMSPage _backingContent = null; 11 | int _backingContentId = 0; 12 | 13 | public CMSPage BackingContentSource { 14 | get { 15 | LoadBackingContentData(); 16 | return _backingContent; 17 | } 18 | } 19 | 20 | public int BackingContentId { 21 | get { 22 | LoadBackingContentData(); 23 | return _backingContentId; 24 | } 25 | } 26 | 27 | void LoadBackingContentData() { 28 | int backingContentId = 0; 29 | if (_backingContent == null && HttpContext.Request.QueryString["backingcontentid"] != null && int.TryParse(HttpContext.Request.QueryString["backingcontentid"], out backingContentId)) { 30 | _backingContentId = backingContentId; 31 | ViewBag.BackingContentId = backingContentId; 32 | _backingContent = N2.Find.Items.Where.ID.Eq(backingContentId).Select().FirstOrDefault(); 33 | } 34 | } 35 | 36 | //inject the backingcontentid into route data to ensure it lands in redirect urls 37 | protected override RedirectToRouteResult RedirectToAction(string actionName, string controllerName, System.Web.Routing.RouteValueDictionary routeValues) { 38 | if (routeValues == null) { 39 | routeValues = new RouteValueDictionary(); 40 | } 41 | if (BackingContentId > 0) { 42 | routeValues.Add("backingcontentid", BackingContentId); 43 | } 44 | return base.RedirectToAction(actionName, controllerName, routeValues); 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /src/htbox/_ImportedCode/Benthos.N2CMS/N2CMSDelegatingControllerFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | using System.Web.SessionState; 8 | 9 | using N2.Web.Mvc; 10 | 11 | // ReSharper disable once CheckNamespace 12 | namespace Benthos.N2CMS { 13 | //class inherited from Tony's soon to be public library to provide support for N2CMS/MVC integration 14 | public class N2CMSDelegatingControllerFactory : IControllerFactory { 15 | private readonly IControllerFactory _factory; 16 | private readonly IControllerFactory _cmsFactory; 17 | 18 | public N2CMSDelegatingControllerFactory(IControllerFactory cmsFactory, IControllerFactory factory) { 19 | this._cmsFactory = cmsFactory; 20 | this._factory = factory; 21 | } 22 | 23 | public IController CreateController(RequestContext requestContext, string controllerName) { 24 | return !(requestContext.RouteData.Route is ContentRoute) ? this._factory.CreateController(requestContext, controllerName) : this._cmsFactory.CreateController(requestContext, controllerName); 25 | } 26 | 27 | public SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName) { 28 | if (requestContext.RouteData.Route is ContentRoute) 29 | return this._cmsFactory.GetControllerSessionBehavior(requestContext, controllerName); 30 | else 31 | return this._factory.GetControllerSessionBehavior(requestContext, controllerName); 32 | } 33 | 34 | public void ReleaseController(IController controller) { 35 | if (((ControllerBase)controller).ControllerContext.RouteData.Route is ContentRoute) 36 | this._cmsFactory.ReleaseController(controller); 37 | else 38 | this._factory.ReleaseController(controller); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /src/htbox/htbox.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | 8 | 9 | 2.0 10 | {38F94502-9556-475D-94DA-FE679C887307} 11 | {E3E379DF-F4C6-4180-9B81-6769533ABE47};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} 12 | Library 13 | Properties 14 | htbox 15 | htbox 16 | v4.5 17 | false 18 | true 19 | 20 | 21 | 22 | 23 | ..\..\ 24 | true 25 | 26 | 27 | 28 | 29 | true 30 | full 31 | false 32 | bin\ 33 | DEBUG;TRACE 34 | prompt 35 | 4 36 | 37 | 38 | pdbonly 39 | true 40 | bin\ 41 | TRACE 42 | prompt 43 | 4 44 | 45 | 46 | 47 | False 48 | ..\..\packages\FSharp.Core.4.0.0\lib\FSharp.Core.dll 49 | 50 | 51 | ..\..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll 52 | 53 | 54 | ..\..\packages\Iesi.Collections.3.2.0.4000\lib\Net35\Iesi.Collections.dll 55 | 56 | 57 | ..\..\packages\Lucene.Net.3.0.3\lib\NET40\Lucene.Net.dll 58 | 59 | 60 | ..\..\packages\MailChimp.Net.V3.4.2.1\lib\net45\MailChimp.Net.dll 61 | 62 | 63 | 64 | False 65 | ..\..\packages\N2CMS.Library.2.5.6.1\lib\N2.dll 66 | 67 | 68 | False 69 | ..\..\packages\N2CMS.Management.2.5.6.1\lib\N2.Extensions.dll 70 | 71 | 72 | False 73 | ..\..\packages\N2CMS.Management.2.5.6.1\lib\N2.IoC.Windsor3.dll 74 | 75 | 76 | False 77 | ..\..\packages\N2CMS.Management.2.5.6.1\lib\N2.Management.dll 78 | 79 | 80 | False 81 | ..\..\packages\N2CMS.Management.2.5.6.1\lib\N2.Packaging.dll 82 | 83 | 84 | False 85 | ..\..\packages\N2CMS.Management.2.5.6.1\lib\N2.ReusableParts.dll 86 | 87 | 88 | ..\..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll 89 | 90 | 91 | ..\..\packages\NHibernate.3.3.3.4001\lib\Net35\NHibernate.dll 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | True 114 | ..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll 115 | 116 | 117 | True 118 | ..\..\packages\Microsoft.AspNet.Mvc.FixedDisplayModes.1.0.0\lib\net40\Microsoft.Web.Mvc.FixedDisplayModes.dll 119 | 120 | 121 | 122 | 123 | ..\..\packages\Microsoft.AspNet.WebApi.Client.4.0.20710.0\lib\net40\System.Net.Http.Formatting.dll 124 | 125 | 126 | 127 | 128 | True 129 | ..\..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.Helpers.dll 130 | 131 | 132 | ..\..\packages\Microsoft.AspNet.WebApi.Core.4.0.20710.0\lib\net40\System.Web.Http.dll 133 | 134 | 135 | ..\..\packages\Microsoft.AspNet.WebApi.WebHost.4.0.20710.0\lib\net40\System.Web.Http.WebHost.dll 136 | 137 | 138 | True 139 | ..\..\packages\Microsoft.AspNet.Mvc.4.0.20710.0\lib\net40\System.Web.Mvc.dll 140 | 141 | 142 | True 143 | ..\..\packages\Microsoft.AspNet.Razor.2.0.20715.0\lib\net40\System.Web.Razor.dll 144 | 145 | 146 | True 147 | ..\..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.dll 148 | 149 | 150 | True 151 | ..\..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.Deployment.dll 152 | 153 | 154 | True 155 | ..\..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.Razor.dll 156 | 157 | 158 | ..\..\packages\WebActivatorEx.2.0.3\lib\net40\WebActivatorEx.dll 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | Global.asax 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | Web.config 233 | 234 | 235 | Web.config 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | Designer 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 10.0 271 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | True 284 | True 285 | 58442 286 | / 287 | http://localhost:58418/ 288 | False 289 | False 290 | 291 | 292 | False 293 | 294 | 295 | 296 | 297 | 298 | 304 | -------------------------------------------------------------------------------- /src/htbox/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/htbox/static/css/app/htbox-website.css: -------------------------------------------------------------------------------- 1 | /* Move down content because we have a fixed navbar that is 50px tall */ 2 | body { 3 | padding-top: 50px; 4 | padding-bottom: 20px; 5 | } 6 | 7 | /* boostrap color overrides for our own 'theme' */ 8 | .navbar { 9 | font-family: "ff-meta-web-pro", "Helvetica Neue", Helvetica, Arial, sans-serif; 10 | } 11 | 12 | .navbar-inverse { 13 | background-color: rgb(213,37,49) 14 | } 15 | 16 | .navbar-inverse .navbar-brand > span { 17 | color: #ffffff; 18 | font-weight: 700; 19 | } 20 | 21 | .navbar-inverse .navbar-nav > li > a { 22 | color: #ffffff; 23 | } 24 | 25 | .navbar-inverse .navbar-nav > li > a:hover, 26 | .navbar-inverse .navbar-nav > li > a:focus { 27 | color: #ffffff; 28 | background-color: transparent; 29 | } 30 | 31 | .navbar-inverse .navbar-nav > .active > a, 32 | .navbar-inverse .navbar-nav > .active > a:hover, 33 | .navbar-inverse .navbar-nav > .active > a:focus { 34 | color: #ffffff; 35 | background-color: #080808; 36 | } 37 | 38 | .navbar-inverse .navbar-nav > .disabled > a, 39 | .navbar-inverse .navbar-nav > .disabled > a:hover, 40 | .navbar-inverse .navbar-nav > .disabled > a:focus { 41 | color: #444444; 42 | background-color: transparent; 43 | } 44 | 45 | .navbar-inverse .navbar-toggle { 46 | border-color: #333333; 47 | } 48 | 49 | .navbar-inverse .navbar-toggle:hover, 50 | .navbar-inverse .navbar-toggle:focus { 51 | background-color: #333333; 52 | } 53 | 54 | .navbar-inverse .navbar-toggle .icon-bar { 55 | background-color: #ffffff; 56 | } 57 | 58 | .navbar-inverse .navbar-nav > .open > a, 59 | .navbar-inverse .navbar-nav > .open > a:hover, 60 | .navbar-inverse .navbar-nav > .open > a:focus { 61 | color: #ffffff; 62 | background-color: #080808; 63 | } 64 | 65 | .navbar-inverse .navbar-nav > .dropdown > a:hover .caret { 66 | border-top-color: #ffffff; 67 | border-bottom-color: #ffffff; 68 | } 69 | 70 | .navbar-inverse .navbar-nav > .dropdown > a .caret { 71 | border-top-color: #ffffff; 72 | border-bottom-color: #ffffff; 73 | } 74 | 75 | .navbar-inverse .navbar-nav > .open > a .caret, 76 | .navbar-inverse .navbar-nav > .open > a:hover .caret, 77 | .navbar-inverse .navbar-nav > .open > a:focus .caret { 78 | border-top-color: #ffffff; 79 | border-bottom-color: #ffffff; 80 | } 81 | 82 | .jumbotron { 83 | position: relative; 84 | overflow: hidden; 85 | background-color: transparent; 86 | } 87 | 88 | .jumbotron > .jcarousel { 89 | } 90 | 91 | .jumbotron > .container { 92 | position: relative; 93 | } 94 | 95 | .jumbotron > .container > .hero-bg { 96 | position: absolute; 97 | z-index: -1; 98 | top: 0; 99 | left: 0; 100 | right: 0; 101 | bottom: 0; 102 | background-color: #ddd; 103 | opacity: 0.8; 104 | border-radius: 6px; 105 | } 106 | .jumbotron > .container > .hero-content { 107 | padding: 15px; 108 | } 109 | 110 | .jcarousel { 111 | position: absolute; 112 | top: 0; 113 | left: 0; 114 | height: 100%; 115 | overflow: hidden; 116 | width: 100%; 117 | z-index: -1; 118 | } 119 | 120 | .jcarousel ul { 121 | width: 2000em; 122 | position: absolute; 123 | list-style: none; 124 | margin: 0; 125 | padding: 0; 126 | } 127 | 128 | .jcarousel li { 129 | float: left; 130 | } 131 | 132 | .sub-hero { 133 | margin-bottom: 50px; 134 | } 135 | 136 | body { 137 | font-family: "ff-meta-serif-web-pro", "Helvetica Neue", Helvetica, Arial, sans-serif; 138 | font-size: 16px; 139 | } 140 | 141 | h1, 142 | h2, 143 | h3, 144 | h4, 145 | h5, 146 | h6, 147 | .h1, 148 | .h2, 149 | .h3, 150 | .h4, 151 | .h5, 152 | .h6 { 153 | font-family: "ff-meta-web-pro", "Helvetica Neue", Helvetica, Arial, sans-serif; 154 | font-weight: 700; 155 | } 156 | 157 | /* reset lead to base p styling in blog post listings */ 158 | .blog-post-listing .lead { 159 | margin-bottom: 10px; 160 | font-size: 16px; 161 | line-height: 1.4285; 162 | } 163 | 164 | footer { 165 | margin-top: 75px; 166 | font-family: "ff-meta-web-pro", "Helvetica Neue", Helvetica, Arial, sans-serif; 167 | font-size: 14px; 168 | color: #999; 169 | } 170 | 171 | footer a { 172 | font-weight: 700; 173 | } 174 | 175 | footer p { 176 | clear: left; 177 | line-height: 1.0; 178 | } -------------------------------------------------------------------------------- /src/htbox/static/css/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HTBox/htbox-website/69c0755249eccd5b360b32e85c143461c90851d8/src/htbox/static/css/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /src/htbox/static/css/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HTBox/htbox-website/69c0755249eccd5b360b32e85c143461c90851d8/src/htbox/static/css/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /src/htbox/static/css/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HTBox/htbox-website/69c0755249eccd5b360b32e85c143461c90851d8/src/htbox/static/css/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /src/htbox/static/css/wp8fix/wp8fix.css: -------------------------------------------------------------------------------- 1 | @-webkit-viewport { width: device-width; } 2 | @-moz-viewport { width: device-width; } 3 | @-ms-viewport { width: device-width; } 4 | @-o-viewport { width: device-width; } 5 | @viewport { width: device-width; } -------------------------------------------------------------------------------- /src/htbox/static/img/appbar.rss.hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HTBox/htbox-website/69c0755249eccd5b360b32e85c143461c90851d8/src/htbox/static/img/appbar.rss.hover.png -------------------------------------------------------------------------------- /src/htbox/static/img/appbar.rss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HTBox/htbox-website/69c0755249eccd5b360b32e85c143461c90851d8/src/htbox/static/img/appbar.rss.png -------------------------------------------------------------------------------- /src/htbox/static/js/html5shiv/html5shiv.js: -------------------------------------------------------------------------------- 1 | /* 2 | HTML5 Shiv v3.6.2pre | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed 3 | */ 4 | (function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag(); 5 | a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/\w+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x"; 6 | c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode|| 7 | "undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",version:"3.6.2pre",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);if(g)return a.createDocumentFragment(); 8 | for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d0;){if(i=t.filter("[data-jcarousel]"),i.size()>0)return i;if(i=t.find("[data-jcarousel]"),i.size()>0)return i;t=t.parent()}return null},i.base=function(s){return{version:i.version,_options:{},_element:null,_carousel:null,_init:t.noop,_create:t.noop,_destroy:t.noop,_reload:t.noop,create:function(){return this._element.attr("data-"+s.toLowerCase(),!0).data(s,this),!1===this._trigger("create")?this:(this._create(),this._trigger("createend"),this)},destroy:function(){return!1===this._trigger("destroy")?this:(this._destroy(),this._trigger("destroyend"),this._element.removeData(s).removeAttr("data-"+s.toLowerCase()),this)},reload:function(t){return!1===this._trigger("reload")?this:(t&&this.options(t),this._reload(),this._trigger("reloadend"),this)},element:function(){return this._element},options:function(i,s){if(0===arguments.length)return t.extend({},this._options);if("string"==typeof i){if(s===void 0)return this._options[i]===void 0?null:this._options[i];this._options[i]=s}else this._options=t.extend({},this._options,i);return this},carousel:function(){return this._carousel||(this._carousel=i.detectCarousel(this.options("carousel")||this._element),this._carousel||t.error('Could not detect carousel for plugin "'+s+'"')),this._carousel},_trigger:function(i,e,r){var n,o=!1;return r=[this].concat(r||[]),(e||this._element).each(function(){n=t.Event((i+"."+s).toLowerCase()),t(this).trigger(n,r),n.isDefaultPrevented()&&(o=!0)}),!o}}},i.plugin=function(s,e){var r=t[s]=function(i,s){this._element=t(i),this.options(s),this._init(),this.create()};return r.fn=r.prototype=t.extend({},i.base(s),e),t.fn[s]=function(i){var e=Array.prototype.slice.call(arguments,1),n=this;return"string"==typeof i?this.each(function(){var r=t(this).data(s);if(!r)return t.error("Cannot call methods on "+s+" prior to initialization; "+'attempted to call method "'+i+'"');if(!t.isFunction(r[i])||"_"===i.charAt(0))return t.error('No such method "'+i+'" for '+s+" instance");var o=r[i].apply(r,e);return o!==r&&o!==void 0?(n=o,!1):void 0}):this.each(function(){var e=t(this).data(s);e instanceof r?e.reload(i):new r(this,i)}),n},r}})(jQuery),function(t,i){"use strict";var s=function(t){return parseFloat(t)||0};t.jCarousel.plugin("jcarousel",{animating:!1,tail:0,inTail:!1,resizeTimer:null,lt:null,vertical:!1,rtl:!1,circular:!1,underflow:!1,_options:{list:function(){return this.element().children().eq(0)},items:function(){return this.list().children()},animation:400,transitions:!1,wrap:null,vertical:null,rtl:null,center:!1},_list:null,_items:null,_target:null,_first:null,_last:null,_visible:null,_fullyvisible:null,_init:function(){var t=this;return this.onWindowResize=function(){t.resizeTimer&&clearTimeout(t.resizeTimer),t.resizeTimer=setTimeout(function(){t.reload()},100)},this},_create:function(){this._reload(),t(i).on("resize.jcarousel",this.onWindowResize)},_destroy:function(){t(i).off("resize.jcarousel",this.onWindowResize)},_reload:function(){this.vertical=this.options("vertical"),null==this.vertical&&(this.vertical=this.list().height()>this.list().width()),this.rtl=this.options("rtl"),null==this.rtl&&(this.rtl=function(i){if("rtl"===(""+i.attr("dir")).toLowerCase())return!0;var s=!1;return i.parents("[dir]").each(function(){return/rtl/i.test(t(this).attr("dir"))?(s=!0,!1):void 0}),s}(this._element)),this.lt=this.vertical?"top":"left",this._list=null,this._items=null;var i=this._target&&this.index(this._target)>=0?this._target:this.closest();this.circular="circular"===this.options("wrap"),this.underflow=!1;var s={left:0,top:0};return i.size()>0&&(this._prepare(i),this.list().find("[data-jcarousel-clone]").remove(),this._items=null,this.underflow=this._fullyvisible.size()>=this.items().size(),this.circular=this.circular&&!this.underflow,s[this.lt]=this._position(i)+"px"),this.move(s),this},list:function(){if(null===this._list){var i=this.options("list");this._list=t.isFunction(i)?i.call(this):this._element.find(i)}return this._list},items:function(){if(null===this._items){var i=this.options("items");this._items=(t.isFunction(i)?i.call(this):this.list().find(i)).not("[data-jcarousel-clone]")}return this._items},index:function(t){return this.items().index(t)},closest:function(){var i,e=this,r=this.list().position()[this.lt],n=t(),o=!1,a=this.vertical?"bottom":this.rtl?"left":"right";return this.rtl&&!this.vertical&&(r=-1*(r+this.list().width()-this.clipping())),this.items().each(function(){if(n=t(this),o)return!1;var l=e.dimension(n);if(r+=l,r>=0){if(i=l-s(n.css("margin-"+a)),!(0>=Math.abs(r)-l+i/2))return!1;o=!0}}),n},target:function(){return this._target},first:function(){return this._first},last:function(){return this._last},visible:function(){return this._visible},fullyvisible:function(){return this._fullyvisible},hasNext:function(){if(!1===this._trigger("hasnext"))return!0;var t=this.options("wrap"),i=this.items().size()-1;return i>=0&&(t&&"first"!==t||i>this.index(this._last)||this.tail&&!this.inTail)?!0:!1},hasPrev:function(){if(!1===this._trigger("hasprev"))return!0;var t=this.options("wrap");return this.items().size()>0&&(t&&"last"!==t||this.index(this._first)>0||this.tail&&this.inTail)?!0:!1},clipping:function(){return this._element["inner"+(this.vertical?"Height":"Width")]()},dimension:function(t){return t["outer"+(this.vertical?"Height":"Width")](!0)},scroll:function(i,e,r){if(this.animating)return this;if(!1===this._trigger("scroll",null,[i,e]))return this;t.isFunction(e)&&(r=e,e=!0);var n=t.jCarousel.parseTarget(i);if(n.relative){var o,a,l,h,u,c,f,d,_=this.items().size()-1,p=Math.abs(n.target),m=this.options("wrap");if(n.target>0){var v=this.index(this._last);if(v>=_&&this.tail)this.inTail?"both"===m||"last"===m?this._scroll(0,e,r):this._scroll(Math.min(this.index(this._target)+p,_),e,r):this._scrollTail(e,r);else if(o=this.index(this._target),this.underflow&&o===_&&("circular"===m||"both"===m||"last"===m)||!this.underflow&&v===_&&("both"===m||"last"===m))this._scroll(0,e,r);else if(l=o+p,this.circular&&l>_){for(d=_,u=this.items().get(-1);l>d++;)u=this.items().eq(0),c=this._visible.index(u)>=0,c&&u.after(u.clone(!0).attr("data-jcarousel-clone",!0)),this.list().append(u),c||(f={},f[this.lt]=this.dimension(u)*(this.rtl?-1:1),this.moveBy(f)),this._items=null;this._scroll(u,e,r)}else this._scroll(Math.min(l,_),e,r)}else if(this.inTail)this._scroll(Math.max(this.index(this._first)-p+1,0),e,r);else if(a=this.index(this._first),o=this.index(this._target),h=this.underflow?o:a,l=h-p,0>=h&&(this.underflow&&"circular"===m||"both"===m||"first"===m))this._scroll(_,e,r);else if(this.circular&&0>l){for(d=l,u=this.items().get(0);0>d++;){u=this.items().eq(-1),c=this._visible.index(u)>=0,c&&u.after(u.clone(!0).attr("data-jcarousel-clone",!0)),this.list().prepend(u),this._items=null;var g=s(this.list().position()[this.lt]),y=this.dimension(u);this.rtl&&!this.vertical?g+=y:g-=y,f={},f[this.lt]=g+"px",this.move(f)}this._scroll(u,e,r)}else this._scroll(Math.max(l,0),e,r)}else this._scroll(n.target,e,r);return this._trigger("scrollend"),this},moveBy:function(t,i){var e=this.list().position();return t.left&&(t.left=e.left+s(t.left)+"px"),t.top&&(t.top=e.top+s(t.top)+"px"),this.move(t,i)},move:function(i,s){s=s||{};var e=this.options("transitions"),r=!!e,n=!!e.transforms,o=!!e.transforms3d,a=s.duration||0,l=this.list();if(!r&&a>0)return l.animate(i,s),void 0;var h=s.complete||t.noop,u={};if(r){var c=l.css(["transitionDuration","transitionTimingFunction","transitionProperty"]),f=h;h=function(){t(this).css(c),f.call(this)},u={transitionDuration:(a>0?a/1e3:0)+"s",transitionTimingFunction:e.easing||s.easing,transitionProperty:a>0?function(){return n||o?"all":i.left?"left":"top"}():"none",transform:"none"}}o?u.transform="translate3d("+(i.left||0)+","+(i.top||0)+",0)":n?u.transform="translate("+(i.left||0)+","+(i.top||0)+")":t.extend(u,i),r&&a>0&&l.one("transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd",h),l.css(u),0>=a&&l.each(function(){h.call(this)})},_scroll:function(i,e,r){if(this.animating)return t.isFunction(r)&&r.call(this,!1),this;if("object"!=typeof i?i=this.items().eq(i):i.jquery===void 0&&(i=t(i)),0===i.size())return t.isFunction(r)&&r.call(this,!1),this;this.inTail=!1,this._prepare(i);var n=this._position(i),o=s(this.list().position()[this.lt]);if(n===o)return t.isFunction(r)&&r.call(this,!1),this;var a={};return a[this.lt]=n+"px",this._animate(a,e,r),this},_scrollTail:function(i,s){if(this.animating||!this.tail)return t.isFunction(s)&&s.call(this,!1),this;var e=this.list().position()[this.lt];this.rtl?e+=this.tail:e-=this.tail,this.inTail=!0;var r={};return r[this.lt]=e+"px",this._update({target:this._target.next(),fullyvisible:this._fullyvisible.slice(1).add(this._visible.last())}),this._animate(r,i,s),this},_animate:function(i,s,e){if(e=e||t.noop,!1===this._trigger("animate"))return e.call(this,!1),this;this.animating=!0;var r=this.options("animation"),n=t.proxy(function(){this.animating=!1;var t=this.list().find("[data-jcarousel-clone]");t.size()>0&&(t.remove(),this._reload()),this._trigger("animateend"),e.call(this,!0)},this),o="object"==typeof r?t.extend({},r):{duration:r},a=o.complete||t.noop;return s===!1?o.duration=0:t.fx.speeds[o.duration]!==void 0&&(o.duration=t.fx.speeds[o.duration]),o.complete=function(){n(),a.call(this)},this.move(i,o),this},_prepare:function(i){var e,r,n,o=this.index(i),a=o,l=this.dimension(i),h=this.clipping(),u=this.vertical?"bottom":this.rtl?"left":"right",c=this.options("center"),f={target:i,first:i,last:i,visible:i,fullyvisible:h>=l?i:t()};if(c&&(l/=2,h/=2),h>l)for(;;){if(e=this.items().eq(++a),0===e.size()){if(!this.circular)break;if(e=this.items().eq(0),i.get(0)===e.get(0))break;if(r=this._visible.index(e)>=0,r&&e.after(e.clone(!0).attr("data-jcarousel-clone",!0)),this.list().append(e),!r){var d={};d[this.lt]=this.dimension(e)*(this.rtl?-1:1),this.moveBy(d)}this._items=null}if(l+=this.dimension(e),f.last=e,f.visible=f.visible.add(e),n=s(e.css("margin-"+u)),h>=l-n&&(f.fullyvisible=f.fullyvisible.add(e)),l>=h)break}if(!this.circular&&!c&&h>l)for(a=o;;){if(0>--a)break;if(e=this.items().eq(a),0===e.size())break;if(l+=this.dimension(e),f.first=e,f.visible=f.visible.add(e),n=s(e.css("margin-"+u)),h>=l-n&&(f.fullyvisible=f.fullyvisible.add(e)),l>=h)break}return this._update(f),this.tail=0,c||"circular"===this.options("wrap")||"custom"===this.options("wrap")||this.index(f.last)!==this.items().size()-1||(l-=s(f.last.css("margin-"+u)),l>h&&(this.tail=l-h)),this},_position:function(t){var i=this._first,s=i.position()[this.lt],e=this.options("center"),r=e?this.clipping()/2-this.dimension(i)/2:0;return this.rtl&&!this.vertical?(s-=this.clipping()-this.dimension(i),s+=r):s-=r,!e&&(this.index(t)>this.index(i)||this.inTail)&&this.tail?(s=this.rtl?s-this.tail:s+this.tail,this.inTail=!0):this.inTail=!1,-s},_update:function(i){var s,e=this,r={target:this._target||t(),first:this._first||t(),last:this._last||t(),visible:this._visible||t(),fullyvisible:this._fullyvisible||t()},n=this.index(i.first||r.first)r[s].index(this)&&o.push(this)}),r[s].each(function(){0>i[s].index(this)&&a.push(this)}),n?o=o.reverse():a=a.reverse(),e._trigger("item"+s+"in",t(o)),e._trigger("item"+s+"out",t(a)),e["_"+s]=i[s]};for(s in i)o(s);return this}})}(jQuery,window),function(t){"use strict";t.jcarousel.fn.scrollIntoView=function(i,s,e){var r,n=t.jCarousel.parseTarget(i),o=this.index(this._fullyvisible.first()),a=this.index(this._fullyvisible.last());if(r=n.relative?0>n.target?Math.max(0,o+n.target):a+n.target:"object"!=typeof n.target?n.target:this.index(n.target),o>r)return this.scroll(r,s,e);if(r>=o&&a>=r)return t.isFunction(e)&&e.call(this,!1),this;for(var l,h=this.items(),u=this.clipping(),c=this.vertical?"bottom":this.rtl?"left":"right",f=0;;){if(l=h.eq(r),0===l.size())break;if(f+=this.dimension(l),f>=u){var d=parseFloat(l.css("margin-"+c))||0;f-d!==u&&r++;break}if(0>=r)break;r--}return this.scroll(r,s,e)}}(jQuery),function(t){"use strict";t.jCarousel.plugin("jcarouselControl",{_options:{target:"+=1",event:"click",method:"scroll"},_active:null,_init:function(){this.onDestroy=t.proxy(function(){this._destroy(),this.carousel().one("createend.jcarousel",t.proxy(this._create,this))},this),this.onReload=t.proxy(this._reload,this),this.onEvent=t.proxy(function(i){i.preventDefault();var s=this.options("method");t.isFunction(s)?s.call(this):this.carousel().jcarousel(this.options("method"),this.options("target"))},this)},_create:function(){this.carousel().one("destroy.jcarousel",this.onDestroy).on("reloadend.jcarousel scrollend.jcarousel",this.onReload),this._element.on(this.options("event")+".jcarouselcontrol",this.onEvent),this._reload()},_destroy:function(){this._element.off(".jcarouselcontrol",this.onEvent),this.carousel().off("destroy.jcarousel",this.onDestroy).off("reloadend.jcarousel scrollend.jcarousel",this.onReload)},_reload:function(){var i,s=t.jCarousel.parseTarget(this.options("target")),e=this.carousel();if(s.relative)i=e.jcarousel(s.target>0?"hasNext":"hasPrev");else{var r="object"!=typeof s.target?e.jcarousel("items").eq(s.target):s.target;i=e.jcarousel("target").index(r)>=0}return this._active!==i&&(this._trigger(i?"active":"inactive"),this._active=i),this}})}(jQuery),function(t){"use strict";t.jCarousel.plugin("jcarouselPagination",{_options:{perPage:null,item:function(t){return''+t+""},event:"click",method:"scroll"},_pages:{},_items:{},_currentPage:null,_init:function(){this.onDestroy=t.proxy(function(){this._destroy(),this.carousel().one("createend.jcarousel",t.proxy(this._create,this))},this),this.onReload=t.proxy(this._reload,this),this.onScroll=t.proxy(this._update,this)},_create:function(){this.carousel().one("destroy.jcarousel",this.onDestroy).on("reloadend.jcarousel",this.onReload).on("scrollend.jcarousel",this.onScroll),this._reload()},_destroy:function(){this._clear(),this.carousel().off("destroy.jcarousel",this.onDestroy).off("reloadend.jcarousel",this.onReload).off("scrollend.jcarousel",this.onScroll)},_reload:function(){var i=this.options("perPage");if(this._pages={},this._items={},t.isFunction(i)&&(i=i.call(this)),null==i)this._pages=this._calculatePages();else for(var s,e=parseInt(i,10)||0,r=this.carousel().jcarousel("items"),n=1,o=0;;){if(s=r.eq(o++),0===s.size())break;this._pages[n]=this._pages[n]?this._pages[n].add(s):s,0===o%e&&n++}this._clear();var a=this,l=this.carousel().data("jcarousel"),h=this._element,u=this.options("item");t.each(this._pages,function(i,s){var e=a._items[i]=t(u.call(a,i,s));e.on(a.options("event")+".jcarouselpagination",t.proxy(function(){var t=s.eq(0);if(l.circular){var e=l.index(l.target()),r=l.index(t);parseFloat(i)>parseFloat(a._currentPage)?e>r&&(t="+="+(l.items().size()-e+r)):r>e&&(t="-="+(e+(l.items().size()-r)))}l[this.options("method")](t)},a)),h.append(e)}),this._update()},_update:function(){var i,s=this.carousel().jcarousel("target");t.each(this._pages,function(t,e){return e.each(function(){return s.is(this)?(i=t,!1):void 0}),i?!1:void 0}),this._currentPage!==i&&(this._trigger("inactive",this._items[this._currentPage]),this._trigger("active",this._items[i])),this._currentPage=i},items:function(){return this._items},_clear:function(){this._element.empty(),this._currentPage=null},_calculatePages:function(){for(var t,i=this.carousel().data("jcarousel"),s=i.items(),e=i.clipping(),r=0,n=0,o=1,a={};;){if(t=s.eq(n++),0===t.size())break;a[o]=a[o]?a[o].add(t):t,r+=i.dimension(t),r>=e&&(o++,r=0)}return a}})}(jQuery),function(t){"use strict";t.jCarousel.plugin("jcarouselAutoscroll",{_options:{target:"+=1",interval:3e3,autostart:!0},_timer:null,_init:function(){this.onDestroy=t.proxy(function(){this._destroy(),this.carousel().one("createend.jcarousel",t.proxy(this._create,this))},this),this.onAnimateEnd=t.proxy(this.start,this)},_create:function(){this.carousel().one("destroy.jcarousel",this.onDestroy),this.options("autostart")&&this.start()},_destroy:function(){this.stop(),this.carousel().off("destroy.jcarousel",this.onDestroy)},start:function(){return this.stop(),this.carousel().one("animateend.jcarousel",this.onAnimateEnd),this._timer=setTimeout(t.proxy(function(){this.carousel().jcarousel("scroll",this.options("target"))},this),this.options("interval")),this},stop:function(){return this._timer&&(this._timer=clearTimeout(this._timer)),this.carousel().off("animateend.jcarousel",this.onAnimateEnd),this}})}(jQuery); -------------------------------------------------------------------------------- /src/htbox/static/js/mvc-validate/jquery.unobtrusive-ajax.js: -------------------------------------------------------------------------------- 1 | /*! 2 | ** Unobtrusive Ajax support library for jQuery 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 window: false, jQuery: false */ 8 | 9 | (function ($) { 10 | var data_click = "unobtrusiveAjaxClick", 11 | data_validation = "unobtrusiveValidation"; 12 | 13 | function getFunction(code, argNames) { 14 | var fn = window, parts = (code || "").split("."); 15 | while (fn && parts.length) { 16 | fn = fn[parts.shift()]; 17 | } 18 | if (typeof (fn) === "function") { 19 | return fn; 20 | } 21 | argNames.push(code); 22 | return Function.constructor.apply(null, argNames); 23 | } 24 | 25 | function isMethodProxySafe(method) { 26 | return method === "GET" || method === "POST"; 27 | } 28 | 29 | function asyncOnBeforeSend(xhr, method) { 30 | if (!isMethodProxySafe(method)) { 31 | xhr.setRequestHeader("X-HTTP-Method-Override", method); 32 | } 33 | } 34 | 35 | function asyncOnSuccess(element, data, contentType) { 36 | var mode; 37 | 38 | if (contentType.indexOf("application/x-javascript") !== -1) { // jQuery already executes JavaScript for us 39 | return; 40 | } 41 | 42 | mode = (element.getAttribute("data-ajax-mode") || "").toUpperCase(); 43 | $(element.getAttribute("data-ajax-update")).each(function (i, update) { 44 | var top; 45 | 46 | switch (mode) { 47 | case "BEFORE": 48 | top = update.firstChild; 49 | $("
    ").html(data).contents().each(function () { 50 | update.insertBefore(this, top); 51 | }); 52 | break; 53 | case "AFTER": 54 | $("
    ").html(data).contents().each(function () { 55 | update.appendChild(this); 56 | }); 57 | break; 58 | default: 59 | $(update).html(data); 60 | break; 61 | } 62 | }); 63 | } 64 | 65 | function asyncRequest(element, options) { 66 | var confirm, loading, method, duration; 67 | 68 | confirm = element.getAttribute("data-ajax-confirm"); 69 | if (confirm && !window.confirm(confirm)) { 70 | return; 71 | } 72 | 73 | loading = $(element.getAttribute("data-ajax-loading")); 74 | duration = element.getAttribute("data-ajax-loading-duration") || 0; 75 | 76 | $.extend(options, { 77 | type: element.getAttribute("data-ajax-method") || undefined, 78 | url: element.getAttribute("data-ajax-url") || undefined, 79 | beforeSend: function (xhr) { 80 | var result; 81 | asyncOnBeforeSend(xhr, method); 82 | result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(this, arguments); 83 | if (result !== false) { 84 | loading.show(duration); 85 | } 86 | return result; 87 | }, 88 | complete: function () { 89 | loading.hide(duration); 90 | getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(this, arguments); 91 | }, 92 | success: function (data, status, xhr) { 93 | asyncOnSuccess(element, data, xhr.getResponseHeader("Content-Type") || "text/html"); 94 | getFunction(element.getAttribute("data-ajax-success"), ["data", "status", "xhr"]).apply(this, arguments); 95 | }, 96 | error: getFunction(element.getAttribute("data-ajax-failure"), ["xhr", "status", "error"]) 97 | }); 98 | 99 | options.data.push({ name: "X-Requested-With", value: "XMLHttpRequest" }); 100 | 101 | method = options.type.toUpperCase(); 102 | if (!isMethodProxySafe(method)) { 103 | options.type = "POST"; 104 | options.data.push({ name: "X-HTTP-Method-Override", value: method }); 105 | } 106 | 107 | $.ajax(options); 108 | } 109 | 110 | function validate(form) { 111 | var validationInfo = $(form).data(data_validation); 112 | return !validationInfo || !validationInfo.validate || validationInfo.validate(); 113 | } 114 | 115 | $(document).on("click", "a[data-ajax=true]", function (evt) { 116 | evt.preventDefault(); 117 | asyncRequest(this, { 118 | url: this.href, 119 | type: "GET", 120 | data: [] 121 | }); 122 | }); 123 | 124 | $(document).on("click", "form[data-ajax=true] input[type=image]", function (evt) { 125 | var name = evt.target.name, 126 | $target = $(evt.target), 127 | form = $target.parents("form")[0], 128 | offset = $target.offset(); 129 | 130 | $(form).data(data_click, [ 131 | { name: name + ".x", value: Math.round(evt.pageX - offset.left) }, 132 | { name: name + ".y", value: Math.round(evt.pageY - offset.top) } 133 | ]); 134 | 135 | setTimeout(function () { 136 | $(form).removeData(data_click); 137 | }, 0); 138 | }); 139 | 140 | $(document).on("click", "form[data-ajax=true] :submit", function (evt) { 141 | var name = evt.target.name, 142 | form = $(evt.target).parents("form")[0]; 143 | 144 | $(form).data(data_click, name ? [{ name: name, value: evt.target.value }] : []); 145 | 146 | setTimeout(function () { 147 | $(form).removeData(data_click); 148 | }, 0); 149 | }); 150 | 151 | $(document).on("submit", "form[data-ajax=true]", function (evt) { 152 | var clickInfo = $(this).data(data_click) || []; 153 | evt.preventDefault(); 154 | if (!validate(this)) { 155 | return; 156 | } 157 | asyncRequest(this, { 158 | url: this.action, 159 | type: this.method || "GET", 160 | data: clickInfo.concat($(this).serializeArray()) 161 | }); 162 | }); 163 | }(jQuery)); -------------------------------------------------------------------------------- /src/htbox/static/js/mvc-validate/jquery.unobtrusive-ajax.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | ** Unobtrusive Ajax support library for jQuery 3 | ** Copyright (C) Microsoft Corporation. All rights reserved. 4 | */ 5 | (function(a){var b="unobtrusiveAjaxClick",g="unobtrusiveValidation";function c(d,b){var a=window,c=(d||"").split(".");while(a&&c.length)a=a[c.shift()];if(typeof a==="function")return a;b.push(d);return Function.constructor.apply(null,b)}function d(a){return a==="GET"||a==="POST"}function f(b,a){!d(a)&&b.setRequestHeader("X-HTTP-Method-Override",a)}function h(c,b,e){var d;if(e.indexOf("application/x-javascript")!==-1)return;d=(c.getAttribute("data-ajax-mode")||"").toUpperCase();a(c.getAttribute("data-ajax-update")).each(function(f,c){var e;switch(d){case"BEFORE":e=c.firstChild;a("
    ").html(b).contents().each(function(){c.insertBefore(this,e)});break;case"AFTER":a("
    ").html(b).contents().each(function(){c.appendChild(this)});break;default:a(c).html(b)}})}function e(b,e){var j,k,g,i;j=b.getAttribute("data-ajax-confirm");if(j&&!window.confirm(j))return;k=a(b.getAttribute("data-ajax-loading"));i=b.getAttribute("data-ajax-loading-duration")||0;a.extend(e,{type:b.getAttribute("data-ajax-method")||undefined,url:b.getAttribute("data-ajax-url")||undefined,beforeSend:function(d){var a;f(d,g);a=c(b.getAttribute("data-ajax-begin"),["xhr"]).apply(this,arguments);a!==false&&k.show(i);return a},complete:function(){k.hide(i);c(b.getAttribute("data-ajax-complete"),["xhr","status"]).apply(this,arguments)},success:function(a,e,d){h(b,a,d.getResponseHeader("Content-Type")||"text/html");c(b.getAttribute("data-ajax-success"),["data","status","xhr"]).apply(this,arguments)},error:c(b.getAttribute("data-ajax-failure"),["xhr","status","error"])});e.data.push({name:"X-Requested-With",value:"XMLHttpRequest"});g=e.type.toUpperCase();if(!d(g)){e.type="POST";e.data.push({name:"X-HTTP-Method-Override",value:g})}a.ajax(e)}function i(c){var b=a(c).data(g);return!b||!b.validate||b.validate()}a(document).on("click","a[data-ajax=true]",function(a){a.preventDefault();e(this,{url:this.href,type:"GET",data:[]})});a(document).on("click","form[data-ajax=true] input[type=image]",function(c){var g=c.target.name,d=a(c.target),f=d.parents("form")[0],e=d.offset();a(f).data(b,[{name:g+".x",value:Math.round(c.pageX-e.left)},{name:g+".y",value:Math.round(c.pageY-e.top)}]);setTimeout(function(){a(f).removeData(b)},0)});a(document).on("click","form[data-ajax=true] :submit",function(c){var e=c.target.name,d=a(c.target).parents("form")[0];a(d).data(b,e?[{name:e,value:c.target.value}]:[]);setTimeout(function(){a(d).removeData(b)},0)});a(document).on("submit","form[data-ajax=true]",function(d){var c=a(this).data(b)||[];d.preventDefault();if(!i(this))return;e(this,{url:this.action,type:this.method||"GET",data:c.concat(a(this).serializeArray())})})})(jQuery); -------------------------------------------------------------------------------- /src/htbox/static/js/mvc-validate/jquery.validate.unobtrusive.bootstrap.js: -------------------------------------------------------------------------------- 1 |  jQuery.validator.setDefaults({ 2 | highlight: function (element, errorClass, validClass) { 3 | if (element.type === 'radio') { 4 | this.findByName(element.name).addClass(errorClass).removeClass(validClass); 5 | } else { 6 | $(element).addClass(errorClass).removeClass(validClass); 7 | $(element).closest('.form-group').removeClass('has-success').addClass('has-error'); 8 | } 9 | }, 10 | unhighlight: function (element, errorClass, validClass) { 11 | if (element.type === 'radio') { 12 | this.findByName(element.name).removeClass(errorClass).addClass(validClass); 13 | } else { 14 | $(element).removeClass(errorClass).addClass(validClass); 15 | $(element).closest('.form-group').removeClass('has-error').addClass('has-success'); 16 | } 17 | } 18 | }); 19 | 20 | 21 | $(document).ready(function() { 22 | $('form').each(function() { 23 | $(this).find('div.form-group').each(function() { 24 | if ($(this).find('span.field-validation-error').length > 0 || $(this).find('input.input-validation-error').length > 0) { 25 | $(this).addClass('has-error'); 26 | } 27 | }); 28 | }); 29 | });; -------------------------------------------------------------------------------- /src/htbox/static/js/mvc-validate/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 | 106 | if (!result) { 107 | result = { 108 | options: { // options structure passed to jQuery Validate's validate() method 109 | errorClass: "input-validation-error", 110 | errorElement: "span", 111 | errorPlacement: $.proxy(onError, form), 112 | invalidHandler: $.proxy(onErrors, form), 113 | messages: {}, 114 | rules: {}, 115 | success: $.proxy(onSuccess, form) 116 | }, 117 | attachValidation: function () { 118 | $form 119 | .unbind("reset." + data_validation, onResetProxy) 120 | .bind("reset." + data_validation, onResetProxy) 121 | .validate(this.options); 122 | }, 123 | validate: function () { // a validation function that is called by unobtrusive Ajax 124 | $form.validate(); 125 | return $form.valid(); 126 | } 127 | }; 128 | $form.data(data_validation, result); 129 | } 130 | 131 | return result; 132 | } 133 | 134 | $jQval.unobtrusive = { 135 | adapters: [], 136 | 137 | parseElement: function (element, skipAttach) { 138 | /// 139 | /// Parses a single HTML element for unobtrusive validation attributes. 140 | /// 141 | /// The HTML element to be parsed. 142 | /// [Optional] true to skip attaching the 143 | /// validation to the form. If parsing just this single element, you should specify true. 144 | /// If parsing several elements, you should specify false, and manually attach the validation 145 | /// to the form when you are finished. The default is false. 146 | var $element = $(element), 147 | form = $element.parents("form")[0], 148 | valInfo, rules, messages; 149 | 150 | if (!form) { // Cannot do client-side validation without a form 151 | return; 152 | } 153 | 154 | valInfo = validationInfo(form); 155 | valInfo.options.rules[element.name] = rules = {}; 156 | valInfo.options.messages[element.name] = messages = {}; 157 | 158 | $.each(this.adapters, function () { 159 | var prefix = "data-val-" + this.name, 160 | message = $element.attr(prefix), 161 | paramValues = {}; 162 | 163 | if (message !== undefined) { // Compare against undefined, because an empty message is legal (and falsy) 164 | prefix += "-"; 165 | 166 | $.each(this.params, function () { 167 | paramValues[this] = $element.attr(prefix + this); 168 | }); 169 | 170 | this.adapt({ 171 | element: element, 172 | form: form, 173 | message: message, 174 | params: paramValues, 175 | rules: rules, 176 | messages: messages 177 | }); 178 | } 179 | }); 180 | 181 | $.extend(rules, { "__dummy__": true }); 182 | 183 | if (!skipAttach) { 184 | valInfo.attachValidation(); 185 | } 186 | }, 187 | 188 | parse: function (selector) { 189 | /// 190 | /// Parses all the HTML elements in the specified selector. It looks for input elements decorated 191 | /// with the [data-val=true] attribute value and enables validation according to the data-val-* 192 | /// attribute values. 193 | /// 194 | /// Any valid jQuery selector. 195 | var $forms = $(selector) 196 | .parents("form") 197 | .andSelf() 198 | .add($(selector).find("form")) 199 | .filter("form"); 200 | 201 | $(selector).find(":input[data-val=true]").each(function () { 202 | $jQval.unobtrusive.parseElement(this, true); 203 | }); 204 | 205 | $forms.each(function () { 206 | var info = validationInfo(this); 207 | if (info) { 208 | info.attachValidation(); 209 | } 210 | }); 211 | } 212 | }; 213 | 214 | adapters = $jQval.unobtrusive.adapters; 215 | 216 | adapters.add = function (adapterName, params, fn) { 217 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation. 218 | /// The name of the adapter to be added. This matches the name used 219 | /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). 220 | /// [Optional] An array of parameter names (strings) that will 221 | /// be extracted from the data-val-nnnn-mmmm HTML attributes (where nnnn is the adapter name, and 222 | /// mmmm is the parameter name). 223 | /// The function to call, which adapts the values from the HTML 224 | /// attributes into jQuery Validate rules and/or messages. 225 | /// 226 | if (!fn) { // Called with no params, just a function 227 | fn = params; 228 | params = []; 229 | } 230 | this.push({ name: adapterName, params: params, adapt: fn }); 231 | return this; 232 | }; 233 | 234 | adapters.addBool = function (adapterName, ruleName) { 235 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where 236 | /// the jQuery Validate validation rule has no parameter values. 237 | /// The name of the adapter to be added. This matches the name used 238 | /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). 239 | /// [Optional] The name of the jQuery Validate rule. If not provided, the value 240 | /// of adapterName will be used instead. 241 | /// 242 | return this.add(adapterName, function (options) { 243 | setValidationValues(options, ruleName || adapterName, true); 244 | }); 245 | }; 246 | 247 | adapters.addMinMax = function (adapterName, minRuleName, maxRuleName, minMaxRuleName, minAttribute, maxAttribute) { 248 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where 249 | /// the jQuery Validate validation has three potential rules (one for min-only, one for max-only, and 250 | /// one for min-and-max). The HTML parameters are expected to be named -min and -max. 251 | /// The name of the adapter to be added. This matches the name used 252 | /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). 253 | /// The name of the jQuery Validate rule to be used when you only 254 | /// have a minimum value. 255 | /// The name of the jQuery Validate rule to be used when you only 256 | /// have a maximum value. 257 | /// The name of the jQuery Validate rule to be used when you 258 | /// have both a minimum and maximum value. 259 | /// [Optional] The name of the HTML attribute that 260 | /// contains the minimum value. The default is "min". 261 | /// [Optional] The name of the HTML attribute that 262 | /// contains the maximum value. The default is "max". 263 | /// 264 | return this.add(adapterName, [minAttribute || "min", maxAttribute || "max"], function (options) { 265 | var min = options.params.min, 266 | max = options.params.max; 267 | 268 | if (min && max) { 269 | setValidationValues(options, minMaxRuleName, [min, max]); 270 | } 271 | else if (min) { 272 | setValidationValues(options, minRuleName, min); 273 | } 274 | else if (max) { 275 | setValidationValues(options, maxRuleName, max); 276 | } 277 | }); 278 | }; 279 | 280 | adapters.addSingleVal = function (adapterName, attribute, ruleName) { 281 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where 282 | /// the jQuery Validate validation rule has a single value. 283 | /// The name of the adapter to be added. This matches the name used 284 | /// in the data-val-nnnn HTML attribute(where nnnn is the adapter name). 285 | /// [Optional] The name of the HTML attribute that contains the value. 286 | /// The default is "val". 287 | /// [Optional] The name of the jQuery Validate rule. If not provided, the value 288 | /// of adapterName will be used instead. 289 | /// 290 | return this.add(adapterName, [attribute || "val"], function (options) { 291 | setValidationValues(options, ruleName || adapterName, options.params[attribute]); 292 | }); 293 | }; 294 | 295 | $jQval.addMethod("__dummy__", function (value, element, params) { 296 | return true; 297 | }); 298 | 299 | $jQval.addMethod("regex", function (value, element, params) { 300 | var match; 301 | if (this.optional(element)) { 302 | return true; 303 | } 304 | 305 | match = new RegExp(params).exec(value); 306 | return (match && (match.index === 0) && (match[0].length === value.length)); 307 | }); 308 | 309 | $jQval.addMethod("nonalphamin", function (value, element, nonalphamin) { 310 | var match; 311 | if (nonalphamin) { 312 | match = value.match(/\W/g); 313 | match = match && match.length >= nonalphamin; 314 | } 315 | return match; 316 | }); 317 | 318 | adapters.addSingleVal("accept", "exts").addSingleVal("regex", "pattern"); 319 | adapters.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"); 320 | adapters.addMinMax("length", "minlength", "maxlength", "rangelength").addMinMax("range", "min", "max", "range"); 321 | adapters.add("equalto", ["other"], function (options) { 322 | var prefix = getModelPrefix(options.element.name), 323 | other = options.params.other, 324 | fullOtherName = appendModelPrefix(other, prefix), 325 | element = $(options.form).find(":input[name='" + escapeAttributeValue(fullOtherName) + "']")[0]; 326 | 327 | setValidationValues(options, "equalTo", element); 328 | }); 329 | adapters.add("required", function (options) { 330 | // jQuery Validate equates "required" with "mandatory" for checkbox elements 331 | if (options.element.tagName.toUpperCase() !== "INPUT" || options.element.type.toUpperCase() !== "CHECKBOX") { 332 | setValidationValues(options, "required", true); 333 | } 334 | }); 335 | adapters.add("remote", ["url", "type", "additionalfields"], function (options) { 336 | var value = { 337 | url: options.params.url, 338 | type: options.params.type || "GET", 339 | data: {} 340 | }, 341 | prefix = getModelPrefix(options.element.name); 342 | 343 | $.each(splitAndTrim(options.params.additionalfields || options.element.name), function (i, fieldName) { 344 | var paramName = appendModelPrefix(fieldName, prefix); 345 | value.data[paramName] = function () { 346 | return $(options.form).find(":input[name='" + escapeAttributeValue(paramName) + "']").val(); 347 | }; 348 | }); 349 | 350 | setValidationValues(options, "remote", value); 351 | }); 352 | adapters.add("password", ["min", "nonalphamin", "regex"], function (options) { 353 | if (options.params.min) { 354 | setValidationValues(options, "minlength", options.params.min); 355 | } 356 | if (options.params.nonalphamin) { 357 | setValidationValues(options, "nonalphamin", options.params.nonalphamin); 358 | } 359 | if (options.params.regex) { 360 | setValidationValues(options, "regex", options.params.regex); 361 | } 362 | }); 363 | 364 | $(function () { 365 | $jQval.unobtrusive.parse(document); 366 | }); 367 | } (jQuery)); -------------------------------------------------------------------------------- /src/htbox/static/js/mvc-validate/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(c){var b=a(c),d=b.data(e),f=a.proxy(n,c);if(!d){d={options:{errorClass:"input-validation-error",errorElement:"span",errorPlacement:a.proxy(m,c),invalidHandler:a.proxy(l,c),messages:{},rules:{},success:a.proxy(k,c)},attachValidation:function(){b.unbind("reset."+e,f).bind("reset."+e,f).validate(this.options)},validate:function(){b.validate();return b.valid()}};b.data(e,d)}return d}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(b){var c=a(b).parents("form").andSelf().add(a(b).find("form")).filter("form");a(b).find(":input[data-val=true]").each(function(){d.unobtrusive.parseElement(this,true)});c.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});b.addSingleVal("accept","exts").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.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[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[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/htbox/static/js/respond/respond.min.js: -------------------------------------------------------------------------------- 1 | /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */ 2 | /*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */ 3 | window.matchMedia=window.matchMedia||(function(e,f){var c,a=e.documentElement,b=a.firstElementChild||a.firstChild,d=e.createElement("body"),g=e.createElement("div");g.id="mq-test-1";g.style.cssText="position:absolute;top:-100em";d.style.background="none";d.appendChild(g);return function(h){g.innerHTML='­';a.insertBefore(d,b);c=g.offsetWidth==42;a.removeChild(d);return{matches:c,media:h}}})(document); 4 | 5 | /*! Respond.js v1.1.0: min/max-width media query polyfill. (c) Scott Jehl. MIT/GPLv2 Lic. j.mp/respondjs */ 6 | (function(e){e.respond={};respond.update=function(){};respond.mediaQueriesSupported=e.matchMedia&&e.matchMedia("only all").matches;if(respond.mediaQueriesSupported){return}var w=e.document,s=w.documentElement,i=[],k=[],q=[],o={},h=30,f=w.getElementsByTagName("head")[0]||s,g=w.getElementsByTagName("base")[0],b=f.getElementsByTagName("link"),d=[],a=function(){var D=b,y=D.length,B=0,A,z,C,x;for(;B-1,minw:F.match(/\(min\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:F.match(/\(max\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}}j()},l,r,v=function(){var z,A=w.createElement("div"),x=w.body,y=false;A.style.cssText="position:absolute;font-size:1em;width:1em";if(!x){x=y=w.createElement("body");x.style.background="none"}x.appendChild(A);s.insertBefore(x,s.firstChild);z=A.offsetWidth;if(y){s.removeChild(x)}else{x.removeChild(A)}z=p=parseFloat(z);return z},p,j=function(I){var x="clientWidth",B=s[x],H=w.compatMode==="CSS1Compat"&&B||w.body[x]||B,D={},G=b[b.length-1],z=(new Date()).getTime();if(I&&l&&z-l-1?(p||v()):1)}if(!!J){J=parseFloat(J)*(J.indexOf(y)>-1?(p||v()):1)}if(!K.hasquery||(!A||!L)&&(A||H>=C)&&(L||H<=J)){if(!D[K.media]){D[K.media]=[]}D[K.media].push(k[K.rules])}}for(var E in q){if(q[E]&&q[E].parentNode===f){f.removeChild(q[E])}}for(var E in D){var M=w.createElement("style"),F=D[E].join("\n");M.type="text/css";M.media=E;f.insertBefore(M,G.nextSibling);if(M.styleSheet){M.styleSheet.cssText=F}else{M.appendChild(w.createTextNode(F))}q.push(M)}},n=function(x,z){var y=c();if(!y){return}y.open("GET",x,true);y.onreadystatechange=function(){if(y.readyState!=4||y.status!=200&&y.status!=304){return}z(y.responseText)};if(y.readyState==4){return}y.send(null)},c=(function(){var x=false;try{x=new XMLHttpRequest()}catch(y){x=new ActiveXObject("Microsoft.XMLHTTP")}return function(){return x}})();a();respond.update=a;function t(){j(true)}if(e.addEventListener){e.addEventListener("resize",t,false)}else{if(e.attachEvent){e.attachEvent("onresize",t)}}})(this); -------------------------------------------------------------------------------- /src/htbox/static/js/respond/respond.src.js: -------------------------------------------------------------------------------- 1 | /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */ 2 | /*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */ 3 | window.matchMedia = window.matchMedia || (function(doc, undefined){ 4 | 5 | var bool, 6 | docElem = doc.documentElement, 7 | refNode = docElem.firstElementChild || docElem.firstChild, 8 | // fakeBody required for 9 | fakeBody = doc.createElement('body'), 10 | div = doc.createElement('div'); 11 | 12 | div.id = 'mq-test-1'; 13 | div.style.cssText = "position:absolute;top:-100em"; 14 | fakeBody.style.background = "none"; 15 | fakeBody.appendChild(div); 16 | 17 | return function(q){ 18 | 19 | div.innerHTML = '­'; 20 | 21 | docElem.insertBefore(fakeBody, refNode); 22 | bool = div.offsetWidth == 42; 23 | docElem.removeChild(fakeBody); 24 | 25 | return { matches: bool, media: q }; 26 | }; 27 | 28 | })(document); 29 | 30 | 31 | 32 | 33 | /*! Respond.js v1.1.0: min/max-width media query polyfill. (c) Scott Jehl. MIT/GPLv2 Lic. j.mp/respondjs */ 34 | (function( win ){ 35 | //exposed namespace 36 | win.respond = {}; 37 | 38 | //define update even in native-mq-supporting browsers, to avoid errors 39 | respond.update = function(){}; 40 | 41 | //expose media query support flag for external use 42 | respond.mediaQueriesSupported = win.matchMedia && win.matchMedia( "only all" ).matches; 43 | 44 | //if media queries are supported, exit here 45 | if( respond.mediaQueriesSupported ){ return; } 46 | 47 | //define vars 48 | var doc = win.document, 49 | docElem = doc.documentElement, 50 | mediastyles = [], 51 | rules = [], 52 | appendedEls = [], 53 | parsedSheets = {}, 54 | resizeThrottle = 30, 55 | head = doc.getElementsByTagName( "head" )[0] || docElem, 56 | base = doc.getElementsByTagName( "base" )[0], 57 | links = head.getElementsByTagName( "link" ), 58 | requestQueue = [], 59 | 60 | //loop stylesheets, send text content to translate 61 | ripCSS = function(){ 62 | var sheets = links, 63 | sl = sheets.length, 64 | i = 0, 65 | //vars for loop: 66 | sheet, href, media, isCSS; 67 | 68 | for( ; i < sl; i++ ){ 69 | sheet = sheets[ i ], 70 | href = sheet.href, 71 | media = sheet.media, 72 | isCSS = sheet.rel && sheet.rel.toLowerCase() === "stylesheet"; 73 | 74 | //only links plz and prevent re-parsing 75 | if( !!href && isCSS && !parsedSheets[ href ] ){ 76 | // selectivizr exposes css through the rawCssText expando 77 | if (sheet.styleSheet && sheet.styleSheet.rawCssText) { 78 | translate( sheet.styleSheet.rawCssText, href, media ); 79 | parsedSheets[ href ] = true; 80 | } else { 81 | if( (!/^([a-zA-Z:]*\/\/)/.test( href ) && !base) 82 | || href.replace( RegExp.$1, "" ).split( "/" )[0] === win.location.host ){ 83 | requestQueue.push( { 84 | href: href, 85 | media: media 86 | } ); 87 | } 88 | } 89 | } 90 | } 91 | makeRequests(); 92 | }, 93 | 94 | //recurse through request queue, get css text 95 | makeRequests = function(){ 96 | if( requestQueue.length ){ 97 | var thisRequest = requestQueue.shift(); 98 | 99 | ajax( thisRequest.href, function( styles ){ 100 | translate( styles, thisRequest.href, thisRequest.media ); 101 | parsedSheets[ thisRequest.href ] = true; 102 | makeRequests(); 103 | } ); 104 | } 105 | }, 106 | 107 | //find media blocks in css text, convert to style blocks 108 | translate = function( styles, href, media ){ 109 | var qs = styles.match( /@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi ), 110 | ql = qs && qs.length || 0, 111 | //try to get CSS path 112 | href = href.substring( 0, href.lastIndexOf( "/" )), 113 | repUrls = function( css ){ 114 | return css.replace( /(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g, "$1" + href + "$2$3" ); 115 | }, 116 | useMedia = !ql && media, 117 | //vars used in loop 118 | i = 0, 119 | j, fullq, thisq, eachq, eql; 120 | 121 | //if path exists, tack on trailing slash 122 | if( href.length ){ href += "/"; } 123 | 124 | //if no internal queries exist, but media attr does, use that 125 | //note: this currently lacks support for situations where a media attr is specified on a link AND 126 | //its associated stylesheet has internal CSS media queries. 127 | //In those cases, the media attribute will currently be ignored. 128 | if( useMedia ){ 129 | ql = 1; 130 | } 131 | 132 | 133 | for( ; i < ql; i++ ){ 134 | j = 0; 135 | 136 | //media attr 137 | if( useMedia ){ 138 | fullq = media; 139 | rules.push( repUrls( styles ) ); 140 | } 141 | //parse for styles 142 | else{ 143 | fullq = qs[ i ].match( /@media *([^\{]+)\{([\S\s]+?)$/ ) && RegExp.$1; 144 | rules.push( RegExp.$2 && repUrls( RegExp.$2 ) ); 145 | } 146 | 147 | eachq = fullq.split( "," ); 148 | eql = eachq.length; 149 | 150 | for( ; j < eql; j++ ){ 151 | thisq = eachq[ j ]; 152 | mediastyles.push( { 153 | media : thisq.split( "(" )[ 0 ].match( /(only\s+)?([a-zA-Z]+)\s?/ ) && RegExp.$2 || "all", 154 | rules : rules.length - 1, 155 | hasquery: thisq.indexOf("(") > -1, 156 | minw : thisq.match( /\(min\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/ ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" ), 157 | maxw : thisq.match( /\(max\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/ ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" ) 158 | } ); 159 | } 160 | } 161 | 162 | applyMedia(); 163 | }, 164 | 165 | lastCall, 166 | 167 | resizeDefer, 168 | 169 | // returns the value of 1em in pixels 170 | getEmValue = function() { 171 | var ret, 172 | div = doc.createElement('div'), 173 | body = doc.body, 174 | fakeUsed = false; 175 | 176 | div.style.cssText = "position:absolute;font-size:1em;width:1em"; 177 | 178 | if( !body ){ 179 | body = fakeUsed = doc.createElement( "body" ); 180 | body.style.background = "none"; 181 | } 182 | 183 | body.appendChild( div ); 184 | 185 | docElem.insertBefore( body, docElem.firstChild ); 186 | 187 | ret = div.offsetWidth; 188 | 189 | if( fakeUsed ){ 190 | docElem.removeChild( body ); 191 | } 192 | else { 193 | body.removeChild( div ); 194 | } 195 | 196 | //also update eminpx before returning 197 | ret = eminpx = parseFloat(ret); 198 | 199 | return ret; 200 | }, 201 | 202 | //cached container for 1em value, populated the first time it's needed 203 | eminpx, 204 | 205 | //enable/disable styles 206 | applyMedia = function( fromResize ){ 207 | var name = "clientWidth", 208 | docElemProp = docElem[ name ], 209 | currWidth = doc.compatMode === "CSS1Compat" && docElemProp || doc.body[ name ] || docElemProp, 210 | styleBlocks = {}, 211 | lastLink = links[ links.length-1 ], 212 | now = (new Date()).getTime(); 213 | 214 | //throttle resize calls 215 | if( fromResize && lastCall && now - lastCall < resizeThrottle ){ 216 | clearTimeout( resizeDefer ); 217 | resizeDefer = setTimeout( applyMedia, resizeThrottle ); 218 | return; 219 | } 220 | else { 221 | lastCall = now; 222 | } 223 | 224 | for( var i in mediastyles ){ 225 | var thisstyle = mediastyles[ i ], 226 | min = thisstyle.minw, 227 | max = thisstyle.maxw, 228 | minnull = min === null, 229 | maxnull = max === null, 230 | em = "em"; 231 | 232 | if( !!min ){ 233 | min = parseFloat( min ) * ( min.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 ); 234 | } 235 | if( !!max ){ 236 | max = parseFloat( max ) * ( max.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 ); 237 | } 238 | 239 | // if there's no media query at all (the () part), or min or max is not null, and if either is present, they're true 240 | if( !thisstyle.hasquery || ( !minnull || !maxnull ) && ( minnull || currWidth >= min ) && ( maxnull || currWidth <= max ) ){ 241 | if( !styleBlocks[ thisstyle.media ] ){ 242 | styleBlocks[ thisstyle.media ] = []; 243 | } 244 | styleBlocks[ thisstyle.media ].push( rules[ thisstyle.rules ] ); 245 | } 246 | } 247 | 248 | //remove any existing respond style element(s) 249 | for( var i in appendedEls ){ 250 | if( appendedEls[ i ] && appendedEls[ i ].parentNode === head ){ 251 | head.removeChild( appendedEls[ i ] ); 252 | } 253 | } 254 | 255 | //inject active styles, grouped by media type 256 | for( var i in styleBlocks ){ 257 | var ss = doc.createElement( "style" ), 258 | css = styleBlocks[ i ].join( "\n" ); 259 | 260 | ss.type = "text/css"; 261 | ss.media = i; 262 | 263 | //originally, ss was appended to a documentFragment and sheets were appended in bulk. 264 | //this caused crashes in IE in a number of circumstances, such as when the HTML element had a bg image set, so appending beforehand seems best. Thanks to @dvelyk for the initial research on this one! 265 | head.insertBefore( ss, lastLink.nextSibling ); 266 | 267 | if ( ss.styleSheet ){ 268 | ss.styleSheet.cssText = css; 269 | } 270 | else { 271 | ss.appendChild( doc.createTextNode( css ) ); 272 | } 273 | 274 | //push to appendedEls to track for later removal 275 | appendedEls.push( ss ); 276 | } 277 | }, 278 | //tweaked Ajax functions from Quirksmode 279 | ajax = function( url, callback ) { 280 | var req = xmlHttp(); 281 | if (!req){ 282 | return; 283 | } 284 | req.open( "GET", url, true ); 285 | req.onreadystatechange = function () { 286 | if ( req.readyState != 4 || req.status != 200 && req.status != 304 ){ 287 | return; 288 | } 289 | callback( req.responseText ); 290 | } 291 | if ( req.readyState == 4 ){ 292 | return; 293 | } 294 | req.send( null ); 295 | }, 296 | //define ajax obj 297 | xmlHttp = (function() { 298 | var xmlhttpmethod = false; 299 | try { 300 | xmlhttpmethod = new XMLHttpRequest(); 301 | } 302 | catch( e ){ 303 | xmlhttpmethod = new ActiveXObject( "Microsoft.XMLHTTP" ); 304 | } 305 | return function(){ 306 | return xmlhttpmethod; 307 | }; 308 | })(); 309 | 310 | //translate CSS 311 | ripCSS(); 312 | 313 | //expose update for re-running respond later on 314 | respond.update = ripCSS; 315 | 316 | //adjust on resize 317 | function callMedia(){ 318 | applyMedia( true ); 319 | } 320 | if( win.addEventListener ){ 321 | win.addEventListener( "resize", callMedia, false ); 322 | } 323 | else if( win.attachEvent ){ 324 | win.attachEvent( "onresize", callMedia ); 325 | } 326 | })(this); 327 | -------------------------------------------------------------------------------- /src/htbox/static/js/wp8fix/wp8fix.js: -------------------------------------------------------------------------------- 1 | if (navigator.userAgent.match(/IEMobile\/10\.0/)) { 2 | var msViewportStyle = document.createElement("style"); 3 | msViewportStyle.appendChild( 4 | document.createTextNode( 5 | "@-ms-viewport{width:auto!important}" 6 | ) 7 | ); 8 | document.getElementsByTagName("head")[0].appendChild(msViewportStyle); 9 | } 10 | -------------------------------------------------------------------------------- /src/htbox/upload/about/Kenya 294.JPG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HTBox/htbox-website/69c0755249eccd5b360b32e85c143461c90851d8/src/htbox/upload/about/Kenya 294.JPG.png --------------------------------------------------------------------------------