├── .gitignore ├── Books.sln └── Books ├── App_Start ├── BundleConfig.cs ├── FilterConfig.cs ├── RouteConfig.cs └── WebApiConfig.cs ├── Books.csproj ├── Books.csproj.user ├── Content ├── Site.css ├── bootstrap-grid.css ├── bootstrap-grid.css.map ├── bootstrap-grid.min.css ├── bootstrap-grid.min.css.map ├── bootstrap-reboot.css ├── bootstrap-reboot.css.map ├── bootstrap-reboot.min.css ├── bootstrap-reboot.min.css.map ├── bootstrap.css ├── bootstrap.css.map ├── bootstrap.min.css ├── bootstrap.min.css.map ├── fonts │ ├── icofont.eot │ ├── icofont.svg │ ├── icofont.ttf │ ├── icofont.woff │ └── icofont.woff2 ├── icofont.min.css ├── toastr.css ├── toastr.less ├── toastr.min.css └── toastr.scss ├── Controllers ├── Api │ └── BooksController.cs ├── BooksController.cs └── HomeController.cs ├── Global.asax ├── Global.asax.cs ├── Migrations ├── 202008150041214_AddNeededTables.Designer.cs ├── 202008150041214_AddNeededTables.cs ├── 202008150041214_AddNeededTables.resx └── Configuration.cs ├── Models ├── ApplicationDbContext.cs ├── Book.cs └── Category.cs ├── Properties └── AssemblyInfo.cs ├── Scripts ├── README.md ├── bootbox.min.js ├── bootstrap.bundle.js ├── bootstrap.bundle.js.map ├── bootstrap.bundle.min.js ├── bootstrap.bundle.min.js.map ├── bootstrap.js ├── bootstrap.js.map ├── bootstrap.min.js ├── bootstrap.min.js.map ├── esm │ ├── popper-utils.js │ ├── popper-utils.js.map │ ├── popper-utils.min.js │ ├── popper-utils.min.js.map │ ├── popper.js │ ├── popper.js.map │ ├── popper.min.js │ └── popper.min.js.map ├── index.d.ts ├── index.js.flow ├── jquery-3.4.1.intellisense.js ├── jquery-3.4.1.js ├── jquery-3.4.1.min.js ├── jquery-3.4.1.min.map ├── jquery-3.4.1.slim.js ├── jquery-3.4.1.slim.min.js ├── jquery-3.4.1.slim.min.map ├── jquery.validate-vsdoc.js ├── jquery.validate.js ├── jquery.validate.min.js ├── jquery.validate.unobtrusive.js ├── jquery.validate.unobtrusive.min.js ├── modernizr-2.8.3.js ├── popper-utils.js ├── popper-utils.js.map ├── popper-utils.min.js ├── popper-utils.min.js.map ├── popper.js ├── popper.js.map ├── popper.min.js ├── popper.min.js.map ├── src │ ├── index.js │ ├── methods │ │ ├── defaults.js │ │ ├── destroy.js │ │ ├── disableEventListeners.js │ │ ├── enableEventListeners.js │ │ ├── placements.js │ │ └── update.js │ ├── modifiers │ │ ├── applyStyle.js │ │ ├── arrow.js │ │ ├── computeStyle.js │ │ ├── flip.js │ │ ├── hide.js │ │ ├── index.js │ │ ├── inner.js │ │ ├── keepTogether.js │ │ ├── offset.js │ │ ├── preventOverflow.js │ │ └── shift.js │ └── utils │ │ ├── clockwise.js │ │ ├── computeAutoPlacement.js │ │ ├── debounce.js │ │ ├── find.js │ │ ├── findCommonOffsetParent.js │ │ ├── findIndex.js │ │ ├── getBordersSize.js │ │ ├── getBoundaries.js │ │ ├── getBoundingClientRect.js │ │ ├── getClientRect.js │ │ ├── getFixedPositionOffsetParent.js │ │ ├── getOffsetParent.js │ │ ├── getOffsetRect.js │ │ ├── getOffsetRectRelativeToArbitraryNode.js │ │ ├── getOppositePlacement.js │ │ ├── getOppositeVariation.js │ │ ├── getOuterSizes.js │ │ ├── getParentNode.js │ │ ├── getPopperOffsets.js │ │ ├── getReferenceNode.js │ │ ├── getReferenceOffsets.js │ │ ├── getRoot.js │ │ ├── getRoundedOffsets.js │ │ ├── getScroll.js │ │ ├── getScrollParent.js │ │ ├── getStyleComputedProperty.js │ │ ├── getSupportedPropertyName.js │ │ ├── getViewportOffsetRectRelativeToArtbitraryNode.js │ │ ├── getWindow.js │ │ ├── getWindowSizes.js │ │ ├── includeScroll.js │ │ ├── index.js │ │ ├── isBrowser.js │ │ ├── isFixed.js │ │ ├── isFunction.js │ │ ├── isIE.js │ │ ├── isModifierEnabled.js │ │ ├── isModifierRequired.js │ │ ├── isNumeric.js │ │ ├── isOffsetContainer.js │ │ ├── removeEventListeners.js │ │ ├── runModifiers.js │ │ ├── setAttributes.js │ │ ├── setStyles.js │ │ └── setupEventListeners.js ├── toastr.js ├── toastr.min.js └── umd │ ├── popper-utils.js │ ├── popper-utils.js.map │ ├── popper-utils.min.js │ ├── popper-utils.min.js.map │ ├── popper.js │ ├── popper.js.flow │ ├── popper.js.map │ ├── popper.min.js │ └── popper.min.js.map ├── ViewModels └── BookFormViewModel.cs ├── Views ├── Books │ ├── BookForm.cshtml │ ├── Details.cshtml │ └── Index.cshtml ├── Home │ ├── About.cshtml │ ├── Contact.cshtml │ └── Index.cshtml ├── Shared │ ├── Error.cshtml │ └── _Layout.cshtml ├── Web.config └── _ViewStart.cshtml ├── Web.Debug.config ├── Web.Release.config ├── Web.config ├── favicon.ico └── packages.config /.gitignore: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # This .gitignore file was automatically created by Microsoft(R) Visual Studio. 3 | ################################################################################ 4 | 5 | /.vs/Books/config 6 | /.vs/Books/v16 7 | /Books/bin 8 | /Books/obj/Debug 9 | /packages 10 | -------------------------------------------------------------------------------- /Books.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30406.217 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Books", "Books\Books.csproj", "{8B389CF6-9DBF-4425-9B91-B51FCBD15880}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {8B389CF6-9DBF-4425-9B91-B51FCBD15880}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {8B389CF6-9DBF-4425-9B91-B51FCBD15880}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {8B389CF6-9DBF-4425-9B91-B51FCBD15880}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {8B389CF6-9DBF-4425-9B91-B51FCBD15880}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {CA6BA095-42B5-424A-9957-6547FAFB7120} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Books/App_Start/BundleConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web.Optimization; 2 | 3 | namespace Books 4 | { 5 | public class BundleConfig 6 | { 7 | // For more information on bundling, visit https://go.microsoft.com/fwlink/?LinkId=301862 8 | public static void RegisterBundles(BundleCollection bundles) 9 | { 10 | bundles.Add(new ScriptBundle("~/bundles/jquery").Include( 11 | "~/Scripts/jquery-{version}.js")); 12 | 13 | bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include( 14 | "~/Scripts/jquery.validate*")); 15 | 16 | // Use the development version of Modernizr to develop with and learn from. Then, when you're 17 | // ready for production, use the build tool at https://modernizr.com to pick only the tests you need. 18 | bundles.Add(new ScriptBundle("~/bundles/modernizr").Include( 19 | "~/Scripts/modernizr-*")); 20 | 21 | bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include( 22 | "~/Scripts/bootstrap.js", 23 | "~/Scripts/bootbox.min.js", 24 | "~/Scripts/toastr.min.js")); 25 | 26 | bundles.Add(new StyleBundle("~/Content/css").Include( 27 | "~/Content/bootstrap.css", 28 | "~/Content/icofont.min.css", 29 | "~/Content/toastr.min.css", 30 | "~/Content/site.css")); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Books/App_Start/FilterConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Mvc; 3 | 4 | namespace Books 5 | { 6 | public class FilterConfig 7 | { 8 | public static void RegisterGlobalFilters(GlobalFilterCollection filters) 9 | { 10 | filters.Add(new HandleErrorAttribute()); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Books/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 Books 9 | { 10 | public class RouteConfig 11 | { 12 | public static void RegisterRoutes(RouteCollection routes) 13 | { 14 | routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 15 | 16 | routes.MapRoute( 17 | name: "Default", 18 | url: "{controller}/{action}/{id}", 19 | defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 20 | ); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Books/App_Start/WebApiConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web.Http; 5 | 6 | namespace Books 7 | { 8 | public static class WebApiConfig 9 | { 10 | public static void Register(HttpConfiguration config) 11 | { 12 | config.MapHttpAttributeRoutes(); 13 | 14 | config.Routes.MapHttpRoute( 15 | name: "DefaultApi", 16 | routeTemplate: "api/{controller}/{id}", 17 | defaults: new { id = RouteParameter.Optional } 18 | ); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Books/Books.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | true 5 | 6 | 44399 7 | 8 | 9 | 10 | 11 | Debug|Any CPU 12 | ApiControllerEmptyScaffolder 13 | root/Controller 14 | 600 15 | True 16 | False 17 | False 18 | 19 | False 20 | 600 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | CurrentPage 29 | True 30 | False 31 | False 32 | False 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | True 42 | False 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /Books/Content/Site.css: -------------------------------------------------------------------------------- 1 | body { 2 | /*padding-top: 50px;*/ 3 | padding-bottom: 20px; 4 | } 5 | 6 | /* Set padding to keep content from hitting the edges */ 7 | .body-content { 8 | padding-left: 15px; 9 | padding-right: 15px; 10 | padding-top: 50px; 11 | } 12 | 13 | /* Override the default bootstrap behavior where horizontal description lists 14 | will truncate terms that are too long to fit in the left column 15 | */ 16 | .dl-horizontal dt { 17 | white-space: normal; 18 | } 19 | 20 | /* Set width on the form input elements since they're 100% wide by default */ 21 | input, 22 | select, 23 | textarea { 24 | max-width: 280px; 25 | } 26 | 27 | /* Toastr override */ 28 | #toast-container { 29 | margin-top: 50px; 30 | } 31 | -------------------------------------------------------------------------------- /Books/Content/bootstrap-reboot.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Reboot v4.5.2 (https://getbootstrap.com/) 3 | * Copyright 2011-2020 The Bootstrap Authors 4 | * Copyright 2011-2020 Twitter, Inc. 5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) 7 | */ 8 | *, 9 | *::before, 10 | *::after { 11 | box-sizing: border-box; 12 | } 13 | 14 | html { 15 | font-family: sans-serif; 16 | line-height: 1.15; 17 | -webkit-text-size-adjust: 100%; 18 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 19 | } 20 | 21 | article, aside, figcaption, figure, footer, header, hgroup, main, nav, section { 22 | display: block; 23 | } 24 | 25 | body { 26 | margin: 0; 27 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; 28 | font-size: 1rem; 29 | font-weight: 400; 30 | line-height: 1.5; 31 | color: #212529; 32 | text-align: left; 33 | background-color: #fff; 34 | } 35 | 36 | [tabindex="-1"]:focus:not(:focus-visible) { 37 | outline: 0 !important; 38 | } 39 | 40 | hr { 41 | box-sizing: content-box; 42 | height: 0; 43 | overflow: visible; 44 | } 45 | 46 | h1, h2, h3, h4, h5, h6 { 47 | margin-top: 0; 48 | margin-bottom: 0.5rem; 49 | } 50 | 51 | p { 52 | margin-top: 0; 53 | margin-bottom: 1rem; 54 | } 55 | 56 | abbr[title], 57 | abbr[data-original-title] { 58 | text-decoration: underline; 59 | -webkit-text-decoration: underline dotted; 60 | text-decoration: underline dotted; 61 | cursor: help; 62 | border-bottom: 0; 63 | -webkit-text-decoration-skip-ink: none; 64 | text-decoration-skip-ink: none; 65 | } 66 | 67 | address { 68 | margin-bottom: 1rem; 69 | font-style: normal; 70 | line-height: inherit; 71 | } 72 | 73 | ol, 74 | ul, 75 | dl { 76 | margin-top: 0; 77 | margin-bottom: 1rem; 78 | } 79 | 80 | ol ol, 81 | ul ul, 82 | ol ul, 83 | ul ol { 84 | margin-bottom: 0; 85 | } 86 | 87 | dt { 88 | font-weight: 700; 89 | } 90 | 91 | dd { 92 | margin-bottom: .5rem; 93 | margin-left: 0; 94 | } 95 | 96 | blockquote { 97 | margin: 0 0 1rem; 98 | } 99 | 100 | b, 101 | strong { 102 | font-weight: bolder; 103 | } 104 | 105 | small { 106 | font-size: 80%; 107 | } 108 | 109 | sub, 110 | sup { 111 | position: relative; 112 | font-size: 75%; 113 | line-height: 0; 114 | vertical-align: baseline; 115 | } 116 | 117 | sub { 118 | bottom: -.25em; 119 | } 120 | 121 | sup { 122 | top: -.5em; 123 | } 124 | 125 | a { 126 | color: #007bff; 127 | text-decoration: none; 128 | background-color: transparent; 129 | } 130 | 131 | a:hover { 132 | color: #0056b3; 133 | text-decoration: underline; 134 | } 135 | 136 | a:not([href]):not([class]) { 137 | color: inherit; 138 | text-decoration: none; 139 | } 140 | 141 | a:not([href]):not([class]):hover { 142 | color: inherit; 143 | text-decoration: none; 144 | } 145 | 146 | pre, 147 | code, 148 | kbd, 149 | samp { 150 | font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; 151 | font-size: 1em; 152 | } 153 | 154 | pre { 155 | margin-top: 0; 156 | margin-bottom: 1rem; 157 | overflow: auto; 158 | -ms-overflow-style: scrollbar; 159 | } 160 | 161 | figure { 162 | margin: 0 0 1rem; 163 | } 164 | 165 | img { 166 | vertical-align: middle; 167 | border-style: none; 168 | } 169 | 170 | svg { 171 | overflow: hidden; 172 | vertical-align: middle; 173 | } 174 | 175 | table { 176 | border-collapse: collapse; 177 | } 178 | 179 | caption { 180 | padding-top: 0.75rem; 181 | padding-bottom: 0.75rem; 182 | color: #6c757d; 183 | text-align: left; 184 | caption-side: bottom; 185 | } 186 | 187 | th { 188 | text-align: inherit; 189 | } 190 | 191 | label { 192 | display: inline-block; 193 | margin-bottom: 0.5rem; 194 | } 195 | 196 | button { 197 | border-radius: 0; 198 | } 199 | 200 | button:focus { 201 | outline: 1px dotted; 202 | outline: 5px auto -webkit-focus-ring-color; 203 | } 204 | 205 | input, 206 | button, 207 | select, 208 | optgroup, 209 | textarea { 210 | margin: 0; 211 | font-family: inherit; 212 | font-size: inherit; 213 | line-height: inherit; 214 | } 215 | 216 | button, 217 | input { 218 | overflow: visible; 219 | } 220 | 221 | button, 222 | select { 223 | text-transform: none; 224 | } 225 | 226 | [role="button"] { 227 | cursor: pointer; 228 | } 229 | 230 | select { 231 | word-wrap: normal; 232 | } 233 | 234 | button, 235 | [type="button"], 236 | [type="reset"], 237 | [type="submit"] { 238 | -webkit-appearance: button; 239 | } 240 | 241 | button:not(:disabled), 242 | [type="button"]:not(:disabled), 243 | [type="reset"]:not(:disabled), 244 | [type="submit"]:not(:disabled) { 245 | cursor: pointer; 246 | } 247 | 248 | button::-moz-focus-inner, 249 | [type="button"]::-moz-focus-inner, 250 | [type="reset"]::-moz-focus-inner, 251 | [type="submit"]::-moz-focus-inner { 252 | padding: 0; 253 | border-style: none; 254 | } 255 | 256 | input[type="radio"], 257 | input[type="checkbox"] { 258 | box-sizing: border-box; 259 | padding: 0; 260 | } 261 | 262 | textarea { 263 | overflow: auto; 264 | resize: vertical; 265 | } 266 | 267 | fieldset { 268 | min-width: 0; 269 | padding: 0; 270 | margin: 0; 271 | border: 0; 272 | } 273 | 274 | legend { 275 | display: block; 276 | width: 100%; 277 | max-width: 100%; 278 | padding: 0; 279 | margin-bottom: .5rem; 280 | font-size: 1.5rem; 281 | line-height: inherit; 282 | color: inherit; 283 | white-space: normal; 284 | } 285 | 286 | progress { 287 | vertical-align: baseline; 288 | } 289 | 290 | [type="number"]::-webkit-inner-spin-button, 291 | [type="number"]::-webkit-outer-spin-button { 292 | height: auto; 293 | } 294 | 295 | [type="search"] { 296 | outline-offset: -2px; 297 | -webkit-appearance: none; 298 | } 299 | 300 | [type="search"]::-webkit-search-decoration { 301 | -webkit-appearance: none; 302 | } 303 | 304 | ::-webkit-file-upload-button { 305 | font: inherit; 306 | -webkit-appearance: button; 307 | } 308 | 309 | output { 310 | display: inline-block; 311 | } 312 | 313 | summary { 314 | display: list-item; 315 | cursor: pointer; 316 | } 317 | 318 | template { 319 | display: none; 320 | } 321 | 322 | [hidden] { 323 | display: none !important; 324 | } 325 | /*# sourceMappingURL=bootstrap-reboot.css.map */ -------------------------------------------------------------------------------- /Books/Content/bootstrap-reboot.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Reboot v4.5.2 (https://getbootstrap.com/) 3 | * Copyright 2011-2020 The Bootstrap Authors 4 | * Copyright 2011-2020 Twitter, Inc. 5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) 7 | */*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([class]){color:inherit;text-decoration:none}a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important} 8 | /*# sourceMappingURL=bootstrap-reboot.min.css.map */ -------------------------------------------------------------------------------- /Books/Content/fonts/icofont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadelhelaly/Books_ASPNETMVC5/59f95a2116df2cf41647168f81e0d878a2093a50/Books/Content/fonts/icofont.ttf -------------------------------------------------------------------------------- /Books/Content/fonts/icofont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadelhelaly/Books_ASPNETMVC5/59f95a2116df2cf41647168f81e0d878a2093a50/Books/Content/fonts/icofont.woff -------------------------------------------------------------------------------- /Books/Content/fonts/icofont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadelhelaly/Books_ASPNETMVC5/59f95a2116df2cf41647168f81e0d878a2093a50/Books/Content/fonts/icofont.woff2 -------------------------------------------------------------------------------- /Books/Content/toastr.css: -------------------------------------------------------------------------------- 1 | .toast-title { 2 | font-weight: bold; 3 | } 4 | .toast-message { 5 | -ms-word-wrap: break-word; 6 | word-wrap: break-word; 7 | } 8 | .toast-message a, 9 | .toast-message label { 10 | color: #ffffff; 11 | } 12 | .toast-message a:hover { 13 | color: #cccccc; 14 | text-decoration: none; 15 | } 16 | .toast-close-button { 17 | position: relative; 18 | right: -0.3em; 19 | top: -0.3em; 20 | float: right; 21 | font-size: 20px; 22 | font-weight: bold; 23 | color: #ffffff; 24 | -webkit-text-shadow: 0 1px 0 #ffffff; 25 | text-shadow: 0 1px 0 #ffffff; 26 | opacity: 0.8; 27 | -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); 28 | filter: alpha(opacity=80); 29 | } 30 | .toast-close-button:hover, 31 | .toast-close-button:focus { 32 | color: #000000; 33 | text-decoration: none; 34 | cursor: pointer; 35 | opacity: 0.4; 36 | -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40); 37 | filter: alpha(opacity=40); 38 | } 39 | /*Additional properties for button version 40 | iOS requires the button element instead of an anchor tag. 41 | If you want the anchor version, it requires `href="#"`.*/ 42 | button.toast-close-button { 43 | padding: 0; 44 | cursor: pointer; 45 | background: transparent; 46 | border: 0; 47 | -webkit-appearance: none; 48 | } 49 | .toast-top-center { 50 | top: 0; 51 | right: 0; 52 | width: 100%; 53 | } 54 | .toast-bottom-center { 55 | bottom: 0; 56 | right: 0; 57 | width: 100%; 58 | } 59 | .toast-top-full-width { 60 | top: 0; 61 | right: 0; 62 | width: 100%; 63 | } 64 | .toast-bottom-full-width { 65 | bottom: 0; 66 | right: 0; 67 | width: 100%; 68 | } 69 | .toast-top-left { 70 | top: 12px; 71 | left: 12px; 72 | } 73 | .toast-top-right { 74 | top: 12px; 75 | right: 12px; 76 | } 77 | .toast-bottom-right { 78 | right: 12px; 79 | bottom: 12px; 80 | } 81 | .toast-bottom-left { 82 | bottom: 12px; 83 | left: 12px; 84 | } 85 | #toast-container { 86 | position: fixed; 87 | z-index: 999999; 88 | /*overrides*/ 89 | 90 | } 91 | #toast-container * { 92 | -moz-box-sizing: border-box; 93 | -webkit-box-sizing: border-box; 94 | box-sizing: border-box; 95 | } 96 | #toast-container > div { 97 | position: relative; 98 | overflow: hidden; 99 | margin: 0 0 6px; 100 | padding: 15px 15px 15px 50px; 101 | width: 300px; 102 | -moz-border-radius: 3px 3px 3px 3px; 103 | -webkit-border-radius: 3px 3px 3px 3px; 104 | border-radius: 3px 3px 3px 3px; 105 | background-position: 15px center; 106 | background-repeat: no-repeat; 107 | -moz-box-shadow: 0 0 12px #999999; 108 | -webkit-box-shadow: 0 0 12px #999999; 109 | box-shadow: 0 0 12px #999999; 110 | color: #ffffff; 111 | opacity: 0.8; 112 | -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); 113 | filter: alpha(opacity=80); 114 | } 115 | #toast-container > :hover { 116 | -moz-box-shadow: 0 0 12px #000000; 117 | -webkit-box-shadow: 0 0 12px #000000; 118 | box-shadow: 0 0 12px #000000; 119 | opacity: 1; 120 | -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100); 121 | filter: alpha(opacity=100); 122 | cursor: pointer; 123 | } 124 | #toast-container > .toast-info { 125 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=") !important; 126 | } 127 | #toast-container > .toast-error { 128 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=") !important; 129 | } 130 | #toast-container > .toast-success { 131 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==") !important; 132 | } 133 | #toast-container > .toast-warning { 134 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=") !important; 135 | } 136 | #toast-container.toast-top-center > div, 137 | #toast-container.toast-bottom-center > div { 138 | width: 300px; 139 | margin: auto; 140 | } 141 | #toast-container.toast-top-full-width > div, 142 | #toast-container.toast-bottom-full-width > div { 143 | width: 96%; 144 | margin: auto; 145 | } 146 | .toast { 147 | background-color: #030303; 148 | } 149 | .toast-success { 150 | background-color: #51a351; 151 | } 152 | .toast-error { 153 | background-color: #bd362f; 154 | } 155 | .toast-info { 156 | background-color: #2f96b4; 157 | } 158 | .toast-warning { 159 | background-color: #f89406; 160 | } 161 | .toast-progress { 162 | position: absolute; 163 | left: 0; 164 | bottom: 0; 165 | height: 4px; 166 | background-color: #000000; 167 | opacity: 0.4; 168 | -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40); 169 | filter: alpha(opacity=40); 170 | } 171 | /*Responsive Design*/ 172 | @media all and (max-width: 240px) { 173 | #toast-container > div { 174 | padding: 8px 8px 8px 50px; 175 | width: 11em; 176 | } 177 | #toast-container .toast-close-button { 178 | right: -0.2em; 179 | top: -0.2em; 180 | } 181 | } 182 | @media all and (min-width: 241px) and (max-width: 480px) { 183 | #toast-container > div { 184 | padding: 8px 8px 8px 50px; 185 | width: 18em; 186 | } 187 | #toast-container .toast-close-button { 188 | right: -0.2em; 189 | top: -0.2em; 190 | } 191 | } 192 | @media all and (min-width: 481px) and (max-width: 768px) { 193 | #toast-container > div { 194 | padding: 15px 15px 15px 50px; 195 | width: 25em; 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /Books/Content/toastr.less: -------------------------------------------------------------------------------- 1 | // Mix-ins 2 | .borderRadius(@radius) { 3 | -moz-border-radius: @radius; 4 | -webkit-border-radius: @radius; 5 | border-radius: @radius; 6 | } 7 | 8 | .boxShadow(@boxShadow) { 9 | -moz-box-shadow: @boxShadow; 10 | -webkit-box-shadow: @boxShadow; 11 | box-shadow: @boxShadow; 12 | } 13 | 14 | .opacity(@opacity) { 15 | @opacityPercent: @opacity * 100; 16 | opacity: @opacity; 17 | -ms-filter: ~"progid:DXImageTransform.Microsoft.Alpha(Opacity=@{opacityPercent})"; 18 | filter: ~"alpha(opacity=@{opacityPercent})"; 19 | } 20 | 21 | .wordWrap(@wordWrap: break-word) { 22 | -ms-word-wrap: @wordWrap; 23 | word-wrap: @wordWrap; 24 | } 25 | 26 | // Variables 27 | @black: #000000; 28 | @grey: #999999; 29 | @light-grey: #CCCCCC; 30 | @white: #FFFFFF; 31 | @near-black: #030303; 32 | @green: #51A351; 33 | @red: #BD362F; 34 | @blue: #2F96B4; 35 | @orange: #F89406; 36 | 37 | // Styles 38 | .toast-title { 39 | font-weight: bold; 40 | } 41 | 42 | .toast-message { 43 | .wordWrap(); 44 | 45 | a, 46 | label { 47 | color: @white; 48 | } 49 | 50 | a:hover { 51 | color: @light-grey; 52 | text-decoration: none; 53 | } 54 | } 55 | 56 | .toast-close-button { 57 | position: relative; 58 | right: -0.3em; 59 | top: -0.3em; 60 | float: right; 61 | font-size: 20px; 62 | font-weight: bold; 63 | color: @white; 64 | -webkit-text-shadow: 0 1px 0 rgba(255,255,255,1); 65 | text-shadow: 0 1px 0 rgba(255,255,255,1); 66 | .opacity(0.8); 67 | 68 | &:hover, 69 | &:focus { 70 | color: @black; 71 | text-decoration: none; 72 | cursor: pointer; 73 | .opacity(0.4); 74 | } 75 | } 76 | 77 | /*Additional properties for button version 78 | iOS requires the button element instead of an anchor tag. 79 | If you want the anchor version, it requires `href="#"`.*/ 80 | button.toast-close-button { 81 | padding: 0; 82 | cursor: pointer; 83 | background: transparent; 84 | border: 0; 85 | -webkit-appearance: none; 86 | } 87 | 88 | //#endregion 89 | 90 | .toast-top-center { 91 | top: 0; 92 | right: 0; 93 | width: 100%; 94 | } 95 | 96 | .toast-bottom-center { 97 | bottom: 0; 98 | right: 0; 99 | width: 100%; 100 | } 101 | 102 | .toast-top-full-width { 103 | top: 0; 104 | right: 0; 105 | width: 100%; 106 | } 107 | 108 | .toast-bottom-full-width { 109 | bottom: 0; 110 | right: 0; 111 | width: 100%; 112 | } 113 | 114 | .toast-top-left { 115 | top: 12px; 116 | left: 12px; 117 | } 118 | 119 | .toast-top-right { 120 | top: 12px; 121 | right: 12px; 122 | } 123 | 124 | .toast-bottom-right { 125 | right: 12px; 126 | bottom: 12px; 127 | } 128 | 129 | .toast-bottom-left { 130 | bottom: 12px; 131 | left: 12px; 132 | } 133 | 134 | #toast-container { 135 | position: fixed; 136 | z-index: 999999; 137 | 138 | * { 139 | -moz-box-sizing: border-box; 140 | -webkit-box-sizing: border-box; 141 | box-sizing: border-box; 142 | } 143 | 144 | > div { 145 | position: relative; 146 | overflow: hidden; 147 | margin: 0 0 6px; 148 | padding: 15px 15px 15px 50px; 149 | width: 300px; 150 | .borderRadius(3px 3px 3px 3px); 151 | background-position: 15px center; 152 | background-repeat: no-repeat; 153 | .boxShadow(0 0 12px @grey); 154 | color: @white; 155 | .opacity(0.8); 156 | } 157 | 158 | > :hover { 159 | .boxShadow(0 0 12px @black); 160 | .opacity(1); 161 | cursor: pointer; 162 | } 163 | 164 | > .toast-info { 165 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=") !important; 166 | } 167 | 168 | > .toast-error { 169 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=") !important; 170 | } 171 | 172 | > .toast-success { 173 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==") !important; 174 | } 175 | 176 | > .toast-warning { 177 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=") !important; 178 | } 179 | 180 | /*overrides*/ 181 | &.toast-top-center > div, 182 | &.toast-bottom-center > div { 183 | width: 300px; 184 | margin: auto; 185 | } 186 | 187 | &.toast-top-full-width > div, 188 | &.toast-bottom-full-width > div { 189 | width: 96%; 190 | margin: auto; 191 | } 192 | } 193 | 194 | .toast { 195 | background-color: @near-black; 196 | } 197 | 198 | .toast-success { 199 | background-color: @green; 200 | } 201 | 202 | .toast-error { 203 | background-color: @red; 204 | } 205 | 206 | .toast-info { 207 | background-color: @blue; 208 | } 209 | 210 | .toast-warning { 211 | background-color: @orange; 212 | } 213 | 214 | .toast-progress { 215 | position: absolute; 216 | left: 0; 217 | bottom: 0; 218 | height: 4px; 219 | background-color: @black; 220 | .opacity(0.4); 221 | } 222 | 223 | /*Responsive Design*/ 224 | 225 | @media all and (max-width: 240px) { 226 | #toast-container { 227 | 228 | > div { 229 | padding: 8px 8px 8px 50px; 230 | width: 11em; 231 | } 232 | 233 | & .toast-close-button { 234 | right: -0.2em; 235 | top: -0.2em; 236 | } 237 | } 238 | } 239 | 240 | @media all and (min-width: 241px) and (max-width: 480px) { 241 | #toast-container { 242 | > div { 243 | padding: 8px 8px 8px 50px; 244 | width: 18em; 245 | } 246 | 247 | & .toast-close-button { 248 | right: -0.2em; 249 | top: -0.2em; 250 | } 251 | } 252 | } 253 | 254 | @media all and (min-width: 481px) and (max-width: 768px) { 255 | #toast-container { 256 | > div { 257 | padding: 15px 15px 15px 50px; 258 | width: 25em; 259 | } 260 | } 261 | } 262 | -------------------------------------------------------------------------------- /Books/Content/toastr.min.css: -------------------------------------------------------------------------------- 1 | .toast-title{font-weight:700}.toast-message{-ms-word-wrap:break-word;word-wrap:break-word}.toast-message a,.toast-message label{color:#fff}.toast-message a:hover{color:#ccc;text-decoration:none}.toast-close-button{position:relative;right:-.3em;top:-.3em;float:right;font-size:20px;font-weight:700;color:#fff;-webkit-text-shadow:0 1px 0 #fff;text-shadow:0 1px 0 #fff;opacity:.8;-ms-filter:alpha(Opacity=80);filter:alpha(opacity=80)}.toast-close-button:focus,.toast-close-button:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.4;-ms-filter:alpha(Opacity=40);filter:alpha(opacity=40)}button.toast-close-button{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}.toast-top-center{top:0;right:0;width:100%}.toast-bottom-center{bottom:0;right:0;width:100%}.toast-top-full-width{top:0;right:0;width:100%}.toast-bottom-full-width{bottom:0;right:0;width:100%}.toast-top-left{top:12px;left:12px}.toast-top-right{top:12px;right:12px}.toast-bottom-right{right:12px;bottom:12px}.toast-bottom-left{bottom:12px;left:12px}#toast-container{position:fixed;z-index:999999}#toast-container *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}#toast-container>div{position:relative;overflow:hidden;margin:0 0 6px;padding:15px 15px 15px 50px;width:300px;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;background-position:15px center;background-repeat:no-repeat;-moz-box-shadow:0 0 12px #999;-webkit-box-shadow:0 0 12px #999;box-shadow:0 0 12px #999;color:#fff;opacity:.8;-ms-filter:alpha(Opacity=80);filter:alpha(opacity=80)}#toast-container>:hover{-moz-box-shadow:0 0 12px #000;-webkit-box-shadow:0 0 12px #000;box-shadow:0 0 12px #000;opacity:1;-ms-filter:alpha(Opacity=100);filter:alpha(opacity=100);cursor:pointer}#toast-container>.toast-info{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=)!important}#toast-container>.toast-error{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=)!important}#toast-container>.toast-success{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==)!important}#toast-container>.toast-warning{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=)!important}#toast-container.toast-bottom-center>div,#toast-container.toast-top-center>div{width:300px;margin:auto}#toast-container.toast-bottom-full-width>div,#toast-container.toast-top-full-width>div{width:96%;margin:auto}.toast{background-color:#030303}.toast-success{background-color:#51a351}.toast-error{background-color:#bd362f}.toast-info{background-color:#2f96b4}.toast-warning{background-color:#f89406}.toast-progress{position:absolute;left:0;bottom:0;height:4px;background-color:#000;opacity:.4;-ms-filter:alpha(Opacity=40);filter:alpha(opacity=40)}@media all and (max-width:240px){#toast-container>div{padding:8px 8px 8px 50px;width:11em}#toast-container .toast-close-button{right:-.2em;top:-.2em}}@media all and (min-width:241px) and (max-width:480px){#toast-container>div{padding:8px 8px 8px 50px;width:18em}#toast-container .toast-close-button{right:-.2em;top:-.2em}}@media all and (min-width:481px) and (max-width:768px){#toast-container>div{padding:15px 15px 15px 50px;width:25em}} 2 | -------------------------------------------------------------------------------- /Books/Content/toastr.scss: -------------------------------------------------------------------------------- 1 | .toast-title { 2 | font-weight: bold; 3 | } 4 | .toast-message { 5 | -ms-word-wrap: break-word; 6 | word-wrap: break-word; 7 | } 8 | .toast-message a, 9 | .toast-message label { 10 | color: #ffffff; 11 | } 12 | .toast-message a:hover { 13 | color: #cccccc; 14 | text-decoration: none; 15 | } 16 | .toast-close-button { 17 | position: relative; 18 | right: -0.3em; 19 | top: -0.3em; 20 | float: right; 21 | font-size: 20px; 22 | font-weight: bold; 23 | color: #ffffff; 24 | -webkit-text-shadow: 0 1px 0 #ffffff; 25 | text-shadow: 0 1px 0 #ffffff; 26 | opacity: 0.8; 27 | -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); 28 | filter: alpha(opacity=80); 29 | } 30 | .toast-close-button:hover, 31 | .toast-close-button:focus { 32 | color: #000000; 33 | text-decoration: none; 34 | cursor: pointer; 35 | opacity: 0.4; 36 | -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40); 37 | filter: alpha(opacity=40); 38 | } 39 | /*Additional properties for button version 40 | iOS requires the button element instead of an anchor tag. 41 | If you want the anchor version, it requires `href="#"`.*/ 42 | button.toast-close-button { 43 | padding: 0; 44 | cursor: pointer; 45 | background: transparent; 46 | border: 0; 47 | -webkit-appearance: none; 48 | } 49 | .toast-top-center { 50 | top: 0; 51 | right: 0; 52 | width: 100%; 53 | } 54 | .toast-bottom-center { 55 | bottom: 0; 56 | right: 0; 57 | width: 100%; 58 | } 59 | .toast-top-full-width { 60 | top: 0; 61 | right: 0; 62 | width: 100%; 63 | } 64 | .toast-bottom-full-width { 65 | bottom: 0; 66 | right: 0; 67 | width: 100%; 68 | } 69 | .toast-top-left { 70 | top: 12px; 71 | left: 12px; 72 | } 73 | .toast-top-right { 74 | top: 12px; 75 | right: 12px; 76 | } 77 | .toast-bottom-right { 78 | right: 12px; 79 | bottom: 12px; 80 | } 81 | .toast-bottom-left { 82 | bottom: 12px; 83 | left: 12px; 84 | } 85 | #toast-container { 86 | position: fixed; 87 | z-index: 999999; 88 | /*overrides*/ 89 | 90 | } 91 | #toast-container * { 92 | -moz-box-sizing: border-box; 93 | -webkit-box-sizing: border-box; 94 | box-sizing: border-box; 95 | } 96 | #toast-container > div { 97 | position: relative; 98 | overflow: hidden; 99 | margin: 0 0 6px; 100 | padding: 15px 15px 15px 50px; 101 | width: 300px; 102 | -moz-border-radius: 3px 3px 3px 3px; 103 | -webkit-border-radius: 3px 3px 3px 3px; 104 | border-radius: 3px 3px 3px 3px; 105 | background-position: 15px center; 106 | background-repeat: no-repeat; 107 | -moz-box-shadow: 0 0 12px #999999; 108 | -webkit-box-shadow: 0 0 12px #999999; 109 | box-shadow: 0 0 12px #999999; 110 | color: #ffffff; 111 | opacity: 0.8; 112 | -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); 113 | filter: alpha(opacity=80); 114 | } 115 | #toast-container > :hover { 116 | -moz-box-shadow: 0 0 12px #000000; 117 | -webkit-box-shadow: 0 0 12px #000000; 118 | box-shadow: 0 0 12px #000000; 119 | opacity: 1; 120 | -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100); 121 | filter: alpha(opacity=100); 122 | cursor: pointer; 123 | } 124 | #toast-container > .toast-info { 125 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=") !important; 126 | } 127 | #toast-container > .toast-error { 128 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=") !important; 129 | } 130 | #toast-container > .toast-success { 131 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==") !important; 132 | } 133 | #toast-container > .toast-warning { 134 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=") !important; 135 | } 136 | #toast-container.toast-top-center > div, 137 | #toast-container.toast-bottom-center > div { 138 | width: 300px; 139 | margin: auto; 140 | } 141 | #toast-container.toast-top-full-width > div, 142 | #toast-container.toast-bottom-full-width > div { 143 | width: 96%; 144 | margin: auto; 145 | } 146 | .toast { 147 | background-color: #030303; 148 | } 149 | .toast-success { 150 | background-color: #51a351; 151 | } 152 | .toast-error { 153 | background-color: #bd362f; 154 | } 155 | .toast-info { 156 | background-color: #2f96b4; 157 | } 158 | .toast-warning { 159 | background-color: #f89406; 160 | } 161 | 162 | .toast-progress { 163 | position: absolute; 164 | left: 0; 165 | bottom: 0; 166 | height: 4px; 167 | background-color: #000000; 168 | opacity: 0.4; 169 | -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40); 170 | filter: alpha(opacity=40); 171 | } 172 | 173 | /*Responsive Design*/ 174 | @media all and (max-width: 240px) { 175 | #toast-container > div { 176 | padding: 8px 8px 8px 50px; 177 | width: 11em; 178 | } 179 | #toast-container .toast-close-button { 180 | right: -0.2em; 181 | top: -0.2em; 182 | } 183 | } 184 | @media all and (min-width: 241px) and (max-width: 480px) { 185 | #toast-container > div { 186 | padding: 8px 8px 8px 50px; 187 | width: 18em; 188 | } 189 | #toast-container .toast-close-button { 190 | right: -0.2em; 191 | top: -0.2em; 192 | } 193 | } 194 | @media all and (min-width: 481px) and (max-width: 768px) { 195 | #toast-container > div { 196 | padding: 15px 15px 15px 50px; 197 | width: 25em; 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /Books/Controllers/Api/BooksController.cs: -------------------------------------------------------------------------------- 1 | using Books.Models; 2 | using System.Web.Http; 3 | 4 | namespace Books.Controllers.Api 5 | { 6 | public class BooksController : ApiController 7 | { 8 | private readonly ApplicationDbContext _context; 9 | 10 | public BooksController() 11 | { 12 | _context = new ApplicationDbContext(); 13 | } 14 | 15 | [HttpDelete] 16 | public IHttpActionResult DeleteBook(int id) 17 | { 18 | var book = _context.Books.Find(id); 19 | 20 | if (book == null) 21 | return NotFound(); 22 | 23 | _context.Books.Remove(book); 24 | _context.SaveChanges(); 25 | 26 | return Ok(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Books/Controllers/BooksController.cs: -------------------------------------------------------------------------------- 1 | using Books.Models; 2 | using Books.ViewModels; 3 | using System.Data.Entity; 4 | using System.Linq; 5 | using System.Net; 6 | using System.Web.Mvc; 7 | 8 | namespace Books.Controllers 9 | { 10 | public class BooksController : Controller 11 | { 12 | private readonly ApplicationDbContext _context; 13 | 14 | public BooksController() 15 | { 16 | _context = new ApplicationDbContext(); 17 | } 18 | 19 | // GET: Books 20 | public ActionResult Index() 21 | { 22 | var books = _context.Books.Include(m => m.Category).ToList(); 23 | return View(books); 24 | } 25 | 26 | public ActionResult Details(int? id) 27 | { 28 | if (id == null) 29 | return new HttpStatusCodeResult(HttpStatusCode.BadRequest); 30 | 31 | var book = _context.Books.Include(m => m.Category).SingleOrDefault(m => m.Id == id); 32 | 33 | if (book == null) 34 | return HttpNotFound(); 35 | 36 | return View(book); 37 | } 38 | 39 | public ActionResult Create() 40 | { 41 | var viewModel = new BookFormViewModel 42 | { 43 | Categories = _context.Categories.Where(m => m.IsActive).ToList() 44 | }; 45 | 46 | return View("BookForm", viewModel); 47 | } 48 | 49 | public ActionResult Edit(int? id) 50 | { 51 | if (id == null) 52 | return new HttpStatusCodeResult(HttpStatusCode.BadRequest); 53 | 54 | var book = _context.Books.Find(id); 55 | 56 | if (book == null) 57 | return HttpNotFound(); 58 | 59 | var viewModel = new BookFormViewModel 60 | { 61 | Id = book.Id, 62 | Title = book.Title, 63 | Author = book.Author, 64 | CategoryId = book.CategoryId, 65 | Description = book.Description, 66 | Categories = _context.Categories.Where(m => m.IsActive).ToList() 67 | }; 68 | 69 | return View("BookForm", viewModel); 70 | } 71 | 72 | [HttpPost] 73 | [ValidateAntiForgeryToken] 74 | public ActionResult Save(BookFormViewModel model) 75 | { 76 | if (!ModelState.IsValid) 77 | { 78 | model.Categories = _context.Categories.Where(m => m.IsActive).ToList(); 79 | return View("BookForm", model); 80 | } 81 | 82 | if (model.Id == 0) 83 | { 84 | var book = new Book 85 | { 86 | Title = model.Title, 87 | Author = model.Author, 88 | CategoryId = model.CategoryId, 89 | Description = model.Description 90 | }; 91 | 92 | _context.Books.Add(book); 93 | } 94 | 95 | else 96 | { 97 | var book = _context.Books.Find(model.Id); 98 | 99 | if (book == null) 100 | return HttpNotFound(); 101 | 102 | book.Title = model.Title; 103 | book.Author = model.Author; 104 | book.CategoryId = model.CategoryId; 105 | book.Description = model.Description; 106 | } 107 | 108 | _context.SaveChanges(); 109 | 110 | TempData["Message"] = "Saved successfully"; 111 | return RedirectToAction("Index"); 112 | } 113 | } 114 | } -------------------------------------------------------------------------------- /Books/Controllers/HomeController.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 Books.Controllers 8 | { 9 | public class HomeController : Controller 10 | { 11 | public ActionResult Index() 12 | { 13 | return View(); 14 | } 15 | 16 | public ActionResult About() 17 | { 18 | ViewBag.Message = "Your application description page."; 19 | 20 | return View(); 21 | } 22 | 23 | public ActionResult Contact() 24 | { 25 | ViewBag.Message = "Your contact page."; 26 | 27 | return View(); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /Books/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="Books.MvcApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /Books/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System.Web.Http; 2 | using System.Web.Mvc; 3 | using System.Web.Optimization; 4 | using System.Web.Routing; 5 | 6 | namespace Books 7 | { 8 | public class MvcApplication : System.Web.HttpApplication 9 | { 10 | protected void Application_Start() 11 | { 12 | GlobalConfiguration.Configure(WebApiConfig.Register); 13 | AreaRegistration.RegisterAllAreas(); 14 | FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 15 | RouteConfig.RegisterRoutes(RouteTable.Routes); 16 | BundleConfig.RegisterBundles(BundleTable.Bundles); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Books/Migrations/202008150041214_AddNeededTables.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | namespace Books.Migrations 3 | { 4 | using System.CodeDom.Compiler; 5 | using System.Data.Entity.Migrations; 6 | using System.Data.Entity.Migrations.Infrastructure; 7 | using System.Resources; 8 | 9 | [GeneratedCode("EntityFramework.Migrations", "6.4.4")] 10 | public sealed partial class AddNeededTables : IMigrationMetadata 11 | { 12 | private readonly ResourceManager Resources = new ResourceManager(typeof(AddNeededTables)); 13 | 14 | string IMigrationMetadata.Id 15 | { 16 | get { return "202008150041214_AddNeededTables"; } 17 | } 18 | 19 | string IMigrationMetadata.Source 20 | { 21 | get { return null; } 22 | } 23 | 24 | string IMigrationMetadata.Target 25 | { 26 | get { return Resources.GetString("Target"); } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Books/Migrations/202008150041214_AddNeededTables.cs: -------------------------------------------------------------------------------- 1 | namespace Books.Migrations 2 | { 3 | using System; 4 | using System.Data.Entity.Migrations; 5 | 6 | public partial class AddNeededTables : DbMigration 7 | { 8 | public override void Up() 9 | { 10 | CreateTable( 11 | "dbo.Books", 12 | c => new 13 | { 14 | Id = c.Int(nullable: false, identity: true), 15 | Title = c.String(nullable: false, maxLength: 256), 16 | Author = c.String(nullable: false, maxLength: 128), 17 | Description = c.String(nullable: false, maxLength: 2000), 18 | CategoryId = c.Byte(nullable: false), 19 | AddedOn = c.DateTime(nullable: false), 20 | }) 21 | .PrimaryKey(t => t.Id) 22 | .ForeignKey("dbo.Categories", t => t.CategoryId, cascadeDelete: true) 23 | .Index(t => t.CategoryId); 24 | 25 | CreateTable( 26 | "dbo.Categories", 27 | c => new 28 | { 29 | Id = c.Byte(nullable: false, identity: true), 30 | Name = c.String(nullable: false, maxLength: 128), 31 | IsActive = c.Boolean(nullable: false), 32 | }) 33 | .PrimaryKey(t => t.Id); 34 | 35 | } 36 | 37 | public override void Down() 38 | { 39 | DropForeignKey("dbo.Books", "CategoryId", "dbo.Categories"); 40 | DropIndex("dbo.Books", new[] { "CategoryId" }); 41 | DropTable("dbo.Categories"); 42 | DropTable("dbo.Books"); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Books/Migrations/202008150041214_AddNeededTables.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 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 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | H4sIAAAAAAAEANVZ224bNxB9L9B/IPaxcLSSgxapISVwZLsQGluB5QR9C6jdkUyES25JriEh6Jf1oZ/UX+hwr9ybJF/RwIDhJWfODIeHwxn637//Gb/bRJzcgdJMiok3Ggw9AiKQIRPriZeY1as33ru3P/4wPg+jDflcyL22cqgp9MS7NSY+8X0d3EJE9SBigZJarswgkJFPQ+kfD4e/+qORDwjhIRYh4+tEGBZB+oGfUykCiE1C+aUMget8HGcWKSq5ohHomAYw8d5L+VUPMjmPnHJG0YcF8JVHqBDSUIMennzSsDBKivUixgHKb7YxoNyKcg255yeV+KGLGB7bRfiVYgEVJNrI6J6Ao9d5VPym+oNi65VRw7idY3zN1q46jV0WNo80DZ1MubJC9bAO7McRSYeOyk1HbtifIzJNuEkUTAQkRlF+RD4mS86C32F7I7+CmIiEc9cZdAfnagM49FHJGJTZXsMqd3EWesSv6/lNxVLN0ckWMBPm9bFHrtA4XXIo99pZ7MJIBb+BAEUNhB+pMaCExYA0Wi3rDVs3zHAozCG78Ih45JJuPoBYm9uJd/zzLx65YBsIi5HchU+C4YlCJaMS6HBxt9nTxNxKtcPu6PjNc9g9Ax0oFmd87F/0cDh8DutT3KK1VNtqg99vzQOCF4YQzssFnCHqDSae/ThX9I6tU9r0OOaRa+CpgL5lcZaC0oPzpZK4UDK6ljw/XuXEl4VMVGCpJLtmb6hag6l7NParE73znFfGDzzrhcL3dt576PB0x93+fvlTN9OngWF3pWXcFA5U7MHpo8ep1jJgaTice6BiaN2VcxGSnXTNYlEQHcOBzGAxcgFNT7yfWmvrAywY7gBWvK2DjrwmkebiDDgYIDZQ9qqdUh3QsB1ZjElYH0HugbK7TzmWHBrZzIRpE5WJgMWU73K9oXQgv61TJXxz5gxiEJabu/bgELtu6mzbL800grUvNmPfIVM7BaGOQQ1QReKN7RamwmdLOwkb05GTsE7L05LOD0yTQRZ8AcahL5Z9FdtrfGzRr66cB4ZBF0JFwAaKs+y6H06id2Q6b4LmLuw7aaXn5YpbG7nvbDkQ7rqbZ6S+uo6UUm5sVZT7WVVeVO9+T/k+vqRxjGnTKefzEbLIavnpq8X9S90ow/AD3VHxlt6WlvASoGtozKJp9PSCKW2wJKBLahPqNIxaYp007mFZYdJlanvXCtoV0vZvR8MtwTtOe651gWuKbKpI77gGW9pqaSNFOVUdt+lU8iQS/RmrXzuvh12AfOhwjKK4dUGKscNRaqWqC1WbOBzPzaAu3K7MumONRQ1aW2Qx2MYZ+41dbuXwFotaF1+dkgcR1skSD2ZtX8I7gLn9qs/D3qy8c/WzkcMRqlKt5kU5+sI720rYTZHSepm4Gwl6nCfL/Y8wreyZiXgEQ3THQps5F1ttIBpYgcHiTz7lDNdbCVxSwVagTdZCYBs5Om685vx/XlZ8rUN+wPPKi/dAzEZ0b5tzzw6k9swh7qgKbqlqP3Q86hWjEzbtqB7/SNHtcvpM8eg3CMPENg16q5CdYU29mXjfUtUTMvvjS6V9ROYKKX9ChuSvx75ghIhq9r9g3P+94MXJW8byqQnsNu5PRrRmX75k5oV78qrbeOm2ud5qPOAd4EF9945a4ll67e+nt273Lvub5t6eObu5MbEsJe5sxubOnrOvnd7ubKa74Hf0o8/bbDc9rhee+3rsVlv+PN10uwhDAjn/L0PyarauIOx/zwQENeqUMjOxkgWLGx4VIo1EdwmG4iVDT5VhKxoYnA5A6/T58zPlCYqcR0sIZ2KemDgxuGSIlrwWPnsSdtlPnwzqPo/n6SWun2IJ6Caz9+RcvE8YD0u/LzqSdA+EPWL5lWT30tirab0tka6kOBAoD1+ZGW4gijmC6blYUHud3N+3Txo+wJoG26KW7gfZvxH1sI/PGF0rGukco9LHT+RwGG3e/gdyQyu2Nh4AAA== 122 | 123 | 124 | dbo 125 | 126 | -------------------------------------------------------------------------------- /Books/Migrations/Configuration.cs: -------------------------------------------------------------------------------- 1 | namespace Books.Migrations 2 | { 3 | using System; 4 | using System.Data.Entity; 5 | using System.Data.Entity.Migrations; 6 | using System.Linq; 7 | 8 | internal sealed class Configuration : DbMigrationsConfiguration 9 | { 10 | public Configuration() 11 | { 12 | AutomaticMigrationsEnabled = false; 13 | } 14 | 15 | protected override void Seed(Books.Models.ApplicationDbContext context) 16 | { 17 | // This method will be called after migrating to the latest version. 18 | 19 | // You can use the DbSet.AddOrUpdate() helper extension method 20 | // to avoid creating duplicate seed data. 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Books/Models/ApplicationDbContext.cs: -------------------------------------------------------------------------------- 1 | using System.Data.Entity; 2 | 3 | namespace Books.Models 4 | { 5 | public class ApplicationDbContext : DbContext 6 | { 7 | public ApplicationDbContext() : base("DefaultConnection") 8 | { 9 | } 10 | 11 | public DbSet Categories { get; set; } 12 | public DbSet Books { get; set; } 13 | } 14 | } -------------------------------------------------------------------------------- /Books/Models/Book.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace Books.Models 5 | { 6 | public class Book 7 | { 8 | public int Id { get; set; } 9 | 10 | [Required] 11 | [MaxLength(256)] 12 | public string Title { get; set; } 13 | 14 | [Required] 15 | [MaxLength(128)] 16 | public string Author { get; set; } 17 | 18 | [Required] 19 | [MaxLength(2000)] 20 | public string Description { get; set; } 21 | 22 | public byte CategoryId { get; set; } 23 | 24 | public Category Category { get; set; } 25 | 26 | public DateTime AddedOn { get; set; } 27 | 28 | public Book() 29 | { 30 | AddedOn = DateTime.Now; 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /Books/Models/Category.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | 4 | namespace Books.Models 5 | { 6 | public class Category 7 | { 8 | [Key] 9 | [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 10 | public byte Id { get; set; } 11 | 12 | [Required] 13 | [MaxLength(128)] 14 | public string Name { get; set; } 15 | 16 | public bool IsActive { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /Books/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("Books")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("HP Inc.")] 12 | [assembly: AssemblyProduct("Books")] 13 | [assembly: AssemblyCopyright("Copyright © HP Inc. 2020")] 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("b0ff09a8-1b12-4b3f-9d13-9e157865466a")] 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 | -------------------------------------------------------------------------------- /Books/Scripts/index.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @fileoverview This file only declares the public portions of the API. 3 | * It should not define internal pieces such as utils or modifier details. 4 | * 5 | * Original definitions by: edcarroll , ggray , rhysd , joscha , seckardt , marcfallows 6 | */ 7 | 8 | /** 9 | * This kind of namespace declaration is not necessary, but is kept here for backwards-compatibility with 10 | * popper.js 1.x. It can be removed in 2.x so that the default export is simply the Popper class 11 | * and all the types / interfaces are top-level named exports. 12 | */ 13 | declare namespace Popper { 14 | export type Position = 'top' | 'right' | 'bottom' | 'left'; 15 | 16 | export type Placement = 'auto-start' 17 | | 'auto' 18 | | 'auto-end' 19 | | 'top-start' 20 | | 'top' 21 | | 'top-end' 22 | | 'right-start' 23 | | 'right' 24 | | 'right-end' 25 | | 'bottom-end' 26 | | 'bottom' 27 | | 'bottom-start' 28 | | 'left-end' 29 | | 'left' 30 | | 'left-start'; 31 | 32 | export type Boundary = 'scrollParent' | 'viewport' | 'window'; 33 | 34 | export type Behavior = 'flip' | 'clockwise' | 'counterclockwise'; 35 | 36 | export type ModifierFn = (data: Data, options: Object) => Data; 37 | 38 | export interface Attributes { 39 | 'x-out-of-boundaries': '' | false; 40 | 'x-placement': Placement; 41 | } 42 | 43 | export interface Padding { 44 | top?: number, 45 | bottom?: number, 46 | left?: number, 47 | right?: number, 48 | } 49 | 50 | export interface BaseModifier { 51 | order?: number; 52 | enabled?: boolean; 53 | fn?: ModifierFn; 54 | } 55 | 56 | export interface Modifiers { 57 | shift?: BaseModifier; 58 | offset?: BaseModifier & { 59 | offset?: number | string, 60 | }; 61 | preventOverflow?: BaseModifier & { 62 | priority?: Position[], 63 | padding?: number | Padding, 64 | boundariesElement?: Boundary | Element, 65 | escapeWithReference?: boolean 66 | }; 67 | keepTogether?: BaseModifier; 68 | arrow?: BaseModifier & { 69 | element?: string | Element, 70 | }; 71 | flip?: BaseModifier & { 72 | behavior?: Behavior | Position[], 73 | padding?: number | Padding, 74 | boundariesElement?: Boundary | Element, 75 | flipVariations?: boolean, 76 | flipVariationsByContent?: boolean, 77 | }; 78 | inner?: BaseModifier; 79 | hide?: BaseModifier; 80 | applyStyle?: BaseModifier & { 81 | onLoad?: Function, 82 | gpuAcceleration?: boolean, 83 | }; 84 | computeStyle?: BaseModifier & { 85 | gpuAcceleration?: boolean; 86 | x?: 'bottom' | 'top', 87 | y?: 'left' | 'right' 88 | }; 89 | 90 | [name: string]: (BaseModifier & Record) | undefined; 91 | } 92 | 93 | export interface Offset { 94 | top: number; 95 | left: number; 96 | width: number; 97 | height: number; 98 | } 99 | 100 | export interface Data { 101 | instance: Popper; 102 | placement: Placement; 103 | originalPlacement: Placement; 104 | flipped: boolean; 105 | hide: boolean; 106 | arrowElement: Element; 107 | styles: CSSStyleDeclaration; 108 | arrowStyles: CSSStyleDeclaration; 109 | attributes: Attributes; 110 | boundaries: Object; 111 | offsets: { 112 | popper: Offset, 113 | reference: Offset, 114 | arrow: { 115 | top: number, 116 | left: number, 117 | }, 118 | }; 119 | } 120 | 121 | export interface PopperOptions { 122 | placement?: Placement; 123 | positionFixed?: boolean; 124 | eventsEnabled?: boolean; 125 | modifiers?: Modifiers; 126 | removeOnDestroy?: boolean; 127 | 128 | onCreate?(data: Data): void; 129 | 130 | onUpdate?(data: Data): void; 131 | } 132 | 133 | export interface ReferenceObject { 134 | clientHeight: number; 135 | clientWidth: number; 136 | referenceNode?: Node; 137 | 138 | getBoundingClientRect(): ClientRect; 139 | } 140 | } 141 | 142 | // Re-export types in the Popper namespace so that they can be accessed as top-level named exports. 143 | // These re-exports should be removed in 2.x when the "declare namespace Popper" syntax is removed. 144 | export type Padding = Popper.Padding; 145 | export type Position = Popper.Position; 146 | export type Placement = Popper.Placement; 147 | export type Boundary = Popper.Boundary; 148 | export type Behavior = Popper.Behavior; 149 | export type ModifierFn = Popper.ModifierFn; 150 | export type BaseModifier = Popper.BaseModifier; 151 | export type Modifiers = Popper.Modifiers; 152 | export type Offset = Popper.Offset; 153 | export type Data = Popper.Data; 154 | export type PopperOptions = Popper.PopperOptions; 155 | export type ReferenceObject = Popper.ReferenceObject; 156 | 157 | declare class Popper { 158 | static modifiers: (BaseModifier & { name: string })[]; 159 | static placements: Placement[]; 160 | static Defaults: PopperOptions; 161 | 162 | options: PopperOptions; 163 | popper: Element; 164 | reference: Element | ReferenceObject; 165 | 166 | constructor(reference: Element | ReferenceObject, popper: Element, options?: PopperOptions); 167 | 168 | destroy(): void; 169 | 170 | update(): void; 171 | 172 | scheduleUpdate(): void; 173 | 174 | enableEventListeners(): void; 175 | 176 | disableEventListeners(): void; 177 | } 178 | 179 | export default Popper; 180 | -------------------------------------------------------------------------------- /Books/Scripts/index.js.flow: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export type Position = 'top' | 'right' | 'bottom' | 'left'; 4 | 5 | export type Placement = 6 | | 'auto-start' 7 | | 'auto' 8 | | 'auto-end' 9 | | 'top-start' 10 | | 'top' 11 | | 'top-end' 12 | | 'right-start' 13 | | 'right' 14 | | 'right-end' 15 | | 'bottom-end' 16 | | 'bottom' 17 | | 'bottom-start' 18 | | 'left-end' 19 | | 'left' 20 | | 'left-start'; 21 | 22 | export type Offset = { 23 | top: number, 24 | left: number, 25 | width: number, 26 | height: number, 27 | position: Position, 28 | }; 29 | 30 | export type Boundary = 'scrollParent' | 'viewport' | 'window'; 31 | 32 | export type Behavior = 'flip' | 'clockwise' | 'counterclockwise'; 33 | 34 | export type Data = { 35 | instance: Popper, 36 | placement: Placement, 37 | originalPlacement: Placement, 38 | flipped: boolean, 39 | hide: boolean, 40 | arrowElement: Element, 41 | styles: CSSStyleDeclaration, 42 | arrowStyles: CSSStyleDeclaration, 43 | boundaries: Object, 44 | offsets: { 45 | popper: Offset, 46 | reference: Offset, 47 | arrow: { 48 | top: number, 49 | left: number, 50 | }, 51 | }, 52 | }; 53 | 54 | export type ModifierFn = (data: Data, options: Object) => Data; 55 | 56 | export type Padding = { 57 | top?: number, 58 | bottom?: number, 59 | left?: number, 60 | right?: number, 61 | }; 62 | 63 | export type BaseModifier = { 64 | order?: number, 65 | enabled?: boolean, 66 | fn?: ModifierFn, 67 | }; 68 | 69 | export type Modifiers = { 70 | shift?: BaseModifier, 71 | offset?: BaseModifier & { 72 | offset?: number | string, 73 | }, 74 | preventOverflow?: BaseModifier & { 75 | priority?: Position[], 76 | padding?: number | Padding, 77 | boundariesElement?: Boundary | Element, 78 | escapeWithReference?: boolean, 79 | }, 80 | keepTogether?: BaseModifier, 81 | arrow?: BaseModifier & { 82 | element?: string | Element | null, 83 | }, 84 | flip?: BaseModifier & { 85 | behavior?: Behavior | Position[], 86 | padding?: number | Padding, 87 | boundariesElement?: Boundary | Element, 88 | flipVariations?: boolean, 89 | flipVariationsByContent?: boolean, 90 | }, 91 | inner?: BaseModifier, 92 | hide?: BaseModifier, 93 | applyStyle?: BaseModifier & { 94 | onLoad?: Function, 95 | gpuAcceleration?: boolean, 96 | }, 97 | computeStyle?: BaseModifier & { 98 | gpuAcceleration?: boolean, 99 | x?: 'bottom' | 'top', 100 | y?: 'left' | 'right', 101 | }, 102 | 103 | [name: string]: (BaseModifier & { [string]: * }) | null, 104 | }; 105 | 106 | export type Options = { 107 | placement?: Placement, 108 | positionFixed?: boolean, 109 | eventsEnabled?: boolean, 110 | modifiers?: Modifiers, 111 | removeOnDestroy?: boolean, 112 | 113 | onCreate?: (data: Data) => void, 114 | 115 | onUpdate?: (data: Data) => void, 116 | }; 117 | 118 | export type ReferenceObject = { 119 | +clientHeight: number, 120 | +clientWidth: number, 121 | +referenceNode?: Node, 122 | 123 | getBoundingClientRect(): 124 | | ClientRect 125 | | { 126 | width: number, 127 | height: number, 128 | top: number, 129 | right: number, 130 | bottom: number, 131 | left: number, 132 | }, 133 | }; 134 | 135 | export type Instance = { 136 | destroy: () => void, 137 | scheduleUpdate: () => void, 138 | update: () => void, 139 | enableEventListeners: () => void, 140 | disableEventListeners: () => void, 141 | }; 142 | 143 | declare class Popper { 144 | static placements: Placement; 145 | 146 | popper: Element; 147 | reference: Element | ReferenceObject; 148 | 149 | constructor( 150 | reference: Element | ReferenceObject, 151 | popper: Element, 152 | options?: Options 153 | ): Instance; 154 | } 155 | 156 | declare export default typeof Popper; 157 | -------------------------------------------------------------------------------- /Books/Scripts/jquery.validate.unobtrusive.min.js: -------------------------------------------------------------------------------- 1 | // Unobtrusive validation support library for jQuery and jQuery Validate 2 | // Copyright (c) .NET Foundation. All rights reserved. 3 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 4 | // @version v3.2.11 5 | !function(a){"function"==typeof define&&define.amd?define("jquery.validate.unobtrusive",["jquery-validation"],a):"object"==typeof module&&module.exports?module.exports=a(require("jquery-validation")):jQuery.validator.unobtrusive=a(jQuery)}(function(a){function e(a,e,n){a.rules[e]=n,a.message&&(a.messages[e]=a.message)}function n(a){return a.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/g)}function t(a){return a.replace(/([!"#$%&'()*+,.\/:;<=>?@\[\\\]^`{|}~])/g,"\\$1")}function r(a){return a.substr(0,a.lastIndexOf(".")+1)}function i(a,e){return 0===a.indexOf("*.")&&(a=a.replace("*.",e)),a}function o(e,n){var r=a(this).find("[data-valmsg-for='"+t(n[0].name)+"']"),i=r.attr("data-valmsg-replace"),o=i?a.parseJSON(i)!==!1:null;r.removeClass("field-validation-valid").addClass("field-validation-error"),e.data("unobtrusiveContainer",r),o?(r.empty(),e.removeClass("input-validation-error").appendTo(r)):e.hide()}function d(e,n){var t=a(this).find("[data-valmsg-summary=true]"),r=t.find("ul");r&&r.length&&n.errorList.length&&(r.empty(),t.addClass("validation-summary-errors").removeClass("validation-summary-valid"),a.each(n.errorList,function(){a("
  • ").html(this.message).appendTo(r)}))}function s(e){var n=e.data("unobtrusiveContainer");if(n){var t=n.attr("data-valmsg-replace"),r=t?a.parseJSON(t):null;n.addClass("field-validation-valid").removeClass("field-validation-error"),e.removeData("unobtrusiveContainer"),r&&n.empty()}}function l(e){var n=a(this),t="__jquery_unobtrusive_validation_form_reset";if(!n.data(t)){n.data(t,!0);try{n.data("validator").resetForm()}finally{n.removeData(t)}n.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors"),n.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")}}function u(e){var n=a(e),t=n.data(v),r=a.proxy(l,e),i=f.unobtrusive.options||{},u=function(n,t){var r=i[n];r&&a.isFunction(r)&&r.apply(e,t)};return t||(t={options:{errorClass:i.errorClass||"input-validation-error",errorElement:i.errorElement||"span",errorPlacement:function(){o.apply(e,arguments),u("errorPlacement",arguments)},invalidHandler:function(){d.apply(e,arguments),u("invalidHandler",arguments)},messages:{},rules:{},success:function(){s.apply(e,arguments),u("success",arguments)}},attachValidation:function(){n.off("reset."+v,r).on("reset."+v,r).validate(this.options)},validate:function(){return n.validate(),n.valid()}},n.data(v,t)),t}var m,f=a.validator,v="unobtrusiveValidation";return f.unobtrusive={adapters:[],parseElement:function(e,n){var t,r,i,o=a(e),d=o.parents("form")[0];d&&(t=u(d),t.options.rules[e.name]=r={},t.options.messages[e.name]=i={},a.each(this.adapters,function(){var n="data-val-"+this.name,t=o.attr(n),s={};void 0!==t&&(n+="-",a.each(this.params,function(){s[this]=o.attr(n+this)}),this.adapt({element:e,form:d,message:t,params:s,rules:r,messages:i}))}),a.extend(r,{__dummy__:!0}),n||t.attachValidation())},parse:function(e){var n=a(e),t=n.parents().addBack().filter("form").add(n.find("form")).has("[data-val=true]");n.find("[data-val=true]").each(function(){f.unobtrusive.parseElement(this,!0)}),t.each(function(){var a=u(this);a&&a.attachValidation()})}},m=f.unobtrusive.adapters,m.add=function(a,e,n){return n||(n=e,e=[]),this.push({name:a,params:e,adapt:n}),this},m.addBool=function(a,n){return this.add(a,function(t){e(t,n||a,!0)})},m.addMinMax=function(a,n,t,r,i,o){return this.add(a,[i||"min",o||"max"],function(a){var i=a.params.min,o=a.params.max;i&&o?e(a,r,[i,o]):i?e(a,n,i):o&&e(a,t,o)})},m.addSingleVal=function(a,n,t){return this.add(a,[n||"val"],function(r){e(r,t||a,r.params[n])})},f.addMethod("__dummy__",function(a,e,n){return!0}),f.addMethod("regex",function(a,e,n){var t;return!!this.optional(e)||(t=new RegExp(n).exec(a),t&&0===t.index&&t[0].length===a.length)}),f.addMethod("nonalphamin",function(a,e,n){var t;return n&&(t=a.match(/\W/g),t=t&&t.length>=n),t}),f.methods.extension?(m.addSingleVal("accept","mimtype"),m.addSingleVal("extension","extension")):m.addSingleVal("extension","extension","accept"),m.addSingleVal("regex","pattern"),m.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"),m.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range"),m.addMinMax("minlength","minlength").addMinMax("maxlength","minlength","maxlength"),m.add("equalto",["other"],function(n){var o=r(n.element.name),d=n.params.other,s=i(d,o),l=a(n.form).find(":input").filter("[name='"+t(s)+"']")[0];e(n,"equalTo",l)}),m.add("required",function(a){"INPUT"===a.element.tagName.toUpperCase()&&"CHECKBOX"===a.element.type.toUpperCase()||e(a,"required",!0)}),m.add("remote",["url","type","additionalfields"],function(o){var d={url:o.params.url,type:o.params.type||"GET",data:{}},s=r(o.element.name);a.each(n(o.params.additionalfields||o.element.name),function(e,n){var r=i(n,s);d.data[r]=function(){var e=a(o.form).find(":input").filter("[name='"+t(r)+"']");return e.is(":checkbox")?e.filter(":checked").val()||e.filter(":hidden").val()||"":e.is(":radio")?e.filter(":checked").val()||"":e.val()}}),e(o,"remote",d)}),m.add("password",["min","nonalphamin","regex"],function(a){a.params.min&&e(a,"minlength",a.params.min),a.params.nonalphamin&&e(a,"nonalphamin",a.params.nonalphamin),a.params.regex&&e(a,"regex",a.params.regex)}),m.add("fileextensions",["extensions"],function(a){e(a,"extension",a.params.extensions)}),a(function(){f.unobtrusive.parse(document)}),f.unobtrusive}); -------------------------------------------------------------------------------- /Books/Scripts/popper-utils.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) Federico Zivolo 2020 3 | Distributed under the MIT License (license terms are at http://opensource.org/licenses/MIT). 4 | */function a(a,b){if(1!==a.nodeType)return[];const c=a.ownerDocument.defaultView,d=c.getComputedStyle(a,null);return b?d[b]:d}function b(a){return'HTML'===a.nodeName?a:a.parentNode||a.host}function c(d){if(!d)return document.body;switch(d.nodeName){case'HTML':case'BODY':return d.ownerDocument.body;case'#document':return d.body;}const{overflow:e,overflowX:f,overflowY:g}=a(d);return /(auto|scroll|overlay)/.test(e+g+f)?d:c(b(d))}function d(a){return a&&a.referenceNode?a.referenceNode:a}var e='undefined'!=typeof window&&'undefined'!=typeof document&&'undefined'!=typeof navigator;const f=e&&!!(window.MSInputMethodContext&&document.documentMode),g=e&&/MSIE 10/.test(navigator.userAgent);function h(a){return 11===a?f:10===a?g:f||g}function i(b){if(!b)return document.documentElement;const c=h(10)?document.body:null;let d=b.offsetParent||null;for(;d===c&&b.nextElementSibling;)d=(b=b.nextElementSibling).offsetParent;const e=d&&d.nodeName;return e&&'BODY'!==e&&'HTML'!==e?-1!==['TH','TD','TABLE'].indexOf(d.nodeName)&&'static'===a(d,'position')?i(d):d:b?b.ownerDocument.documentElement:document.documentElement}function j(a){const{nodeName:b}=a;return'BODY'!==b&&('HTML'===b||i(a.firstElementChild)===a)}function k(a){return null===a.parentNode?a:k(a.parentNode)}function l(a,b){if(!a||!a.nodeType||!b||!b.nodeType)return document.documentElement;const c=a.compareDocumentPosition(b)&Node.DOCUMENT_POSITION_FOLLOWING,d=c?a:b,e=c?b:a,f=document.createRange();f.setStart(d,0),f.setEnd(e,0);const{commonAncestorContainer:g}=f;if(a!==g&&b!==g||d.contains(e))return j(g)?g:i(g);const h=k(a);return h.host?l(h.host,b):l(a,k(b).host)}function m(a,b='top'){const c='top'===b?'scrollTop':'scrollLeft',d=a.nodeName;if('BODY'===d||'HTML'===d){const b=a.ownerDocument.documentElement,d=a.ownerDocument.scrollingElement||b;return d[c]}return a[c]}function n(a,b,c=!1){const d=m(b,'top'),e=m(b,'left'),f=c?-1:1;return a.top+=d*f,a.bottom+=d*f,a.left+=e*f,a.right+=e*f,a}function o(a,b){const c='x'===b?'Left':'Top',d='Left'==c?'Right':'Bottom';return parseFloat(a[`border${c}Width`])+parseFloat(a[`border${d}Width`])}function p(a,b,c,d){return Math.max(b[`offset${a}`],b[`scroll${a}`],c[`client${a}`],c[`offset${a}`],c[`scroll${a}`],h(10)?parseInt(c[`offset${a}`])+parseInt(d[`margin${'Height'===a?'Top':'Left'}`])+parseInt(d[`margin${'Height'===a?'Bottom':'Right'}`]):0)}function q(a){const b=a.body,c=a.documentElement,d=h(10)&&getComputedStyle(c);return{height:p('Height',b,c,d),width:p('Width',b,c,d)}}var r=Object.assign||function(a){for(var b,c=1;cr({key:a},h[a],{area:z(h[a])})).sort((c,a)=>a.area-c.area),j=i.filter(({width:a,height:b})=>a>=c.clientWidth&&b>=c.clientHeight),k=0{b||(b=!0,window.Promise.resolve().then(()=>{b=!1,a()}))}}function D(a){let b=!1;return()=>{b||(b=!0,setTimeout(()=>{b=!1,a()},B))}}const E=e&&window.Promise;var F=E?C:D;function G(a,b){return Array.prototype.find?a.find(b):a.filter(b)[0]}function H(a,b,c){if(Array.prototype.findIndex)return a.findIndex((a)=>a[b]===c);const d=G(a,(a)=>a[b]===c);return a.indexOf(d)}function I(a){let b;if('HTML'===a.nodeName){const{width:c,height:d}=q(a.ownerDocument);b={width:c,height:d,left:0,top:0}}else b={width:a.offsetWidth,height:a.offsetHeight,left:a.offsetLeft,top:a.offsetTop};return s(b)}function J(a){const b=a.ownerDocument.defaultView,c=b.getComputedStyle(a),d=parseFloat(c.marginTop||0)+parseFloat(c.marginBottom||0),e=parseFloat(c.marginLeft||0)+parseFloat(c.marginRight||0),f={width:a.offsetWidth+e,height:a.offsetHeight+d};return f}function K(a){const b={left:'right',right:'left',bottom:'top',top:'bottom'};return a.replace(/left|right|bottom|top/g,(a)=>b[a])}function L(a,b,c){c=c.split('-')[0];const d=J(a),e={width:d.width,height:d.height},f=-1!==['right','left'].indexOf(c),g=f?'top':'left',h=f?'left':'top',i=f?'height':'width',j=f?'width':'height';return e[g]=b[g]+b[i]/2-d[i]/2,e[h]=c===h?b[h]-d[j]:b[K(h)],e}function M(a,b,c,e=null){const f=e?x(b):l(b,d(c));return u(c,f,e)}function N(a){const b=[!1,'ms','Webkit','Moz','O'],c=a.charAt(0).toUpperCase()+a.slice(1);for(let d=0;dc&&a===b)}function Q(a,b,c){const d=G(a,({name:a})=>a===b),e=!!d&&a.some((a)=>a.name===c&&a.enabled&&a.order{a.removeEventListener('scroll',b.updateBound)}),b.updateBound=null,b.scrollParents=[],b.scrollElement=null,b.eventsEnabled=!1,b}function U(a,b,c){const d=void 0===c?a:a.slice(0,H(a,'name',c));return d.forEach((a)=>{a['function']&&console.warn('`modifier.function` is deprecated, use `modifier.fn`!');const c=a['function']||a.fn;a.enabled&&O(c)&&(b.offsets.popper=s(b.offsets.popper),b.offsets.reference=s(b.offsets.reference),b=c(b,a))}),b}function V(a,b){Object.keys(b).forEach(function(c){const d=b[c];!1===d?a.removeAttribute(c):a.setAttribute(c,b[c])})}function W(a,b){Object.keys(b).forEach((c)=>{let d='';-1!==['width','height','top','right','bottom','left'].indexOf(c)&&R(b[c])&&(d='px'),a.style[c]=b[c]+d})}function X(a,b,d,e){const f='BODY'===a.nodeName,g=f?a.ownerDocument.defaultView:a;g.addEventListener(b,d,{passive:!0}),f||X(c(g.parentNode),b,d,e),e.push(g)}function Y(a,b,d,e){d.updateBound=e,S(a).addEventListener('resize',d.updateBound,{passive:!0});const f=c(a);return X(f,'scroll',d.updateBound,d.scrollParents),d.scrollElement=f,d.eventsEnabled=!0,d}var Z={computeAutoPlacement:A,debounce:F,findIndex:H,getBordersSize:o,getBoundaries:y,getBoundingClientRect:t,getClientRect:s,getOffsetParent:i,getOffsetRect:I,getOffsetRectRelativeToArbitraryNode:u,getOuterSizes:J,getParentNode:b,getPopperOffsets:L,getReferenceOffsets:M,getScroll:m,getScrollParent:c,getStyleComputedProperty:a,getSupportedPropertyName:N,getWindowSizes:q,isFixed:w,isFunction:O,isModifierEnabled:P,isModifierRequired:Q,isNumeric:R,removeEventListeners:T,runModifiers:U,setAttributes:V,setStyles:W,setupEventListeners:Y};export{A as computeAutoPlacement,F as debounce,H as findIndex,o as getBordersSize,y as getBoundaries,t as getBoundingClientRect,s as getClientRect,i as getOffsetParent,I as getOffsetRect,u as getOffsetRectRelativeToArbitraryNode,J as getOuterSizes,b as getParentNode,L as getPopperOffsets,M as getReferenceOffsets,m as getScroll,c as getScrollParent,a as getStyleComputedProperty,N as getSupportedPropertyName,q as getWindowSizes,w as isFixed,O as isFunction,P as isModifierEnabled,Q as isModifierRequired,R as isNumeric,T as removeEventListeners,U as runModifiers,V as setAttributes,W as setStyles,Y as setupEventListeners};export default Z; 5 | //# sourceMappingURL=popper-utils.min.js.map 6 | -------------------------------------------------------------------------------- /Books/Scripts/src/index.js: -------------------------------------------------------------------------------- 1 | // Utils 2 | import debounce from './utils/debounce'; 3 | import isFunction from './utils/isFunction'; 4 | 5 | // Methods 6 | import update from './methods/update'; 7 | import destroy from './methods/destroy'; 8 | import enableEventListeners from './methods/enableEventListeners'; 9 | import disableEventListeners from './methods/disableEventListeners'; 10 | import Defaults from './methods/defaults'; 11 | import placements from './methods/placements'; 12 | 13 | export default class Popper { 14 | /** 15 | * Creates a new Popper.js instance. 16 | * @class Popper 17 | * @param {Element|referenceObject} reference - The reference element used to position the popper 18 | * @param {Element} popper - The HTML / XML element used as the popper 19 | * @param {Object} options - Your custom options to override the ones defined in [Defaults](#defaults) 20 | * @return {Object} instance - The generated Popper.js instance 21 | */ 22 | constructor(reference, popper, options = {}) { 23 | // make update() debounced, so that it only runs at most once-per-tick 24 | this.update = debounce(this.update.bind(this)); 25 | 26 | // with {} we create a new object with the options inside it 27 | this.options = { ...Popper.Defaults, ...options }; 28 | 29 | // init state 30 | this.state = { 31 | isDestroyed: false, 32 | isCreated: false, 33 | scrollParents: [], 34 | }; 35 | 36 | // get reference and popper elements (allow jQuery wrappers) 37 | this.reference = reference && reference.jquery ? reference[0] : reference; 38 | this.popper = popper && popper.jquery ? popper[0] : popper; 39 | 40 | // Deep merge modifiers options 41 | this.options.modifiers = {}; 42 | Object.keys({ 43 | ...Popper.Defaults.modifiers, 44 | ...options.modifiers, 45 | }).forEach(name => { 46 | this.options.modifiers[name] = { 47 | // If it's a built-in modifier, use it as base 48 | ...(Popper.Defaults.modifiers[name] || {}), 49 | // If there are custom options, override and merge with default ones 50 | ...(options.modifiers ? options.modifiers[name] : {}), 51 | }; 52 | }); 53 | 54 | // Refactoring modifiers' list (Object => Array) 55 | this.modifiers = Object.keys(this.options.modifiers) 56 | .map(name => ({ 57 | name, 58 | ...this.options.modifiers[name], 59 | })) 60 | // sort the modifiers by order 61 | .sort((a, b) => a.order - b.order); 62 | 63 | // modifiers have the ability to execute arbitrary code when Popper.js get inited 64 | // such code is executed in the same order of its modifier 65 | // they could add new properties to their options configuration 66 | // BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`! 67 | this.modifiers.forEach(modifierOptions => { 68 | if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) { 69 | modifierOptions.onLoad( 70 | this.reference, 71 | this.popper, 72 | this.options, 73 | modifierOptions, 74 | this.state 75 | ); 76 | } 77 | }); 78 | 79 | // fire the first update to position the popper in the right place 80 | this.update(); 81 | 82 | const eventsEnabled = this.options.eventsEnabled; 83 | if (eventsEnabled) { 84 | // setup event listeners, they will take care of update the position in specific situations 85 | this.enableEventListeners(); 86 | } 87 | 88 | this.state.eventsEnabled = eventsEnabled; 89 | } 90 | 91 | // We can't use class properties because they don't get listed in the 92 | // class prototype and break stuff like Sinon stubs 93 | update() { 94 | return update.call(this); 95 | } 96 | destroy() { 97 | return destroy.call(this); 98 | } 99 | enableEventListeners() { 100 | return enableEventListeners.call(this); 101 | } 102 | disableEventListeners() { 103 | return disableEventListeners.call(this); 104 | } 105 | 106 | /** 107 | * Schedules an update. It will run on the next UI update available. 108 | * @method scheduleUpdate 109 | * @memberof Popper 110 | */ 111 | scheduleUpdate = () => requestAnimationFrame(this.update); 112 | 113 | /** 114 | * Collection of utilities useful when writing custom modifiers. 115 | * Starting from version 1.7, this method is available only if you 116 | * include `popper-utils.js` before `popper.js`. 117 | * 118 | * **DEPRECATION**: This way to access PopperUtils is deprecated 119 | * and will be removed in v2! Use the PopperUtils module directly instead. 120 | * Due to the high instability of the methods contained in Utils, we can't 121 | * guarantee them to follow semver. Use them at your own risk! 122 | * @static 123 | * @private 124 | * @type {Object} 125 | * @deprecated since version 1.8 126 | * @member Utils 127 | * @memberof Popper 128 | */ 129 | static Utils = (typeof window !== 'undefined' ? window : global).PopperUtils; 130 | 131 | static placements = placements; 132 | 133 | static Defaults = Defaults; 134 | } 135 | 136 | /** 137 | * The `referenceObject` is an object that provides an interface compatible with Popper.js 138 | * and lets you use it as replacement of a real DOM node.
    139 | * You can use this method to position a popper relatively to a set of coordinates 140 | * in case you don't have a DOM node to use as reference. 141 | * 142 | * ``` 143 | * new Popper(referenceObject, popperNode); 144 | * ``` 145 | * 146 | * NB: This feature isn't supported in Internet Explorer 10. 147 | * @name referenceObject 148 | * @property {Function} data.getBoundingClientRect 149 | * A function that returns a set of coordinates compatible with the native `getBoundingClientRect` method. 150 | * @property {number} data.clientWidth 151 | * An ES6 getter that will return the width of the virtual reference element. 152 | * @property {number} data.clientHeight 153 | * An ES6 getter that will return the height of the virtual reference element. 154 | */ 155 | -------------------------------------------------------------------------------- /Books/Scripts/src/methods/defaults.js: -------------------------------------------------------------------------------- 1 | import modifiers from '../modifiers/index'; 2 | 3 | /** 4 | * Default options provided to Popper.js constructor.
    5 | * These can be overridden using the `options` argument of Popper.js.
    6 | * To override an option, simply pass an object with the same 7 | * structure of the `options` object, as the 3rd argument. For example: 8 | * ``` 9 | * new Popper(ref, pop, { 10 | * modifiers: { 11 | * preventOverflow: { enabled: false } 12 | * } 13 | * }) 14 | * ``` 15 | * @type {Object} 16 | * @static 17 | * @memberof Popper 18 | */ 19 | export default { 20 | /** 21 | * Popper's placement. 22 | * @prop {Popper.placements} placement='bottom' 23 | */ 24 | placement: 'bottom', 25 | 26 | /** 27 | * Set this to true if you want popper to position it self in 'fixed' mode 28 | * @prop {Boolean} positionFixed=false 29 | */ 30 | positionFixed: false, 31 | 32 | /** 33 | * Whether events (resize, scroll) are initially enabled. 34 | * @prop {Boolean} eventsEnabled=true 35 | */ 36 | eventsEnabled: true, 37 | 38 | /** 39 | * Set to true if you want to automatically remove the popper when 40 | * you call the `destroy` method. 41 | * @prop {Boolean} removeOnDestroy=false 42 | */ 43 | removeOnDestroy: false, 44 | 45 | /** 46 | * Callback called when the popper is created.
    47 | * By default, it is set to no-op.
    48 | * Access Popper.js instance with `data.instance`. 49 | * @prop {onCreate} 50 | */ 51 | onCreate: () => {}, 52 | 53 | /** 54 | * Callback called when the popper is updated. This callback is not called 55 | * on the initialization/creation of the popper, but only on subsequent 56 | * updates.
    57 | * By default, it is set to no-op.
    58 | * Access Popper.js instance with `data.instance`. 59 | * @prop {onUpdate} 60 | */ 61 | onUpdate: () => {}, 62 | 63 | /** 64 | * List of modifiers used to modify the offsets before they are applied to the popper. 65 | * They provide most of the functionalities of Popper.js. 66 | * @prop {modifiers} 67 | */ 68 | modifiers, 69 | }; 70 | 71 | /** 72 | * @callback onCreate 73 | * @param {dataObject} data 74 | */ 75 | 76 | /** 77 | * @callback onUpdate 78 | * @param {dataObject} data 79 | */ 80 | -------------------------------------------------------------------------------- /Books/Scripts/src/methods/destroy.js: -------------------------------------------------------------------------------- 1 | import isModifierEnabled from '../utils/isModifierEnabled'; 2 | import getSupportedPropertyName from '../utils/getSupportedPropertyName'; 3 | 4 | /** 5 | * Destroys the popper. 6 | * @method 7 | * @memberof Popper 8 | */ 9 | export default function destroy() { 10 | this.state.isDestroyed = true; 11 | 12 | // touch DOM only if `applyStyle` modifier is enabled 13 | if (isModifierEnabled(this.modifiers, 'applyStyle')) { 14 | this.popper.removeAttribute('x-placement'); 15 | this.popper.style.position = ''; 16 | this.popper.style.top = ''; 17 | this.popper.style.left = ''; 18 | this.popper.style.right = ''; 19 | this.popper.style.bottom = ''; 20 | this.popper.style.willChange = ''; 21 | this.popper.style[getSupportedPropertyName('transform')] = ''; 22 | } 23 | 24 | this.disableEventListeners(); 25 | 26 | // remove the popper if user explicitly asked for the deletion on destroy 27 | // do not use `remove` because IE11 doesn't support it 28 | if (this.options.removeOnDestroy) { 29 | this.popper.parentNode.removeChild(this.popper); 30 | } 31 | return this; 32 | } 33 | -------------------------------------------------------------------------------- /Books/Scripts/src/methods/disableEventListeners.js: -------------------------------------------------------------------------------- 1 | import removeEventListeners from '../utils/removeEventListeners'; 2 | 3 | /** 4 | * It will remove resize/scroll events and won't recalculate popper position 5 | * when they are triggered. It also won't trigger `onUpdate` callback anymore, 6 | * unless you call `update` method manually. 7 | * @method 8 | * @memberof Popper 9 | */ 10 | export default function disableEventListeners() { 11 | if (this.state.eventsEnabled) { 12 | cancelAnimationFrame(this.scheduleUpdate); 13 | this.state = removeEventListeners(this.reference, this.state); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Books/Scripts/src/methods/enableEventListeners.js: -------------------------------------------------------------------------------- 1 | import setupEventListeners from '../utils/setupEventListeners'; 2 | 3 | /** 4 | * It will add resize/scroll events and start recalculating 5 | * position of the popper element when they are triggered. 6 | * @method 7 | * @memberof Popper 8 | */ 9 | export default function enableEventListeners() { 10 | if (!this.state.eventsEnabled) { 11 | this.state = setupEventListeners( 12 | this.reference, 13 | this.options, 14 | this.state, 15 | this.scheduleUpdate 16 | ); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Books/Scripts/src/methods/placements.js: -------------------------------------------------------------------------------- 1 | /** 2 | * List of accepted placements to use as values of the `placement` option.
    3 | * Valid placements are: 4 | * - `auto` 5 | * - `top` 6 | * - `right` 7 | * - `bottom` 8 | * - `left` 9 | * 10 | * Each placement can have a variation from this list: 11 | * - `-start` 12 | * - `-end` 13 | * 14 | * Variations are interpreted easily if you think of them as the left to right 15 | * written languages. Horizontally (`top` and `bottom`), `start` is left and `end` 16 | * is right.
    17 | * Vertically (`left` and `right`), `start` is top and `end` is bottom. 18 | * 19 | * Some valid examples are: 20 | * - `top-end` (on top of reference, right aligned) 21 | * - `right-start` (on right of reference, top aligned) 22 | * - `bottom` (on bottom, centered) 23 | * - `auto-end` (on the side with more space available, alignment depends by placement) 24 | * 25 | * @static 26 | * @type {Array} 27 | * @enum {String} 28 | * @readonly 29 | * @method placements 30 | * @memberof Popper 31 | */ 32 | export default [ 33 | 'auto-start', 34 | 'auto', 35 | 'auto-end', 36 | 'top-start', 37 | 'top', 38 | 'top-end', 39 | 'right-start', 40 | 'right', 41 | 'right-end', 42 | 'bottom-end', 43 | 'bottom', 44 | 'bottom-start', 45 | 'left-end', 46 | 'left', 47 | 'left-start', 48 | ]; 49 | -------------------------------------------------------------------------------- /Books/Scripts/src/methods/update.js: -------------------------------------------------------------------------------- 1 | import computeAutoPlacement from '../utils/computeAutoPlacement'; 2 | import getReferenceOffsets from '../utils/getReferenceOffsets'; 3 | import getPopperOffsets from '../utils/getPopperOffsets'; 4 | import runModifiers from '../utils/runModifiers'; 5 | 6 | /** 7 | * Updates the position of the popper, computing the new offsets and applying 8 | * the new style.
    9 | * Prefer `scheduleUpdate` over `update` because of performance reasons. 10 | * @method 11 | * @memberof Popper 12 | */ 13 | export default function update() { 14 | // if popper is destroyed, don't perform any further update 15 | if (this.state.isDestroyed) { 16 | return; 17 | } 18 | 19 | let data = { 20 | instance: this, 21 | styles: {}, 22 | arrowStyles: {}, 23 | attributes: {}, 24 | flipped: false, 25 | offsets: {}, 26 | }; 27 | 28 | // compute reference element offsets 29 | data.offsets.reference = getReferenceOffsets( 30 | this.state, 31 | this.popper, 32 | this.reference, 33 | this.options.positionFixed 34 | ); 35 | 36 | // compute auto placement, store placement inside the data object, 37 | // modifiers will be able to edit `placement` if needed 38 | // and refer to originalPlacement to know the original value 39 | data.placement = computeAutoPlacement( 40 | this.options.placement, 41 | data.offsets.reference, 42 | this.popper, 43 | this.reference, 44 | this.options.modifiers.flip.boundariesElement, 45 | this.options.modifiers.flip.padding 46 | ); 47 | 48 | // store the computed placement inside `originalPlacement` 49 | data.originalPlacement = data.placement; 50 | 51 | data.positionFixed = this.options.positionFixed; 52 | 53 | // compute the popper offsets 54 | data.offsets.popper = getPopperOffsets( 55 | this.popper, 56 | data.offsets.reference, 57 | data.placement 58 | ); 59 | 60 | data.offsets.popper.position = this.options.positionFixed 61 | ? 'fixed' 62 | : 'absolute'; 63 | 64 | // run the modifiers 65 | data = runModifiers(this.modifiers, data); 66 | 67 | // the first `update` will call `onCreate` callback 68 | // the other ones will call `onUpdate` callback 69 | if (!this.state.isCreated) { 70 | this.state.isCreated = true; 71 | this.options.onCreate(data); 72 | } else { 73 | this.options.onUpdate(data); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Books/Scripts/src/modifiers/applyStyle.js: -------------------------------------------------------------------------------- 1 | import setStyles from '../utils/setStyles'; 2 | import setAttributes from '../utils/setAttributes'; 3 | import getReferenceOffsets from '../utils/getReferenceOffsets'; 4 | import computeAutoPlacement from '../utils/computeAutoPlacement'; 5 | 6 | /** 7 | * @function 8 | * @memberof Modifiers 9 | * @argument {Object} data - The data object generated by `update` method 10 | * @argument {Object} data.styles - List of style properties - values to apply to popper element 11 | * @argument {Object} data.attributes - List of attribute properties - values to apply to popper element 12 | * @argument {Object} options - Modifiers configuration and options 13 | * @returns {Object} The same data object 14 | */ 15 | export default function applyStyle(data) { 16 | // any property present in `data.styles` will be applied to the popper, 17 | // in this way we can make the 3rd party modifiers add custom styles to it 18 | // Be aware, modifiers could override the properties defined in the previous 19 | // lines of this modifier! 20 | setStyles(data.instance.popper, data.styles); 21 | 22 | // any property present in `data.attributes` will be applied to the popper, 23 | // they will be set as HTML attributes of the element 24 | setAttributes(data.instance.popper, data.attributes); 25 | 26 | // if arrowElement is defined and arrowStyles has some properties 27 | if (data.arrowElement && Object.keys(data.arrowStyles).length) { 28 | setStyles(data.arrowElement, data.arrowStyles); 29 | } 30 | 31 | return data; 32 | } 33 | 34 | /** 35 | * Set the x-placement attribute before everything else because it could be used 36 | * to add margins to the popper margins needs to be calculated to get the 37 | * correct popper offsets. 38 | * @method 39 | * @memberof Popper.modifiers 40 | * @param {HTMLElement} reference - The reference element used to position the popper 41 | * @param {HTMLElement} popper - The HTML element used as popper 42 | * @param {Object} options - Popper.js options 43 | */ 44 | export function applyStyleOnLoad( 45 | reference, 46 | popper, 47 | options, 48 | modifierOptions, 49 | state 50 | ) { 51 | // compute reference element offsets 52 | const referenceOffsets = getReferenceOffsets(state, popper, reference, options.positionFixed); 53 | 54 | // compute auto placement, store placement inside the data object, 55 | // modifiers will be able to edit `placement` if needed 56 | // and refer to originalPlacement to know the original value 57 | const placement = computeAutoPlacement( 58 | options.placement, 59 | referenceOffsets, 60 | popper, 61 | reference, 62 | options.modifiers.flip.boundariesElement, 63 | options.modifiers.flip.padding 64 | ); 65 | 66 | popper.setAttribute('x-placement', placement); 67 | 68 | // Apply `position` to popper before anything else because 69 | // without the position applied we can't guarantee correct computations 70 | setStyles(popper, { position: options.positionFixed ? 'fixed' : 'absolute' }); 71 | 72 | return options; 73 | } 74 | -------------------------------------------------------------------------------- /Books/Scripts/src/modifiers/arrow.js: -------------------------------------------------------------------------------- 1 | import getClientRect from '../utils/getClientRect'; 2 | import getOuterSizes from '../utils/getOuterSizes'; 3 | import isModifierRequired from '../utils/isModifierRequired'; 4 | import getStyleComputedProperty from '../utils/getStyleComputedProperty'; 5 | 6 | /** 7 | * @function 8 | * @memberof Modifiers 9 | * @argument {Object} data - The data object generated by update method 10 | * @argument {Object} options - Modifiers configuration and options 11 | * @returns {Object} The data object, properly modified 12 | */ 13 | export default function arrow(data, options) { 14 | // arrow depends on keepTogether in order to work 15 | if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) { 16 | return data; 17 | } 18 | 19 | let arrowElement = options.element; 20 | 21 | // if arrowElement is a string, suppose it's a CSS selector 22 | if (typeof arrowElement === 'string') { 23 | arrowElement = data.instance.popper.querySelector(arrowElement); 24 | 25 | // if arrowElement is not found, don't run the modifier 26 | if (!arrowElement) { 27 | return data; 28 | } 29 | } else { 30 | // if the arrowElement isn't a query selector we must check that the 31 | // provided DOM node is child of its popper node 32 | if (!data.instance.popper.contains(arrowElement)) { 33 | console.warn( 34 | 'WARNING: `arrow.element` must be child of its popper element!' 35 | ); 36 | return data; 37 | } 38 | } 39 | 40 | const placement = data.placement.split('-')[0]; 41 | const { popper, reference } = data.offsets; 42 | const isVertical = ['left', 'right'].indexOf(placement) !== -1; 43 | 44 | const len = isVertical ? 'height' : 'width'; 45 | const sideCapitalized = isVertical ? 'Top' : 'Left'; 46 | const side = sideCapitalized.toLowerCase(); 47 | const altSide = isVertical ? 'left' : 'top'; 48 | const opSide = isVertical ? 'bottom' : 'right'; 49 | const arrowElementSize = getOuterSizes(arrowElement)[len]; 50 | 51 | // 52 | // extends keepTogether behavior making sure the popper and its 53 | // reference have enough pixels in conjunction 54 | // 55 | 56 | // top/left side 57 | if (reference[opSide] - arrowElementSize < popper[side]) { 58 | data.offsets.popper[side] -= 59 | popper[side] - (reference[opSide] - arrowElementSize); 60 | } 61 | // bottom/right side 62 | if (reference[side] + arrowElementSize > popper[opSide]) { 63 | data.offsets.popper[side] += 64 | reference[side] + arrowElementSize - popper[opSide]; 65 | } 66 | data.offsets.popper = getClientRect(data.offsets.popper); 67 | 68 | // compute center of the popper 69 | const center = reference[side] + reference[len] / 2 - arrowElementSize / 2; 70 | 71 | // Compute the sideValue using the updated popper offsets 72 | // take popper margin in account because we don't have this info available 73 | const css = getStyleComputedProperty(data.instance.popper); 74 | const popperMarginSide = parseFloat(css[`margin${sideCapitalized}`]); 75 | const popperBorderSide = parseFloat(css[`border${sideCapitalized}Width`]); 76 | let sideValue = 77 | center - data.offsets.popper[side] - popperMarginSide - popperBorderSide; 78 | 79 | // prevent arrowElement from being placed not contiguously to its popper 80 | sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0); 81 | 82 | data.arrowElement = arrowElement; 83 | data.offsets.arrow = { 84 | [side]: Math.round(sideValue), 85 | [altSide]: '', // make sure to unset any eventual altSide value from the DOM node 86 | }; 87 | 88 | return data; 89 | } 90 | -------------------------------------------------------------------------------- /Books/Scripts/src/modifiers/computeStyle.js: -------------------------------------------------------------------------------- 1 | import getSupportedPropertyName from '../utils/getSupportedPropertyName'; 2 | import find from '../utils/find'; 3 | import getOffsetParent from '../utils/getOffsetParent'; 4 | import getBoundingClientRect from '../utils/getBoundingClientRect'; 5 | import getRoundedOffsets from '../utils/getRoundedOffsets'; 6 | import isBrowser from '../utils/isBrowser'; 7 | 8 | const isFirefox = isBrowser && /Firefox/i.test(navigator.userAgent); 9 | 10 | /** 11 | * @function 12 | * @memberof Modifiers 13 | * @argument {Object} data - The data object generated by `update` method 14 | * @argument {Object} options - Modifiers configuration and options 15 | * @returns {Object} The data object, properly modified 16 | */ 17 | export default function computeStyle(data, options) { 18 | const { x, y } = options; 19 | const { popper } = data.offsets; 20 | 21 | // Remove this legacy support in Popper.js v2 22 | const legacyGpuAccelerationOption = find( 23 | data.instance.modifiers, 24 | modifier => modifier.name === 'applyStyle' 25 | ).gpuAcceleration; 26 | if (legacyGpuAccelerationOption !== undefined) { 27 | console.warn( 28 | 'WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!' 29 | ); 30 | } 31 | const gpuAcceleration = 32 | legacyGpuAccelerationOption !== undefined 33 | ? legacyGpuAccelerationOption 34 | : options.gpuAcceleration; 35 | 36 | const offsetParent = getOffsetParent(data.instance.popper); 37 | const offsetParentRect = getBoundingClientRect(offsetParent); 38 | 39 | // Styles 40 | const styles = { 41 | position: popper.position, 42 | }; 43 | 44 | const offsets = getRoundedOffsets( 45 | data, 46 | window.devicePixelRatio < 2 || !isFirefox 47 | ); 48 | 49 | const sideA = x === 'bottom' ? 'top' : 'bottom'; 50 | const sideB = y === 'right' ? 'left' : 'right'; 51 | 52 | // if gpuAcceleration is set to `true` and transform is supported, 53 | // we use `translate3d` to apply the position to the popper we 54 | // automatically use the supported prefixed version if needed 55 | const prefixedProperty = getSupportedPropertyName('transform'); 56 | 57 | // now, let's make a step back and look at this code closely (wtf?) 58 | // If the content of the popper grows once it's been positioned, it 59 | // may happen that the popper gets misplaced because of the new content 60 | // overflowing its reference element 61 | // To avoid this problem, we provide two options (x and y), which allow 62 | // the consumer to define the offset origin. 63 | // If we position a popper on top of a reference element, we can set 64 | // `x` to `top` to make the popper grow towards its top instead of 65 | // its bottom. 66 | let left, top; 67 | if (sideA === 'bottom') { 68 | // when offsetParent is the positioning is relative to the bottom of the screen (excluding the scrollbar) 69 | // and not the bottom of the html element 70 | if (offsetParent.nodeName === 'HTML') { 71 | top = -offsetParent.clientHeight + offsets.bottom; 72 | } else { 73 | top = -offsetParentRect.height + offsets.bottom; 74 | } 75 | } else { 76 | top = offsets.top; 77 | } 78 | if (sideB === 'right') { 79 | if (offsetParent.nodeName === 'HTML') { 80 | left = -offsetParent.clientWidth + offsets.right; 81 | } else { 82 | left = -offsetParentRect.width + offsets.right; 83 | } 84 | } else { 85 | left = offsets.left; 86 | } 87 | if (gpuAcceleration && prefixedProperty) { 88 | styles[prefixedProperty] = `translate3d(${left}px, ${top}px, 0)`; 89 | styles[sideA] = 0; 90 | styles[sideB] = 0; 91 | styles.willChange = 'transform'; 92 | } else { 93 | // othwerise, we use the standard `top`, `left`, `bottom` and `right` properties 94 | const invertTop = sideA === 'bottom' ? -1 : 1; 95 | const invertLeft = sideB === 'right' ? -1 : 1; 96 | styles[sideA] = top * invertTop; 97 | styles[sideB] = left * invertLeft; 98 | styles.willChange = `${sideA}, ${sideB}`; 99 | } 100 | 101 | // Attributes 102 | const attributes = { 103 | 'x-placement': data.placement, 104 | }; 105 | 106 | // Update `data` attributes, styles and arrowStyles 107 | data.attributes = { ...attributes, ...data.attributes }; 108 | data.styles = { ...styles, ...data.styles }; 109 | data.arrowStyles = { ...data.offsets.arrow, ...data.arrowStyles }; 110 | 111 | return data; 112 | } 113 | -------------------------------------------------------------------------------- /Books/Scripts/src/modifiers/flip.js: -------------------------------------------------------------------------------- 1 | import getOppositePlacement from '../utils/getOppositePlacement'; 2 | import getOppositeVariation from '../utils/getOppositeVariation'; 3 | import getPopperOffsets from '../utils/getPopperOffsets'; 4 | import runModifiers from '../utils/runModifiers'; 5 | import getBoundaries from '../utils/getBoundaries'; 6 | import isModifierEnabled from '../utils/isModifierEnabled'; 7 | import clockwise from '../utils/clockwise'; 8 | 9 | const BEHAVIORS = { 10 | FLIP: 'flip', 11 | CLOCKWISE: 'clockwise', 12 | COUNTERCLOCKWISE: 'counterclockwise', 13 | }; 14 | 15 | /** 16 | * @function 17 | * @memberof Modifiers 18 | * @argument {Object} data - The data object generated by update method 19 | * @argument {Object} options - Modifiers configuration and options 20 | * @returns {Object} The data object, properly modified 21 | */ 22 | export default function flip(data, options) { 23 | // if `inner` modifier is enabled, we can't use the `flip` modifier 24 | if (isModifierEnabled(data.instance.modifiers, 'inner')) { 25 | return data; 26 | } 27 | 28 | if (data.flipped && data.placement === data.originalPlacement) { 29 | // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides 30 | return data; 31 | } 32 | 33 | const boundaries = getBoundaries( 34 | data.instance.popper, 35 | data.instance.reference, 36 | options.padding, 37 | options.boundariesElement, 38 | data.positionFixed 39 | ); 40 | 41 | let placement = data.placement.split('-')[0]; 42 | let placementOpposite = getOppositePlacement(placement); 43 | let variation = data.placement.split('-')[1] || ''; 44 | 45 | let flipOrder = []; 46 | 47 | switch (options.behavior) { 48 | case BEHAVIORS.FLIP: 49 | flipOrder = [placement, placementOpposite]; 50 | break; 51 | case BEHAVIORS.CLOCKWISE: 52 | flipOrder = clockwise(placement); 53 | break; 54 | case BEHAVIORS.COUNTERCLOCKWISE: 55 | flipOrder = clockwise(placement, true); 56 | break; 57 | default: 58 | flipOrder = options.behavior; 59 | } 60 | 61 | flipOrder.forEach((step, index) => { 62 | if (placement !== step || flipOrder.length === index + 1) { 63 | return data; 64 | } 65 | 66 | placement = data.placement.split('-')[0]; 67 | placementOpposite = getOppositePlacement(placement); 68 | 69 | const popperOffsets = data.offsets.popper; 70 | const refOffsets = data.offsets.reference; 71 | 72 | // using floor because the reference offsets may contain decimals we are not going to consider here 73 | const floor = Math.floor; 74 | const overlapsRef = 75 | (placement === 'left' && 76 | floor(popperOffsets.right) > floor(refOffsets.left)) || 77 | (placement === 'right' && 78 | floor(popperOffsets.left) < floor(refOffsets.right)) || 79 | (placement === 'top' && 80 | floor(popperOffsets.bottom) > floor(refOffsets.top)) || 81 | (placement === 'bottom' && 82 | floor(popperOffsets.top) < floor(refOffsets.bottom)); 83 | 84 | const overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left); 85 | const overflowsRight = floor(popperOffsets.right) > floor(boundaries.right); 86 | const overflowsTop = floor(popperOffsets.top) < floor(boundaries.top); 87 | const overflowsBottom = 88 | floor(popperOffsets.bottom) > floor(boundaries.bottom); 89 | 90 | const overflowsBoundaries = 91 | (placement === 'left' && overflowsLeft) || 92 | (placement === 'right' && overflowsRight) || 93 | (placement === 'top' && overflowsTop) || 94 | (placement === 'bottom' && overflowsBottom); 95 | 96 | // flip the variation if required 97 | const isVertical = ['top', 'bottom'].indexOf(placement) !== -1; 98 | 99 | // flips variation if reference element overflows boundaries 100 | const flippedVariationByRef = 101 | !!options.flipVariations && 102 | ((isVertical && variation === 'start' && overflowsLeft) || 103 | (isVertical && variation === 'end' && overflowsRight) || 104 | (!isVertical && variation === 'start' && overflowsTop) || 105 | (!isVertical && variation === 'end' && overflowsBottom)); 106 | 107 | // flips variation if popper content overflows boundaries 108 | const flippedVariationByContent = 109 | !!options.flipVariationsByContent && 110 | ((isVertical && variation === 'start' && overflowsRight) || 111 | (isVertical && variation === 'end' && overflowsLeft) || 112 | (!isVertical && variation === 'start' && overflowsBottom) || 113 | (!isVertical && variation === 'end' && overflowsTop)); 114 | 115 | const flippedVariation = flippedVariationByRef || flippedVariationByContent; 116 | 117 | if (overlapsRef || overflowsBoundaries || flippedVariation) { 118 | // this boolean to detect any flip loop 119 | data.flipped = true; 120 | 121 | if (overlapsRef || overflowsBoundaries) { 122 | placement = flipOrder[index + 1]; 123 | } 124 | 125 | if (flippedVariation) { 126 | variation = getOppositeVariation(variation); 127 | } 128 | 129 | data.placement = placement + (variation ? '-' + variation : ''); 130 | 131 | // this object contains `position`, we want to preserve it along with 132 | // any additional property we may add in the future 133 | data.offsets.popper = { 134 | ...data.offsets.popper, 135 | ...getPopperOffsets( 136 | data.instance.popper, 137 | data.offsets.reference, 138 | data.placement 139 | ), 140 | }; 141 | 142 | data = runModifiers(data.instance.modifiers, data, 'flip'); 143 | } 144 | }); 145 | return data; 146 | } 147 | -------------------------------------------------------------------------------- /Books/Scripts/src/modifiers/hide.js: -------------------------------------------------------------------------------- 1 | import isModifierRequired from '../utils/isModifierRequired'; 2 | import find from '../utils/find'; 3 | 4 | /** 5 | * @function 6 | * @memberof Modifiers 7 | * @argument {Object} data - The data object generated by update method 8 | * @argument {Object} options - Modifiers configuration and options 9 | * @returns {Object} The data object, properly modified 10 | */ 11 | export default function hide(data) { 12 | if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) { 13 | return data; 14 | } 15 | 16 | const refRect = data.offsets.reference; 17 | const bound = find( 18 | data.instance.modifiers, 19 | modifier => modifier.name === 'preventOverflow' 20 | ).boundaries; 21 | 22 | if ( 23 | refRect.bottom < bound.top || 24 | refRect.left > bound.right || 25 | refRect.top > bound.bottom || 26 | refRect.right < bound.left 27 | ) { 28 | // Avoid unnecessary DOM access if visibility hasn't changed 29 | if (data.hide === true) { 30 | return data; 31 | } 32 | 33 | data.hide = true; 34 | data.attributes['x-out-of-boundaries'] = ''; 35 | } else { 36 | // Avoid unnecessary DOM access if visibility hasn't changed 37 | if (data.hide === false) { 38 | return data; 39 | } 40 | 41 | data.hide = false; 42 | data.attributes['x-out-of-boundaries'] = false; 43 | } 44 | 45 | return data; 46 | } 47 | -------------------------------------------------------------------------------- /Books/Scripts/src/modifiers/inner.js: -------------------------------------------------------------------------------- 1 | import getClientRect from '../utils/getClientRect'; 2 | import getOppositePlacement from '../utils/getOppositePlacement'; 3 | 4 | /** 5 | * @function 6 | * @memberof Modifiers 7 | * @argument {Object} data - The data object generated by `update` method 8 | * @argument {Object} options - Modifiers configuration and options 9 | * @returns {Object} The data object, properly modified 10 | */ 11 | export default function inner(data) { 12 | const placement = data.placement; 13 | const basePlacement = placement.split('-')[0]; 14 | const { popper, reference } = data.offsets; 15 | const isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1; 16 | 17 | const subtractLength = ['top', 'left'].indexOf(basePlacement) === -1; 18 | 19 | popper[isHoriz ? 'left' : 'top'] = 20 | reference[basePlacement] - 21 | (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0); 22 | 23 | data.placement = getOppositePlacement(placement); 24 | data.offsets.popper = getClientRect(popper); 25 | 26 | return data; 27 | } 28 | -------------------------------------------------------------------------------- /Books/Scripts/src/modifiers/keepTogether.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @function 3 | * @memberof Modifiers 4 | * @argument {Object} data - The data object generated by update method 5 | * @argument {Object} options - Modifiers configuration and options 6 | * @returns {Object} The data object, properly modified 7 | */ 8 | export default function keepTogether(data) { 9 | const { popper, reference } = data.offsets; 10 | const placement = data.placement.split('-')[0]; 11 | const floor = Math.floor; 12 | const isVertical = ['top', 'bottom'].indexOf(placement) !== -1; 13 | const side = isVertical ? 'right' : 'bottom'; 14 | const opSide = isVertical ? 'left' : 'top'; 15 | const measurement = isVertical ? 'width' : 'height'; 16 | 17 | if (popper[side] < floor(reference[opSide])) { 18 | data.offsets.popper[opSide] = 19 | floor(reference[opSide]) - popper[measurement]; 20 | } 21 | if (popper[opSide] > floor(reference[side])) { 22 | data.offsets.popper[opSide] = floor(reference[side]); 23 | } 24 | 25 | return data; 26 | } 27 | -------------------------------------------------------------------------------- /Books/Scripts/src/modifiers/offset.js: -------------------------------------------------------------------------------- 1 | import isNumeric from '../utils/isNumeric'; 2 | import getClientRect from '../utils/getClientRect'; 3 | import find from '../utils/find'; 4 | 5 | /** 6 | * Converts a string containing value + unit into a px value number 7 | * @function 8 | * @memberof {modifiers~offset} 9 | * @private 10 | * @argument {String} str - Value + unit string 11 | * @argument {String} measurement - `height` or `width` 12 | * @argument {Object} popperOffsets 13 | * @argument {Object} referenceOffsets 14 | * @returns {Number|String} 15 | * Value in pixels, or original string if no values were extracted 16 | */ 17 | export function toValue(str, measurement, popperOffsets, referenceOffsets) { 18 | // separate value from unit 19 | const split = str.match(/((?:\-|\+)?\d*\.?\d*)(.*)/); 20 | const value = +split[1]; 21 | const unit = split[2]; 22 | 23 | // If it's not a number it's an operator, I guess 24 | if (!value) { 25 | return str; 26 | } 27 | 28 | if (unit.indexOf('%') === 0) { 29 | let element; 30 | switch (unit) { 31 | case '%p': 32 | element = popperOffsets; 33 | break; 34 | case '%': 35 | case '%r': 36 | default: 37 | element = referenceOffsets; 38 | } 39 | 40 | const rect = getClientRect(element); 41 | return rect[measurement] / 100 * value; 42 | } else if (unit === 'vh' || unit === 'vw') { 43 | // if is a vh or vw, we calculate the size based on the viewport 44 | let size; 45 | if (unit === 'vh') { 46 | size = Math.max( 47 | document.documentElement.clientHeight, 48 | window.innerHeight || 0 49 | ); 50 | } else { 51 | size = Math.max( 52 | document.documentElement.clientWidth, 53 | window.innerWidth || 0 54 | ); 55 | } 56 | return size / 100 * value; 57 | } else { 58 | // if is an explicit pixel unit, we get rid of the unit and keep the value 59 | // if is an implicit unit, it's px, and we return just the value 60 | return value; 61 | } 62 | } 63 | 64 | /** 65 | * Parse an `offset` string to extrapolate `x` and `y` numeric offsets. 66 | * @function 67 | * @memberof {modifiers~offset} 68 | * @private 69 | * @argument {String} offset 70 | * @argument {Object} popperOffsets 71 | * @argument {Object} referenceOffsets 72 | * @argument {String} basePlacement 73 | * @returns {Array} a two cells array with x and y offsets in numbers 74 | */ 75 | export function parseOffset( 76 | offset, 77 | popperOffsets, 78 | referenceOffsets, 79 | basePlacement 80 | ) { 81 | const offsets = [0, 0]; 82 | 83 | // Use height if placement is left or right and index is 0 otherwise use width 84 | // in this way the first offset will use an axis and the second one 85 | // will use the other one 86 | const useHeight = ['right', 'left'].indexOf(basePlacement) !== -1; 87 | 88 | // Split the offset string to obtain a list of values and operands 89 | // The regex addresses values with the plus or minus sign in front (+10, -20, etc) 90 | const fragments = offset.split(/(\+|\-)/).map(frag => frag.trim()); 91 | 92 | // Detect if the offset string contains a pair of values or a single one 93 | // they could be separated by comma or space 94 | const divider = fragments.indexOf( 95 | find(fragments, frag => frag.search(/,|\s/) !== -1) 96 | ); 97 | 98 | if (fragments[divider] && fragments[divider].indexOf(',') === -1) { 99 | console.warn( 100 | 'Offsets separated by white space(s) are deprecated, use a comma (,) instead.' 101 | ); 102 | } 103 | 104 | // If divider is found, we divide the list of values and operands to divide 105 | // them by ofset X and Y. 106 | const splitRegex = /\s*,\s*|\s+/; 107 | let ops = divider !== -1 108 | ? [ 109 | fragments 110 | .slice(0, divider) 111 | .concat([fragments[divider].split(splitRegex)[0]]), 112 | [fragments[divider].split(splitRegex)[1]].concat( 113 | fragments.slice(divider + 1) 114 | ), 115 | ] 116 | : [fragments]; 117 | 118 | // Convert the values with units to absolute pixels to allow our computations 119 | ops = ops.map((op, index) => { 120 | // Most of the units rely on the orientation of the popper 121 | const measurement = (index === 1 ? !useHeight : useHeight) 122 | ? 'height' 123 | : 'width'; 124 | let mergeWithPrevious = false; 125 | return ( 126 | op 127 | // This aggregates any `+` or `-` sign that aren't considered operators 128 | // e.g.: 10 + +5 => [10, +, +5] 129 | .reduce((a, b) => { 130 | if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) { 131 | a[a.length - 1] = b; 132 | mergeWithPrevious = true; 133 | return a; 134 | } else if (mergeWithPrevious) { 135 | a[a.length - 1] += b; 136 | mergeWithPrevious = false; 137 | return a; 138 | } else { 139 | return a.concat(b); 140 | } 141 | }, []) 142 | // Here we convert the string values into number values (in px) 143 | .map(str => toValue(str, measurement, popperOffsets, referenceOffsets)) 144 | ); 145 | }); 146 | 147 | // Loop trough the offsets arrays and execute the operations 148 | ops.forEach((op, index) => { 149 | op.forEach((frag, index2) => { 150 | if (isNumeric(frag)) { 151 | offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1); 152 | } 153 | }); 154 | }); 155 | return offsets; 156 | } 157 | 158 | /** 159 | * @function 160 | * @memberof Modifiers 161 | * @argument {Object} data - The data object generated by update method 162 | * @argument {Object} options - Modifiers configuration and options 163 | * @argument {Number|String} options.offset=0 164 | * The offset value as described in the modifier description 165 | * @returns {Object} The data object, properly modified 166 | */ 167 | export default function offset(data, { offset }) { 168 | const { placement, offsets: { popper, reference } } = data; 169 | const basePlacement = placement.split('-')[0]; 170 | 171 | let offsets; 172 | if (isNumeric(+offset)) { 173 | offsets = [+offset, 0]; 174 | } else { 175 | offsets = parseOffset(offset, popper, reference, basePlacement); 176 | } 177 | 178 | if (basePlacement === 'left') { 179 | popper.top += offsets[0]; 180 | popper.left -= offsets[1]; 181 | } else if (basePlacement === 'right') { 182 | popper.top += offsets[0]; 183 | popper.left += offsets[1]; 184 | } else if (basePlacement === 'top') { 185 | popper.left += offsets[0]; 186 | popper.top -= offsets[1]; 187 | } else if (basePlacement === 'bottom') { 188 | popper.left += offsets[0]; 189 | popper.top += offsets[1]; 190 | } 191 | 192 | data.popper = popper; 193 | return data; 194 | } 195 | -------------------------------------------------------------------------------- /Books/Scripts/src/modifiers/preventOverflow.js: -------------------------------------------------------------------------------- 1 | import getOffsetParent from '../utils/getOffsetParent'; 2 | import getBoundaries from '../utils/getBoundaries'; 3 | import getSupportedPropertyName from '../utils/getSupportedPropertyName'; 4 | 5 | /** 6 | * @function 7 | * @memberof Modifiers 8 | * @argument {Object} data - The data object generated by `update` method 9 | * @argument {Object} options - Modifiers configuration and options 10 | * @returns {Object} The data object, properly modified 11 | */ 12 | export default function preventOverflow(data, options) { 13 | let boundariesElement = 14 | options.boundariesElement || getOffsetParent(data.instance.popper); 15 | 16 | // If offsetParent is the reference element, we really want to 17 | // go one step up and use the next offsetParent as reference to 18 | // avoid to make this modifier completely useless and look like broken 19 | if (data.instance.reference === boundariesElement) { 20 | boundariesElement = getOffsetParent(boundariesElement); 21 | } 22 | 23 | // NOTE: DOM access here 24 | // resets the popper's position so that the document size can be calculated excluding 25 | // the size of the popper element itself 26 | const transformProp = getSupportedPropertyName('transform'); 27 | const popperStyles = data.instance.popper.style; // assignment to help minification 28 | const { top, left, [transformProp]: transform } = popperStyles; 29 | popperStyles.top = ''; 30 | popperStyles.left = ''; 31 | popperStyles[transformProp] = ''; 32 | 33 | const boundaries = getBoundaries( 34 | data.instance.popper, 35 | data.instance.reference, 36 | options.padding, 37 | boundariesElement, 38 | data.positionFixed 39 | ); 40 | 41 | // NOTE: DOM access here 42 | // restores the original style properties after the offsets have been computed 43 | popperStyles.top = top; 44 | popperStyles.left = left; 45 | popperStyles[transformProp] = transform; 46 | 47 | options.boundaries = boundaries; 48 | 49 | const order = options.priority; 50 | let popper = data.offsets.popper; 51 | 52 | const check = { 53 | primary(placement) { 54 | let value = popper[placement]; 55 | if ( 56 | popper[placement] < boundaries[placement] && 57 | !options.escapeWithReference 58 | ) { 59 | value = Math.max(popper[placement], boundaries[placement]); 60 | } 61 | return { [placement]: value }; 62 | }, 63 | secondary(placement) { 64 | const mainSide = placement === 'right' ? 'left' : 'top'; 65 | let value = popper[mainSide]; 66 | if ( 67 | popper[placement] > boundaries[placement] && 68 | !options.escapeWithReference 69 | ) { 70 | value = Math.min( 71 | popper[mainSide], 72 | boundaries[placement] - 73 | (placement === 'right' ? popper.width : popper.height) 74 | ); 75 | } 76 | return { [mainSide]: value }; 77 | }, 78 | }; 79 | 80 | order.forEach(placement => { 81 | const side = 82 | ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary'; 83 | popper = { ...popper, ...check[side](placement) }; 84 | }); 85 | 86 | data.offsets.popper = popper; 87 | 88 | return data; 89 | } 90 | -------------------------------------------------------------------------------- /Books/Scripts/src/modifiers/shift.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @function 3 | * @memberof Modifiers 4 | * @argument {Object} data - The data object generated by `update` method 5 | * @argument {Object} options - Modifiers configuration and options 6 | * @returns {Object} The data object, properly modified 7 | */ 8 | export default function shift(data) { 9 | const placement = data.placement; 10 | const basePlacement = placement.split('-')[0]; 11 | const shiftvariation = placement.split('-')[1]; 12 | 13 | // if shift shiftvariation is specified, run the modifier 14 | if (shiftvariation) { 15 | const { reference, popper } = data.offsets; 16 | const isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1; 17 | const side = isVertical ? 'left' : 'top'; 18 | const measurement = isVertical ? 'width' : 'height'; 19 | 20 | const shiftOffsets = { 21 | start: { [side]: reference[side] }, 22 | end: { 23 | [side]: reference[side] + reference[measurement] - popper[measurement], 24 | }, 25 | }; 26 | 27 | data.offsets.popper = { ...popper, ...shiftOffsets[shiftvariation] }; 28 | } 29 | 30 | return data; 31 | } 32 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/clockwise.js: -------------------------------------------------------------------------------- 1 | import placements from '../methods/placements'; 2 | 3 | // Get rid of `auto` `auto-start` and `auto-end` 4 | const validPlacements = placements.slice(3); 5 | 6 | /** 7 | * Given an initial placement, returns all the subsequent placements 8 | * clockwise (or counter-clockwise). 9 | * 10 | * @method 11 | * @memberof Popper.Utils 12 | * @argument {String} placement - A valid placement (it accepts variations) 13 | * @argument {Boolean} counter - Set to true to walk the placements counterclockwise 14 | * @returns {Array} placements including their variations 15 | */ 16 | export default function clockwise(placement, counter = false) { 17 | const index = validPlacements.indexOf(placement); 18 | const arr = validPlacements 19 | .slice(index + 1) 20 | .concat(validPlacements.slice(0, index)); 21 | return counter ? arr.reverse() : arr; 22 | } 23 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/computeAutoPlacement.js: -------------------------------------------------------------------------------- 1 | import getBoundaries from '../utils/getBoundaries'; 2 | 3 | function getArea({ width, height }) { 4 | return width * height; 5 | } 6 | 7 | /** 8 | * Utility used to transform the `auto` placement to the placement with more 9 | * available space. 10 | * @method 11 | * @memberof Popper.Utils 12 | * @argument {Object} data - The data object generated by update method 13 | * @argument {Object} options - Modifiers configuration and options 14 | * @returns {Object} The data object, properly modified 15 | */ 16 | export default function computeAutoPlacement( 17 | placement, 18 | refRect, 19 | popper, 20 | reference, 21 | boundariesElement, 22 | padding = 0 23 | ) { 24 | if (placement.indexOf('auto') === -1) { 25 | return placement; 26 | } 27 | 28 | const boundaries = getBoundaries( 29 | popper, 30 | reference, 31 | padding, 32 | boundariesElement 33 | ); 34 | 35 | const rects = { 36 | top: { 37 | width: boundaries.width, 38 | height: refRect.top - boundaries.top, 39 | }, 40 | right: { 41 | width: boundaries.right - refRect.right, 42 | height: boundaries.height, 43 | }, 44 | bottom: { 45 | width: boundaries.width, 46 | height: boundaries.bottom - refRect.bottom, 47 | }, 48 | left: { 49 | width: refRect.left - boundaries.left, 50 | height: boundaries.height, 51 | }, 52 | }; 53 | 54 | const sortedAreas = Object.keys(rects) 55 | .map(key => ({ 56 | key, 57 | ...rects[key], 58 | area: getArea(rects[key]), 59 | })) 60 | .sort((a, b) => b.area - a.area); 61 | 62 | const filteredAreas = sortedAreas.filter( 63 | ({ width, height }) => 64 | width >= popper.clientWidth && height >= popper.clientHeight 65 | ); 66 | 67 | const computedPlacement = filteredAreas.length > 0 68 | ? filteredAreas[0].key 69 | : sortedAreas[0].key; 70 | 71 | const variation = placement.split('-')[1]; 72 | 73 | return computedPlacement + (variation ? `-${variation}` : ''); 74 | } 75 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/debounce.js: -------------------------------------------------------------------------------- 1 | import isBrowser from './isBrowser'; 2 | 3 | const timeoutDuration = (function(){ 4 | const longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox']; 5 | for (let i = 0; i < longerTimeoutBrowsers.length; i += 1) { 6 | if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) { 7 | return 1; 8 | } 9 | } 10 | return 0; 11 | }()); 12 | 13 | export function microtaskDebounce(fn) { 14 | let called = false 15 | return () => { 16 | if (called) { 17 | return 18 | } 19 | called = true 20 | window.Promise.resolve().then(() => { 21 | called = false 22 | fn() 23 | }) 24 | } 25 | } 26 | 27 | export function taskDebounce(fn) { 28 | let scheduled = false; 29 | return () => { 30 | if (!scheduled) { 31 | scheduled = true; 32 | setTimeout(() => { 33 | scheduled = false; 34 | fn(); 35 | }, timeoutDuration); 36 | } 37 | }; 38 | } 39 | 40 | const supportsMicroTasks = isBrowser && window.Promise 41 | 42 | 43 | /** 44 | * Create a debounced version of a method, that's asynchronously deferred 45 | * but called in the minimum time possible. 46 | * 47 | * @method 48 | * @memberof Popper.Utils 49 | * @argument {Function} fn 50 | * @returns {Function} 51 | */ 52 | export default (supportsMicroTasks 53 | ? microtaskDebounce 54 | : taskDebounce); 55 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/find.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Mimics the `find` method of Array 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Array} arr 6 | * @argument prop 7 | * @argument value 8 | * @returns index or -1 9 | */ 10 | export default function find(arr, check) { 11 | // use native find if supported 12 | if (Array.prototype.find) { 13 | return arr.find(check); 14 | } 15 | 16 | // use `filter` to obtain the same behavior of `find` 17 | return arr.filter(check)[0]; 18 | } 19 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/findCommonOffsetParent.js: -------------------------------------------------------------------------------- 1 | import isOffsetContainer from './isOffsetContainer'; 2 | import getRoot from './getRoot'; 3 | import getOffsetParent from './getOffsetParent'; 4 | 5 | /** 6 | * Finds the offset parent common to the two provided nodes 7 | * @method 8 | * @memberof Popper.Utils 9 | * @argument {Element} element1 10 | * @argument {Element} element2 11 | * @returns {Element} common offset parent 12 | */ 13 | export default function findCommonOffsetParent(element1, element2) { 14 | // This check is needed to avoid errors in case one of the elements isn't defined for any reason 15 | if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) { 16 | return document.documentElement; 17 | } 18 | 19 | // Here we make sure to give as "start" the element that comes first in the DOM 20 | const order = 21 | element1.compareDocumentPosition(element2) & 22 | Node.DOCUMENT_POSITION_FOLLOWING; 23 | const start = order ? element1 : element2; 24 | const end = order ? element2 : element1; 25 | 26 | // Get common ancestor container 27 | const range = document.createRange(); 28 | range.setStart(start, 0); 29 | range.setEnd(end, 0); 30 | const { commonAncestorContainer } = range; 31 | 32 | // Both nodes are inside #document 33 | if ( 34 | (element1 !== commonAncestorContainer && 35 | element2 !== commonAncestorContainer) || 36 | start.contains(end) 37 | ) { 38 | if (isOffsetContainer(commonAncestorContainer)) { 39 | return commonAncestorContainer; 40 | } 41 | 42 | return getOffsetParent(commonAncestorContainer); 43 | } 44 | 45 | // one of the nodes is inside shadowDOM, find which one 46 | const element1root = getRoot(element1); 47 | if (element1root.host) { 48 | return findCommonOffsetParent(element1root.host, element2); 49 | } else { 50 | return findCommonOffsetParent(element1, getRoot(element2).host); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/findIndex.js: -------------------------------------------------------------------------------- 1 | import find from './find'; 2 | 3 | /** 4 | * Return the index of the matching object 5 | * @method 6 | * @memberof Popper.Utils 7 | * @argument {Array} arr 8 | * @argument prop 9 | * @argument value 10 | * @returns index or -1 11 | */ 12 | export default function findIndex(arr, prop, value) { 13 | // use native findIndex if supported 14 | if (Array.prototype.findIndex) { 15 | return arr.findIndex(cur => cur[prop] === value); 16 | } 17 | 18 | // use `find` + `indexOf` if `findIndex` isn't supported 19 | const match = find(arr, obj => obj[prop] === value); 20 | return arr.indexOf(match); 21 | } 22 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/getBordersSize.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Helper to detect borders of a given element 3 | * @method 4 | * @memberof Popper.Utils 5 | * @param {CSSStyleDeclaration} styles 6 | * Result of `getStyleComputedProperty` on the given element 7 | * @param {String} axis - `x` or `y` 8 | * @return {number} borders - The borders size of the given axis 9 | */ 10 | 11 | export default function getBordersSize(styles, axis) { 12 | const sideA = axis === 'x' ? 'Left' : 'Top'; 13 | const sideB = sideA === 'Left' ? 'Right' : 'Bottom'; 14 | 15 | return ( 16 | parseFloat(styles[`border${sideA}Width`]) + 17 | parseFloat(styles[`border${sideB}Width`]) 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/getBoundaries.js: -------------------------------------------------------------------------------- 1 | import getScrollParent from './getScrollParent'; 2 | import getParentNode from './getParentNode'; 3 | import getReferenceNode from './getReferenceNode'; 4 | import findCommonOffsetParent from './findCommonOffsetParent'; 5 | import getOffsetRectRelativeToArbitraryNode from './getOffsetRectRelativeToArbitraryNode'; 6 | import getViewportOffsetRectRelativeToArtbitraryNode from './getViewportOffsetRectRelativeToArtbitraryNode'; 7 | import getWindowSizes from './getWindowSizes'; 8 | import isFixed from './isFixed'; 9 | import getFixedPositionOffsetParent from './getFixedPositionOffsetParent'; 10 | 11 | /** 12 | * Computed the boundaries limits and return them 13 | * @method 14 | * @memberof Popper.Utils 15 | * @param {HTMLElement} popper 16 | * @param {HTMLElement} reference 17 | * @param {number} padding 18 | * @param {HTMLElement} boundariesElement - Element used to define the boundaries 19 | * @param {Boolean} fixedPosition - Is in fixed position mode 20 | * @returns {Object} Coordinates of the boundaries 21 | */ 22 | export default function getBoundaries( 23 | popper, 24 | reference, 25 | padding, 26 | boundariesElement, 27 | fixedPosition = false 28 | ) { 29 | // NOTE: 1 DOM access here 30 | 31 | let boundaries = { top: 0, left: 0 }; 32 | const offsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, getReferenceNode(reference)); 33 | 34 | // Handle viewport case 35 | if (boundariesElement === 'viewport' ) { 36 | boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent, fixedPosition); 37 | } 38 | 39 | else { 40 | // Handle other cases based on DOM element used as boundaries 41 | let boundariesNode; 42 | if (boundariesElement === 'scrollParent') { 43 | boundariesNode = getScrollParent(getParentNode(reference)); 44 | if (boundariesNode.nodeName === 'BODY') { 45 | boundariesNode = popper.ownerDocument.documentElement; 46 | } 47 | } else if (boundariesElement === 'window') { 48 | boundariesNode = popper.ownerDocument.documentElement; 49 | } else { 50 | boundariesNode = boundariesElement; 51 | } 52 | 53 | const offsets = getOffsetRectRelativeToArbitraryNode( 54 | boundariesNode, 55 | offsetParent, 56 | fixedPosition 57 | ); 58 | 59 | // In case of HTML, we need a different computation 60 | if (boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) { 61 | const { height, width } = getWindowSizes(popper.ownerDocument); 62 | boundaries.top += offsets.top - offsets.marginTop; 63 | boundaries.bottom = height + offsets.top; 64 | boundaries.left += offsets.left - offsets.marginLeft; 65 | boundaries.right = width + offsets.left; 66 | } else { 67 | // for all the other DOM elements, this one is good 68 | boundaries = offsets; 69 | } 70 | } 71 | 72 | // Add paddings 73 | padding = padding || 0; 74 | const isPaddingNumber = typeof padding === 'number'; 75 | boundaries.left += isPaddingNumber ? padding : padding.left || 0; 76 | boundaries.top += isPaddingNumber ? padding : padding.top || 0; 77 | boundaries.right -= isPaddingNumber ? padding : padding.right || 0; 78 | boundaries.bottom -= isPaddingNumber ? padding : padding.bottom || 0; 79 | 80 | return boundaries; 81 | } 82 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/getBoundingClientRect.js: -------------------------------------------------------------------------------- 1 | import getStyleComputedProperty from './getStyleComputedProperty'; 2 | import getBordersSize from './getBordersSize'; 3 | import getWindowSizes from './getWindowSizes'; 4 | import getScroll from './getScroll'; 5 | import getClientRect from './getClientRect'; 6 | import isIE from './isIE'; 7 | 8 | /** 9 | * Get bounding client rect of given element 10 | * @method 11 | * @memberof Popper.Utils 12 | * @param {HTMLElement} element 13 | * @return {Object} client rect 14 | */ 15 | export default function getBoundingClientRect(element) { 16 | let rect = {}; 17 | 18 | // IE10 10 FIX: Please, don't ask, the element isn't 19 | // considered in DOM in some circumstances... 20 | // This isn't reproducible in IE10 compatibility mode of IE11 21 | try { 22 | if (isIE(10)) { 23 | rect = element.getBoundingClientRect(); 24 | const scrollTop = getScroll(element, 'top'); 25 | const scrollLeft = getScroll(element, 'left'); 26 | rect.top += scrollTop; 27 | rect.left += scrollLeft; 28 | rect.bottom += scrollTop; 29 | rect.right += scrollLeft; 30 | } 31 | else { 32 | rect = element.getBoundingClientRect(); 33 | } 34 | } 35 | catch(e){} 36 | 37 | const result = { 38 | left: rect.left, 39 | top: rect.top, 40 | width: rect.right - rect.left, 41 | height: rect.bottom - rect.top, 42 | }; 43 | 44 | // subtract scrollbar size from sizes 45 | const sizes = element.nodeName === 'HTML' ? getWindowSizes(element.ownerDocument) : {}; 46 | const width = 47 | sizes.width || element.clientWidth || result.width; 48 | const height = 49 | sizes.height || element.clientHeight || result.height; 50 | 51 | let horizScrollbar = element.offsetWidth - width; 52 | let vertScrollbar = element.offsetHeight - height; 53 | 54 | // if an hypothetical scrollbar is detected, we must be sure it's not a `border` 55 | // we make this check conditional for performance reasons 56 | if (horizScrollbar || vertScrollbar) { 57 | const styles = getStyleComputedProperty(element); 58 | horizScrollbar -= getBordersSize(styles, 'x'); 59 | vertScrollbar -= getBordersSize(styles, 'y'); 60 | 61 | result.width -= horizScrollbar; 62 | result.height -= vertScrollbar; 63 | } 64 | 65 | return getClientRect(result); 66 | } 67 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/getClientRect.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Given element offsets, generate an output similar to getBoundingClientRect 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Object} offsets 6 | * @returns {Object} ClientRect like output 7 | */ 8 | export default function getClientRect(offsets) { 9 | return { 10 | ...offsets, 11 | right: offsets.left + offsets.width, 12 | bottom: offsets.top + offsets.height, 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/getFixedPositionOffsetParent.js: -------------------------------------------------------------------------------- 1 | import getStyleComputedProperty from './getStyleComputedProperty'; 2 | import isIE from './isIE'; 3 | /** 4 | * Finds the first parent of an element that has a transformed property defined 5 | * @method 6 | * @memberof Popper.Utils 7 | * @argument {Element} element 8 | * @returns {Element} first transformed parent or documentElement 9 | */ 10 | 11 | export default function getFixedPositionOffsetParent(element) { 12 | // This check is needed to avoid errors in case one of the elements isn't defined for any reason 13 | if (!element || !element.parentElement || isIE()) { 14 | return document.documentElement; 15 | } 16 | let el = element.parentElement; 17 | while (el && getStyleComputedProperty(el, 'transform') === 'none') { 18 | el = el.parentElement; 19 | } 20 | return el || document.documentElement; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/getOffsetParent.js: -------------------------------------------------------------------------------- 1 | import getStyleComputedProperty from './getStyleComputedProperty'; 2 | import isIE from './isIE'; 3 | /** 4 | * Returns the offset parent of the given element 5 | * @method 6 | * @memberof Popper.Utils 7 | * @argument {Element} element 8 | * @returns {Element} offset parent 9 | */ 10 | export default function getOffsetParent(element) { 11 | if (!element) { 12 | return document.documentElement; 13 | } 14 | 15 | const noOffsetParent = isIE(10) ? document.body : null; 16 | 17 | // NOTE: 1 DOM access here 18 | let offsetParent = element.offsetParent || null; 19 | // Skip hidden elements which don't have an offsetParent 20 | while (offsetParent === noOffsetParent && element.nextElementSibling) { 21 | offsetParent = (element = element.nextElementSibling).offsetParent; 22 | } 23 | 24 | const nodeName = offsetParent && offsetParent.nodeName; 25 | 26 | if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') { 27 | return element ? element.ownerDocument.documentElement : document.documentElement; 28 | } 29 | 30 | // .offsetParent will return the closest TH, TD or TABLE in case 31 | // no offsetParent is present, I hate this job... 32 | if ( 33 | ['TH', 'TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && 34 | getStyleComputedProperty(offsetParent, 'position') === 'static' 35 | ) { 36 | return getOffsetParent(offsetParent); 37 | } 38 | 39 | return offsetParent; 40 | } 41 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/getOffsetRect.js: -------------------------------------------------------------------------------- 1 | import getWindowSizes from './getWindowSizes'; 2 | import getClientRect from './getClientRect'; 3 | 4 | /** 5 | * Get the position of the given element, relative to its offset parent 6 | * @method 7 | * @memberof Popper.Utils 8 | * @param {Element} element 9 | * @return {Object} position - Coordinates of the element and its `scrollTop` 10 | */ 11 | export default function getOffsetRect(element) { 12 | let elementRect; 13 | if (element.nodeName === 'HTML') { 14 | const { width, height } = getWindowSizes(element.ownerDocument); 15 | elementRect = { 16 | width, 17 | height, 18 | left: 0, 19 | top: 0, 20 | }; 21 | } else { 22 | elementRect = { 23 | width: element.offsetWidth, 24 | height: element.offsetHeight, 25 | left: element.offsetLeft, 26 | top: element.offsetTop, 27 | }; 28 | } 29 | 30 | // position 31 | return getClientRect(elementRect); 32 | } 33 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/getOffsetRectRelativeToArbitraryNode.js: -------------------------------------------------------------------------------- 1 | import getStyleComputedProperty from './getStyleComputedProperty'; 2 | import includeScroll from './includeScroll'; 3 | import getScrollParent from './getScrollParent'; 4 | import getBoundingClientRect from './getBoundingClientRect'; 5 | import runIsIE from './isIE'; 6 | import getClientRect from './getClientRect'; 7 | 8 | export default function getOffsetRectRelativeToArbitraryNode(children, parent, fixedPosition = false) { 9 | const isIE10 = runIsIE(10); 10 | const isHTML = parent.nodeName === 'HTML'; 11 | const childrenRect = getBoundingClientRect(children); 12 | const parentRect = getBoundingClientRect(parent); 13 | const scrollParent = getScrollParent(children); 14 | 15 | const styles = getStyleComputedProperty(parent); 16 | const borderTopWidth = parseFloat(styles.borderTopWidth); 17 | const borderLeftWidth = parseFloat(styles.borderLeftWidth); 18 | 19 | // In cases where the parent is fixed, we must ignore negative scroll in offset calc 20 | if(fixedPosition && isHTML) { 21 | parentRect.top = Math.max(parentRect.top, 0); 22 | parentRect.left = Math.max(parentRect.left, 0); 23 | } 24 | let offsets = getClientRect({ 25 | top: childrenRect.top - parentRect.top - borderTopWidth, 26 | left: childrenRect.left - parentRect.left - borderLeftWidth, 27 | width: childrenRect.width, 28 | height: childrenRect.height, 29 | }); 30 | offsets.marginTop = 0; 31 | offsets.marginLeft = 0; 32 | 33 | // Subtract margins of documentElement in case it's being used as parent 34 | // we do this only on HTML because it's the only element that behaves 35 | // differently when margins are applied to it. The margins are included in 36 | // the box of the documentElement, in the other cases not. 37 | if (!isIE10 && isHTML) { 38 | const marginTop = parseFloat(styles.marginTop); 39 | const marginLeft = parseFloat(styles.marginLeft); 40 | 41 | offsets.top -= borderTopWidth - marginTop; 42 | offsets.bottom -= borderTopWidth - marginTop; 43 | offsets.left -= borderLeftWidth - marginLeft; 44 | offsets.right -= borderLeftWidth - marginLeft; 45 | 46 | // Attach marginTop and marginLeft because in some circumstances we may need them 47 | offsets.marginTop = marginTop; 48 | offsets.marginLeft = marginLeft; 49 | } 50 | 51 | if ( 52 | isIE10 && !fixedPosition 53 | ? parent.contains(scrollParent) 54 | : parent === scrollParent && scrollParent.nodeName !== 'BODY' 55 | ) { 56 | offsets = includeScroll(offsets, parent); 57 | } 58 | 59 | return offsets; 60 | } 61 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/getOppositePlacement.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Get the opposite placement of the given one 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {String} placement 6 | * @returns {String} flipped placement 7 | */ 8 | export default function getOppositePlacement(placement) { 9 | const hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' }; 10 | return placement.replace(/left|right|bottom|top/g, matched => hash[matched]); 11 | } 12 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/getOppositeVariation.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Get the opposite placement variation of the given one 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {String} placement variation 6 | * @returns {String} flipped placement variation 7 | */ 8 | export default function getOppositeVariation(variation) { 9 | if (variation === 'end') { 10 | return 'start'; 11 | } else if (variation === 'start') { 12 | return 'end'; 13 | } 14 | return variation; 15 | } 16 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/getOuterSizes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Get the outer sizes of the given element (offset size + margins) 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Element} element 6 | * @returns {Object} object containing width and height properties 7 | */ 8 | export default function getOuterSizes(element) { 9 | const window = element.ownerDocument.defaultView; 10 | const styles = window.getComputedStyle(element); 11 | const x = parseFloat(styles.marginTop || 0) + parseFloat(styles.marginBottom || 0); 12 | const y = parseFloat(styles.marginLeft || 0) + parseFloat(styles.marginRight || 0); 13 | const result = { 14 | width: element.offsetWidth + y, 15 | height: element.offsetHeight + x, 16 | }; 17 | return result; 18 | } 19 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/getParentNode.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns the parentNode or the host of the element 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Element} element 6 | * @returns {Element} parent 7 | */ 8 | export default function getParentNode(element) { 9 | if (element.nodeName === 'HTML') { 10 | return element; 11 | } 12 | return element.parentNode || element.host; 13 | } 14 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/getPopperOffsets.js: -------------------------------------------------------------------------------- 1 | import getOuterSizes from './getOuterSizes'; 2 | import getOppositePlacement from './getOppositePlacement'; 3 | 4 | /** 5 | * Get offsets to the popper 6 | * @method 7 | * @memberof Popper.Utils 8 | * @param {Object} position - CSS position the Popper will get applied 9 | * @param {HTMLElement} popper - the popper element 10 | * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this) 11 | * @param {String} placement - one of the valid placement options 12 | * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper 13 | */ 14 | export default function getPopperOffsets(popper, referenceOffsets, placement) { 15 | placement = placement.split('-')[0]; 16 | 17 | // Get popper node sizes 18 | const popperRect = getOuterSizes(popper); 19 | 20 | // Add position, width and height to our offsets object 21 | const popperOffsets = { 22 | width: popperRect.width, 23 | height: popperRect.height, 24 | }; 25 | 26 | // depending by the popper placement we have to compute its offsets slightly differently 27 | const isHoriz = ['right', 'left'].indexOf(placement) !== -1; 28 | const mainSide = isHoriz ? 'top' : 'left'; 29 | const secondarySide = isHoriz ? 'left' : 'top'; 30 | const measurement = isHoriz ? 'height' : 'width'; 31 | const secondaryMeasurement = !isHoriz ? 'height' : 'width'; 32 | 33 | popperOffsets[mainSide] = 34 | referenceOffsets[mainSide] + 35 | referenceOffsets[measurement] / 2 - 36 | popperRect[measurement] / 2; 37 | if (placement === secondarySide) { 38 | popperOffsets[secondarySide] = 39 | referenceOffsets[secondarySide] - popperRect[secondaryMeasurement]; 40 | } else { 41 | popperOffsets[secondarySide] = 42 | referenceOffsets[getOppositePlacement(secondarySide)]; 43 | } 44 | 45 | return popperOffsets; 46 | } 47 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/getReferenceNode.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns the reference node of the reference object, or the reference object itself. 3 | * @method 4 | * @memberof Popper.Utils 5 | * @param {Element|Object} reference - the reference element (the popper will be relative to this) 6 | * @returns {Element} parent 7 | */ 8 | export default function getReferenceNode(reference) { 9 | return reference && reference.referenceNode ? reference.referenceNode : reference; 10 | } 11 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/getReferenceOffsets.js: -------------------------------------------------------------------------------- 1 | import findCommonOffsetParent from './findCommonOffsetParent'; 2 | import getOffsetRectRelativeToArbitraryNode from './getOffsetRectRelativeToArbitraryNode'; 3 | import getFixedPositionOffsetParent from './getFixedPositionOffsetParent'; 4 | import getReferenceNode from './getReferenceNode'; 5 | 6 | /** 7 | * Get offsets to the reference element 8 | * @method 9 | * @memberof Popper.Utils 10 | * @param {Object} state 11 | * @param {Element} popper - the popper element 12 | * @param {Element} reference - the reference element (the popper will be relative to this) 13 | * @param {Element} fixedPosition - is in fixed position mode 14 | * @returns {Object} An object containing the offsets which will be applied to the popper 15 | */ 16 | export default function getReferenceOffsets(state, popper, reference, fixedPosition = null) { 17 | const commonOffsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, getReferenceNode(reference)); 18 | return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent, fixedPosition); 19 | } 20 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/getRoot.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Finds the root node (document, shadowDOM root) of the given element 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Element} node 6 | * @returns {Element} root node 7 | */ 8 | export default function getRoot(node) { 9 | if (node.parentNode !== null) { 10 | return getRoot(node.parentNode); 11 | } 12 | 13 | return node; 14 | } 15 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/getRoundedOffsets.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @function 3 | * @memberof Popper.Utils 4 | * @argument {Object} data - The data object generated by `update` method 5 | * @argument {Boolean} shouldRound - If the offsets should be rounded at all 6 | * @returns {Object} The popper's position offsets rounded 7 | * 8 | * The tale of pixel-perfect positioning. It's still not 100% perfect, but as 9 | * good as it can be within reason. 10 | * Discussion here: https://github.com/FezVrasta/popper.js/pull/715 11 | * 12 | * Low DPI screens cause a popper to be blurry if not using full pixels (Safari 13 | * as well on High DPI screens). 14 | * 15 | * Firefox prefers no rounding for positioning and does not have blurriness on 16 | * high DPI screens. 17 | * 18 | * Only horizontal placement and left/right values need to be considered. 19 | */ 20 | export default function getRoundedOffsets(data, shouldRound) { 21 | const { popper, reference } = data.offsets; 22 | const { round, floor } = Math; 23 | const noRound = v => v; 24 | 25 | const referenceWidth = round(reference.width); 26 | const popperWidth = round(popper.width); 27 | 28 | const isVertical = ['left', 'right'].indexOf(data.placement) !== -1; 29 | const isVariation = data.placement.indexOf('-') !== -1; 30 | const sameWidthParity = referenceWidth % 2 === popperWidth % 2; 31 | const bothOddWidth = referenceWidth % 2 === 1 && popperWidth % 2 === 1; 32 | 33 | const horizontalToInteger = !shouldRound 34 | ? noRound 35 | : isVertical || isVariation || sameWidthParity 36 | ? round 37 | : floor; 38 | const verticalToInteger = !shouldRound ? noRound : round; 39 | 40 | return { 41 | left: horizontalToInteger( 42 | bothOddWidth && !isVariation && shouldRound 43 | ? popper.left - 1 44 | : popper.left 45 | ), 46 | top: verticalToInteger(popper.top), 47 | bottom: verticalToInteger(popper.bottom), 48 | right: horizontalToInteger(popper.right), 49 | }; 50 | } 51 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/getScroll.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Gets the scroll value of the given element in the given side (top and left) 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Element} element 6 | * @argument {String} side `top` or `left` 7 | * @returns {number} amount of scrolled pixels 8 | */ 9 | export default function getScroll(element, side = 'top') { 10 | const upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft'; 11 | const nodeName = element.nodeName; 12 | 13 | if (nodeName === 'BODY' || nodeName === 'HTML') { 14 | const html = element.ownerDocument.documentElement; 15 | const scrollingElement = element.ownerDocument.scrollingElement || html; 16 | return scrollingElement[upperSide]; 17 | } 18 | 19 | return element[upperSide]; 20 | } 21 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/getScrollParent.js: -------------------------------------------------------------------------------- 1 | import getStyleComputedProperty from './getStyleComputedProperty'; 2 | import getParentNode from './getParentNode'; 3 | 4 | /** 5 | * Returns the scrolling parent of the given element 6 | * @method 7 | * @memberof Popper.Utils 8 | * @argument {Element} element 9 | * @returns {Element} scroll parent 10 | */ 11 | export default function getScrollParent(element) { 12 | // Return body, `getScroll` will take care to get the correct `scrollTop` from it 13 | if (!element) { 14 | return document.body 15 | } 16 | 17 | switch (element.nodeName) { 18 | case 'HTML': 19 | case 'BODY': 20 | return element.ownerDocument.body 21 | case '#document': 22 | return element.body 23 | } 24 | 25 | // Firefox want us to check `-x` and `-y` variations as well 26 | const { overflow, overflowX, overflowY } = getStyleComputedProperty(element); 27 | if (/(auto|scroll|overlay)/.test(overflow + overflowY + overflowX)) { 28 | return element; 29 | } 30 | 31 | return getScrollParent(getParentNode(element)); 32 | } 33 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/getStyleComputedProperty.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Get CSS computed property of the given element 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Eement} element 6 | * @argument {String} property 7 | */ 8 | export default function getStyleComputedProperty(element, property) { 9 | if (element.nodeType !== 1) { 10 | return []; 11 | } 12 | // NOTE: 1 DOM access here 13 | const window = element.ownerDocument.defaultView; 14 | const css = window.getComputedStyle(element, null); 15 | return property ? css[property] : css; 16 | } 17 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/getSupportedPropertyName.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Get the prefixed supported property name 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {String} property (camelCase) 6 | * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix) 7 | */ 8 | export default function getSupportedPropertyName(property) { 9 | const prefixes = [false, 'ms', 'Webkit', 'Moz', 'O']; 10 | const upperProp = property.charAt(0).toUpperCase() + property.slice(1); 11 | 12 | for (let i = 0; i < prefixes.length; i++) { 13 | const prefix = prefixes[i]; 14 | const toCheck = prefix ? `${prefix}${upperProp}` : property; 15 | if (typeof document.body.style[toCheck] !== 'undefined') { 16 | return toCheck; 17 | } 18 | } 19 | return null; 20 | } 21 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/getViewportOffsetRectRelativeToArtbitraryNode.js: -------------------------------------------------------------------------------- 1 | import getOffsetRectRelativeToArbitraryNode from './getOffsetRectRelativeToArbitraryNode'; 2 | import getScroll from './getScroll'; 3 | import getClientRect from './getClientRect'; 4 | 5 | export default function getViewportOffsetRectRelativeToArtbitraryNode(element, excludeScroll = false) { 6 | const html = element.ownerDocument.documentElement; 7 | const relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html); 8 | const width = Math.max(html.clientWidth, window.innerWidth || 0); 9 | const height = Math.max(html.clientHeight, window.innerHeight || 0); 10 | 11 | const scrollTop = !excludeScroll ? getScroll(html) : 0; 12 | const scrollLeft = !excludeScroll ? getScroll(html, 'left') : 0; 13 | 14 | const offset = { 15 | top: scrollTop - relativeOffset.top + relativeOffset.marginTop, 16 | left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft, 17 | width, 18 | height, 19 | }; 20 | 21 | return getClientRect(offset); 22 | } 23 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/getWindow.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Get the window associated with the element 3 | * @argument {Element} element 4 | * @returns {Window} 5 | */ 6 | export default function getWindow(element) { 7 | const ownerDocument = element.ownerDocument; 8 | return ownerDocument ? ownerDocument.defaultView : window; 9 | } 10 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/getWindowSizes.js: -------------------------------------------------------------------------------- 1 | import isIE from './isIE'; 2 | 3 | function getSize(axis, body, html, computedStyle) { 4 | return Math.max( 5 | body[`offset${axis}`], 6 | body[`scroll${axis}`], 7 | html[`client${axis}`], 8 | html[`offset${axis}`], 9 | html[`scroll${axis}`], 10 | isIE(10) 11 | ? (parseInt(html[`offset${axis}`]) + 12 | parseInt(computedStyle[`margin${axis === 'Height' ? 'Top' : 'Left'}`]) + 13 | parseInt(computedStyle[`margin${axis === 'Height' ? 'Bottom' : 'Right'}`])) 14 | : 0 15 | ); 16 | } 17 | 18 | export default function getWindowSizes(document) { 19 | const body = document.body; 20 | const html = document.documentElement; 21 | const computedStyle = isIE(10) && getComputedStyle(html); 22 | 23 | return { 24 | height: getSize('Height', body, html, computedStyle), 25 | width: getSize('Width', body, html, computedStyle), 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/includeScroll.js: -------------------------------------------------------------------------------- 1 | import getScroll from './getScroll'; 2 | 3 | /* 4 | * Sum or subtract the element scroll values (left and top) from a given rect object 5 | * @method 6 | * @memberof Popper.Utils 7 | * @param {Object} rect - Rect object you want to change 8 | * @param {HTMLElement} element - The element from the function reads the scroll values 9 | * @param {Boolean} subtract - set to true if you want to subtract the scroll values 10 | * @return {Object} rect - The modifier rect object 11 | */ 12 | export default function includeScroll(rect, element, subtract = false) { 13 | const scrollTop = getScroll(element, 'top'); 14 | const scrollLeft = getScroll(element, 'left'); 15 | const modifier = subtract ? -1 : 1; 16 | rect.top += scrollTop * modifier; 17 | rect.bottom += scrollTop * modifier; 18 | rect.left += scrollLeft * modifier; 19 | rect.right += scrollLeft * modifier; 20 | return rect; 21 | } 22 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/index.js: -------------------------------------------------------------------------------- 1 | import computeAutoPlacement from './computeAutoPlacement'; 2 | import debounce from './debounce'; 3 | import findIndex from './findIndex'; 4 | import getBordersSize from './getBordersSize'; 5 | import getBoundaries from './getBoundaries'; 6 | import getBoundingClientRect from './getBoundingClientRect'; 7 | import getClientRect from './getClientRect'; 8 | import getOffsetParent from './getOffsetParent'; 9 | import getOffsetRect from './getOffsetRect'; 10 | import getOffsetRectRelativeToArbitraryNode from './getOffsetRectRelativeToArbitraryNode'; 11 | import getOuterSizes from './getOuterSizes'; 12 | import getParentNode from './getParentNode'; 13 | import getPopperOffsets from './getPopperOffsets'; 14 | import getReferenceOffsets from './getReferenceOffsets'; 15 | import getScroll from './getScroll'; 16 | import getScrollParent from './getScrollParent'; 17 | import getStyleComputedProperty from './getStyleComputedProperty'; 18 | import getSupportedPropertyName from './getSupportedPropertyName'; 19 | import getWindowSizes from './getWindowSizes'; 20 | import isFixed from './isFixed'; 21 | import isFunction from './isFunction'; 22 | import isModifierEnabled from './isModifierEnabled'; 23 | import isModifierRequired from './isModifierRequired'; 24 | import isNumeric from './isNumeric'; 25 | import removeEventListeners from './removeEventListeners'; 26 | import runModifiers from './runModifiers'; 27 | import setAttributes from './setAttributes'; 28 | import setStyles from './setStyles'; 29 | import setupEventListeners from './setupEventListeners'; 30 | 31 | /** @namespace Popper.Utils */ 32 | export { 33 | computeAutoPlacement, 34 | debounce, 35 | findIndex, 36 | getBordersSize, 37 | getBoundaries, 38 | getBoundingClientRect, 39 | getClientRect, 40 | getOffsetParent, 41 | getOffsetRect, 42 | getOffsetRectRelativeToArbitraryNode, 43 | getOuterSizes, 44 | getParentNode, 45 | getPopperOffsets, 46 | getReferenceOffsets, 47 | getScroll, 48 | getScrollParent, 49 | getStyleComputedProperty, 50 | getSupportedPropertyName, 51 | getWindowSizes, 52 | isFixed, 53 | isFunction, 54 | isModifierEnabled, 55 | isModifierRequired, 56 | isNumeric, 57 | removeEventListeners, 58 | runModifiers, 59 | setAttributes, 60 | setStyles, 61 | setupEventListeners, 62 | }; 63 | 64 | // This is here just for backward compatibility with versions lower than v1.10.3 65 | // you should import the utilities using named exports, if you want them all use: 66 | // ``` 67 | // import * as PopperUtils from 'popper-utils'; 68 | // ``` 69 | // The default export will be removed in the next major version. 70 | export default { 71 | computeAutoPlacement, 72 | debounce, 73 | findIndex, 74 | getBordersSize, 75 | getBoundaries, 76 | getBoundingClientRect, 77 | getClientRect, 78 | getOffsetParent, 79 | getOffsetRect, 80 | getOffsetRectRelativeToArbitraryNode, 81 | getOuterSizes, 82 | getParentNode, 83 | getPopperOffsets, 84 | getReferenceOffsets, 85 | getScroll, 86 | getScrollParent, 87 | getStyleComputedProperty, 88 | getSupportedPropertyName, 89 | getWindowSizes, 90 | isFixed, 91 | isFunction, 92 | isModifierEnabled, 93 | isModifierRequired, 94 | isNumeric, 95 | removeEventListeners, 96 | runModifiers, 97 | setAttributes, 98 | setStyles, 99 | setupEventListeners, 100 | }; 101 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/isBrowser.js: -------------------------------------------------------------------------------- 1 | export default typeof window !== 'undefined' && typeof document !== 'undefined' && typeof navigator !== 'undefined'; 2 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/isFixed.js: -------------------------------------------------------------------------------- 1 | import getStyleComputedProperty from './getStyleComputedProperty'; 2 | import getParentNode from './getParentNode'; 3 | 4 | /** 5 | * Check if the given element is fixed or is inside a fixed parent 6 | * @method 7 | * @memberof Popper.Utils 8 | * @argument {Element} element 9 | * @argument {Element} customContainer 10 | * @returns {Boolean} answer to "isFixed?" 11 | */ 12 | export default function isFixed(element) { 13 | const nodeName = element.nodeName; 14 | if (nodeName === 'BODY' || nodeName === 'HTML') { 15 | return false; 16 | } 17 | if (getStyleComputedProperty(element, 'position') === 'fixed') { 18 | return true; 19 | } 20 | const parentNode = getParentNode(element); 21 | if (!parentNode) { 22 | return false; 23 | } 24 | return isFixed(parentNode); 25 | } 26 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/isFunction.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Check if the given variable is a function 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Any} functionToCheck - variable to check 6 | * @returns {Boolean} answer to: is a function? 7 | */ 8 | export default function isFunction(functionToCheck) { 9 | const getType = {}; 10 | return ( 11 | functionToCheck && 12 | getType.toString.call(functionToCheck) === '[object Function]' 13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/isIE.js: -------------------------------------------------------------------------------- 1 | import isBrowser from './isBrowser'; 2 | 3 | const isIE11 = isBrowser && !!(window.MSInputMethodContext && document.documentMode); 4 | const isIE10 = isBrowser && /MSIE 10/.test(navigator.userAgent); 5 | 6 | /** 7 | * Determines if the browser is Internet Explorer 8 | * @method 9 | * @memberof Popper.Utils 10 | * @param {Number} version to check 11 | * @returns {Boolean} isIE 12 | */ 13 | export default function isIE(version) { 14 | if (version === 11) { 15 | return isIE11; 16 | } 17 | if (version === 10) { 18 | return isIE10; 19 | } 20 | return isIE11 || isIE10; 21 | } 22 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/isModifierEnabled.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Helper used to know if the given modifier is enabled. 3 | * @method 4 | * @memberof Popper.Utils 5 | * @returns {Boolean} 6 | */ 7 | export default function isModifierEnabled(modifiers, modifierName) { 8 | return modifiers.some( 9 | ({ name, enabled }) => enabled && name === modifierName 10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/isModifierRequired.js: -------------------------------------------------------------------------------- 1 | import find from './find'; 2 | 3 | /** 4 | * Helper used to know if the given modifier depends from another one.
    5 | * It checks if the needed modifier is listed and enabled. 6 | * @method 7 | * @memberof Popper.Utils 8 | * @param {Array} modifiers - list of modifiers 9 | * @param {String} requestingName - name of requesting modifier 10 | * @param {String} requestedName - name of requested modifier 11 | * @returns {Boolean} 12 | */ 13 | export default function isModifierRequired( 14 | modifiers, 15 | requestingName, 16 | requestedName 17 | ) { 18 | const requesting = find(modifiers, ({ name }) => name === requestingName); 19 | 20 | const isRequired = 21 | !!requesting && 22 | modifiers.some(modifier => { 23 | return ( 24 | modifier.name === requestedName && 25 | modifier.enabled && 26 | modifier.order < requesting.order 27 | ); 28 | }); 29 | 30 | if (!isRequired) { 31 | const requesting = `\`${requestingName}\``; 32 | const requested = `\`${requestedName}\``; 33 | console.warn( 34 | `${requested} modifier is required by ${requesting} modifier in order to work, be sure to include it before ${requesting}!` 35 | ); 36 | } 37 | return isRequired; 38 | } 39 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/isNumeric.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Tells if a given input is a number 3 | * @method 4 | * @memberof Popper.Utils 5 | * @param {*} input to check 6 | * @return {Boolean} 7 | */ 8 | export default function isNumeric(n) { 9 | return n !== '' && !isNaN(parseFloat(n)) && isFinite(n); 10 | } 11 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/isOffsetContainer.js: -------------------------------------------------------------------------------- 1 | import getOffsetParent from './getOffsetParent'; 2 | 3 | export default function isOffsetContainer(element) { 4 | const { nodeName } = element; 5 | if (nodeName === 'BODY') { 6 | return false; 7 | } 8 | return ( 9 | nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element 10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/removeEventListeners.js: -------------------------------------------------------------------------------- 1 | import getWindow from './getWindow'; 2 | 3 | /** 4 | * Remove event listeners used to update the popper position 5 | * @method 6 | * @memberof Popper.Utils 7 | * @private 8 | */ 9 | export default function removeEventListeners(reference, state) { 10 | // Remove resize event listener on window 11 | getWindow(reference).removeEventListener('resize', state.updateBound); 12 | 13 | // Remove scroll event listener on scroll parents 14 | state.scrollParents.forEach(target => { 15 | target.removeEventListener('scroll', state.updateBound); 16 | }); 17 | 18 | // Reset state 19 | state.updateBound = null; 20 | state.scrollParents = []; 21 | state.scrollElement = null; 22 | state.eventsEnabled = false; 23 | return state; 24 | } 25 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/runModifiers.js: -------------------------------------------------------------------------------- 1 | import isFunction from './isFunction'; 2 | import findIndex from './findIndex'; 3 | import getClientRect from '../utils/getClientRect'; 4 | 5 | /** 6 | * Loop trough the list of modifiers and run them in order, 7 | * each of them will then edit the data object. 8 | * @method 9 | * @memberof Popper.Utils 10 | * @param {dataObject} data 11 | * @param {Array} modifiers 12 | * @param {String} ends - Optional modifier name used as stopper 13 | * @returns {dataObject} 14 | */ 15 | export default function runModifiers(modifiers, data, ends) { 16 | const modifiersToRun = ends === undefined 17 | ? modifiers 18 | : modifiers.slice(0, findIndex(modifiers, 'name', ends)); 19 | 20 | modifiersToRun.forEach(modifier => { 21 | if (modifier['function']) { // eslint-disable-line dot-notation 22 | console.warn('`modifier.function` is deprecated, use `modifier.fn`!'); 23 | } 24 | const fn = modifier['function'] || modifier.fn; // eslint-disable-line dot-notation 25 | if (modifier.enabled && isFunction(fn)) { 26 | // Add properties to offsets to make them a complete clientRect object 27 | // we do this before each modifier to make sure the previous one doesn't 28 | // mess with these values 29 | data.offsets.popper = getClientRect(data.offsets.popper); 30 | data.offsets.reference = getClientRect(data.offsets.reference); 31 | 32 | data = fn(data, modifier); 33 | } 34 | }); 35 | 36 | return data; 37 | } 38 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/setAttributes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Set the attributes to the given popper 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Element} element - Element to apply the attributes to 6 | * @argument {Object} styles 7 | * Object with a list of properties and values which will be applied to the element 8 | */ 9 | export default function setAttributes(element, attributes) { 10 | Object.keys(attributes).forEach(function(prop) { 11 | const value = attributes[prop]; 12 | if (value !== false) { 13 | element.setAttribute(prop, attributes[prop]); 14 | } else { 15 | element.removeAttribute(prop); 16 | } 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/setStyles.js: -------------------------------------------------------------------------------- 1 | import isNumeric from './isNumeric'; 2 | 3 | /** 4 | * Set the style to the given popper 5 | * @method 6 | * @memberof Popper.Utils 7 | * @argument {Element} element - Element to apply the style to 8 | * @argument {Object} styles 9 | * Object with a list of properties and values which will be applied to the element 10 | */ 11 | export default function setStyles(element, styles) { 12 | Object.keys(styles).forEach(prop => { 13 | let unit = ''; 14 | // add unit if the value is numeric and is one of the following 15 | if ( 16 | ['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== 17 | -1 && 18 | isNumeric(styles[prop]) 19 | ) { 20 | unit = 'px'; 21 | } 22 | element.style[prop] = styles[prop] + unit; 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /Books/Scripts/src/utils/setupEventListeners.js: -------------------------------------------------------------------------------- 1 | import getScrollParent from './getScrollParent'; 2 | import getWindow from './getWindow'; 3 | 4 | function attachToScrollParents(scrollParent, event, callback, scrollParents) { 5 | const isBody = scrollParent.nodeName === 'BODY'; 6 | const target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent; 7 | target.addEventListener(event, callback, { passive: true }); 8 | 9 | if (!isBody) { 10 | attachToScrollParents( 11 | getScrollParent(target.parentNode), 12 | event, 13 | callback, 14 | scrollParents 15 | ); 16 | } 17 | scrollParents.push(target); 18 | } 19 | 20 | /** 21 | * Setup needed event listeners used to update the popper position 22 | * @method 23 | * @memberof Popper.Utils 24 | * @private 25 | */ 26 | export default function setupEventListeners( 27 | reference, 28 | options, 29 | state, 30 | updateBound 31 | ) { 32 | // Resize event listener on window 33 | state.updateBound = updateBound; 34 | getWindow(reference).addEventListener('resize', state.updateBound, { passive: true }); 35 | 36 | // Scroll event listener on scroll parents 37 | const scrollElement = getScrollParent(reference); 38 | attachToScrollParents( 39 | scrollElement, 40 | 'scroll', 41 | state.updateBound, 42 | state.scrollParents 43 | ); 44 | state.scrollElement = scrollElement; 45 | state.eventsEnabled = true; 46 | 47 | return state; 48 | } 49 | -------------------------------------------------------------------------------- /Books/Scripts/toastr.min.js: -------------------------------------------------------------------------------- 1 | !function(e){e(["jquery"],function(e){return function(){function t(e,t,n){return f({type:O.error,iconClass:g().iconClasses.error,message:e,optionsOverride:n,title:t})}function n(t,n){return t||(t=g()),v=e("#"+t.containerId),v.length?v:(n&&(v=c(t)),v)}function i(e,t,n){return f({type:O.info,iconClass:g().iconClasses.info,message:e,optionsOverride:n,title:t})}function o(e){w=e}function s(e,t,n){return f({type:O.success,iconClass:g().iconClasses.success,message:e,optionsOverride:n,title:t})}function a(e,t,n){return f({type:O.warning,iconClass:g().iconClasses.warning,message:e,optionsOverride:n,title:t})}function r(e){var t=g();v||n(t),l(e,t)||u(t)}function d(t){var i=g();return v||n(i),t&&0===e(":focus",t).length?void h(t):void(v.children().length&&v.remove())}function u(t){for(var n=v.children(),i=n.length-1;i>=0;i--)l(e(n[i]),t)}function l(t,n){return t&&0===e(":focus",t).length?(t[n.hideMethod]({duration:n.hideDuration,easing:n.hideEasing,complete:function(){h(t)}}),!0):!1}function c(t){return v=e("
    ").attr("id",t.containerId).addClass(t.positionClass).attr("aria-live","polite").attr("role","alert"),v.appendTo(e(t.target)),v}function p(){return{tapToDismiss:!0,toastClass:"toast",containerId:"toast-container",debug:!1,showMethod:"fadeIn",showDuration:300,showEasing:"swing",onShown:void 0,hideMethod:"fadeOut",hideDuration:1e3,hideEasing:"swing",onHidden:void 0,extendedTimeOut:1e3,iconClasses:{error:"toast-error",info:"toast-info",success:"toast-success",warning:"toast-warning"},iconClass:"toast-info",positionClass:"toast-top-right",timeOut:5e3,titleClass:"toast-title",messageClass:"toast-message",target:"body",closeHtml:'',newestOnTop:!0,preventDuplicates:!1,progressBar:!1}}function m(e){w&&w(e)}function f(t){function i(t){return!e(":focus",l).length||t?(clearTimeout(O.intervalId),l[r.hideMethod]({duration:r.hideDuration,easing:r.hideEasing,complete:function(){h(l),r.onHidden&&"hidden"!==b.state&&r.onHidden(),b.state="hidden",b.endTime=new Date,m(b)}})):void 0}function o(){(r.timeOut>0||r.extendedTimeOut>0)&&(u=setTimeout(i,r.extendedTimeOut),O.maxHideTime=parseFloat(r.extendedTimeOut),O.hideEta=(new Date).getTime()+O.maxHideTime)}function s(){clearTimeout(u),O.hideEta=0,l.stop(!0,!0)[r.showMethod]({duration:r.showDuration,easing:r.showEasing})}function a(){var e=(O.hideEta-(new Date).getTime())/O.maxHideTime*100;f.width(e+"%")}var r=g(),d=t.iconClass||r.iconClass;if("undefined"!=typeof t.optionsOverride&&(r=e.extend(r,t.optionsOverride),d=t.optionsOverride.iconClass||d),r.preventDuplicates){if(t.message===C)return;C=t.message}T++,v=n(r,!0);var u=null,l=e("
    "),c=e("
    "),p=e("
    "),f=e("
    "),w=e(r.closeHtml),O={intervalId:null,hideEta:null,maxHideTime:null},b={toastId:T,state:"visible",startTime:new Date,options:r,map:t};return t.iconClass&&l.addClass(r.toastClass).addClass(d),t.title&&(c.append(t.title).addClass(r.titleClass),l.append(c)),t.message&&(p.append(t.message).addClass(r.messageClass),l.append(p)),r.closeButton&&(w.addClass("toast-close-button").attr("role","button"),l.prepend(w)),r.progressBar&&(f.addClass("toast-progress"),l.prepend(f)),l.hide(),r.newestOnTop?v.prepend(l):v.append(l),l[r.showMethod]({duration:r.showDuration,easing:r.showEasing,complete:r.onShown}),r.timeOut>0&&(u=setTimeout(i,r.timeOut),O.maxHideTime=parseFloat(r.timeOut),O.hideEta=(new Date).getTime()+O.maxHideTime,r.progressBar&&(O.intervalId=setInterval(a,10))),l.hover(s,o),!r.onclick&&r.tapToDismiss&&l.click(i),r.closeButton&&w&&w.click(function(e){e.stopPropagation?e.stopPropagation():void 0!==e.cancelBubble&&e.cancelBubble!==!0&&(e.cancelBubble=!0),i(!0)}),r.onclick&&l.click(function(){r.onclick(),i()}),m(b),r.debug&&console&&console.log(b),l}function g(){return e.extend({},p(),b.options)}function h(e){v||(v=n()),e.is(":visible")||(e.remove(),e=null,0===v.children().length&&(v.remove(),C=void 0))}var v,w,C,T=0,O={error:"error",info:"info",success:"success",warning:"warning"},b={clear:r,remove:d,error:t,getContainer:n,info:i,options:{},subscribe:o,success:s,version:"2.1.0",warning:a};return b}()})}("function"==typeof define&&define.amd?define:function(e,t){"undefined"!=typeof module&&module.exports?module.exports=t(require("jquery")):window.toastr=t(window.jQuery)}); 2 | //# sourceMappingURL=toastr.js.map 3 | -------------------------------------------------------------------------------- /Books/Scripts/umd/popper.js.flow: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export type Position = 'top' | 'right' | 'bottom' | 'left'; 4 | 5 | export type Placement = 6 | | 'auto-start' 7 | | 'auto' 8 | | 'auto-end' 9 | | 'top-start' 10 | | 'top' 11 | | 'top-end' 12 | | 'right-start' 13 | | 'right' 14 | | 'right-end' 15 | | 'bottom-end' 16 | | 'bottom' 17 | | 'bottom-start' 18 | | 'left-end' 19 | | 'left' 20 | | 'left-start'; 21 | 22 | export type Offset = { 23 | top: number, 24 | left: number, 25 | width: number, 26 | height: number, 27 | position: Position, 28 | }; 29 | 30 | export type Boundary = 'scrollParent' | 'viewport' | 'window'; 31 | 32 | export type Behavior = 'flip' | 'clockwise' | 'counterclockwise'; 33 | 34 | export type Data = { 35 | instance: Popper, 36 | placement: Placement, 37 | originalPlacement: Placement, 38 | flipped: boolean, 39 | hide: boolean, 40 | arrowElement: Element, 41 | styles: CSSStyleDeclaration, 42 | arrowStyles: CSSStyleDeclaration, 43 | boundaries: Object, 44 | offsets: { 45 | popper: Offset, 46 | reference: Offset, 47 | arrow: { 48 | top: number, 49 | left: number, 50 | }, 51 | }, 52 | }; 53 | 54 | export type ModifierFn = (data: Data, options: Object) => Data; 55 | 56 | export type Padding = { 57 | top?: number, 58 | bottom?: number, 59 | left?: number, 60 | right?: number, 61 | }; 62 | 63 | export type BaseModifier = { 64 | order?: number, 65 | enabled?: boolean, 66 | fn?: ModifierFn, 67 | }; 68 | 69 | export type Modifiers = { 70 | shift?: BaseModifier, 71 | offset?: BaseModifier & { 72 | offset?: number | string, 73 | }, 74 | preventOverflow?: BaseModifier & { 75 | priority?: Position[], 76 | padding?: number | Padding, 77 | boundariesElement?: Boundary | Element, 78 | escapeWithReference?: boolean, 79 | }, 80 | keepTogether?: BaseModifier, 81 | arrow?: BaseModifier & { 82 | element?: string | Element | null, 83 | }, 84 | flip?: BaseModifier & { 85 | behavior?: Behavior | Position[], 86 | padding?: number | Padding, 87 | boundariesElement?: Boundary | Element, 88 | flipVariations?: boolean, 89 | flipVariationsByContent?: boolean, 90 | }, 91 | inner?: BaseModifier, 92 | hide?: BaseModifier, 93 | applyStyle?: BaseModifier & { 94 | onLoad?: Function, 95 | gpuAcceleration?: boolean, 96 | }, 97 | computeStyle?: BaseModifier & { 98 | gpuAcceleration?: boolean, 99 | x?: 'bottom' | 'top', 100 | y?: 'left' | 'right', 101 | }, 102 | 103 | [name: string]: (BaseModifier & { [string]: * }) | null, 104 | }; 105 | 106 | export type Options = { 107 | placement?: Placement, 108 | positionFixed?: boolean, 109 | eventsEnabled?: boolean, 110 | modifiers?: Modifiers, 111 | removeOnDestroy?: boolean, 112 | 113 | onCreate?: (data: Data) => void, 114 | 115 | onUpdate?: (data: Data) => void, 116 | }; 117 | 118 | export type ReferenceObject = { 119 | +clientHeight: number, 120 | +clientWidth: number, 121 | +referenceNode?: Node, 122 | 123 | getBoundingClientRect(): 124 | | ClientRect 125 | | { 126 | width: number, 127 | height: number, 128 | top: number, 129 | right: number, 130 | bottom: number, 131 | left: number, 132 | }, 133 | }; 134 | 135 | export type Instance = { 136 | destroy: () => void, 137 | scheduleUpdate: () => void, 138 | update: () => void, 139 | enableEventListeners: () => void, 140 | disableEventListeners: () => void, 141 | }; 142 | 143 | declare class Popper { 144 | static placements: Placement; 145 | 146 | popper: Element; 147 | reference: Element | ReferenceObject; 148 | 149 | constructor( 150 | reference: Element | ReferenceObject, 151 | popper: Element, 152 | options?: Options 153 | ): Instance; 154 | } 155 | 156 | declare export default typeof Popper; 157 | -------------------------------------------------------------------------------- /Books/ViewModels/BookFormViewModel.cs: -------------------------------------------------------------------------------- 1 | using Books.Models; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | namespace Books.ViewModels 6 | { 7 | public class BookFormViewModel 8 | { 9 | public int Id { get; set; } 10 | 11 | [Required] 12 | [MaxLength(256)] 13 | public string Title { get; set; } 14 | 15 | [Required] 16 | [MaxLength(128)] 17 | public string Author { get; set; } 18 | 19 | [Required] 20 | [MaxLength(2000)] 21 | public string Description { get; set; } 22 | 23 | [Display(Name = "Category")] 24 | public byte CategoryId { get; set; } 25 | 26 | public IEnumerable Categories { get; set; } 27 | } 28 | } -------------------------------------------------------------------------------- /Books/Views/Books/BookForm.cshtml: -------------------------------------------------------------------------------- 1 | @model Books.ViewModels.BookFormViewModel 2 | 3 | @{ 4 | ViewBag.Title = "Create"; 5 | } 6 | 7 |

    8 | @(Model.Id == 0 ? "Add New Book" : "Edit Book") 9 |

    10 | 11 |
    12 | 13 | @using (Html.BeginForm("Save", "Books")) 14 | { 15 | @Html.AntiForgeryToken() 16 | 17 | @Html.HiddenFor(m => m.Id) 18 | 19 |
    20 | @Html.LabelFor(m => m.Title) 21 | @Html.TextBoxFor(m => m.Title, new { @class = "form-control" }) 22 | @Html.ValidationMessageFor(m => m.Title, null, new { @class = "text-danger" }) 23 |
    24 | 25 |
    26 | @Html.LabelFor(m => m.Author) 27 | @Html.TextBoxFor(m => m.Author, new { @class = "form-control" }) 28 | @Html.ValidationMessageFor(m => m.Author, null, new { @class = "text-danger" }) 29 |
    30 | 31 |
    32 | @Html.LabelFor(m => m.CategoryId) 33 | @Html.DropDownListFor(m => m.CategoryId, new SelectList(Model.Categories, "Id", "Name"), "", new { @class = "form-control" }) 34 | @Html.ValidationMessageFor(m => m.CategoryId, null, new { @class = "text-danger" }) 35 |
    36 | 37 |
    38 | @Html.LabelFor(m => m.Description) 39 | @Html.TextAreaFor(m => m.Description, new { @class = "form-control" }) 40 | @Html.ValidationMessageFor(m => m.Description, null, new { @class = "text-danger" }) 41 |
    42 | 43 | 44 | } 45 | 46 | @section Scripts 47 | { 48 | @Scripts.Render("~/bundles/jqueryval") 49 | } -------------------------------------------------------------------------------- /Books/Views/Books/Details.cshtml: -------------------------------------------------------------------------------- 1 | @model Books.Models.Book 2 | 3 | @{ 4 | ViewBag.Title = "Details"; 5 | } 6 | 7 |
      8 |
    • 9 | @Model.Title 10 | 11 | 12 | 13 |
    • 14 |
    • @Model.Author
    • 15 |
    • @Model.Category.Name
    • 16 |
    • @Model.Description
    • 17 |
    • @Model.AddedOn
    • 18 |
    19 | -------------------------------------------------------------------------------- /Books/Views/Books/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model IEnumerable 2 | 3 | @{ 4 | ViewBag.Title = "Index"; 5 | } 6 | 7 |

    Books

    8 | 9 |
    10 | 11 | 12 | 13 | Add New 14 | 15 | 16 | @TempData["Message"] 17 | 18 | 19 |
    20 | No books added yet! 21 |
    22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | @foreach (var book in Model) 36 | { 37 | 38 | 39 | 40 | 41 | 42 | 43 | 53 | 54 | } 55 | 56 |
    TitleAuthorCategoryDescriptionAdded OnAction
    @Html.ActionLink(book.Title, "Details", "Books", new { id = book.Id }, null)@book.Author@book.Category.Name@book.Description@book.AddedOn 44 | 45 | 46 | Edit 47 | 48 | 49 | 50 | Delete 51 | 52 |
    57 | 58 | @section Scripts 59 | { 60 | 117 | } -------------------------------------------------------------------------------- /Books/Views/Home/About.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "About"; 3 | } 4 |

    @ViewBag.Title.

    5 |

    @ViewBag.Message

    6 | 7 |

    Use this area to provide additional information.

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

    @ViewBag.Title.

    5 |

    @ViewBag.Message

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

    ASP.NET

    7 |

    ASP.NET is a free web framework for building great Web sites and Web applications using HTML, CSS and JavaScript.

    8 |

    Learn more »

    9 |
    10 | 11 |
    12 |
    13 |

    Getting started

    14 |

    15 | ASP.NET MVC gives you a powerful, patterns-based way to build dynamic websites that 16 | enables a clean separation of concerns and gives you full control over markup 17 | for enjoyable, agile development. 18 |

    19 |

    Learn more »

    20 |
    21 |
    22 |

    Get more libraries

    23 |

    NuGet is a free Visual Studio extension that makes it easy to add, remove, and update libraries and tools in Visual Studio projects.

    24 |

    Learn more »

    25 |
    26 |
    27 |

    Web Hosting

    28 |

    You can easily find a web hosting company that offers the right mix of features and price for your applications.

    29 |

    Learn more »

    30 |
    31 |
    -------------------------------------------------------------------------------- /Books/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Error 6 | 7 | 8 |
    9 |

    Error.

    10 |

    An error occurred while processing your request.

    11 |
    12 | 13 | 14 | -------------------------------------------------------------------------------- /Books/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | @ViewBag.Title - Books 7 | @Styles.Render("~/Content/css") 8 | @Scripts.Render("~/bundles/modernizr") 9 | 10 | 11 | 27 |
    28 | @RenderBody() 29 |
    30 |
    31 |

    © @DateTime.Now.Year - Books

    32 |
    33 |
    34 | 35 | @Scripts.Render("~/bundles/jquery") 36 | @Scripts.Render("~/bundles/bootstrap") 37 | @RenderSection("scripts", required: false) 38 | 39 | 40 | -------------------------------------------------------------------------------- /Books/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 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /Books/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "~/Views/Shared/_Layout.cshtml"; 3 | } 4 | -------------------------------------------------------------------------------- /Books/Web.Debug.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Books/Web.Release.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Books/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 | -------------------------------------------------------------------------------- /Books/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadelhelaly/Books_ASPNETMVC5/59f95a2116df2cf41647168f81e0d878a2093a50/Books/favicon.ico -------------------------------------------------------------------------------- /Books/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 | --------------------------------------------------------------------------------