| @ -0,0 +1 @@ | |||||
| mongodb/ | |||||
| @ -1,3 +1,3 @@ | |||||
| #!/bin/bash | #!/bin/bash | ||||
| npm i | |||||
| npm i --unsafe-perm | |||||
| node server | node server | ||||
| @ -1,8 +1,7 @@ | |||||
| const mongoose = require('mongoose'), | const mongoose = require('mongoose'), | ||||
| speciesModel = new mongoose.Schema({ | speciesModel = new mongoose.Schema({ | ||||
| id: mongoose.Schema.Types.ObjectId, | |||||
| name: mongoose.Schema.Types.String, | name: mongoose.Schema.Types.String, | ||||
| descripotion: mongoose.Schema.Types.String | |||||
| description: mongoose.Schema.Types.String | |||||
| }) | }) | ||||
| module.exports = db => db.model('species', speciesModel) | module.exports = db => db.model('species', speciesModel) | ||||
| @ -0,0 +1,22 @@ | |||||
| The MIT License (MIT) | |||||
| Copyright (c) 2011-2019 Twitter, Inc. | |||||
| Copyright (c) 2011-2019 The Bootstrap Authors | |||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | |||||
| of this software and associated documentation files (the "Software"), to deal | |||||
| in the Software without restriction, including without limitation the rights | |||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||||
| copies of the Software, and to permit persons to whom the Software is | |||||
| furnished to do so, subject to the following conditions: | |||||
| The above copyright notice and this permission notice shall be included in | |||||
| all copies or substantial portions of the Software. | |||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||||
| THE SOFTWARE. | |||||
| @ -0,0 +1,209 @@ | |||||
| <p align="center"> | |||||
| <a href="https://getbootstrap.com/"> | |||||
| <img src="https://getbootstrap.com/docs/4.4/assets/brand/bootstrap-solid.svg" alt="Bootstrap logo" width="72" height="72"> | |||||
| </a> | |||||
| </p> | |||||
| <h3 align="center">Bootstrap</h3> | |||||
| <p align="center"> | |||||
| Sleek, intuitive, and powerful front-end framework for faster and easier web development. | |||||
| <br> | |||||
| <a href="https://getbootstrap.com/docs/4.4/"><strong>Explore Bootstrap docs »</strong></a> | |||||
| <br> | |||||
| <br> | |||||
| <a href="https://github.com/twbs/bootstrap/issues/new?template=bug.md">Report bug</a> | |||||
| · | |||||
| <a href="https://github.com/twbs/bootstrap/issues/new?template=feature.md&labels=feature">Request feature</a> | |||||
| · | |||||
| <a href="https://themes.getbootstrap.com/">Themes</a> | |||||
| · | |||||
| <a href="https://blog.getbootstrap.com/">Blog</a> | |||||
| </p> | |||||
| ## Table of contents | |||||
| - [Quick start](#quick-start) | |||||
| - [Status](#status) | |||||
| - [What's included](#whats-included) | |||||
| - [Bugs and feature requests](#bugs-and-feature-requests) | |||||
| - [Documentation](#documentation) | |||||
| - [Contributing](#contributing) | |||||
| - [Community](#community) | |||||
| - [Versioning](#versioning) | |||||
| - [Creators](#creators) | |||||
| - [Thanks](#thanks) | |||||
| - [Copyright and license](#copyright-and-license) | |||||
| ## Quick start | |||||
| Several quick start options are available: | |||||
| - [Download the latest release.](https://github.com/twbs/bootstrap/archive/v4.4.1.zip) | |||||
| - Clone the repo: `git clone https://github.com/twbs/bootstrap.git` | |||||
| - Install with [npm](https://www.npmjs.com/): `npm install bootstrap` | |||||
| - Install with [yarn](https://yarnpkg.com/): `yarn add bootstrap@4.4.1` | |||||
| - Install with [Composer](https://getcomposer.org/): `composer require twbs/bootstrap:4.4.1` | |||||
| - Install with [NuGet](https://www.nuget.org/): CSS: `Install-Package bootstrap` Sass: `Install-Package bootstrap.sass` | |||||
| Read the [Getting started page](https://getbootstrap.com/docs/4.4/getting-started/introduction/) for information on the framework contents, templates and examples, and more. | |||||
| ## Status | |||||
| [](https://bootstrap-slack.herokuapp.com/) | |||||
| [](https://github.com/twbs/bootstrap/actions?workflow=Tests) | |||||
| [](https://www.npmjs.com/package/bootstrap) | |||||
| [](https://rubygems.org/gems/bootstrap) | |||||
| [](https://atmospherejs.com/twbs/bootstrap) | |||||
| [](https://packagist.org/packages/twbs/bootstrap) | |||||
| [](https://www.nuget.org/packages/bootstrap/absoluteLatest) | |||||
| [](https://david-dm.org/twbs/bootstrap?type=peer) | |||||
| [](https://david-dm.org/twbs/bootstrap?type=dev) | |||||
| [](https://coveralls.io/github/twbs/bootstrap?branch=v4-dev) | |||||
| [](https://github.com/twbs/bootstrap/tree/v4-dev/dist/css/bootstrap.min.css) | |||||
| [](https://github.com/twbs/bootstrap/tree/v4-dev/dist/js/bootstrap.min.js) | |||||
| [](https://www.browserstack.com/automate/public-build/SkxZcStBeExEdVJqQ2hWYnlWckpkNmNEY213SFp6WHFETWk2bGFuY3pCbz0tLXhqbHJsVlZhQnRBdEpod3NLSDMzaHc9PQ==--3d0b75245708616eb93113221beece33e680b229) | |||||
| [](#backers) | |||||
| [](#sponsors) | |||||
| ## What's included | |||||
| Within the download you'll find the following directories and files, logically grouping common assets and providing both compiled and minified variations. You'll see something like this: | |||||
| ```text | |||||
| bootstrap/ | |||||
| └── dist/ | |||||
| ├── 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 | |||||
| └── 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 | |||||
| ``` | |||||
| We provide compiled CSS and JS (`bootstrap.*`), as well as compiled and minified CSS and JS (`bootstrap.min.*`). [source maps](https://developers.google.com/web/tools/chrome-devtools/javascript/source-maps) (`bootstrap.*.map`) are available for use with certain browsers' developer tools. Bundled JS files (`bootstrap.bundle.js` and minified `bootstrap.bundle.min.js`) include [Popper](https://popper.js.org/), but not [jQuery](https://jquery.com/). | |||||
| ## Bugs and feature requests | |||||
| Have a bug or a feature request? Please first read the [issue guidelines](https://github.com/twbs/bootstrap/blob/master/CONTRIBUTING.md#using-the-issue-tracker) and search for existing and closed issues. If your problem or idea is not addressed yet, [please open a new issue](https://github.com/twbs/bootstrap/issues/new). | |||||
| ## Documentation | |||||
| Bootstrap's documentation, included in this repo in the root directory, is built with [Jekyll](https://jekyllrb.com/) and publicly hosted on GitHub Pages at <https://getbootstrap.com/>. The docs may also be run locally. | |||||
| Documentation search is powered by [Algolia's DocSearch](https://community.algolia.com/docsearch/). Working on our search? Be sure to set `debug: true` in `site/docs/4.4/assets/js/src/search.js` file. | |||||
| ### Running documentation locally | |||||
| 1. Run through the [tooling setup](https://getbootstrap.com/docs/4.4/getting-started/build-tools/#tooling-setup) to install Jekyll (the site builder) and other Ruby dependencies with `bundle install`. | |||||
| 2. Run `npm install` to install Node.js dependencies. | |||||
| 3. Run `npm start` to compile CSS and JavaScript files, generate our docs, and watch for changes. | |||||
| 4. Open `http://localhost:9001` in your browser, and voilà. | |||||
| Learn more about using Jekyll by reading its [documentation](https://jekyllrb.com/docs/). | |||||
| ### Documentation for previous releases | |||||
| You can find all our previous releases docs on <https://getbootstrap.com/docs/versions/>. | |||||
| [Previous releases](https://github.com/twbs/bootstrap/releases) and their documentation are also available for download. | |||||
| ## Contributing | |||||
| Please read through our [contributing guidelines](https://github.com/twbs/bootstrap/blob/master/CONTRIBUTING.md). Included are directions for opening issues, coding standards, and notes on development. | |||||
| Moreover, if your pull request contains JavaScript patches or features, you must include [relevant unit tests](https://github.com/twbs/bootstrap/tree/master/js/tests). All HTML and CSS should conform to the [Code Guide](https://github.com/mdo/code-guide), maintained by [Mark Otto](https://github.com/mdo). | |||||
| Editor preferences are available in the [editor config](https://github.com/twbs/bootstrap/blob/master/.editorconfig) for easy use in common text editors. Read more and download plugins at <https://editorconfig.org/>. | |||||
| ## Community | |||||
| Get updates on Bootstrap's development and chat with the project maintainers and community members. | |||||
| - Follow [@getbootstrap on Twitter](https://twitter.com/getbootstrap). | |||||
| - Read and subscribe to [The Official Bootstrap Blog](https://blog.getbootstrap.com/). | |||||
| - Join [the official Slack room](https://bootstrap-slack.herokuapp.com/). | |||||
| - Chat with fellow Bootstrappers in IRC. On the `irc.freenode.net` server, in the `##bootstrap` channel. | |||||
| - Implementation help may be found at Stack Overflow (tagged [`bootstrap-4`](https://stackoverflow.com/questions/tagged/bootstrap-4)). | |||||
| - Developers should use the keyword `bootstrap` on packages which modify or add to the functionality of Bootstrap when distributing through [npm](https://www.npmjs.com/browse/keyword/bootstrap) or similar delivery mechanisms for maximum discoverability. | |||||
| ## Versioning | |||||
| For transparency into our release cycle and in striving to maintain backward compatibility, Bootstrap is maintained under [the Semantic Versioning guidelines](https://semver.org/). Sometimes we screw up, but we adhere to those rules whenever possible. | |||||
| See [the Releases section of our GitHub project](https://github.com/twbs/bootstrap/releases) for changelogs for each release version of Bootstrap. Release announcement posts on [the official Bootstrap blog](https://blog.getbootstrap.com/) contain summaries of the most noteworthy changes made in each release. | |||||
| ## Creators | |||||
| **Mark Otto** | |||||
| - <https://twitter.com/mdo> | |||||
| - <https://github.com/mdo> | |||||
| **Jacob Thornton** | |||||
| - <https://twitter.com/fat> | |||||
| - <https://github.com/fat> | |||||
| ## Thanks | |||||
| <a href="https://www.browserstack.com/"> | |||||
| <img src="https://live.browserstack.com/images/opensource/browserstack-logo.svg" alt="BrowserStack Logo" width="192" height="42"> | |||||
| </a> | |||||
| Thanks to [BrowserStack](https://www.browserstack.com/) for providing the infrastructure that allows us to test in real browsers! | |||||
| ## Backers | |||||
| Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/bootstrap#backer)] | |||||
| [](https://opencollective.com/bootstrap#backers) | |||||
| ## Sponsors | |||||
| Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/bootstrap#sponsor)] | |||||
| [](https://opencollective.com/bootstrap/sponsor/0/website) | |||||
| [](https://opencollective.com/bootstrap/sponsor/1/website) | |||||
| [](https://opencollective.com/bootstrap/sponsor/2/website) | |||||
| [](https://opencollective.com/bootstrap/sponsor/3/website) | |||||
| [](https://opencollective.com/bootstrap/sponsor/4/website) | |||||
| [](https://opencollective.com/bootstrap/sponsor/5/website) | |||||
| [](https://opencollective.com/bootstrap/sponsor/6/website) | |||||
| [](https://opencollective.com/bootstrap/sponsor/7/website) | |||||
| [](https://opencollective.com/bootstrap/sponsor/8/website) | |||||
| [](https://opencollective.com/bootstrap/sponsor/9/website) | |||||
| ## Copyright and license | |||||
| Code and documentation copyright 2011-2019 the [Bootstrap Authors](https://github.com/twbs/bootstrap/graphs/contributors) and [Twitter, Inc.](https://twitter.com) Code released under the [MIT License](https://github.com/twbs/bootstrap/blob/master/LICENSE). Docs released under [Creative Commons](https://creativecommons.org/licenses/by/3.0/). | |||||
| @ -0,0 +1,327 @@ | |||||
| /*! | |||||
| * Bootstrap Reboot v4.4.1 (https://getbootstrap.com/) | |||||
| * Copyright 2011-2019 The Bootstrap Authors | |||||
| * Copyright 2011-2019 Twitter, Inc. | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) | |||||
| */ | |||||
| *, | |||||
| *::before, | |||||
| *::after { | |||||
| box-sizing: border-box; | |||||
| } | |||||
| html { | |||||
| font-family: sans-serif; | |||||
| line-height: 1.15; | |||||
| -webkit-text-size-adjust: 100%; | |||||
| -webkit-tap-highlight-color: rgba(0, 0, 0, 0); | |||||
| } | |||||
| 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: 0.5rem; | |||||
| } | |||||
| p { | |||||
| margin-top: 0; | |||||
| margin-bottom: 1rem; | |||||
| } | |||||
| abbr[title], | |||||
| abbr[data-original-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; | |||||
| } | |||||
| ol, | |||||
| ul, | |||||
| dl { | |||||
| margin-top: 0; | |||||
| margin-bottom: 1rem; | |||||
| } | |||||
| ol ol, | |||||
| ul ul, | |||||
| ol ul, | |||||
| ul ol { | |||||
| 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]) { | |||||
| color: inherit; | |||||
| text-decoration: none; | |||||
| } | |||||
| a:not([href]):hover { | |||||
| color: inherit; | |||||
| text-decoration: none; | |||||
| } | |||||
| pre, | |||||
| code, | |||||
| kbd, | |||||
| 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; | |||||
| } | |||||
| 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: 0.75rem; | |||||
| padding-bottom: 0.75rem; | |||||
| color: #6c757d; | |||||
| text-align: left; | |||||
| caption-side: bottom; | |||||
| } | |||||
| th { | |||||
| text-align: inherit; | |||||
| } | |||||
| label { | |||||
| display: inline-block; | |||||
| margin-bottom: 0.5rem; | |||||
| } | |||||
| button { | |||||
| border-radius: 0; | |||||
| } | |||||
| button:focus { | |||||
| outline: 1px dotted; | |||||
| outline: 5px auto -webkit-focus-ring-color; | |||||
| } | |||||
| input, | |||||
| button, | |||||
| select, | |||||
| optgroup, | |||||
| textarea { | |||||
| margin: 0; | |||||
| font-family: inherit; | |||||
| font-size: inherit; | |||||
| line-height: inherit; | |||||
| } | |||||
| button, | |||||
| input { | |||||
| overflow: visible; | |||||
| } | |||||
| button, | |||||
| select { | |||||
| text-transform: none; | |||||
| } | |||||
| select { | |||||
| word-wrap: normal; | |||||
| } | |||||
| button, | |||||
| [type="button"], | |||||
| [type="reset"], | |||||
| [type="submit"] { | |||||
| -webkit-appearance: button; | |||||
| } | |||||
| button:not(:disabled), | |||||
| [type="button"]:not(:disabled), | |||||
| [type="reset"]:not(:disabled), | |||||
| [type="submit"]:not(:disabled) { | |||||
| cursor: pointer; | |||||
| } | |||||
| button::-moz-focus-inner, | |||||
| [type="button"]::-moz-focus-inner, | |||||
| [type="reset"]::-moz-focus-inner, | |||||
| [type="submit"]::-moz-focus-inner { | |||||
| padding: 0; | |||||
| border-style: none; | |||||
| } | |||||
| input[type="radio"], | |||||
| input[type="checkbox"] { | |||||
| box-sizing: border-box; | |||||
| padding: 0; | |||||
| } | |||||
| input[type="date"], | |||||
| input[type="time"], | |||||
| input[type="datetime-local"], | |||||
| input[type="month"] { | |||||
| -webkit-appearance: listbox; | |||||
| } | |||||
| 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; | |||||
| } | |||||
| /*# sourceMappingURL=bootstrap-reboot.css.map */ | |||||
| @ -0,0 +1,8 @@ | |||||
| /*! | |||||
| * Bootstrap Reboot v4.4.1 (https://getbootstrap.com/) | |||||
| * Copyright 2011-2019 The Bootstrap Authors | |||||
| * Copyright 2011-2019 Twitter, Inc. | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) | |||||
| */*,::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]){color:inherit;text-decoration:none}a:not([href]):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}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}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}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}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} | |||||
| /*# sourceMappingURL=bootstrap-reboot.min.css.map */ | |||||
| @ -0,0 +1,198 @@ | |||||
| /*! | |||||
| * Bootstrap alert.js v4.4.1 (https://getbootstrap.com/) | |||||
| * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| */ | |||||
| (function (global, factory) { | |||||
| typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('./util.js')) : | |||||
| typeof define === 'function' && define.amd ? define(['jquery', './util.js'], factory) : | |||||
| (global = global || self, global.Alert = factory(global.jQuery, global.Util)); | |||||
| }(this, (function ($, Util) { 'use strict'; | |||||
| $ = $ && $.hasOwnProperty('default') ? $['default'] : $; | |||||
| Util = Util && Util.hasOwnProperty('default') ? Util['default'] : Util; | |||||
| function _defineProperties(target, props) { | |||||
| for (var i = 0; i < props.length; i++) { | |||||
| var descriptor = props[i]; | |||||
| descriptor.enumerable = descriptor.enumerable || false; | |||||
| descriptor.configurable = true; | |||||
| if ("value" in descriptor) descriptor.writable = true; | |||||
| Object.defineProperty(target, descriptor.key, descriptor); | |||||
| } | |||||
| } | |||||
| function _createClass(Constructor, protoProps, staticProps) { | |||||
| if (protoProps) _defineProperties(Constructor.prototype, protoProps); | |||||
| if (staticProps) _defineProperties(Constructor, staticProps); | |||||
| return Constructor; | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Constants | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| var NAME = 'alert'; | |||||
| var VERSION = '4.4.1'; | |||||
| var DATA_KEY = 'bs.alert'; | |||||
| var EVENT_KEY = "." + DATA_KEY; | |||||
| var DATA_API_KEY = '.data-api'; | |||||
| var JQUERY_NO_CONFLICT = $.fn[NAME]; | |||||
| var Selector = { | |||||
| DISMISS: '[data-dismiss="alert"]' | |||||
| }; | |||||
| var Event = { | |||||
| CLOSE: "close" + EVENT_KEY, | |||||
| CLOSED: "closed" + EVENT_KEY, | |||||
| CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY | |||||
| }; | |||||
| var ClassName = { | |||||
| ALERT: 'alert', | |||||
| FADE: 'fade', | |||||
| SHOW: 'show' | |||||
| }; | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Class Definition | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| var Alert = | |||||
| /*#__PURE__*/ | |||||
| function () { | |||||
| function Alert(element) { | |||||
| this._element = element; | |||||
| } // Getters | |||||
| var _proto = Alert.prototype; | |||||
| // Public | |||||
| _proto.close = function close(element) { | |||||
| var rootElement = this._element; | |||||
| if (element) { | |||||
| rootElement = this._getRootElement(element); | |||||
| } | |||||
| var customEvent = this._triggerCloseEvent(rootElement); | |||||
| if (customEvent.isDefaultPrevented()) { | |||||
| return; | |||||
| } | |||||
| this._removeElement(rootElement); | |||||
| }; | |||||
| _proto.dispose = function dispose() { | |||||
| $.removeData(this._element, DATA_KEY); | |||||
| this._element = null; | |||||
| } // Private | |||||
| ; | |||||
| _proto._getRootElement = function _getRootElement(element) { | |||||
| var selector = Util.getSelectorFromElement(element); | |||||
| var parent = false; | |||||
| if (selector) { | |||||
| parent = document.querySelector(selector); | |||||
| } | |||||
| if (!parent) { | |||||
| parent = $(element).closest("." + ClassName.ALERT)[0]; | |||||
| } | |||||
| return parent; | |||||
| }; | |||||
| _proto._triggerCloseEvent = function _triggerCloseEvent(element) { | |||||
| var closeEvent = $.Event(Event.CLOSE); | |||||
| $(element).trigger(closeEvent); | |||||
| return closeEvent; | |||||
| }; | |||||
| _proto._removeElement = function _removeElement(element) { | |||||
| var _this = this; | |||||
| $(element).removeClass(ClassName.SHOW); | |||||
| if (!$(element).hasClass(ClassName.FADE)) { | |||||
| this._destroyElement(element); | |||||
| return; | |||||
| } | |||||
| var transitionDuration = Util.getTransitionDurationFromElement(element); | |||||
| $(element).one(Util.TRANSITION_END, function (event) { | |||||
| return _this._destroyElement(element, event); | |||||
| }).emulateTransitionEnd(transitionDuration); | |||||
| }; | |||||
| _proto._destroyElement = function _destroyElement(element) { | |||||
| $(element).detach().trigger(Event.CLOSED).remove(); | |||||
| } // Static | |||||
| ; | |||||
| Alert._jQueryInterface = function _jQueryInterface(config) { | |||||
| return this.each(function () { | |||||
| var $element = $(this); | |||||
| var data = $element.data(DATA_KEY); | |||||
| if (!data) { | |||||
| data = new Alert(this); | |||||
| $element.data(DATA_KEY, data); | |||||
| } | |||||
| if (config === 'close') { | |||||
| data[config](this); | |||||
| } | |||||
| }); | |||||
| }; | |||||
| Alert._handleDismiss = function _handleDismiss(alertInstance) { | |||||
| return function (event) { | |||||
| if (event) { | |||||
| event.preventDefault(); | |||||
| } | |||||
| alertInstance.close(this); | |||||
| }; | |||||
| }; | |||||
| _createClass(Alert, null, [{ | |||||
| key: "VERSION", | |||||
| get: function get() { | |||||
| return VERSION; | |||||
| } | |||||
| }]); | |||||
| return Alert; | |||||
| }(); | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Data Api implementation | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $(document).on(Event.CLICK_DATA_API, Selector.DISMISS, Alert._handleDismiss(new Alert())); | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * jQuery | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $.fn[NAME] = Alert._jQueryInterface; | |||||
| $.fn[NAME].Constructor = Alert; | |||||
| $.fn[NAME].noConflict = function () { | |||||
| $.fn[NAME] = JQUERY_NO_CONFLICT; | |||||
| return Alert._jQueryInterface; | |||||
| }; | |||||
| return Alert; | |||||
| }))); | |||||
| //# sourceMappingURL=alert.js.map | |||||
| @ -0,0 +1,234 @@ | |||||
| /*! | |||||
| * Bootstrap button.js v4.4.1 (https://getbootstrap.com/) | |||||
| * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| */ | |||||
| (function (global, factory) { | |||||
| typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery')) : | |||||
| typeof define === 'function' && define.amd ? define(['jquery'], factory) : | |||||
| (global = global || self, global.Button = factory(global.jQuery)); | |||||
| }(this, (function ($) { 'use strict'; | |||||
| $ = $ && $.hasOwnProperty('default') ? $['default'] : $; | |||||
| function _defineProperties(target, props) { | |||||
| for (var i = 0; i < props.length; i++) { | |||||
| var descriptor = props[i]; | |||||
| descriptor.enumerable = descriptor.enumerable || false; | |||||
| descriptor.configurable = true; | |||||
| if ("value" in descriptor) descriptor.writable = true; | |||||
| Object.defineProperty(target, descriptor.key, descriptor); | |||||
| } | |||||
| } | |||||
| function _createClass(Constructor, protoProps, staticProps) { | |||||
| if (protoProps) _defineProperties(Constructor.prototype, protoProps); | |||||
| if (staticProps) _defineProperties(Constructor, staticProps); | |||||
| return Constructor; | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Constants | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| var NAME = 'button'; | |||||
| var VERSION = '4.4.1'; | |||||
| var DATA_KEY = 'bs.button'; | |||||
| var EVENT_KEY = "." + DATA_KEY; | |||||
| var DATA_API_KEY = '.data-api'; | |||||
| var JQUERY_NO_CONFLICT = $.fn[NAME]; | |||||
| var ClassName = { | |||||
| ACTIVE: 'active', | |||||
| BUTTON: 'btn', | |||||
| FOCUS: 'focus' | |||||
| }; | |||||
| var Selector = { | |||||
| DATA_TOGGLE_CARROT: '[data-toggle^="button"]', | |||||
| DATA_TOGGLES: '[data-toggle="buttons"]', | |||||
| DATA_TOGGLE: '[data-toggle="button"]', | |||||
| DATA_TOGGLES_BUTTONS: '[data-toggle="buttons"] .btn', | |||||
| INPUT: 'input:not([type="hidden"])', | |||||
| ACTIVE: '.active', | |||||
| BUTTON: '.btn' | |||||
| }; | |||||
| var Event = { | |||||
| CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY, | |||||
| FOCUS_BLUR_DATA_API: "focus" + EVENT_KEY + DATA_API_KEY + " " + ("blur" + EVENT_KEY + DATA_API_KEY), | |||||
| LOAD_DATA_API: "load" + EVENT_KEY + DATA_API_KEY | |||||
| }; | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Class Definition | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| var Button = | |||||
| /*#__PURE__*/ | |||||
| function () { | |||||
| function Button(element) { | |||||
| this._element = element; | |||||
| } // Getters | |||||
| var _proto = Button.prototype; | |||||
| // Public | |||||
| _proto.toggle = function toggle() { | |||||
| var triggerChangeEvent = true; | |||||
| var addAriaPressed = true; | |||||
| var rootElement = $(this._element).closest(Selector.DATA_TOGGLES)[0]; | |||||
| if (rootElement) { | |||||
| var input = this._element.querySelector(Selector.INPUT); | |||||
| if (input) { | |||||
| if (input.type === 'radio') { | |||||
| if (input.checked && this._element.classList.contains(ClassName.ACTIVE)) { | |||||
| triggerChangeEvent = false; | |||||
| } else { | |||||
| var activeElement = rootElement.querySelector(Selector.ACTIVE); | |||||
| if (activeElement) { | |||||
| $(activeElement).removeClass(ClassName.ACTIVE); | |||||
| } | |||||
| } | |||||
| } else if (input.type === 'checkbox') { | |||||
| if (this._element.tagName === 'LABEL' && input.checked === this._element.classList.contains(ClassName.ACTIVE)) { | |||||
| triggerChangeEvent = false; | |||||
| } | |||||
| } else { | |||||
| // if it's not a radio button or checkbox don't add a pointless/invalid checked property to the input | |||||
| triggerChangeEvent = false; | |||||
| } | |||||
| if (triggerChangeEvent) { | |||||
| input.checked = !this._element.classList.contains(ClassName.ACTIVE); | |||||
| $(input).trigger('change'); | |||||
| } | |||||
| input.focus(); | |||||
| addAriaPressed = false; | |||||
| } | |||||
| } | |||||
| if (!(this._element.hasAttribute('disabled') || this._element.classList.contains('disabled'))) { | |||||
| if (addAriaPressed) { | |||||
| this._element.setAttribute('aria-pressed', !this._element.classList.contains(ClassName.ACTIVE)); | |||||
| } | |||||
| if (triggerChangeEvent) { | |||||
| $(this._element).toggleClass(ClassName.ACTIVE); | |||||
| } | |||||
| } | |||||
| }; | |||||
| _proto.dispose = function dispose() { | |||||
| $.removeData(this._element, DATA_KEY); | |||||
| this._element = null; | |||||
| } // Static | |||||
| ; | |||||
| Button._jQueryInterface = function _jQueryInterface(config) { | |||||
| return this.each(function () { | |||||
| var data = $(this).data(DATA_KEY); | |||||
| if (!data) { | |||||
| data = new Button(this); | |||||
| $(this).data(DATA_KEY, data); | |||||
| } | |||||
| if (config === 'toggle') { | |||||
| data[config](); | |||||
| } | |||||
| }); | |||||
| }; | |||||
| _createClass(Button, null, [{ | |||||
| key: "VERSION", | |||||
| get: function get() { | |||||
| return VERSION; | |||||
| } | |||||
| }]); | |||||
| return Button; | |||||
| }(); | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Data Api implementation | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) { | |||||
| var button = event.target; | |||||
| if (!$(button).hasClass(ClassName.BUTTON)) { | |||||
| button = $(button).closest(Selector.BUTTON)[0]; | |||||
| } | |||||
| if (!button || button.hasAttribute('disabled') || button.classList.contains('disabled')) { | |||||
| event.preventDefault(); // work around Firefox bug #1540995 | |||||
| } else { | |||||
| var inputBtn = button.querySelector(Selector.INPUT); | |||||
| if (inputBtn && (inputBtn.hasAttribute('disabled') || inputBtn.classList.contains('disabled'))) { | |||||
| event.preventDefault(); // work around Firefox bug #1540995 | |||||
| return; | |||||
| } | |||||
| Button._jQueryInterface.call($(button), 'toggle'); | |||||
| } | |||||
| }).on(Event.FOCUS_BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) { | |||||
| var button = $(event.target).closest(Selector.BUTTON)[0]; | |||||
| $(button).toggleClass(ClassName.FOCUS, /^focus(in)?$/.test(event.type)); | |||||
| }); | |||||
| $(window).on(Event.LOAD_DATA_API, function () { | |||||
| // ensure correct active class is set to match the controls' actual values/states | |||||
| // find all checkboxes/readio buttons inside data-toggle groups | |||||
| var buttons = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLES_BUTTONS)); | |||||
| for (var i = 0, len = buttons.length; i < len; i++) { | |||||
| var button = buttons[i]; | |||||
| var input = button.querySelector(Selector.INPUT); | |||||
| if (input.checked || input.hasAttribute('checked')) { | |||||
| button.classList.add(ClassName.ACTIVE); | |||||
| } else { | |||||
| button.classList.remove(ClassName.ACTIVE); | |||||
| } | |||||
| } // find all button toggles | |||||
| buttons = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE)); | |||||
| for (var _i = 0, _len = buttons.length; _i < _len; _i++) { | |||||
| var _button = buttons[_i]; | |||||
| if (_button.getAttribute('aria-pressed') === 'true') { | |||||
| _button.classList.add(ClassName.ACTIVE); | |||||
| } else { | |||||
| _button.classList.remove(ClassName.ACTIVE); | |||||
| } | |||||
| } | |||||
| }); | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * jQuery | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $.fn[NAME] = Button._jQueryInterface; | |||||
| $.fn[NAME].Constructor = Button; | |||||
| $.fn[NAME].noConflict = function () { | |||||
| $.fn[NAME] = JQUERY_NO_CONFLICT; | |||||
| return Button._jQueryInterface; | |||||
| }; | |||||
| return Button; | |||||
| }))); | |||||
| //# sourceMappingURL=button.js.map | |||||
| @ -0,0 +1,681 @@ | |||||
| /*! | |||||
| * Bootstrap carousel.js v4.4.1 (https://getbootstrap.com/) | |||||
| * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| */ | |||||
| (function (global, factory) { | |||||
| typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('./util.js')) : | |||||
| typeof define === 'function' && define.amd ? define(['jquery', './util.js'], factory) : | |||||
| (global = global || self, global.Carousel = factory(global.jQuery, global.Util)); | |||||
| }(this, (function ($, Util) { 'use strict'; | |||||
| $ = $ && $.hasOwnProperty('default') ? $['default'] : $; | |||||
| Util = Util && Util.hasOwnProperty('default') ? Util['default'] : Util; | |||||
| function _defineProperties(target, props) { | |||||
| for (var i = 0; i < props.length; i++) { | |||||
| var descriptor = props[i]; | |||||
| descriptor.enumerable = descriptor.enumerable || false; | |||||
| descriptor.configurable = true; | |||||
| if ("value" in descriptor) descriptor.writable = true; | |||||
| Object.defineProperty(target, descriptor.key, descriptor); | |||||
| } | |||||
| } | |||||
| function _createClass(Constructor, protoProps, staticProps) { | |||||
| if (protoProps) _defineProperties(Constructor.prototype, protoProps); | |||||
| if (staticProps) _defineProperties(Constructor, staticProps); | |||||
| return Constructor; | |||||
| } | |||||
| function _defineProperty(obj, key, value) { | |||||
| if (key in obj) { | |||||
| Object.defineProperty(obj, key, { | |||||
| value: value, | |||||
| enumerable: true, | |||||
| configurable: true, | |||||
| writable: true | |||||
| }); | |||||
| } else { | |||||
| obj[key] = value; | |||||
| } | |||||
| return obj; | |||||
| } | |||||
| function ownKeys(object, enumerableOnly) { | |||||
| var keys = Object.keys(object); | |||||
| if (Object.getOwnPropertySymbols) { | |||||
| var symbols = Object.getOwnPropertySymbols(object); | |||||
| if (enumerableOnly) symbols = symbols.filter(function (sym) { | |||||
| return Object.getOwnPropertyDescriptor(object, sym).enumerable; | |||||
| }); | |||||
| keys.push.apply(keys, symbols); | |||||
| } | |||||
| return keys; | |||||
| } | |||||
| function _objectSpread2(target) { | |||||
| for (var i = 1; i < arguments.length; i++) { | |||||
| var source = arguments[i] != null ? arguments[i] : {}; | |||||
| if (i % 2) { | |||||
| ownKeys(Object(source), true).forEach(function (key) { | |||||
| _defineProperty(target, key, source[key]); | |||||
| }); | |||||
| } else if (Object.getOwnPropertyDescriptors) { | |||||
| Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); | |||||
| } else { | |||||
| ownKeys(Object(source)).forEach(function (key) { | |||||
| Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); | |||||
| }); | |||||
| } | |||||
| } | |||||
| return target; | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Constants | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| var NAME = 'carousel'; | |||||
| var VERSION = '4.4.1'; | |||||
| var DATA_KEY = 'bs.carousel'; | |||||
| var EVENT_KEY = "." + DATA_KEY; | |||||
| var DATA_API_KEY = '.data-api'; | |||||
| var JQUERY_NO_CONFLICT = $.fn[NAME]; | |||||
| var ARROW_LEFT_KEYCODE = 37; // KeyboardEvent.which value for left arrow key | |||||
| var ARROW_RIGHT_KEYCODE = 39; // KeyboardEvent.which value for right arrow key | |||||
| var TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch | |||||
| var SWIPE_THRESHOLD = 40; | |||||
| var Default = { | |||||
| interval: 5000, | |||||
| keyboard: true, | |||||
| slide: false, | |||||
| pause: 'hover', | |||||
| wrap: true, | |||||
| touch: true | |||||
| }; | |||||
| var DefaultType = { | |||||
| interval: '(number|boolean)', | |||||
| keyboard: 'boolean', | |||||
| slide: '(boolean|string)', | |||||
| pause: '(string|boolean)', | |||||
| wrap: 'boolean', | |||||
| touch: 'boolean' | |||||
| }; | |||||
| var Direction = { | |||||
| NEXT: 'next', | |||||
| PREV: 'prev', | |||||
| LEFT: 'left', | |||||
| RIGHT: 'right' | |||||
| }; | |||||
| var Event = { | |||||
| SLIDE: "slide" + EVENT_KEY, | |||||
| SLID: "slid" + EVENT_KEY, | |||||
| KEYDOWN: "keydown" + EVENT_KEY, | |||||
| MOUSEENTER: "mouseenter" + EVENT_KEY, | |||||
| MOUSELEAVE: "mouseleave" + EVENT_KEY, | |||||
| TOUCHSTART: "touchstart" + EVENT_KEY, | |||||
| TOUCHMOVE: "touchmove" + EVENT_KEY, | |||||
| TOUCHEND: "touchend" + EVENT_KEY, | |||||
| POINTERDOWN: "pointerdown" + EVENT_KEY, | |||||
| POINTERUP: "pointerup" + EVENT_KEY, | |||||
| DRAG_START: "dragstart" + EVENT_KEY, | |||||
| LOAD_DATA_API: "load" + EVENT_KEY + DATA_API_KEY, | |||||
| CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY | |||||
| }; | |||||
| var ClassName = { | |||||
| CAROUSEL: 'carousel', | |||||
| ACTIVE: 'active', | |||||
| SLIDE: 'slide', | |||||
| RIGHT: 'carousel-item-right', | |||||
| LEFT: 'carousel-item-left', | |||||
| NEXT: 'carousel-item-next', | |||||
| PREV: 'carousel-item-prev', | |||||
| ITEM: 'carousel-item', | |||||
| POINTER_EVENT: 'pointer-event' | |||||
| }; | |||||
| var Selector = { | |||||
| ACTIVE: '.active', | |||||
| ACTIVE_ITEM: '.active.carousel-item', | |||||
| ITEM: '.carousel-item', | |||||
| ITEM_IMG: '.carousel-item img', | |||||
| NEXT_PREV: '.carousel-item-next, .carousel-item-prev', | |||||
| INDICATORS: '.carousel-indicators', | |||||
| DATA_SLIDE: '[data-slide], [data-slide-to]', | |||||
| DATA_RIDE: '[data-ride="carousel"]' | |||||
| }; | |||||
| var PointerType = { | |||||
| TOUCH: 'touch', | |||||
| PEN: 'pen' | |||||
| }; | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Class Definition | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| var Carousel = | |||||
| /*#__PURE__*/ | |||||
| function () { | |||||
| function Carousel(element, config) { | |||||
| this._items = null; | |||||
| this._interval = null; | |||||
| this._activeElement = null; | |||||
| this._isPaused = false; | |||||
| this._isSliding = false; | |||||
| this.touchTimeout = null; | |||||
| this.touchStartX = 0; | |||||
| this.touchDeltaX = 0; | |||||
| this._config = this._getConfig(config); | |||||
| this._element = element; | |||||
| this._indicatorsElement = this._element.querySelector(Selector.INDICATORS); | |||||
| this._touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0; | |||||
| this._pointerEvent = Boolean(window.PointerEvent || window.MSPointerEvent); | |||||
| this._addEventListeners(); | |||||
| } // Getters | |||||
| var _proto = Carousel.prototype; | |||||
| // Public | |||||
| _proto.next = function next() { | |||||
| if (!this._isSliding) { | |||||
| this._slide(Direction.NEXT); | |||||
| } | |||||
| }; | |||||
| _proto.nextWhenVisible = function nextWhenVisible() { | |||||
| // Don't call next when the page isn't visible | |||||
| // or the carousel or its parent isn't visible | |||||
| if (!document.hidden && $(this._element).is(':visible') && $(this._element).css('visibility') !== 'hidden') { | |||||
| this.next(); | |||||
| } | |||||
| }; | |||||
| _proto.prev = function prev() { | |||||
| if (!this._isSliding) { | |||||
| this._slide(Direction.PREV); | |||||
| } | |||||
| }; | |||||
| _proto.pause = function pause(event) { | |||||
| if (!event) { | |||||
| this._isPaused = true; | |||||
| } | |||||
| if (this._element.querySelector(Selector.NEXT_PREV)) { | |||||
| Util.triggerTransitionEnd(this._element); | |||||
| this.cycle(true); | |||||
| } | |||||
| clearInterval(this._interval); | |||||
| this._interval = null; | |||||
| }; | |||||
| _proto.cycle = function cycle(event) { | |||||
| if (!event) { | |||||
| this._isPaused = false; | |||||
| } | |||||
| if (this._interval) { | |||||
| clearInterval(this._interval); | |||||
| this._interval = null; | |||||
| } | |||||
| if (this._config.interval && !this._isPaused) { | |||||
| this._interval = setInterval((document.visibilityState ? this.nextWhenVisible : this.next).bind(this), this._config.interval); | |||||
| } | |||||
| }; | |||||
| _proto.to = function to(index) { | |||||
| var _this = this; | |||||
| this._activeElement = this._element.querySelector(Selector.ACTIVE_ITEM); | |||||
| var activeIndex = this._getItemIndex(this._activeElement); | |||||
| if (index > this._items.length - 1 || index < 0) { | |||||
| return; | |||||
| } | |||||
| if (this._isSliding) { | |||||
| $(this._element).one(Event.SLID, function () { | |||||
| return _this.to(index); | |||||
| }); | |||||
| return; | |||||
| } | |||||
| if (activeIndex === index) { | |||||
| this.pause(); | |||||
| this.cycle(); | |||||
| return; | |||||
| } | |||||
| var direction = index > activeIndex ? Direction.NEXT : Direction.PREV; | |||||
| this._slide(direction, this._items[index]); | |||||
| }; | |||||
| _proto.dispose = function dispose() { | |||||
| $(this._element).off(EVENT_KEY); | |||||
| $.removeData(this._element, DATA_KEY); | |||||
| this._items = null; | |||||
| this._config = null; | |||||
| this._element = null; | |||||
| this._interval = null; | |||||
| this._isPaused = null; | |||||
| this._isSliding = null; | |||||
| this._activeElement = null; | |||||
| this._indicatorsElement = null; | |||||
| } // Private | |||||
| ; | |||||
| _proto._getConfig = function _getConfig(config) { | |||||
| config = _objectSpread2({}, Default, {}, config); | |||||
| Util.typeCheckConfig(NAME, config, DefaultType); | |||||
| return config; | |||||
| }; | |||||
| _proto._handleSwipe = function _handleSwipe() { | |||||
| var absDeltax = Math.abs(this.touchDeltaX); | |||||
| if (absDeltax <= SWIPE_THRESHOLD) { | |||||
| return; | |||||
| } | |||||
| var direction = absDeltax / this.touchDeltaX; | |||||
| this.touchDeltaX = 0; // swipe left | |||||
| if (direction > 0) { | |||||
| this.prev(); | |||||
| } // swipe right | |||||
| if (direction < 0) { | |||||
| this.next(); | |||||
| } | |||||
| }; | |||||
| _proto._addEventListeners = function _addEventListeners() { | |||||
| var _this2 = this; | |||||
| if (this._config.keyboard) { | |||||
| $(this._element).on(Event.KEYDOWN, function (event) { | |||||
| return _this2._keydown(event); | |||||
| }); | |||||
| } | |||||
| if (this._config.pause === 'hover') { | |||||
| $(this._element).on(Event.MOUSEENTER, function (event) { | |||||
| return _this2.pause(event); | |||||
| }).on(Event.MOUSELEAVE, function (event) { | |||||
| return _this2.cycle(event); | |||||
| }); | |||||
| } | |||||
| if (this._config.touch) { | |||||
| this._addTouchEventListeners(); | |||||
| } | |||||
| }; | |||||
| _proto._addTouchEventListeners = function _addTouchEventListeners() { | |||||
| var _this3 = this; | |||||
| if (!this._touchSupported) { | |||||
| return; | |||||
| } | |||||
| var start = function start(event) { | |||||
| if (_this3._pointerEvent && PointerType[event.originalEvent.pointerType.toUpperCase()]) { | |||||
| _this3.touchStartX = event.originalEvent.clientX; | |||||
| } else if (!_this3._pointerEvent) { | |||||
| _this3.touchStartX = event.originalEvent.touches[0].clientX; | |||||
| } | |||||
| }; | |||||
| var move = function move(event) { | |||||
| // ensure swiping with one touch and not pinching | |||||
| if (event.originalEvent.touches && event.originalEvent.touches.length > 1) { | |||||
| _this3.touchDeltaX = 0; | |||||
| } else { | |||||
| _this3.touchDeltaX = event.originalEvent.touches[0].clientX - _this3.touchStartX; | |||||
| } | |||||
| }; | |||||
| var end = function end(event) { | |||||
| if (_this3._pointerEvent && PointerType[event.originalEvent.pointerType.toUpperCase()]) { | |||||
| _this3.touchDeltaX = event.originalEvent.clientX - _this3.touchStartX; | |||||
| } | |||||
| _this3._handleSwipe(); | |||||
| if (_this3._config.pause === 'hover') { | |||||
| // If it's a touch-enabled device, mouseenter/leave are fired as | |||||
| // part of the mouse compatibility events on first tap - the carousel | |||||
| // would stop cycling until user tapped out of it; | |||||
| // here, we listen for touchend, explicitly pause the carousel | |||||
| // (as if it's the second time we tap on it, mouseenter compat event | |||||
| // is NOT fired) and after a timeout (to allow for mouse compatibility | |||||
| // events to fire) we explicitly restart cycling | |||||
| _this3.pause(); | |||||
| if (_this3.touchTimeout) { | |||||
| clearTimeout(_this3.touchTimeout); | |||||
| } | |||||
| _this3.touchTimeout = setTimeout(function (event) { | |||||
| return _this3.cycle(event); | |||||
| }, TOUCHEVENT_COMPAT_WAIT + _this3._config.interval); | |||||
| } | |||||
| }; | |||||
| $(this._element.querySelectorAll(Selector.ITEM_IMG)).on(Event.DRAG_START, function (e) { | |||||
| return e.preventDefault(); | |||||
| }); | |||||
| if (this._pointerEvent) { | |||||
| $(this._element).on(Event.POINTERDOWN, function (event) { | |||||
| return start(event); | |||||
| }); | |||||
| $(this._element).on(Event.POINTERUP, function (event) { | |||||
| return end(event); | |||||
| }); | |||||
| this._element.classList.add(ClassName.POINTER_EVENT); | |||||
| } else { | |||||
| $(this._element).on(Event.TOUCHSTART, function (event) { | |||||
| return start(event); | |||||
| }); | |||||
| $(this._element).on(Event.TOUCHMOVE, function (event) { | |||||
| return move(event); | |||||
| }); | |||||
| $(this._element).on(Event.TOUCHEND, function (event) { | |||||
| return end(event); | |||||
| }); | |||||
| } | |||||
| }; | |||||
| _proto._keydown = function _keydown(event) { | |||||
| if (/input|textarea/i.test(event.target.tagName)) { | |||||
| return; | |||||
| } | |||||
| switch (event.which) { | |||||
| case ARROW_LEFT_KEYCODE: | |||||
| event.preventDefault(); | |||||
| this.prev(); | |||||
| break; | |||||
| case ARROW_RIGHT_KEYCODE: | |||||
| event.preventDefault(); | |||||
| this.next(); | |||||
| break; | |||||
| } | |||||
| }; | |||||
| _proto._getItemIndex = function _getItemIndex(element) { | |||||
| this._items = element && element.parentNode ? [].slice.call(element.parentNode.querySelectorAll(Selector.ITEM)) : []; | |||||
| return this._items.indexOf(element); | |||||
| }; | |||||
| _proto._getItemByDirection = function _getItemByDirection(direction, activeElement) { | |||||
| var isNextDirection = direction === Direction.NEXT; | |||||
| var isPrevDirection = direction === Direction.PREV; | |||||
| var activeIndex = this._getItemIndex(activeElement); | |||||
| var lastItemIndex = this._items.length - 1; | |||||
| var isGoingToWrap = isPrevDirection && activeIndex === 0 || isNextDirection && activeIndex === lastItemIndex; | |||||
| if (isGoingToWrap && !this._config.wrap) { | |||||
| return activeElement; | |||||
| } | |||||
| var delta = direction === Direction.PREV ? -1 : 1; | |||||
| var itemIndex = (activeIndex + delta) % this._items.length; | |||||
| return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex]; | |||||
| }; | |||||
| _proto._triggerSlideEvent = function _triggerSlideEvent(relatedTarget, eventDirectionName) { | |||||
| var targetIndex = this._getItemIndex(relatedTarget); | |||||
| var fromIndex = this._getItemIndex(this._element.querySelector(Selector.ACTIVE_ITEM)); | |||||
| var slideEvent = $.Event(Event.SLIDE, { | |||||
| relatedTarget: relatedTarget, | |||||
| direction: eventDirectionName, | |||||
| from: fromIndex, | |||||
| to: targetIndex | |||||
| }); | |||||
| $(this._element).trigger(slideEvent); | |||||
| return slideEvent; | |||||
| }; | |||||
| _proto._setActiveIndicatorElement = function _setActiveIndicatorElement(element) { | |||||
| if (this._indicatorsElement) { | |||||
| var indicators = [].slice.call(this._indicatorsElement.querySelectorAll(Selector.ACTIVE)); | |||||
| $(indicators).removeClass(ClassName.ACTIVE); | |||||
| var nextIndicator = this._indicatorsElement.children[this._getItemIndex(element)]; | |||||
| if (nextIndicator) { | |||||
| $(nextIndicator).addClass(ClassName.ACTIVE); | |||||
| } | |||||
| } | |||||
| }; | |||||
| _proto._slide = function _slide(direction, element) { | |||||
| var _this4 = this; | |||||
| var activeElement = this._element.querySelector(Selector.ACTIVE_ITEM); | |||||
| var activeElementIndex = this._getItemIndex(activeElement); | |||||
| var nextElement = element || activeElement && this._getItemByDirection(direction, activeElement); | |||||
| var nextElementIndex = this._getItemIndex(nextElement); | |||||
| var isCycling = Boolean(this._interval); | |||||
| var directionalClassName; | |||||
| var orderClassName; | |||||
| var eventDirectionName; | |||||
| if (direction === Direction.NEXT) { | |||||
| directionalClassName = ClassName.LEFT; | |||||
| orderClassName = ClassName.NEXT; | |||||
| eventDirectionName = Direction.LEFT; | |||||
| } else { | |||||
| directionalClassName = ClassName.RIGHT; | |||||
| orderClassName = ClassName.PREV; | |||||
| eventDirectionName = Direction.RIGHT; | |||||
| } | |||||
| if (nextElement && $(nextElement).hasClass(ClassName.ACTIVE)) { | |||||
| this._isSliding = false; | |||||
| return; | |||||
| } | |||||
| var slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName); | |||||
| if (slideEvent.isDefaultPrevented()) { | |||||
| return; | |||||
| } | |||||
| if (!activeElement || !nextElement) { | |||||
| // Some weirdness is happening, so we bail | |||||
| return; | |||||
| } | |||||
| this._isSliding = true; | |||||
| if (isCycling) { | |||||
| this.pause(); | |||||
| } | |||||
| this._setActiveIndicatorElement(nextElement); | |||||
| var slidEvent = $.Event(Event.SLID, { | |||||
| relatedTarget: nextElement, | |||||
| direction: eventDirectionName, | |||||
| from: activeElementIndex, | |||||
| to: nextElementIndex | |||||
| }); | |||||
| if ($(this._element).hasClass(ClassName.SLIDE)) { | |||||
| $(nextElement).addClass(orderClassName); | |||||
| Util.reflow(nextElement); | |||||
| $(activeElement).addClass(directionalClassName); | |||||
| $(nextElement).addClass(directionalClassName); | |||||
| var nextElementInterval = parseInt(nextElement.getAttribute('data-interval'), 10); | |||||
| if (nextElementInterval) { | |||||
| this._config.defaultInterval = this._config.defaultInterval || this._config.interval; | |||||
| this._config.interval = nextElementInterval; | |||||
| } else { | |||||
| this._config.interval = this._config.defaultInterval || this._config.interval; | |||||
| } | |||||
| var transitionDuration = Util.getTransitionDurationFromElement(activeElement); | |||||
| $(activeElement).one(Util.TRANSITION_END, function () { | |||||
| $(nextElement).removeClass(directionalClassName + " " + orderClassName).addClass(ClassName.ACTIVE); | |||||
| $(activeElement).removeClass(ClassName.ACTIVE + " " + orderClassName + " " + directionalClassName); | |||||
| _this4._isSliding = false; | |||||
| setTimeout(function () { | |||||
| return $(_this4._element).trigger(slidEvent); | |||||
| }, 0); | |||||
| }).emulateTransitionEnd(transitionDuration); | |||||
| } else { | |||||
| $(activeElement).removeClass(ClassName.ACTIVE); | |||||
| $(nextElement).addClass(ClassName.ACTIVE); | |||||
| this._isSliding = false; | |||||
| $(this._element).trigger(slidEvent); | |||||
| } | |||||
| if (isCycling) { | |||||
| this.cycle(); | |||||
| } | |||||
| } // Static | |||||
| ; | |||||
| Carousel._jQueryInterface = function _jQueryInterface(config) { | |||||
| return this.each(function () { | |||||
| var data = $(this).data(DATA_KEY); | |||||
| var _config = _objectSpread2({}, Default, {}, $(this).data()); | |||||
| if (typeof config === 'object') { | |||||
| _config = _objectSpread2({}, _config, {}, config); | |||||
| } | |||||
| var action = typeof config === 'string' ? config : _config.slide; | |||||
| if (!data) { | |||||
| data = new Carousel(this, _config); | |||||
| $(this).data(DATA_KEY, data); | |||||
| } | |||||
| if (typeof config === 'number') { | |||||
| data.to(config); | |||||
| } else if (typeof action === 'string') { | |||||
| if (typeof data[action] === 'undefined') { | |||||
| throw new TypeError("No method named \"" + action + "\""); | |||||
| } | |||||
| data[action](); | |||||
| } else if (_config.interval && _config.ride) { | |||||
| data.pause(); | |||||
| data.cycle(); | |||||
| } | |||||
| }); | |||||
| }; | |||||
| Carousel._dataApiClickHandler = function _dataApiClickHandler(event) { | |||||
| var selector = Util.getSelectorFromElement(this); | |||||
| if (!selector) { | |||||
| return; | |||||
| } | |||||
| var target = $(selector)[0]; | |||||
| if (!target || !$(target).hasClass(ClassName.CAROUSEL)) { | |||||
| return; | |||||
| } | |||||
| var config = _objectSpread2({}, $(target).data(), {}, $(this).data()); | |||||
| var slideIndex = this.getAttribute('data-slide-to'); | |||||
| if (slideIndex) { | |||||
| config.interval = false; | |||||
| } | |||||
| Carousel._jQueryInterface.call($(target), config); | |||||
| if (slideIndex) { | |||||
| $(target).data(DATA_KEY).to(slideIndex); | |||||
| } | |||||
| event.preventDefault(); | |||||
| }; | |||||
| _createClass(Carousel, null, [{ | |||||
| key: "VERSION", | |||||
| get: function get() { | |||||
| return VERSION; | |||||
| } | |||||
| }, { | |||||
| key: "Default", | |||||
| get: function get() { | |||||
| return Default; | |||||
| } | |||||
| }]); | |||||
| return Carousel; | |||||
| }(); | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Data Api implementation | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $(document).on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler); | |||||
| $(window).on(Event.LOAD_DATA_API, function () { | |||||
| var carousels = [].slice.call(document.querySelectorAll(Selector.DATA_RIDE)); | |||||
| for (var i = 0, len = carousels.length; i < len; i++) { | |||||
| var $carousel = $(carousels[i]); | |||||
| Carousel._jQueryInterface.call($carousel, $carousel.data()); | |||||
| } | |||||
| }); | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * jQuery | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $.fn[NAME] = Carousel._jQueryInterface; | |||||
| $.fn[NAME].Constructor = Carousel; | |||||
| $.fn[NAME].noConflict = function () { | |||||
| $.fn[NAME] = JQUERY_NO_CONFLICT; | |||||
| return Carousel._jQueryInterface; | |||||
| }; | |||||
| return Carousel; | |||||
| }))); | |||||
| //# sourceMappingURL=carousel.js.map | |||||
| @ -0,0 +1,442 @@ | |||||
| /*! | |||||
| * Bootstrap collapse.js v4.4.1 (https://getbootstrap.com/) | |||||
| * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| */ | |||||
| (function (global, factory) { | |||||
| typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('./util.js')) : | |||||
| typeof define === 'function' && define.amd ? define(['jquery', './util.js'], factory) : | |||||
| (global = global || self, global.Collapse = factory(global.jQuery, global.Util)); | |||||
| }(this, (function ($, Util) { 'use strict'; | |||||
| $ = $ && $.hasOwnProperty('default') ? $['default'] : $; | |||||
| Util = Util && Util.hasOwnProperty('default') ? Util['default'] : Util; | |||||
| function _defineProperties(target, props) { | |||||
| for (var i = 0; i < props.length; i++) { | |||||
| var descriptor = props[i]; | |||||
| descriptor.enumerable = descriptor.enumerable || false; | |||||
| descriptor.configurable = true; | |||||
| if ("value" in descriptor) descriptor.writable = true; | |||||
| Object.defineProperty(target, descriptor.key, descriptor); | |||||
| } | |||||
| } | |||||
| function _createClass(Constructor, protoProps, staticProps) { | |||||
| if (protoProps) _defineProperties(Constructor.prototype, protoProps); | |||||
| if (staticProps) _defineProperties(Constructor, staticProps); | |||||
| return Constructor; | |||||
| } | |||||
| function _defineProperty(obj, key, value) { | |||||
| if (key in obj) { | |||||
| Object.defineProperty(obj, key, { | |||||
| value: value, | |||||
| enumerable: true, | |||||
| configurable: true, | |||||
| writable: true | |||||
| }); | |||||
| } else { | |||||
| obj[key] = value; | |||||
| } | |||||
| return obj; | |||||
| } | |||||
| function ownKeys(object, enumerableOnly) { | |||||
| var keys = Object.keys(object); | |||||
| if (Object.getOwnPropertySymbols) { | |||||
| var symbols = Object.getOwnPropertySymbols(object); | |||||
| if (enumerableOnly) symbols = symbols.filter(function (sym) { | |||||
| return Object.getOwnPropertyDescriptor(object, sym).enumerable; | |||||
| }); | |||||
| keys.push.apply(keys, symbols); | |||||
| } | |||||
| return keys; | |||||
| } | |||||
| function _objectSpread2(target) { | |||||
| for (var i = 1; i < arguments.length; i++) { | |||||
| var source = arguments[i] != null ? arguments[i] : {}; | |||||
| if (i % 2) { | |||||
| ownKeys(Object(source), true).forEach(function (key) { | |||||
| _defineProperty(target, key, source[key]); | |||||
| }); | |||||
| } else if (Object.getOwnPropertyDescriptors) { | |||||
| Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); | |||||
| } else { | |||||
| ownKeys(Object(source)).forEach(function (key) { | |||||
| Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); | |||||
| }); | |||||
| } | |||||
| } | |||||
| return target; | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Constants | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| var NAME = 'collapse'; | |||||
| var VERSION = '4.4.1'; | |||||
| var DATA_KEY = 'bs.collapse'; | |||||
| var EVENT_KEY = "." + DATA_KEY; | |||||
| var DATA_API_KEY = '.data-api'; | |||||
| var JQUERY_NO_CONFLICT = $.fn[NAME]; | |||||
| var Default = { | |||||
| toggle: true, | |||||
| parent: '' | |||||
| }; | |||||
| var DefaultType = { | |||||
| toggle: 'boolean', | |||||
| parent: '(string|element)' | |||||
| }; | |||||
| var Event = { | |||||
| SHOW: "show" + EVENT_KEY, | |||||
| SHOWN: "shown" + EVENT_KEY, | |||||
| HIDE: "hide" + EVENT_KEY, | |||||
| HIDDEN: "hidden" + EVENT_KEY, | |||||
| CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY | |||||
| }; | |||||
| var ClassName = { | |||||
| SHOW: 'show', | |||||
| COLLAPSE: 'collapse', | |||||
| COLLAPSING: 'collapsing', | |||||
| COLLAPSED: 'collapsed' | |||||
| }; | |||||
| var Dimension = { | |||||
| WIDTH: 'width', | |||||
| HEIGHT: 'height' | |||||
| }; | |||||
| var Selector = { | |||||
| ACTIVES: '.show, .collapsing', | |||||
| DATA_TOGGLE: '[data-toggle="collapse"]' | |||||
| }; | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Class Definition | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| var Collapse = | |||||
| /*#__PURE__*/ | |||||
| function () { | |||||
| function Collapse(element, config) { | |||||
| this._isTransitioning = false; | |||||
| this._element = element; | |||||
| this._config = this._getConfig(config); | |||||
| this._triggerArray = [].slice.call(document.querySelectorAll("[data-toggle=\"collapse\"][href=\"#" + element.id + "\"]," + ("[data-toggle=\"collapse\"][data-target=\"#" + element.id + "\"]"))); | |||||
| var toggleList = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE)); | |||||
| for (var i = 0, len = toggleList.length; i < len; i++) { | |||||
| var elem = toggleList[i]; | |||||
| var selector = Util.getSelectorFromElement(elem); | |||||
| var filterElement = [].slice.call(document.querySelectorAll(selector)).filter(function (foundElem) { | |||||
| return foundElem === element; | |||||
| }); | |||||
| if (selector !== null && filterElement.length > 0) { | |||||
| this._selector = selector; | |||||
| this._triggerArray.push(elem); | |||||
| } | |||||
| } | |||||
| this._parent = this._config.parent ? this._getParent() : null; | |||||
| if (!this._config.parent) { | |||||
| this._addAriaAndCollapsedClass(this._element, this._triggerArray); | |||||
| } | |||||
| if (this._config.toggle) { | |||||
| this.toggle(); | |||||
| } | |||||
| } // Getters | |||||
| var _proto = Collapse.prototype; | |||||
| // Public | |||||
| _proto.toggle = function toggle() { | |||||
| if ($(this._element).hasClass(ClassName.SHOW)) { | |||||
| this.hide(); | |||||
| } else { | |||||
| this.show(); | |||||
| } | |||||
| }; | |||||
| _proto.show = function show() { | |||||
| var _this = this; | |||||
| if (this._isTransitioning || $(this._element).hasClass(ClassName.SHOW)) { | |||||
| return; | |||||
| } | |||||
| var actives; | |||||
| var activesData; | |||||
| if (this._parent) { | |||||
| actives = [].slice.call(this._parent.querySelectorAll(Selector.ACTIVES)).filter(function (elem) { | |||||
| if (typeof _this._config.parent === 'string') { | |||||
| return elem.getAttribute('data-parent') === _this._config.parent; | |||||
| } | |||||
| return elem.classList.contains(ClassName.COLLAPSE); | |||||
| }); | |||||
| if (actives.length === 0) { | |||||
| actives = null; | |||||
| } | |||||
| } | |||||
| if (actives) { | |||||
| activesData = $(actives).not(this._selector).data(DATA_KEY); | |||||
| if (activesData && activesData._isTransitioning) { | |||||
| return; | |||||
| } | |||||
| } | |||||
| var startEvent = $.Event(Event.SHOW); | |||||
| $(this._element).trigger(startEvent); | |||||
| if (startEvent.isDefaultPrevented()) { | |||||
| return; | |||||
| } | |||||
| if (actives) { | |||||
| Collapse._jQueryInterface.call($(actives).not(this._selector), 'hide'); | |||||
| if (!activesData) { | |||||
| $(actives).data(DATA_KEY, null); | |||||
| } | |||||
| } | |||||
| var dimension = this._getDimension(); | |||||
| $(this._element).removeClass(ClassName.COLLAPSE).addClass(ClassName.COLLAPSING); | |||||
| this._element.style[dimension] = 0; | |||||
| if (this._triggerArray.length) { | |||||
| $(this._triggerArray).removeClass(ClassName.COLLAPSED).attr('aria-expanded', true); | |||||
| } | |||||
| this.setTransitioning(true); | |||||
| var complete = function complete() { | |||||
| $(_this._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).addClass(ClassName.SHOW); | |||||
| _this._element.style[dimension] = ''; | |||||
| _this.setTransitioning(false); | |||||
| $(_this._element).trigger(Event.SHOWN); | |||||
| }; | |||||
| var capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1); | |||||
| var scrollSize = "scroll" + capitalizedDimension; | |||||
| var transitionDuration = Util.getTransitionDurationFromElement(this._element); | |||||
| $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration); | |||||
| this._element.style[dimension] = this._element[scrollSize] + "px"; | |||||
| }; | |||||
| _proto.hide = function hide() { | |||||
| var _this2 = this; | |||||
| if (this._isTransitioning || !$(this._element).hasClass(ClassName.SHOW)) { | |||||
| return; | |||||
| } | |||||
| var startEvent = $.Event(Event.HIDE); | |||||
| $(this._element).trigger(startEvent); | |||||
| if (startEvent.isDefaultPrevented()) { | |||||
| return; | |||||
| } | |||||
| var dimension = this._getDimension(); | |||||
| this._element.style[dimension] = this._element.getBoundingClientRect()[dimension] + "px"; | |||||
| Util.reflow(this._element); | |||||
| $(this._element).addClass(ClassName.COLLAPSING).removeClass(ClassName.COLLAPSE).removeClass(ClassName.SHOW); | |||||
| var triggerArrayLength = this._triggerArray.length; | |||||
| if (triggerArrayLength > 0) { | |||||
| for (var i = 0; i < triggerArrayLength; i++) { | |||||
| var trigger = this._triggerArray[i]; | |||||
| var selector = Util.getSelectorFromElement(trigger); | |||||
| if (selector !== null) { | |||||
| var $elem = $([].slice.call(document.querySelectorAll(selector))); | |||||
| if (!$elem.hasClass(ClassName.SHOW)) { | |||||
| $(trigger).addClass(ClassName.COLLAPSED).attr('aria-expanded', false); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| this.setTransitioning(true); | |||||
| var complete = function complete() { | |||||
| _this2.setTransitioning(false); | |||||
| $(_this2._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).trigger(Event.HIDDEN); | |||||
| }; | |||||
| this._element.style[dimension] = ''; | |||||
| var transitionDuration = Util.getTransitionDurationFromElement(this._element); | |||||
| $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration); | |||||
| }; | |||||
| _proto.setTransitioning = function setTransitioning(isTransitioning) { | |||||
| this._isTransitioning = isTransitioning; | |||||
| }; | |||||
| _proto.dispose = function dispose() { | |||||
| $.removeData(this._element, DATA_KEY); | |||||
| this._config = null; | |||||
| this._parent = null; | |||||
| this._element = null; | |||||
| this._triggerArray = null; | |||||
| this._isTransitioning = null; | |||||
| } // Private | |||||
| ; | |||||
| _proto._getConfig = function _getConfig(config) { | |||||
| config = _objectSpread2({}, Default, {}, config); | |||||
| config.toggle = Boolean(config.toggle); // Coerce string values | |||||
| Util.typeCheckConfig(NAME, config, DefaultType); | |||||
| return config; | |||||
| }; | |||||
| _proto._getDimension = function _getDimension() { | |||||
| var hasWidth = $(this._element).hasClass(Dimension.WIDTH); | |||||
| return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT; | |||||
| }; | |||||
| _proto._getParent = function _getParent() { | |||||
| var _this3 = this; | |||||
| var parent; | |||||
| if (Util.isElement(this._config.parent)) { | |||||
| parent = this._config.parent; // It's a jQuery object | |||||
| if (typeof this._config.parent.jquery !== 'undefined') { | |||||
| parent = this._config.parent[0]; | |||||
| } | |||||
| } else { | |||||
| parent = document.querySelector(this._config.parent); | |||||
| } | |||||
| var selector = "[data-toggle=\"collapse\"][data-parent=\"" + this._config.parent + "\"]"; | |||||
| var children = [].slice.call(parent.querySelectorAll(selector)); | |||||
| $(children).each(function (i, element) { | |||||
| _this3._addAriaAndCollapsedClass(Collapse._getTargetFromElement(element), [element]); | |||||
| }); | |||||
| return parent; | |||||
| }; | |||||
| _proto._addAriaAndCollapsedClass = function _addAriaAndCollapsedClass(element, triggerArray) { | |||||
| var isOpen = $(element).hasClass(ClassName.SHOW); | |||||
| if (triggerArray.length) { | |||||
| $(triggerArray).toggleClass(ClassName.COLLAPSED, !isOpen).attr('aria-expanded', isOpen); | |||||
| } | |||||
| } // Static | |||||
| ; | |||||
| Collapse._getTargetFromElement = function _getTargetFromElement(element) { | |||||
| var selector = Util.getSelectorFromElement(element); | |||||
| return selector ? document.querySelector(selector) : null; | |||||
| }; | |||||
| Collapse._jQueryInterface = function _jQueryInterface(config) { | |||||
| return this.each(function () { | |||||
| var $this = $(this); | |||||
| var data = $this.data(DATA_KEY); | |||||
| var _config = _objectSpread2({}, Default, {}, $this.data(), {}, typeof config === 'object' && config ? config : {}); | |||||
| if (!data && _config.toggle && /show|hide/.test(config)) { | |||||
| _config.toggle = false; | |||||
| } | |||||
| if (!data) { | |||||
| data = new Collapse(this, _config); | |||||
| $this.data(DATA_KEY, data); | |||||
| } | |||||
| if (typeof config === 'string') { | |||||
| if (typeof data[config] === 'undefined') { | |||||
| throw new TypeError("No method named \"" + config + "\""); | |||||
| } | |||||
| data[config](); | |||||
| } | |||||
| }); | |||||
| }; | |||||
| _createClass(Collapse, null, [{ | |||||
| key: "VERSION", | |||||
| get: function get() { | |||||
| return VERSION; | |||||
| } | |||||
| }, { | |||||
| key: "Default", | |||||
| get: function get() { | |||||
| return Default; | |||||
| } | |||||
| }]); | |||||
| return Collapse; | |||||
| }(); | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Data Api implementation | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { | |||||
| // preventDefault only for <a> elements (which change the URL) not inside the collapsible element | |||||
| if (event.currentTarget.tagName === 'A') { | |||||
| event.preventDefault(); | |||||
| } | |||||
| var $trigger = $(this); | |||||
| var selector = Util.getSelectorFromElement(this); | |||||
| var selectors = [].slice.call(document.querySelectorAll(selector)); | |||||
| $(selectors).each(function () { | |||||
| var $target = $(this); | |||||
| var data = $target.data(DATA_KEY); | |||||
| var config = data ? 'toggle' : $trigger.data(); | |||||
| Collapse._jQueryInterface.call($target, config); | |||||
| }); | |||||
| }); | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * jQuery | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $.fn[NAME] = Collapse._jQueryInterface; | |||||
| $.fn[NAME].Constructor = Collapse; | |||||
| $.fn[NAME].noConflict = function () { | |||||
| $.fn[NAME] = JQUERY_NO_CONFLICT; | |||||
| return Collapse._jQueryInterface; | |||||
| }; | |||||
| return Collapse; | |||||
| }))); | |||||
| //# sourceMappingURL=collapse.js.map | |||||
| @ -0,0 +1,616 @@ | |||||
| /*! | |||||
| * Bootstrap dropdown.js v4.4.1 (https://getbootstrap.com/) | |||||
| * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| */ | |||||
| (function (global, factory) { | |||||
| typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('popper.js'), require('./util.js')) : | |||||
| typeof define === 'function' && define.amd ? define(['jquery', 'popper.js', './util.js'], factory) : | |||||
| (global = global || self, global.Dropdown = factory(global.jQuery, global.Popper, global.Util)); | |||||
| }(this, (function ($, Popper, Util) { 'use strict'; | |||||
| $ = $ && $.hasOwnProperty('default') ? $['default'] : $; | |||||
| Popper = Popper && Popper.hasOwnProperty('default') ? Popper['default'] : Popper; | |||||
| Util = Util && Util.hasOwnProperty('default') ? Util['default'] : Util; | |||||
| function _defineProperties(target, props) { | |||||
| for (var i = 0; i < props.length; i++) { | |||||
| var descriptor = props[i]; | |||||
| descriptor.enumerable = descriptor.enumerable || false; | |||||
| descriptor.configurable = true; | |||||
| if ("value" in descriptor) descriptor.writable = true; | |||||
| Object.defineProperty(target, descriptor.key, descriptor); | |||||
| } | |||||
| } | |||||
| function _createClass(Constructor, protoProps, staticProps) { | |||||
| if (protoProps) _defineProperties(Constructor.prototype, protoProps); | |||||
| if (staticProps) _defineProperties(Constructor, staticProps); | |||||
| return Constructor; | |||||
| } | |||||
| function _defineProperty(obj, key, value) { | |||||
| if (key in obj) { | |||||
| Object.defineProperty(obj, key, { | |||||
| value: value, | |||||
| enumerable: true, | |||||
| configurable: true, | |||||
| writable: true | |||||
| }); | |||||
| } else { | |||||
| obj[key] = value; | |||||
| } | |||||
| return obj; | |||||
| } | |||||
| function ownKeys(object, enumerableOnly) { | |||||
| var keys = Object.keys(object); | |||||
| if (Object.getOwnPropertySymbols) { | |||||
| var symbols = Object.getOwnPropertySymbols(object); | |||||
| if (enumerableOnly) symbols = symbols.filter(function (sym) { | |||||
| return Object.getOwnPropertyDescriptor(object, sym).enumerable; | |||||
| }); | |||||
| keys.push.apply(keys, symbols); | |||||
| } | |||||
| return keys; | |||||
| } | |||||
| function _objectSpread2(target) { | |||||
| for (var i = 1; i < arguments.length; i++) { | |||||
| var source = arguments[i] != null ? arguments[i] : {}; | |||||
| if (i % 2) { | |||||
| ownKeys(Object(source), true).forEach(function (key) { | |||||
| _defineProperty(target, key, source[key]); | |||||
| }); | |||||
| } else if (Object.getOwnPropertyDescriptors) { | |||||
| Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); | |||||
| } else { | |||||
| ownKeys(Object(source)).forEach(function (key) { | |||||
| Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); | |||||
| }); | |||||
| } | |||||
| } | |||||
| return target; | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Constants | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| var NAME = 'dropdown'; | |||||
| var VERSION = '4.4.1'; | |||||
| var DATA_KEY = 'bs.dropdown'; | |||||
| var EVENT_KEY = "." + DATA_KEY; | |||||
| var DATA_API_KEY = '.data-api'; | |||||
| var JQUERY_NO_CONFLICT = $.fn[NAME]; | |||||
| var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key | |||||
| var SPACE_KEYCODE = 32; // KeyboardEvent.which value for space key | |||||
| var TAB_KEYCODE = 9; // KeyboardEvent.which value for tab key | |||||
| var ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key | |||||
| var ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key | |||||
| var RIGHT_MOUSE_BUTTON_WHICH = 3; // MouseEvent.which value for the right button (assuming a right-handed mouse) | |||||
| var REGEXP_KEYDOWN = new RegExp(ARROW_UP_KEYCODE + "|" + ARROW_DOWN_KEYCODE + "|" + ESCAPE_KEYCODE); | |||||
| var Event = { | |||||
| HIDE: "hide" + EVENT_KEY, | |||||
| HIDDEN: "hidden" + EVENT_KEY, | |||||
| SHOW: "show" + EVENT_KEY, | |||||
| SHOWN: "shown" + EVENT_KEY, | |||||
| CLICK: "click" + EVENT_KEY, | |||||
| CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY, | |||||
| KEYDOWN_DATA_API: "keydown" + EVENT_KEY + DATA_API_KEY, | |||||
| KEYUP_DATA_API: "keyup" + EVENT_KEY + DATA_API_KEY | |||||
| }; | |||||
| var ClassName = { | |||||
| DISABLED: 'disabled', | |||||
| SHOW: 'show', | |||||
| DROPUP: 'dropup', | |||||
| DROPRIGHT: 'dropright', | |||||
| DROPLEFT: 'dropleft', | |||||
| MENURIGHT: 'dropdown-menu-right', | |||||
| MENULEFT: 'dropdown-menu-left', | |||||
| POSITION_STATIC: 'position-static' | |||||
| }; | |||||
| var Selector = { | |||||
| DATA_TOGGLE: '[data-toggle="dropdown"]', | |||||
| FORM_CHILD: '.dropdown form', | |||||
| MENU: '.dropdown-menu', | |||||
| NAVBAR_NAV: '.navbar-nav', | |||||
| VISIBLE_ITEMS: '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)' | |||||
| }; | |||||
| var AttachmentMap = { | |||||
| TOP: 'top-start', | |||||
| TOPEND: 'top-end', | |||||
| BOTTOM: 'bottom-start', | |||||
| BOTTOMEND: 'bottom-end', | |||||
| RIGHT: 'right-start', | |||||
| RIGHTEND: 'right-end', | |||||
| LEFT: 'left-start', | |||||
| LEFTEND: 'left-end' | |||||
| }; | |||||
| var Default = { | |||||
| offset: 0, | |||||
| flip: true, | |||||
| boundary: 'scrollParent', | |||||
| reference: 'toggle', | |||||
| display: 'dynamic', | |||||
| popperConfig: null | |||||
| }; | |||||
| var DefaultType = { | |||||
| offset: '(number|string|function)', | |||||
| flip: 'boolean', | |||||
| boundary: '(string|element)', | |||||
| reference: '(string|element)', | |||||
| display: 'string', | |||||
| popperConfig: '(null|object)' | |||||
| }; | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Class Definition | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| var Dropdown = | |||||
| /*#__PURE__*/ | |||||
| function () { | |||||
| function Dropdown(element, config) { | |||||
| this._element = element; | |||||
| this._popper = null; | |||||
| this._config = this._getConfig(config); | |||||
| this._menu = this._getMenuElement(); | |||||
| this._inNavbar = this._detectNavbar(); | |||||
| this._addEventListeners(); | |||||
| } // Getters | |||||
| var _proto = Dropdown.prototype; | |||||
| // Public | |||||
| _proto.toggle = function toggle() { | |||||
| if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED)) { | |||||
| return; | |||||
| } | |||||
| var isActive = $(this._menu).hasClass(ClassName.SHOW); | |||||
| Dropdown._clearMenus(); | |||||
| if (isActive) { | |||||
| return; | |||||
| } | |||||
| this.show(true); | |||||
| }; | |||||
| _proto.show = function show(usePopper) { | |||||
| if (usePopper === void 0) { | |||||
| usePopper = false; | |||||
| } | |||||
| if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED) || $(this._menu).hasClass(ClassName.SHOW)) { | |||||
| return; | |||||
| } | |||||
| var relatedTarget = { | |||||
| relatedTarget: this._element | |||||
| }; | |||||
| var showEvent = $.Event(Event.SHOW, relatedTarget); | |||||
| var parent = Dropdown._getParentFromElement(this._element); | |||||
| $(parent).trigger(showEvent); | |||||
| if (showEvent.isDefaultPrevented()) { | |||||
| return; | |||||
| } // Disable totally Popper.js for Dropdown in Navbar | |||||
| if (!this._inNavbar && usePopper) { | |||||
| /** | |||||
| * Check for Popper dependency | |||||
| * Popper - https://popper.js.org | |||||
| */ | |||||
| if (typeof Popper === 'undefined') { | |||||
| throw new TypeError('Bootstrap\'s dropdowns require Popper.js (https://popper.js.org/)'); | |||||
| } | |||||
| var referenceElement = this._element; | |||||
| if (this._config.reference === 'parent') { | |||||
| referenceElement = parent; | |||||
| } else if (Util.isElement(this._config.reference)) { | |||||
| referenceElement = this._config.reference; // Check if it's jQuery element | |||||
| if (typeof this._config.reference.jquery !== 'undefined') { | |||||
| referenceElement = this._config.reference[0]; | |||||
| } | |||||
| } // If boundary is not `scrollParent`, then set position to `static` | |||||
| // to allow the menu to "escape" the scroll parent's boundaries | |||||
| // https://github.com/twbs/bootstrap/issues/24251 | |||||
| if (this._config.boundary !== 'scrollParent') { | |||||
| $(parent).addClass(ClassName.POSITION_STATIC); | |||||
| } | |||||
| this._popper = new Popper(referenceElement, this._menu, this._getPopperConfig()); | |||||
| } // If this is a touch-enabled device we add extra | |||||
| // empty mouseover listeners to the body's immediate children; | |||||
| // only needed because of broken event delegation on iOS | |||||
| // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html | |||||
| if ('ontouchstart' in document.documentElement && $(parent).closest(Selector.NAVBAR_NAV).length === 0) { | |||||
| $(document.body).children().on('mouseover', null, $.noop); | |||||
| } | |||||
| this._element.focus(); | |||||
| this._element.setAttribute('aria-expanded', true); | |||||
| $(this._menu).toggleClass(ClassName.SHOW); | |||||
| $(parent).toggleClass(ClassName.SHOW).trigger($.Event(Event.SHOWN, relatedTarget)); | |||||
| }; | |||||
| _proto.hide = function hide() { | |||||
| if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED) || !$(this._menu).hasClass(ClassName.SHOW)) { | |||||
| return; | |||||
| } | |||||
| var relatedTarget = { | |||||
| relatedTarget: this._element | |||||
| }; | |||||
| var hideEvent = $.Event(Event.HIDE, relatedTarget); | |||||
| var parent = Dropdown._getParentFromElement(this._element); | |||||
| $(parent).trigger(hideEvent); | |||||
| if (hideEvent.isDefaultPrevented()) { | |||||
| return; | |||||
| } | |||||
| if (this._popper) { | |||||
| this._popper.destroy(); | |||||
| } | |||||
| $(this._menu).toggleClass(ClassName.SHOW); | |||||
| $(parent).toggleClass(ClassName.SHOW).trigger($.Event(Event.HIDDEN, relatedTarget)); | |||||
| }; | |||||
| _proto.dispose = function dispose() { | |||||
| $.removeData(this._element, DATA_KEY); | |||||
| $(this._element).off(EVENT_KEY); | |||||
| this._element = null; | |||||
| this._menu = null; | |||||
| if (this._popper !== null) { | |||||
| this._popper.destroy(); | |||||
| this._popper = null; | |||||
| } | |||||
| }; | |||||
| _proto.update = function update() { | |||||
| this._inNavbar = this._detectNavbar(); | |||||
| if (this._popper !== null) { | |||||
| this._popper.scheduleUpdate(); | |||||
| } | |||||
| } // Private | |||||
| ; | |||||
| _proto._addEventListeners = function _addEventListeners() { | |||||
| var _this = this; | |||||
| $(this._element).on(Event.CLICK, function (event) { | |||||
| event.preventDefault(); | |||||
| event.stopPropagation(); | |||||
| _this.toggle(); | |||||
| }); | |||||
| }; | |||||
| _proto._getConfig = function _getConfig(config) { | |||||
| config = _objectSpread2({}, this.constructor.Default, {}, $(this._element).data(), {}, config); | |||||
| Util.typeCheckConfig(NAME, config, this.constructor.DefaultType); | |||||
| return config; | |||||
| }; | |||||
| _proto._getMenuElement = function _getMenuElement() { | |||||
| if (!this._menu) { | |||||
| var parent = Dropdown._getParentFromElement(this._element); | |||||
| if (parent) { | |||||
| this._menu = parent.querySelector(Selector.MENU); | |||||
| } | |||||
| } | |||||
| return this._menu; | |||||
| }; | |||||
| _proto._getPlacement = function _getPlacement() { | |||||
| var $parentDropdown = $(this._element.parentNode); | |||||
| var placement = AttachmentMap.BOTTOM; // Handle dropup | |||||
| if ($parentDropdown.hasClass(ClassName.DROPUP)) { | |||||
| placement = AttachmentMap.TOP; | |||||
| if ($(this._menu).hasClass(ClassName.MENURIGHT)) { | |||||
| placement = AttachmentMap.TOPEND; | |||||
| } | |||||
| } else if ($parentDropdown.hasClass(ClassName.DROPRIGHT)) { | |||||
| placement = AttachmentMap.RIGHT; | |||||
| } else if ($parentDropdown.hasClass(ClassName.DROPLEFT)) { | |||||
| placement = AttachmentMap.LEFT; | |||||
| } else if ($(this._menu).hasClass(ClassName.MENURIGHT)) { | |||||
| placement = AttachmentMap.BOTTOMEND; | |||||
| } | |||||
| return placement; | |||||
| }; | |||||
| _proto._detectNavbar = function _detectNavbar() { | |||||
| return $(this._element).closest('.navbar').length > 0; | |||||
| }; | |||||
| _proto._getOffset = function _getOffset() { | |||||
| var _this2 = this; | |||||
| var offset = {}; | |||||
| if (typeof this._config.offset === 'function') { | |||||
| offset.fn = function (data) { | |||||
| data.offsets = _objectSpread2({}, data.offsets, {}, _this2._config.offset(data.offsets, _this2._element) || {}); | |||||
| return data; | |||||
| }; | |||||
| } else { | |||||
| offset.offset = this._config.offset; | |||||
| } | |||||
| return offset; | |||||
| }; | |||||
| _proto._getPopperConfig = function _getPopperConfig() { | |||||
| var popperConfig = { | |||||
| placement: this._getPlacement(), | |||||
| modifiers: { | |||||
| offset: this._getOffset(), | |||||
| flip: { | |||||
| enabled: this._config.flip | |||||
| }, | |||||
| preventOverflow: { | |||||
| boundariesElement: this._config.boundary | |||||
| } | |||||
| } | |||||
| }; // Disable Popper.js if we have a static display | |||||
| if (this._config.display === 'static') { | |||||
| popperConfig.modifiers.applyStyle = { | |||||
| enabled: false | |||||
| }; | |||||
| } | |||||
| return _objectSpread2({}, popperConfig, {}, this._config.popperConfig); | |||||
| } // Static | |||||
| ; | |||||
| Dropdown._jQueryInterface = function _jQueryInterface(config) { | |||||
| return this.each(function () { | |||||
| var data = $(this).data(DATA_KEY); | |||||
| var _config = typeof config === 'object' ? config : null; | |||||
| if (!data) { | |||||
| data = new Dropdown(this, _config); | |||||
| $(this).data(DATA_KEY, data); | |||||
| } | |||||
| if (typeof config === 'string') { | |||||
| if (typeof data[config] === 'undefined') { | |||||
| throw new TypeError("No method named \"" + config + "\""); | |||||
| } | |||||
| data[config](); | |||||
| } | |||||
| }); | |||||
| }; | |||||
| Dropdown._clearMenus = function _clearMenus(event) { | |||||
| if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH || event.type === 'keyup' && event.which !== TAB_KEYCODE)) { | |||||
| return; | |||||
| } | |||||
| var toggles = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE)); | |||||
| for (var i = 0, len = toggles.length; i < len; i++) { | |||||
| var parent = Dropdown._getParentFromElement(toggles[i]); | |||||
| var context = $(toggles[i]).data(DATA_KEY); | |||||
| var relatedTarget = { | |||||
| relatedTarget: toggles[i] | |||||
| }; | |||||
| if (event && event.type === 'click') { | |||||
| relatedTarget.clickEvent = event; | |||||
| } | |||||
| if (!context) { | |||||
| continue; | |||||
| } | |||||
| var dropdownMenu = context._menu; | |||||
| if (!$(parent).hasClass(ClassName.SHOW)) { | |||||
| continue; | |||||
| } | |||||
| if (event && (event.type === 'click' && /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) && $.contains(parent, event.target)) { | |||||
| continue; | |||||
| } | |||||
| var hideEvent = $.Event(Event.HIDE, relatedTarget); | |||||
| $(parent).trigger(hideEvent); | |||||
| if (hideEvent.isDefaultPrevented()) { | |||||
| continue; | |||||
| } // If this is a touch-enabled device we remove the extra | |||||
| // empty mouseover listeners we added for iOS support | |||||
| if ('ontouchstart' in document.documentElement) { | |||||
| $(document.body).children().off('mouseover', null, $.noop); | |||||
| } | |||||
| toggles[i].setAttribute('aria-expanded', 'false'); | |||||
| if (context._popper) { | |||||
| context._popper.destroy(); | |||||
| } | |||||
| $(dropdownMenu).removeClass(ClassName.SHOW); | |||||
| $(parent).removeClass(ClassName.SHOW).trigger($.Event(Event.HIDDEN, relatedTarget)); | |||||
| } | |||||
| }; | |||||
| Dropdown._getParentFromElement = function _getParentFromElement(element) { | |||||
| var parent; | |||||
| var selector = Util.getSelectorFromElement(element); | |||||
| if (selector) { | |||||
| parent = document.querySelector(selector); | |||||
| } | |||||
| return parent || element.parentNode; | |||||
| } // eslint-disable-next-line complexity | |||||
| ; | |||||
| Dropdown._dataApiKeydownHandler = function _dataApiKeydownHandler(event) { | |||||
| // If not input/textarea: | |||||
| // - And not a key in REGEXP_KEYDOWN => not a dropdown command | |||||
| // If input/textarea: | |||||
| // - If space key => not a dropdown command | |||||
| // - If key is other than escape | |||||
| // - If key is not up or down => not a dropdown command | |||||
| // - If trigger inside the menu => not a dropdown command | |||||
| if (/input|textarea/i.test(event.target.tagName) ? event.which === SPACE_KEYCODE || event.which !== ESCAPE_KEYCODE && (event.which !== ARROW_DOWN_KEYCODE && event.which !== ARROW_UP_KEYCODE || $(event.target).closest(Selector.MENU).length) : !REGEXP_KEYDOWN.test(event.which)) { | |||||
| return; | |||||
| } | |||||
| event.preventDefault(); | |||||
| event.stopPropagation(); | |||||
| if (this.disabled || $(this).hasClass(ClassName.DISABLED)) { | |||||
| return; | |||||
| } | |||||
| var parent = Dropdown._getParentFromElement(this); | |||||
| var isActive = $(parent).hasClass(ClassName.SHOW); | |||||
| if (!isActive && event.which === ESCAPE_KEYCODE) { | |||||
| return; | |||||
| } | |||||
| if (!isActive || isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) { | |||||
| if (event.which === ESCAPE_KEYCODE) { | |||||
| var toggle = parent.querySelector(Selector.DATA_TOGGLE); | |||||
| $(toggle).trigger('focus'); | |||||
| } | |||||
| $(this).trigger('click'); | |||||
| return; | |||||
| } | |||||
| var items = [].slice.call(parent.querySelectorAll(Selector.VISIBLE_ITEMS)).filter(function (item) { | |||||
| return $(item).is(':visible'); | |||||
| }); | |||||
| if (items.length === 0) { | |||||
| return; | |||||
| } | |||||
| var index = items.indexOf(event.target); | |||||
| if (event.which === ARROW_UP_KEYCODE && index > 0) { | |||||
| // Up | |||||
| index--; | |||||
| } | |||||
| if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) { | |||||
| // Down | |||||
| index++; | |||||
| } | |||||
| if (index < 0) { | |||||
| index = 0; | |||||
| } | |||||
| items[index].focus(); | |||||
| }; | |||||
| _createClass(Dropdown, null, [{ | |||||
| key: "VERSION", | |||||
| get: function get() { | |||||
| return VERSION; | |||||
| } | |||||
| }, { | |||||
| key: "Default", | |||||
| get: function get() { | |||||
| return Default; | |||||
| } | |||||
| }, { | |||||
| key: "DefaultType", | |||||
| get: function get() { | |||||
| return DefaultType; | |||||
| } | |||||
| }]); | |||||
| return Dropdown; | |||||
| }(); | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Data Api implementation | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $(document).on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.MENU, Dropdown._dataApiKeydownHandler).on(Event.CLICK_DATA_API + " " + Event.KEYUP_DATA_API, Dropdown._clearMenus).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { | |||||
| event.preventDefault(); | |||||
| event.stopPropagation(); | |||||
| Dropdown._jQueryInterface.call($(this), 'toggle'); | |||||
| }).on(Event.CLICK_DATA_API, Selector.FORM_CHILD, function (e) { | |||||
| e.stopPropagation(); | |||||
| }); | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * jQuery | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $.fn[NAME] = Dropdown._jQueryInterface; | |||||
| $.fn[NAME].Constructor = Dropdown; | |||||
| $.fn[NAME].noConflict = function () { | |||||
| $.fn[NAME] = JQUERY_NO_CONFLICT; | |||||
| return Dropdown._jQueryInterface; | |||||
| }; | |||||
| return Dropdown; | |||||
| }))); | |||||
| //# sourceMappingURL=dropdown.js.map | |||||
| @ -0,0 +1,23 @@ | |||||
| /** | |||||
| * -------------------------------------------------------------------------- | |||||
| * Bootstrap (v4.4.0): index.js | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| * -------------------------------------------------------------------------- | |||||
| */ | |||||
| (function ($) { | |||||
| if (typeof $ === 'undefined') { | |||||
| throw new TypeError('Bootstrap\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\'s JavaScript.'); | |||||
| } | |||||
| var version = $.fn.jquery.split(' ')[0].split('.'); | |||||
| var minMajor = 1; | |||||
| var ltMajor = 2; | |||||
| var minMinor = 9; | |||||
| var minPatch = 1; | |||||
| var maxMajor = 4; | |||||
| if (version[0] < ltMajor && version[1] < minMinor || version[0] === minMajor && version[1] === minMinor && version[2] < minPatch || version[0] >= maxMajor) { | |||||
| throw new Error('Bootstrap\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0'); | |||||
| } | |||||
| })($); | |||||
| //# sourceMappingURL=index.js.map | |||||
| @ -0,0 +1 @@ | |||||
| {"version":3,"sources":["../src/index.js"],"names":["$","TypeError","version","fn","jquery","split","minMajor","ltMajor","minMinor","minPatch","maxMajor","Error"],"mappings":"AAaA;;;;;;AAOA,CAAC,UAACA,CAAD,EAAO;AACN,MAAI,OAAOA,CAAP,KAAa,WAAjB,EAA8B;AAC5B,UAAM,IAAIC,SAAJ,CAAc,kGAAd,CAAN;AACD;;AAED,MAAMC,UAAUF,EAAEG,EAAF,CAAKC,MAAL,CAAYC,KAAZ,CAAkB,GAAlB,EAAuB,CAAvB,EAA0BA,KAA1B,CAAgC,GAAhC,CAAhB;AACA,MAAMC,WAAW,CAAjB;AACA,MAAMC,UAAU,CAAhB;AACA,MAAMC,WAAW,CAAjB;AACA,MAAMC,WAAW,CAAjB;AACA,MAAMC,WAAW,CAAjB;;AAEA,MAAIR,QAAQ,CAAR,IAAaK,OAAb,IAAwBL,QAAQ,CAAR,IAAaM,QAArC,IAAiDN,QAAQ,CAAR,MAAeI,QAAf,IAA2BJ,QAAQ,CAAR,MAAeM,QAA1C,IAAsDN,QAAQ,CAAR,IAAaO,QAApH,IAAgIP,QAAQ,CAAR,KAAcQ,QAAlJ,EAA4J;AAC1J,UAAM,IAAIC,KAAJ,CAAU,8EAAV,CAAN;AACD;AACF,CAfD,EAeGX,CAfH","sourcesContent":["import $ from 'jquery'\nimport Alert from './alert'\nimport Button from './button'\nimport Carousel from './carousel'\nimport Collapse from './collapse'\nimport Dropdown from './dropdown'\nimport Modal from './modal'\nimport Popover from './popover'\nimport Scrollspy from './scrollspy'\nimport Tab from './tab'\nimport Tooltip from './tooltip'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.2): index.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n(($) => {\n if (typeof $ === 'undefined') {\n throw new TypeError('Bootstrap\\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\\'s JavaScript.')\n }\n\n const version = $.fn.jquery.split(' ')[0].split('.')\n const minMajor = 1\n const ltMajor = 2\n const minMinor = 9\n const minPatch = 1\n const maxMajor = 4\n\n if (version[0] < ltMajor && version[1] < minMinor || version[0] === minMajor && version[1] === minMinor && version[2] < minPatch || version[0] >= maxMajor) {\n throw new Error('Bootstrap\\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0')\n }\n})($)\n\nexport {\n Util,\n Alert,\n Button,\n Carousel,\n Collapse,\n Dropdown,\n Modal,\n Popover,\n Scrollspy,\n Tab,\n Tooltip\n}\n"],"file":"index.js"} | |||||
| @ -0,0 +1,685 @@ | |||||
| /*! | |||||
| * Bootstrap modal.js v4.4.1 (https://getbootstrap.com/) | |||||
| * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| */ | |||||
| (function (global, factory) { | |||||
| typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('./util.js')) : | |||||
| typeof define === 'function' && define.amd ? define(['jquery', './util.js'], factory) : | |||||
| (global = global || self, global.Modal = factory(global.jQuery, global.Util)); | |||||
| }(this, (function ($, Util) { 'use strict'; | |||||
| $ = $ && $.hasOwnProperty('default') ? $['default'] : $; | |||||
| Util = Util && Util.hasOwnProperty('default') ? Util['default'] : Util; | |||||
| function _defineProperties(target, props) { | |||||
| for (var i = 0; i < props.length; i++) { | |||||
| var descriptor = props[i]; | |||||
| descriptor.enumerable = descriptor.enumerable || false; | |||||
| descriptor.configurable = true; | |||||
| if ("value" in descriptor) descriptor.writable = true; | |||||
| Object.defineProperty(target, descriptor.key, descriptor); | |||||
| } | |||||
| } | |||||
| function _createClass(Constructor, protoProps, staticProps) { | |||||
| if (protoProps) _defineProperties(Constructor.prototype, protoProps); | |||||
| if (staticProps) _defineProperties(Constructor, staticProps); | |||||
| return Constructor; | |||||
| } | |||||
| function _defineProperty(obj, key, value) { | |||||
| if (key in obj) { | |||||
| Object.defineProperty(obj, key, { | |||||
| value: value, | |||||
| enumerable: true, | |||||
| configurable: true, | |||||
| writable: true | |||||
| }); | |||||
| } else { | |||||
| obj[key] = value; | |||||
| } | |||||
| return obj; | |||||
| } | |||||
| function ownKeys(object, enumerableOnly) { | |||||
| var keys = Object.keys(object); | |||||
| if (Object.getOwnPropertySymbols) { | |||||
| var symbols = Object.getOwnPropertySymbols(object); | |||||
| if (enumerableOnly) symbols = symbols.filter(function (sym) { | |||||
| return Object.getOwnPropertyDescriptor(object, sym).enumerable; | |||||
| }); | |||||
| keys.push.apply(keys, symbols); | |||||
| } | |||||
| return keys; | |||||
| } | |||||
| function _objectSpread2(target) { | |||||
| for (var i = 1; i < arguments.length; i++) { | |||||
| var source = arguments[i] != null ? arguments[i] : {}; | |||||
| if (i % 2) { | |||||
| ownKeys(Object(source), true).forEach(function (key) { | |||||
| _defineProperty(target, key, source[key]); | |||||
| }); | |||||
| } else if (Object.getOwnPropertyDescriptors) { | |||||
| Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); | |||||
| } else { | |||||
| ownKeys(Object(source)).forEach(function (key) { | |||||
| Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); | |||||
| }); | |||||
| } | |||||
| } | |||||
| return target; | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Constants | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| var NAME = 'modal'; | |||||
| var VERSION = '4.4.1'; | |||||
| var DATA_KEY = 'bs.modal'; | |||||
| var EVENT_KEY = "." + DATA_KEY; | |||||
| var DATA_API_KEY = '.data-api'; | |||||
| var JQUERY_NO_CONFLICT = $.fn[NAME]; | |||||
| var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key | |||||
| var Default = { | |||||
| backdrop: true, | |||||
| keyboard: true, | |||||
| focus: true, | |||||
| show: true | |||||
| }; | |||||
| var DefaultType = { | |||||
| backdrop: '(boolean|string)', | |||||
| keyboard: 'boolean', | |||||
| focus: 'boolean', | |||||
| show: 'boolean' | |||||
| }; | |||||
| var Event = { | |||||
| HIDE: "hide" + EVENT_KEY, | |||||
| HIDE_PREVENTED: "hidePrevented" + EVENT_KEY, | |||||
| HIDDEN: "hidden" + EVENT_KEY, | |||||
| SHOW: "show" + EVENT_KEY, | |||||
| SHOWN: "shown" + EVENT_KEY, | |||||
| FOCUSIN: "focusin" + EVENT_KEY, | |||||
| RESIZE: "resize" + EVENT_KEY, | |||||
| CLICK_DISMISS: "click.dismiss" + EVENT_KEY, | |||||
| KEYDOWN_DISMISS: "keydown.dismiss" + EVENT_KEY, | |||||
| MOUSEUP_DISMISS: "mouseup.dismiss" + EVENT_KEY, | |||||
| MOUSEDOWN_DISMISS: "mousedown.dismiss" + EVENT_KEY, | |||||
| CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY | |||||
| }; | |||||
| var ClassName = { | |||||
| SCROLLABLE: 'modal-dialog-scrollable', | |||||
| SCROLLBAR_MEASURER: 'modal-scrollbar-measure', | |||||
| BACKDROP: 'modal-backdrop', | |||||
| OPEN: 'modal-open', | |||||
| FADE: 'fade', | |||||
| SHOW: 'show', | |||||
| STATIC: 'modal-static' | |||||
| }; | |||||
| var Selector = { | |||||
| DIALOG: '.modal-dialog', | |||||
| MODAL_BODY: '.modal-body', | |||||
| DATA_TOGGLE: '[data-toggle="modal"]', | |||||
| DATA_DISMISS: '[data-dismiss="modal"]', | |||||
| FIXED_CONTENT: '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top', | |||||
| STICKY_CONTENT: '.sticky-top' | |||||
| }; | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Class Definition | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| var Modal = | |||||
| /*#__PURE__*/ | |||||
| function () { | |||||
| function Modal(element, config) { | |||||
| this._config = this._getConfig(config); | |||||
| this._element = element; | |||||
| this._dialog = element.querySelector(Selector.DIALOG); | |||||
| this._backdrop = null; | |||||
| this._isShown = false; | |||||
| this._isBodyOverflowing = false; | |||||
| this._ignoreBackdropClick = false; | |||||
| this._isTransitioning = false; | |||||
| this._scrollbarWidth = 0; | |||||
| } // Getters | |||||
| var _proto = Modal.prototype; | |||||
| // Public | |||||
| _proto.toggle = function toggle(relatedTarget) { | |||||
| return this._isShown ? this.hide() : this.show(relatedTarget); | |||||
| }; | |||||
| _proto.show = function show(relatedTarget) { | |||||
| var _this = this; | |||||
| if (this._isShown || this._isTransitioning) { | |||||
| return; | |||||
| } | |||||
| if ($(this._element).hasClass(ClassName.FADE)) { | |||||
| this._isTransitioning = true; | |||||
| } | |||||
| var showEvent = $.Event(Event.SHOW, { | |||||
| relatedTarget: relatedTarget | |||||
| }); | |||||
| $(this._element).trigger(showEvent); | |||||
| if (this._isShown || showEvent.isDefaultPrevented()) { | |||||
| return; | |||||
| } | |||||
| this._isShown = true; | |||||
| this._checkScrollbar(); | |||||
| this._setScrollbar(); | |||||
| this._adjustDialog(); | |||||
| this._setEscapeEvent(); | |||||
| this._setResizeEvent(); | |||||
| $(this._element).on(Event.CLICK_DISMISS, Selector.DATA_DISMISS, function (event) { | |||||
| return _this.hide(event); | |||||
| }); | |||||
| $(this._dialog).on(Event.MOUSEDOWN_DISMISS, function () { | |||||
| $(_this._element).one(Event.MOUSEUP_DISMISS, function (event) { | |||||
| if ($(event.target).is(_this._element)) { | |||||
| _this._ignoreBackdropClick = true; | |||||
| } | |||||
| }); | |||||
| }); | |||||
| this._showBackdrop(function () { | |||||
| return _this._showElement(relatedTarget); | |||||
| }); | |||||
| }; | |||||
| _proto.hide = function hide(event) { | |||||
| var _this2 = this; | |||||
| if (event) { | |||||
| event.preventDefault(); | |||||
| } | |||||
| if (!this._isShown || this._isTransitioning) { | |||||
| return; | |||||
| } | |||||
| var hideEvent = $.Event(Event.HIDE); | |||||
| $(this._element).trigger(hideEvent); | |||||
| if (!this._isShown || hideEvent.isDefaultPrevented()) { | |||||
| return; | |||||
| } | |||||
| this._isShown = false; | |||||
| var transition = $(this._element).hasClass(ClassName.FADE); | |||||
| if (transition) { | |||||
| this._isTransitioning = true; | |||||
| } | |||||
| this._setEscapeEvent(); | |||||
| this._setResizeEvent(); | |||||
| $(document).off(Event.FOCUSIN); | |||||
| $(this._element).removeClass(ClassName.SHOW); | |||||
| $(this._element).off(Event.CLICK_DISMISS); | |||||
| $(this._dialog).off(Event.MOUSEDOWN_DISMISS); | |||||
| if (transition) { | |||||
| var transitionDuration = Util.getTransitionDurationFromElement(this._element); | |||||
| $(this._element).one(Util.TRANSITION_END, function (event) { | |||||
| return _this2._hideModal(event); | |||||
| }).emulateTransitionEnd(transitionDuration); | |||||
| } else { | |||||
| this._hideModal(); | |||||
| } | |||||
| }; | |||||
| _proto.dispose = function dispose() { | |||||
| [window, this._element, this._dialog].forEach(function (htmlElement) { | |||||
| return $(htmlElement).off(EVENT_KEY); | |||||
| }); | |||||
| /** | |||||
| * `document` has 2 events `Event.FOCUSIN` and `Event.CLICK_DATA_API` | |||||
| * Do not move `document` in `htmlElements` array | |||||
| * It will remove `Event.CLICK_DATA_API` event that should remain | |||||
| */ | |||||
| $(document).off(Event.FOCUSIN); | |||||
| $.removeData(this._element, DATA_KEY); | |||||
| this._config = null; | |||||
| this._element = null; | |||||
| this._dialog = null; | |||||
| this._backdrop = null; | |||||
| this._isShown = null; | |||||
| this._isBodyOverflowing = null; | |||||
| this._ignoreBackdropClick = null; | |||||
| this._isTransitioning = null; | |||||
| this._scrollbarWidth = null; | |||||
| }; | |||||
| _proto.handleUpdate = function handleUpdate() { | |||||
| this._adjustDialog(); | |||||
| } // Private | |||||
| ; | |||||
| _proto._getConfig = function _getConfig(config) { | |||||
| config = _objectSpread2({}, Default, {}, config); | |||||
| Util.typeCheckConfig(NAME, config, DefaultType); | |||||
| return config; | |||||
| }; | |||||
| _proto._triggerBackdropTransition = function _triggerBackdropTransition() { | |||||
| var _this3 = this; | |||||
| if (this._config.backdrop === 'static') { | |||||
| var hideEventPrevented = $.Event(Event.HIDE_PREVENTED); | |||||
| $(this._element).trigger(hideEventPrevented); | |||||
| if (hideEventPrevented.defaultPrevented) { | |||||
| return; | |||||
| } | |||||
| this._element.classList.add(ClassName.STATIC); | |||||
| var modalTransitionDuration = Util.getTransitionDurationFromElement(this._element); | |||||
| $(this._element).one(Util.TRANSITION_END, function () { | |||||
| _this3._element.classList.remove(ClassName.STATIC); | |||||
| }).emulateTransitionEnd(modalTransitionDuration); | |||||
| this._element.focus(); | |||||
| } else { | |||||
| this.hide(); | |||||
| } | |||||
| }; | |||||
| _proto._showElement = function _showElement(relatedTarget) { | |||||
| var _this4 = this; | |||||
| var transition = $(this._element).hasClass(ClassName.FADE); | |||||
| var modalBody = this._dialog ? this._dialog.querySelector(Selector.MODAL_BODY) : null; | |||||
| if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) { | |||||
| // Don't move modal's DOM position | |||||
| document.body.appendChild(this._element); | |||||
| } | |||||
| this._element.style.display = 'block'; | |||||
| this._element.removeAttribute('aria-hidden'); | |||||
| this._element.setAttribute('aria-modal', true); | |||||
| if ($(this._dialog).hasClass(ClassName.SCROLLABLE) && modalBody) { | |||||
| modalBody.scrollTop = 0; | |||||
| } else { | |||||
| this._element.scrollTop = 0; | |||||
| } | |||||
| if (transition) { | |||||
| Util.reflow(this._element); | |||||
| } | |||||
| $(this._element).addClass(ClassName.SHOW); | |||||
| if (this._config.focus) { | |||||
| this._enforceFocus(); | |||||
| } | |||||
| var shownEvent = $.Event(Event.SHOWN, { | |||||
| relatedTarget: relatedTarget | |||||
| }); | |||||
| var transitionComplete = function transitionComplete() { | |||||
| if (_this4._config.focus) { | |||||
| _this4._element.focus(); | |||||
| } | |||||
| _this4._isTransitioning = false; | |||||
| $(_this4._element).trigger(shownEvent); | |||||
| }; | |||||
| if (transition) { | |||||
| var transitionDuration = Util.getTransitionDurationFromElement(this._dialog); | |||||
| $(this._dialog).one(Util.TRANSITION_END, transitionComplete).emulateTransitionEnd(transitionDuration); | |||||
| } else { | |||||
| transitionComplete(); | |||||
| } | |||||
| }; | |||||
| _proto._enforceFocus = function _enforceFocus() { | |||||
| var _this5 = this; | |||||
| $(document).off(Event.FOCUSIN) // Guard against infinite focus loop | |||||
| .on(Event.FOCUSIN, function (event) { | |||||
| if (document !== event.target && _this5._element !== event.target && $(_this5._element).has(event.target).length === 0) { | |||||
| _this5._element.focus(); | |||||
| } | |||||
| }); | |||||
| }; | |||||
| _proto._setEscapeEvent = function _setEscapeEvent() { | |||||
| var _this6 = this; | |||||
| if (this._isShown && this._config.keyboard) { | |||||
| $(this._element).on(Event.KEYDOWN_DISMISS, function (event) { | |||||
| if (event.which === ESCAPE_KEYCODE) { | |||||
| _this6._triggerBackdropTransition(); | |||||
| } | |||||
| }); | |||||
| } else if (!this._isShown) { | |||||
| $(this._element).off(Event.KEYDOWN_DISMISS); | |||||
| } | |||||
| }; | |||||
| _proto._setResizeEvent = function _setResizeEvent() { | |||||
| var _this7 = this; | |||||
| if (this._isShown) { | |||||
| $(window).on(Event.RESIZE, function (event) { | |||||
| return _this7.handleUpdate(event); | |||||
| }); | |||||
| } else { | |||||
| $(window).off(Event.RESIZE); | |||||
| } | |||||
| }; | |||||
| _proto._hideModal = function _hideModal() { | |||||
| var _this8 = this; | |||||
| this._element.style.display = 'none'; | |||||
| this._element.setAttribute('aria-hidden', true); | |||||
| this._element.removeAttribute('aria-modal'); | |||||
| this._isTransitioning = false; | |||||
| this._showBackdrop(function () { | |||||
| $(document.body).removeClass(ClassName.OPEN); | |||||
| _this8._resetAdjustments(); | |||||
| _this8._resetScrollbar(); | |||||
| $(_this8._element).trigger(Event.HIDDEN); | |||||
| }); | |||||
| }; | |||||
| _proto._removeBackdrop = function _removeBackdrop() { | |||||
| if (this._backdrop) { | |||||
| $(this._backdrop).remove(); | |||||
| this._backdrop = null; | |||||
| } | |||||
| }; | |||||
| _proto._showBackdrop = function _showBackdrop(callback) { | |||||
| var _this9 = this; | |||||
| var animate = $(this._element).hasClass(ClassName.FADE) ? ClassName.FADE : ''; | |||||
| if (this._isShown && this._config.backdrop) { | |||||
| this._backdrop = document.createElement('div'); | |||||
| this._backdrop.className = ClassName.BACKDROP; | |||||
| if (animate) { | |||||
| this._backdrop.classList.add(animate); | |||||
| } | |||||
| $(this._backdrop).appendTo(document.body); | |||||
| $(this._element).on(Event.CLICK_DISMISS, function (event) { | |||||
| if (_this9._ignoreBackdropClick) { | |||||
| _this9._ignoreBackdropClick = false; | |||||
| return; | |||||
| } | |||||
| if (event.target !== event.currentTarget) { | |||||
| return; | |||||
| } | |||||
| _this9._triggerBackdropTransition(); | |||||
| }); | |||||
| if (animate) { | |||||
| Util.reflow(this._backdrop); | |||||
| } | |||||
| $(this._backdrop).addClass(ClassName.SHOW); | |||||
| if (!callback) { | |||||
| return; | |||||
| } | |||||
| if (!animate) { | |||||
| callback(); | |||||
| return; | |||||
| } | |||||
| var backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop); | |||||
| $(this._backdrop).one(Util.TRANSITION_END, callback).emulateTransitionEnd(backdropTransitionDuration); | |||||
| } else if (!this._isShown && this._backdrop) { | |||||
| $(this._backdrop).removeClass(ClassName.SHOW); | |||||
| var callbackRemove = function callbackRemove() { | |||||
| _this9._removeBackdrop(); | |||||
| if (callback) { | |||||
| callback(); | |||||
| } | |||||
| }; | |||||
| if ($(this._element).hasClass(ClassName.FADE)) { | |||||
| var _backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop); | |||||
| $(this._backdrop).one(Util.TRANSITION_END, callbackRemove).emulateTransitionEnd(_backdropTransitionDuration); | |||||
| } else { | |||||
| callbackRemove(); | |||||
| } | |||||
| } else if (callback) { | |||||
| callback(); | |||||
| } | |||||
| } // ---------------------------------------------------------------------- | |||||
| // the following methods are used to handle overflowing modals | |||||
| // todo (fat): these should probably be refactored out of modal.js | |||||
| // ---------------------------------------------------------------------- | |||||
| ; | |||||
| _proto._adjustDialog = function _adjustDialog() { | |||||
| var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; | |||||
| if (!this._isBodyOverflowing && isModalOverflowing) { | |||||
| this._element.style.paddingLeft = this._scrollbarWidth + "px"; | |||||
| } | |||||
| if (this._isBodyOverflowing && !isModalOverflowing) { | |||||
| this._element.style.paddingRight = this._scrollbarWidth + "px"; | |||||
| } | |||||
| }; | |||||
| _proto._resetAdjustments = function _resetAdjustments() { | |||||
| this._element.style.paddingLeft = ''; | |||||
| this._element.style.paddingRight = ''; | |||||
| }; | |||||
| _proto._checkScrollbar = function _checkScrollbar() { | |||||
| var rect = document.body.getBoundingClientRect(); | |||||
| this._isBodyOverflowing = rect.left + rect.right < window.innerWidth; | |||||
| this._scrollbarWidth = this._getScrollbarWidth(); | |||||
| }; | |||||
| _proto._setScrollbar = function _setScrollbar() { | |||||
| var _this10 = this; | |||||
| if (this._isBodyOverflowing) { | |||||
| // Note: DOMNode.style.paddingRight returns the actual value or '' if not set | |||||
| // while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set | |||||
| var fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT)); | |||||
| var stickyContent = [].slice.call(document.querySelectorAll(Selector.STICKY_CONTENT)); // Adjust fixed content padding | |||||
| $(fixedContent).each(function (index, element) { | |||||
| var actualPadding = element.style.paddingRight; | |||||
| var calculatedPadding = $(element).css('padding-right'); | |||||
| $(element).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + _this10._scrollbarWidth + "px"); | |||||
| }); // Adjust sticky content margin | |||||
| $(stickyContent).each(function (index, element) { | |||||
| var actualMargin = element.style.marginRight; | |||||
| var calculatedMargin = $(element).css('margin-right'); | |||||
| $(element).data('margin-right', actualMargin).css('margin-right', parseFloat(calculatedMargin) - _this10._scrollbarWidth + "px"); | |||||
| }); // Adjust body padding | |||||
| var actualPadding = document.body.style.paddingRight; | |||||
| var calculatedPadding = $(document.body).css('padding-right'); | |||||
| $(document.body).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + this._scrollbarWidth + "px"); | |||||
| } | |||||
| $(document.body).addClass(ClassName.OPEN); | |||||
| }; | |||||
| _proto._resetScrollbar = function _resetScrollbar() { | |||||
| // Restore fixed content padding | |||||
| var fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT)); | |||||
| $(fixedContent).each(function (index, element) { | |||||
| var padding = $(element).data('padding-right'); | |||||
| $(element).removeData('padding-right'); | |||||
| element.style.paddingRight = padding ? padding : ''; | |||||
| }); // Restore sticky content | |||||
| var elements = [].slice.call(document.querySelectorAll("" + Selector.STICKY_CONTENT)); | |||||
| $(elements).each(function (index, element) { | |||||
| var margin = $(element).data('margin-right'); | |||||
| if (typeof margin !== 'undefined') { | |||||
| $(element).css('margin-right', margin).removeData('margin-right'); | |||||
| } | |||||
| }); // Restore body padding | |||||
| var padding = $(document.body).data('padding-right'); | |||||
| $(document.body).removeData('padding-right'); | |||||
| document.body.style.paddingRight = padding ? padding : ''; | |||||
| }; | |||||
| _proto._getScrollbarWidth = function _getScrollbarWidth() { | |||||
| // thx d.walsh | |||||
| var scrollDiv = document.createElement('div'); | |||||
| scrollDiv.className = ClassName.SCROLLBAR_MEASURER; | |||||
| document.body.appendChild(scrollDiv); | |||||
| var scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth; | |||||
| document.body.removeChild(scrollDiv); | |||||
| return scrollbarWidth; | |||||
| } // Static | |||||
| ; | |||||
| Modal._jQueryInterface = function _jQueryInterface(config, relatedTarget) { | |||||
| return this.each(function () { | |||||
| var data = $(this).data(DATA_KEY); | |||||
| var _config = _objectSpread2({}, Default, {}, $(this).data(), {}, typeof config === 'object' && config ? config : {}); | |||||
| if (!data) { | |||||
| data = new Modal(this, _config); | |||||
| $(this).data(DATA_KEY, data); | |||||
| } | |||||
| if (typeof config === 'string') { | |||||
| if (typeof data[config] === 'undefined') { | |||||
| throw new TypeError("No method named \"" + config + "\""); | |||||
| } | |||||
| data[config](relatedTarget); | |||||
| } else if (_config.show) { | |||||
| data.show(relatedTarget); | |||||
| } | |||||
| }); | |||||
| }; | |||||
| _createClass(Modal, null, [{ | |||||
| key: "VERSION", | |||||
| get: function get() { | |||||
| return VERSION; | |||||
| } | |||||
| }, { | |||||
| key: "Default", | |||||
| get: function get() { | |||||
| return Default; | |||||
| } | |||||
| }]); | |||||
| return Modal; | |||||
| }(); | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Data Api implementation | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { | |||||
| var _this11 = this; | |||||
| var target; | |||||
| var selector = Util.getSelectorFromElement(this); | |||||
| if (selector) { | |||||
| target = document.querySelector(selector); | |||||
| } | |||||
| var config = $(target).data(DATA_KEY) ? 'toggle' : _objectSpread2({}, $(target).data(), {}, $(this).data()); | |||||
| if (this.tagName === 'A' || this.tagName === 'AREA') { | |||||
| event.preventDefault(); | |||||
| } | |||||
| var $target = $(target).one(Event.SHOW, function (showEvent) { | |||||
| if (showEvent.isDefaultPrevented()) { | |||||
| // Only register focus restorer if modal will actually get shown | |||||
| return; | |||||
| } | |||||
| $target.one(Event.HIDDEN, function () { | |||||
| if ($(_this11).is(':visible')) { | |||||
| _this11.focus(); | |||||
| } | |||||
| }); | |||||
| }); | |||||
| Modal._jQueryInterface.call($(target), config, this); | |||||
| }); | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * jQuery | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $.fn[NAME] = Modal._jQueryInterface; | |||||
| $.fn[NAME].Constructor = Modal; | |||||
| $.fn[NAME].noConflict = function () { | |||||
| $.fn[NAME] = JQUERY_NO_CONFLICT; | |||||
| return Modal._jQueryInterface; | |||||
| }; | |||||
| return Modal; | |||||
| }))); | |||||
| //# sourceMappingURL=modal.js.map | |||||
| @ -0,0 +1,275 @@ | |||||
| /*! | |||||
| * Bootstrap popover.js v4.4.1 (https://getbootstrap.com/) | |||||
| * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| */ | |||||
| (function (global, factory) { | |||||
| typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('./tooltip.js')) : | |||||
| typeof define === 'function' && define.amd ? define(['jquery', './tooltip.js'], factory) : | |||||
| (global = global || self, global.Popover = factory(global.jQuery, global.Tooltip)); | |||||
| }(this, (function ($, Tooltip) { 'use strict'; | |||||
| $ = $ && $.hasOwnProperty('default') ? $['default'] : $; | |||||
| Tooltip = Tooltip && Tooltip.hasOwnProperty('default') ? Tooltip['default'] : Tooltip; | |||||
| function _defineProperties(target, props) { | |||||
| for (var i = 0; i < props.length; i++) { | |||||
| var descriptor = props[i]; | |||||
| descriptor.enumerable = descriptor.enumerable || false; | |||||
| descriptor.configurable = true; | |||||
| if ("value" in descriptor) descriptor.writable = true; | |||||
| Object.defineProperty(target, descriptor.key, descriptor); | |||||
| } | |||||
| } | |||||
| function _createClass(Constructor, protoProps, staticProps) { | |||||
| if (protoProps) _defineProperties(Constructor.prototype, protoProps); | |||||
| if (staticProps) _defineProperties(Constructor, staticProps); | |||||
| return Constructor; | |||||
| } | |||||
| function _defineProperty(obj, key, value) { | |||||
| if (key in obj) { | |||||
| Object.defineProperty(obj, key, { | |||||
| value: value, | |||||
| enumerable: true, | |||||
| configurable: true, | |||||
| writable: true | |||||
| }); | |||||
| } else { | |||||
| obj[key] = value; | |||||
| } | |||||
| return obj; | |||||
| } | |||||
| function ownKeys(object, enumerableOnly) { | |||||
| var keys = Object.keys(object); | |||||
| if (Object.getOwnPropertySymbols) { | |||||
| var symbols = Object.getOwnPropertySymbols(object); | |||||
| if (enumerableOnly) symbols = symbols.filter(function (sym) { | |||||
| return Object.getOwnPropertyDescriptor(object, sym).enumerable; | |||||
| }); | |||||
| keys.push.apply(keys, symbols); | |||||
| } | |||||
| return keys; | |||||
| } | |||||
| function _objectSpread2(target) { | |||||
| for (var i = 1; i < arguments.length; i++) { | |||||
| var source = arguments[i] != null ? arguments[i] : {}; | |||||
| if (i % 2) { | |||||
| ownKeys(Object(source), true).forEach(function (key) { | |||||
| _defineProperty(target, key, source[key]); | |||||
| }); | |||||
| } else if (Object.getOwnPropertyDescriptors) { | |||||
| Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); | |||||
| } else { | |||||
| ownKeys(Object(source)).forEach(function (key) { | |||||
| Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); | |||||
| }); | |||||
| } | |||||
| } | |||||
| return target; | |||||
| } | |||||
| function _inheritsLoose(subClass, superClass) { | |||||
| subClass.prototype = Object.create(superClass.prototype); | |||||
| subClass.prototype.constructor = subClass; | |||||
| subClass.__proto__ = superClass; | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Constants | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| var NAME = 'popover'; | |||||
| var VERSION = '4.4.1'; | |||||
| var DATA_KEY = 'bs.popover'; | |||||
| var EVENT_KEY = "." + DATA_KEY; | |||||
| var JQUERY_NO_CONFLICT = $.fn[NAME]; | |||||
| var CLASS_PREFIX = 'bs-popover'; | |||||
| var BSCLS_PREFIX_REGEX = new RegExp("(^|\\s)" + CLASS_PREFIX + "\\S+", 'g'); | |||||
| var Default = _objectSpread2({}, Tooltip.Default, { | |||||
| placement: 'right', | |||||
| trigger: 'click', | |||||
| content: '', | |||||
| template: '<div class="popover" role="tooltip">' + '<div class="arrow"></div>' + '<h3 class="popover-header"></h3>' + '<div class="popover-body"></div></div>' | |||||
| }); | |||||
| var DefaultType = _objectSpread2({}, Tooltip.DefaultType, { | |||||
| content: '(string|element|function)' | |||||
| }); | |||||
| var ClassName = { | |||||
| FADE: 'fade', | |||||
| SHOW: 'show' | |||||
| }; | |||||
| var Selector = { | |||||
| TITLE: '.popover-header', | |||||
| CONTENT: '.popover-body' | |||||
| }; | |||||
| var Event = { | |||||
| HIDE: "hide" + EVENT_KEY, | |||||
| HIDDEN: "hidden" + EVENT_KEY, | |||||
| SHOW: "show" + EVENT_KEY, | |||||
| SHOWN: "shown" + EVENT_KEY, | |||||
| INSERTED: "inserted" + EVENT_KEY, | |||||
| CLICK: "click" + EVENT_KEY, | |||||
| FOCUSIN: "focusin" + EVENT_KEY, | |||||
| FOCUSOUT: "focusout" + EVENT_KEY, | |||||
| MOUSEENTER: "mouseenter" + EVENT_KEY, | |||||
| MOUSELEAVE: "mouseleave" + EVENT_KEY | |||||
| }; | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Class Definition | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| var Popover = | |||||
| /*#__PURE__*/ | |||||
| function (_Tooltip) { | |||||
| _inheritsLoose(Popover, _Tooltip); | |||||
| function Popover() { | |||||
| return _Tooltip.apply(this, arguments) || this; | |||||
| } | |||||
| var _proto = Popover.prototype; | |||||
| // Overrides | |||||
| _proto.isWithContent = function isWithContent() { | |||||
| return this.getTitle() || this._getContent(); | |||||
| }; | |||||
| _proto.addAttachmentClass = function addAttachmentClass(attachment) { | |||||
| $(this.getTipElement()).addClass(CLASS_PREFIX + "-" + attachment); | |||||
| }; | |||||
| _proto.getTipElement = function getTipElement() { | |||||
| this.tip = this.tip || $(this.config.template)[0]; | |||||
| return this.tip; | |||||
| }; | |||||
| _proto.setContent = function setContent() { | |||||
| var $tip = $(this.getTipElement()); // We use append for html objects to maintain js events | |||||
| this.setElementContent($tip.find(Selector.TITLE), this.getTitle()); | |||||
| var content = this._getContent(); | |||||
| if (typeof content === 'function') { | |||||
| content = content.call(this.element); | |||||
| } | |||||
| this.setElementContent($tip.find(Selector.CONTENT), content); | |||||
| $tip.removeClass(ClassName.FADE + " " + ClassName.SHOW); | |||||
| } // Private | |||||
| ; | |||||
| _proto._getContent = function _getContent() { | |||||
| return this.element.getAttribute('data-content') || this.config.content; | |||||
| }; | |||||
| _proto._cleanTipClass = function _cleanTipClass() { | |||||
| var $tip = $(this.getTipElement()); | |||||
| var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX); | |||||
| if (tabClass !== null && tabClass.length > 0) { | |||||
| $tip.removeClass(tabClass.join('')); | |||||
| } | |||||
| } // Static | |||||
| ; | |||||
| Popover._jQueryInterface = function _jQueryInterface(config) { | |||||
| return this.each(function () { | |||||
| var data = $(this).data(DATA_KEY); | |||||
| var _config = typeof config === 'object' ? config : null; | |||||
| if (!data && /dispose|hide/.test(config)) { | |||||
| return; | |||||
| } | |||||
| if (!data) { | |||||
| data = new Popover(this, _config); | |||||
| $(this).data(DATA_KEY, data); | |||||
| } | |||||
| if (typeof config === 'string') { | |||||
| if (typeof data[config] === 'undefined') { | |||||
| throw new TypeError("No method named \"" + config + "\""); | |||||
| } | |||||
| data[config](); | |||||
| } | |||||
| }); | |||||
| }; | |||||
| _createClass(Popover, null, [{ | |||||
| key: "VERSION", | |||||
| // Getters | |||||
| get: function get() { | |||||
| return VERSION; | |||||
| } | |||||
| }, { | |||||
| key: "Default", | |||||
| get: function get() { | |||||
| return Default; | |||||
| } | |||||
| }, { | |||||
| key: "NAME", | |||||
| get: function get() { | |||||
| return NAME; | |||||
| } | |||||
| }, { | |||||
| key: "DATA_KEY", | |||||
| get: function get() { | |||||
| return DATA_KEY; | |||||
| } | |||||
| }, { | |||||
| key: "Event", | |||||
| get: function get() { | |||||
| return Event; | |||||
| } | |||||
| }, { | |||||
| key: "EVENT_KEY", | |||||
| get: function get() { | |||||
| return EVENT_KEY; | |||||
| } | |||||
| }, { | |||||
| key: "DefaultType", | |||||
| get: function get() { | |||||
| return DefaultType; | |||||
| } | |||||
| }]); | |||||
| return Popover; | |||||
| }(Tooltip); | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * jQuery | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $.fn[NAME] = Popover._jQueryInterface; | |||||
| $.fn[NAME].Constructor = Popover; | |||||
| $.fn[NAME].noConflict = function () { | |||||
| $.fn[NAME] = JQUERY_NO_CONFLICT; | |||||
| return Popover._jQueryInterface; | |||||
| }; | |||||
| return Popover; | |||||
| }))); | |||||
| //# sourceMappingURL=popover.js.map | |||||
| @ -0,0 +1,389 @@ | |||||
| /*! | |||||
| * Bootstrap scrollspy.js v4.4.1 (https://getbootstrap.com/) | |||||
| * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| */ | |||||
| (function (global, factory) { | |||||
| typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('./util.js')) : | |||||
| typeof define === 'function' && define.amd ? define(['jquery', './util.js'], factory) : | |||||
| (global = global || self, global.ScrollSpy = factory(global.jQuery, global.Util)); | |||||
| }(this, (function ($, Util) { 'use strict'; | |||||
| $ = $ && $.hasOwnProperty('default') ? $['default'] : $; | |||||
| Util = Util && Util.hasOwnProperty('default') ? Util['default'] : Util; | |||||
| function _defineProperties(target, props) { | |||||
| for (var i = 0; i < props.length; i++) { | |||||
| var descriptor = props[i]; | |||||
| descriptor.enumerable = descriptor.enumerable || false; | |||||
| descriptor.configurable = true; | |||||
| if ("value" in descriptor) descriptor.writable = true; | |||||
| Object.defineProperty(target, descriptor.key, descriptor); | |||||
| } | |||||
| } | |||||
| function _createClass(Constructor, protoProps, staticProps) { | |||||
| if (protoProps) _defineProperties(Constructor.prototype, protoProps); | |||||
| if (staticProps) _defineProperties(Constructor, staticProps); | |||||
| return Constructor; | |||||
| } | |||||
| function _defineProperty(obj, key, value) { | |||||
| if (key in obj) { | |||||
| Object.defineProperty(obj, key, { | |||||
| value: value, | |||||
| enumerable: true, | |||||
| configurable: true, | |||||
| writable: true | |||||
| }); | |||||
| } else { | |||||
| obj[key] = value; | |||||
| } | |||||
| return obj; | |||||
| } | |||||
| function ownKeys(object, enumerableOnly) { | |||||
| var keys = Object.keys(object); | |||||
| if (Object.getOwnPropertySymbols) { | |||||
| var symbols = Object.getOwnPropertySymbols(object); | |||||
| if (enumerableOnly) symbols = symbols.filter(function (sym) { | |||||
| return Object.getOwnPropertyDescriptor(object, sym).enumerable; | |||||
| }); | |||||
| keys.push.apply(keys, symbols); | |||||
| } | |||||
| return keys; | |||||
| } | |||||
| function _objectSpread2(target) { | |||||
| for (var i = 1; i < arguments.length; i++) { | |||||
| var source = arguments[i] != null ? arguments[i] : {}; | |||||
| if (i % 2) { | |||||
| ownKeys(Object(source), true).forEach(function (key) { | |||||
| _defineProperty(target, key, source[key]); | |||||
| }); | |||||
| } else if (Object.getOwnPropertyDescriptors) { | |||||
| Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); | |||||
| } else { | |||||
| ownKeys(Object(source)).forEach(function (key) { | |||||
| Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); | |||||
| }); | |||||
| } | |||||
| } | |||||
| return target; | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Constants | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| var NAME = 'scrollspy'; | |||||
| var VERSION = '4.4.1'; | |||||
| var DATA_KEY = 'bs.scrollspy'; | |||||
| var EVENT_KEY = "." + DATA_KEY; | |||||
| var DATA_API_KEY = '.data-api'; | |||||
| var JQUERY_NO_CONFLICT = $.fn[NAME]; | |||||
| var Default = { | |||||
| offset: 10, | |||||
| method: 'auto', | |||||
| target: '' | |||||
| }; | |||||
| var DefaultType = { | |||||
| offset: 'number', | |||||
| method: 'string', | |||||
| target: '(string|element)' | |||||
| }; | |||||
| var Event = { | |||||
| ACTIVATE: "activate" + EVENT_KEY, | |||||
| SCROLL: "scroll" + EVENT_KEY, | |||||
| LOAD_DATA_API: "load" + EVENT_KEY + DATA_API_KEY | |||||
| }; | |||||
| var ClassName = { | |||||
| DROPDOWN_ITEM: 'dropdown-item', | |||||
| DROPDOWN_MENU: 'dropdown-menu', | |||||
| ACTIVE: 'active' | |||||
| }; | |||||
| var Selector = { | |||||
| DATA_SPY: '[data-spy="scroll"]', | |||||
| ACTIVE: '.active', | |||||
| NAV_LIST_GROUP: '.nav, .list-group', | |||||
| NAV_LINKS: '.nav-link', | |||||
| NAV_ITEMS: '.nav-item', | |||||
| LIST_ITEMS: '.list-group-item', | |||||
| DROPDOWN: '.dropdown', | |||||
| DROPDOWN_ITEMS: '.dropdown-item', | |||||
| DROPDOWN_TOGGLE: '.dropdown-toggle' | |||||
| }; | |||||
| var OffsetMethod = { | |||||
| OFFSET: 'offset', | |||||
| POSITION: 'position' | |||||
| }; | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Class Definition | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| var ScrollSpy = | |||||
| /*#__PURE__*/ | |||||
| function () { | |||||
| function ScrollSpy(element, config) { | |||||
| var _this = this; | |||||
| this._element = element; | |||||
| this._scrollElement = element.tagName === 'BODY' ? window : element; | |||||
| this._config = this._getConfig(config); | |||||
| this._selector = this._config.target + " " + Selector.NAV_LINKS + "," + (this._config.target + " " + Selector.LIST_ITEMS + ",") + (this._config.target + " " + Selector.DROPDOWN_ITEMS); | |||||
| this._offsets = []; | |||||
| this._targets = []; | |||||
| this._activeTarget = null; | |||||
| this._scrollHeight = 0; | |||||
| $(this._scrollElement).on(Event.SCROLL, function (event) { | |||||
| return _this._process(event); | |||||
| }); | |||||
| this.refresh(); | |||||
| this._process(); | |||||
| } // Getters | |||||
| var _proto = ScrollSpy.prototype; | |||||
| // Public | |||||
| _proto.refresh = function refresh() { | |||||
| var _this2 = this; | |||||
| var autoMethod = this._scrollElement === this._scrollElement.window ? OffsetMethod.OFFSET : OffsetMethod.POSITION; | |||||
| var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method; | |||||
| var offsetBase = offsetMethod === OffsetMethod.POSITION ? this._getScrollTop() : 0; | |||||
| this._offsets = []; | |||||
| this._targets = []; | |||||
| this._scrollHeight = this._getScrollHeight(); | |||||
| var targets = [].slice.call(document.querySelectorAll(this._selector)); | |||||
| targets.map(function (element) { | |||||
| var target; | |||||
| var targetSelector = Util.getSelectorFromElement(element); | |||||
| if (targetSelector) { | |||||
| target = document.querySelector(targetSelector); | |||||
| } | |||||
| if (target) { | |||||
| var targetBCR = target.getBoundingClientRect(); | |||||
| if (targetBCR.width || targetBCR.height) { | |||||
| // TODO (fat): remove sketch reliance on jQuery position/offset | |||||
| return [$(target)[offsetMethod]().top + offsetBase, targetSelector]; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| }).filter(function (item) { | |||||
| return item; | |||||
| }).sort(function (a, b) { | |||||
| return a[0] - b[0]; | |||||
| }).forEach(function (item) { | |||||
| _this2._offsets.push(item[0]); | |||||
| _this2._targets.push(item[1]); | |||||
| }); | |||||
| }; | |||||
| _proto.dispose = function dispose() { | |||||
| $.removeData(this._element, DATA_KEY); | |||||
| $(this._scrollElement).off(EVENT_KEY); | |||||
| this._element = null; | |||||
| this._scrollElement = null; | |||||
| this._config = null; | |||||
| this._selector = null; | |||||
| this._offsets = null; | |||||
| this._targets = null; | |||||
| this._activeTarget = null; | |||||
| this._scrollHeight = null; | |||||
| } // Private | |||||
| ; | |||||
| _proto._getConfig = function _getConfig(config) { | |||||
| config = _objectSpread2({}, Default, {}, typeof config === 'object' && config ? config : {}); | |||||
| if (typeof config.target !== 'string') { | |||||
| var id = $(config.target).attr('id'); | |||||
| if (!id) { | |||||
| id = Util.getUID(NAME); | |||||
| $(config.target).attr('id', id); | |||||
| } | |||||
| config.target = "#" + id; | |||||
| } | |||||
| Util.typeCheckConfig(NAME, config, DefaultType); | |||||
| return config; | |||||
| }; | |||||
| _proto._getScrollTop = function _getScrollTop() { | |||||
| return this._scrollElement === window ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop; | |||||
| }; | |||||
| _proto._getScrollHeight = function _getScrollHeight() { | |||||
| return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight); | |||||
| }; | |||||
| _proto._getOffsetHeight = function _getOffsetHeight() { | |||||
| return this._scrollElement === window ? window.innerHeight : this._scrollElement.getBoundingClientRect().height; | |||||
| }; | |||||
| _proto._process = function _process() { | |||||
| var scrollTop = this._getScrollTop() + this._config.offset; | |||||
| var scrollHeight = this._getScrollHeight(); | |||||
| var maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight(); | |||||
| if (this._scrollHeight !== scrollHeight) { | |||||
| this.refresh(); | |||||
| } | |||||
| if (scrollTop >= maxScroll) { | |||||
| var target = this._targets[this._targets.length - 1]; | |||||
| if (this._activeTarget !== target) { | |||||
| this._activate(target); | |||||
| } | |||||
| return; | |||||
| } | |||||
| if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) { | |||||
| this._activeTarget = null; | |||||
| this._clear(); | |||||
| return; | |||||
| } | |||||
| var offsetLength = this._offsets.length; | |||||
| for (var i = offsetLength; i--;) { | |||||
| var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (typeof this._offsets[i + 1] === 'undefined' || scrollTop < this._offsets[i + 1]); | |||||
| if (isActiveTarget) { | |||||
| this._activate(this._targets[i]); | |||||
| } | |||||
| } | |||||
| }; | |||||
| _proto._activate = function _activate(target) { | |||||
| this._activeTarget = target; | |||||
| this._clear(); | |||||
| var queries = this._selector.split(',').map(function (selector) { | |||||
| return selector + "[data-target=\"" + target + "\"]," + selector + "[href=\"" + target + "\"]"; | |||||
| }); | |||||
| var $link = $([].slice.call(document.querySelectorAll(queries.join(',')))); | |||||
| if ($link.hasClass(ClassName.DROPDOWN_ITEM)) { | |||||
| $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE); | |||||
| $link.addClass(ClassName.ACTIVE); | |||||
| } else { | |||||
| // Set triggered link as active | |||||
| $link.addClass(ClassName.ACTIVE); // Set triggered links parents as active | |||||
| // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor | |||||
| $link.parents(Selector.NAV_LIST_GROUP).prev(Selector.NAV_LINKS + ", " + Selector.LIST_ITEMS).addClass(ClassName.ACTIVE); // Handle special case when .nav-link is inside .nav-item | |||||
| $link.parents(Selector.NAV_LIST_GROUP).prev(Selector.NAV_ITEMS).children(Selector.NAV_LINKS).addClass(ClassName.ACTIVE); | |||||
| } | |||||
| $(this._scrollElement).trigger(Event.ACTIVATE, { | |||||
| relatedTarget: target | |||||
| }); | |||||
| }; | |||||
| _proto._clear = function _clear() { | |||||
| [].slice.call(document.querySelectorAll(this._selector)).filter(function (node) { | |||||
| return node.classList.contains(ClassName.ACTIVE); | |||||
| }).forEach(function (node) { | |||||
| return node.classList.remove(ClassName.ACTIVE); | |||||
| }); | |||||
| } // Static | |||||
| ; | |||||
| ScrollSpy._jQueryInterface = function _jQueryInterface(config) { | |||||
| return this.each(function () { | |||||
| var data = $(this).data(DATA_KEY); | |||||
| var _config = typeof config === 'object' && config; | |||||
| if (!data) { | |||||
| data = new ScrollSpy(this, _config); | |||||
| $(this).data(DATA_KEY, data); | |||||
| } | |||||
| if (typeof config === 'string') { | |||||
| if (typeof data[config] === 'undefined') { | |||||
| throw new TypeError("No method named \"" + config + "\""); | |||||
| } | |||||
| data[config](); | |||||
| } | |||||
| }); | |||||
| }; | |||||
| _createClass(ScrollSpy, null, [{ | |||||
| key: "VERSION", | |||||
| get: function get() { | |||||
| return VERSION; | |||||
| } | |||||
| }, { | |||||
| key: "Default", | |||||
| get: function get() { | |||||
| return Default; | |||||
| } | |||||
| }]); | |||||
| return ScrollSpy; | |||||
| }(); | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Data Api implementation | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $(window).on(Event.LOAD_DATA_API, function () { | |||||
| var scrollSpys = [].slice.call(document.querySelectorAll(Selector.DATA_SPY)); | |||||
| var scrollSpysLength = scrollSpys.length; | |||||
| for (var i = scrollSpysLength; i--;) { | |||||
| var $spy = $(scrollSpys[i]); | |||||
| ScrollSpy._jQueryInterface.call($spy, $spy.data()); | |||||
| } | |||||
| }); | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * jQuery | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $.fn[NAME] = ScrollSpy._jQueryInterface; | |||||
| $.fn[NAME].Constructor = ScrollSpy; | |||||
| $.fn[NAME].noConflict = function () { | |||||
| $.fn[NAME] = JQUERY_NO_CONFLICT; | |||||
| return ScrollSpy._jQueryInterface; | |||||
| }; | |||||
| return ScrollSpy; | |||||
| }))); | |||||
| //# sourceMappingURL=scrollspy.js.map | |||||
| @ -0,0 +1,268 @@ | |||||
| /*! | |||||
| * Bootstrap tab.js v4.4.1 (https://getbootstrap.com/) | |||||
| * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| */ | |||||
| (function (global, factory) { | |||||
| typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('./util.js')) : | |||||
| typeof define === 'function' && define.amd ? define(['jquery', './util.js'], factory) : | |||||
| (global = global || self, global.Tab = factory(global.jQuery, global.Util)); | |||||
| }(this, (function ($, Util) { 'use strict'; | |||||
| $ = $ && $.hasOwnProperty('default') ? $['default'] : $; | |||||
| Util = Util && Util.hasOwnProperty('default') ? Util['default'] : Util; | |||||
| function _defineProperties(target, props) { | |||||
| for (var i = 0; i < props.length; i++) { | |||||
| var descriptor = props[i]; | |||||
| descriptor.enumerable = descriptor.enumerable || false; | |||||
| descriptor.configurable = true; | |||||
| if ("value" in descriptor) descriptor.writable = true; | |||||
| Object.defineProperty(target, descriptor.key, descriptor); | |||||
| } | |||||
| } | |||||
| function _createClass(Constructor, protoProps, staticProps) { | |||||
| if (protoProps) _defineProperties(Constructor.prototype, protoProps); | |||||
| if (staticProps) _defineProperties(Constructor, staticProps); | |||||
| return Constructor; | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Constants | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| var NAME = 'tab'; | |||||
| var VERSION = '4.4.1'; | |||||
| var DATA_KEY = 'bs.tab'; | |||||
| var EVENT_KEY = "." + DATA_KEY; | |||||
| var DATA_API_KEY = '.data-api'; | |||||
| var JQUERY_NO_CONFLICT = $.fn[NAME]; | |||||
| var Event = { | |||||
| HIDE: "hide" + EVENT_KEY, | |||||
| HIDDEN: "hidden" + EVENT_KEY, | |||||
| SHOW: "show" + EVENT_KEY, | |||||
| SHOWN: "shown" + EVENT_KEY, | |||||
| CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY | |||||
| }; | |||||
| var ClassName = { | |||||
| DROPDOWN_MENU: 'dropdown-menu', | |||||
| ACTIVE: 'active', | |||||
| DISABLED: 'disabled', | |||||
| FADE: 'fade', | |||||
| SHOW: 'show' | |||||
| }; | |||||
| var Selector = { | |||||
| DROPDOWN: '.dropdown', | |||||
| NAV_LIST_GROUP: '.nav, .list-group', | |||||
| ACTIVE: '.active', | |||||
| ACTIVE_UL: '> li > .active', | |||||
| DATA_TOGGLE: '[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]', | |||||
| DROPDOWN_TOGGLE: '.dropdown-toggle', | |||||
| DROPDOWN_ACTIVE_CHILD: '> .dropdown-menu .active' | |||||
| }; | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Class Definition | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| var Tab = | |||||
| /*#__PURE__*/ | |||||
| function () { | |||||
| function Tab(element) { | |||||
| this._element = element; | |||||
| } // Getters | |||||
| var _proto = Tab.prototype; | |||||
| // Public | |||||
| _proto.show = function show() { | |||||
| var _this = this; | |||||
| if (this._element.parentNode && this._element.parentNode.nodeType === Node.ELEMENT_NODE && $(this._element).hasClass(ClassName.ACTIVE) || $(this._element).hasClass(ClassName.DISABLED)) { | |||||
| return; | |||||
| } | |||||
| var target; | |||||
| var previous; | |||||
| var listElement = $(this._element).closest(Selector.NAV_LIST_GROUP)[0]; | |||||
| var selector = Util.getSelectorFromElement(this._element); | |||||
| if (listElement) { | |||||
| var itemSelector = listElement.nodeName === 'UL' || listElement.nodeName === 'OL' ? Selector.ACTIVE_UL : Selector.ACTIVE; | |||||
| previous = $.makeArray($(listElement).find(itemSelector)); | |||||
| previous = previous[previous.length - 1]; | |||||
| } | |||||
| var hideEvent = $.Event(Event.HIDE, { | |||||
| relatedTarget: this._element | |||||
| }); | |||||
| var showEvent = $.Event(Event.SHOW, { | |||||
| relatedTarget: previous | |||||
| }); | |||||
| if (previous) { | |||||
| $(previous).trigger(hideEvent); | |||||
| } | |||||
| $(this._element).trigger(showEvent); | |||||
| if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) { | |||||
| return; | |||||
| } | |||||
| if (selector) { | |||||
| target = document.querySelector(selector); | |||||
| } | |||||
| this._activate(this._element, listElement); | |||||
| var complete = function complete() { | |||||
| var hiddenEvent = $.Event(Event.HIDDEN, { | |||||
| relatedTarget: _this._element | |||||
| }); | |||||
| var shownEvent = $.Event(Event.SHOWN, { | |||||
| relatedTarget: previous | |||||
| }); | |||||
| $(previous).trigger(hiddenEvent); | |||||
| $(_this._element).trigger(shownEvent); | |||||
| }; | |||||
| if (target) { | |||||
| this._activate(target, target.parentNode, complete); | |||||
| } else { | |||||
| complete(); | |||||
| } | |||||
| }; | |||||
| _proto.dispose = function dispose() { | |||||
| $.removeData(this._element, DATA_KEY); | |||||
| this._element = null; | |||||
| } // Private | |||||
| ; | |||||
| _proto._activate = function _activate(element, container, callback) { | |||||
| var _this2 = this; | |||||
| var activeElements = container && (container.nodeName === 'UL' || container.nodeName === 'OL') ? $(container).find(Selector.ACTIVE_UL) : $(container).children(Selector.ACTIVE); | |||||
| var active = activeElements[0]; | |||||
| var isTransitioning = callback && active && $(active).hasClass(ClassName.FADE); | |||||
| var complete = function complete() { | |||||
| return _this2._transitionComplete(element, active, callback); | |||||
| }; | |||||
| if (active && isTransitioning) { | |||||
| var transitionDuration = Util.getTransitionDurationFromElement(active); | |||||
| $(active).removeClass(ClassName.SHOW).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration); | |||||
| } else { | |||||
| complete(); | |||||
| } | |||||
| }; | |||||
| _proto._transitionComplete = function _transitionComplete(element, active, callback) { | |||||
| if (active) { | |||||
| $(active).removeClass(ClassName.ACTIVE); | |||||
| var dropdownChild = $(active.parentNode).find(Selector.DROPDOWN_ACTIVE_CHILD)[0]; | |||||
| if (dropdownChild) { | |||||
| $(dropdownChild).removeClass(ClassName.ACTIVE); | |||||
| } | |||||
| if (active.getAttribute('role') === 'tab') { | |||||
| active.setAttribute('aria-selected', false); | |||||
| } | |||||
| } | |||||
| $(element).addClass(ClassName.ACTIVE); | |||||
| if (element.getAttribute('role') === 'tab') { | |||||
| element.setAttribute('aria-selected', true); | |||||
| } | |||||
| Util.reflow(element); | |||||
| if (element.classList.contains(ClassName.FADE)) { | |||||
| element.classList.add(ClassName.SHOW); | |||||
| } | |||||
| if (element.parentNode && $(element.parentNode).hasClass(ClassName.DROPDOWN_MENU)) { | |||||
| var dropdownElement = $(element).closest(Selector.DROPDOWN)[0]; | |||||
| if (dropdownElement) { | |||||
| var dropdownToggleList = [].slice.call(dropdownElement.querySelectorAll(Selector.DROPDOWN_TOGGLE)); | |||||
| $(dropdownToggleList).addClass(ClassName.ACTIVE); | |||||
| } | |||||
| element.setAttribute('aria-expanded', true); | |||||
| } | |||||
| if (callback) { | |||||
| callback(); | |||||
| } | |||||
| } // Static | |||||
| ; | |||||
| Tab._jQueryInterface = function _jQueryInterface(config) { | |||||
| return this.each(function () { | |||||
| var $this = $(this); | |||||
| var data = $this.data(DATA_KEY); | |||||
| if (!data) { | |||||
| data = new Tab(this); | |||||
| $this.data(DATA_KEY, data); | |||||
| } | |||||
| if (typeof config === 'string') { | |||||
| if (typeof data[config] === 'undefined') { | |||||
| throw new TypeError("No method named \"" + config + "\""); | |||||
| } | |||||
| data[config](); | |||||
| } | |||||
| }); | |||||
| }; | |||||
| _createClass(Tab, null, [{ | |||||
| key: "VERSION", | |||||
| get: function get() { | |||||
| return VERSION; | |||||
| } | |||||
| }]); | |||||
| return Tab; | |||||
| }(); | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Data Api implementation | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { | |||||
| event.preventDefault(); | |||||
| Tab._jQueryInterface.call($(this), 'show'); | |||||
| }); | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * jQuery | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $.fn[NAME] = Tab._jQueryInterface; | |||||
| $.fn[NAME].Constructor = Tab; | |||||
| $.fn[NAME].noConflict = function () { | |||||
| $.fn[NAME] = JQUERY_NO_CONFLICT; | |||||
| return Tab._jQueryInterface; | |||||
| }; | |||||
| return Tab; | |||||
| }))); | |||||
| //# sourceMappingURL=tab.js.map | |||||
| @ -0,0 +1,303 @@ | |||||
| /*! | |||||
| * Bootstrap toast.js v4.4.1 (https://getbootstrap.com/) | |||||
| * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| */ | |||||
| (function (global, factory) { | |||||
| typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('./util.js')) : | |||||
| typeof define === 'function' && define.amd ? define(['jquery', './util.js'], factory) : | |||||
| (global = global || self, global.Toast = factory(global.jQuery, global.Util)); | |||||
| }(this, (function ($, Util) { 'use strict'; | |||||
| $ = $ && $.hasOwnProperty('default') ? $['default'] : $; | |||||
| Util = Util && Util.hasOwnProperty('default') ? Util['default'] : Util; | |||||
| function _defineProperties(target, props) { | |||||
| for (var i = 0; i < props.length; i++) { | |||||
| var descriptor = props[i]; | |||||
| descriptor.enumerable = descriptor.enumerable || false; | |||||
| descriptor.configurable = true; | |||||
| if ("value" in descriptor) descriptor.writable = true; | |||||
| Object.defineProperty(target, descriptor.key, descriptor); | |||||
| } | |||||
| } | |||||
| function _createClass(Constructor, protoProps, staticProps) { | |||||
| if (protoProps) _defineProperties(Constructor.prototype, protoProps); | |||||
| if (staticProps) _defineProperties(Constructor, staticProps); | |||||
| return Constructor; | |||||
| } | |||||
| function _defineProperty(obj, key, value) { | |||||
| if (key in obj) { | |||||
| Object.defineProperty(obj, key, { | |||||
| value: value, | |||||
| enumerable: true, | |||||
| configurable: true, | |||||
| writable: true | |||||
| }); | |||||
| } else { | |||||
| obj[key] = value; | |||||
| } | |||||
| return obj; | |||||
| } | |||||
| function ownKeys(object, enumerableOnly) { | |||||
| var keys = Object.keys(object); | |||||
| if (Object.getOwnPropertySymbols) { | |||||
| var symbols = Object.getOwnPropertySymbols(object); | |||||
| if (enumerableOnly) symbols = symbols.filter(function (sym) { | |||||
| return Object.getOwnPropertyDescriptor(object, sym).enumerable; | |||||
| }); | |||||
| keys.push.apply(keys, symbols); | |||||
| } | |||||
| return keys; | |||||
| } | |||||
| function _objectSpread2(target) { | |||||
| for (var i = 1; i < arguments.length; i++) { | |||||
| var source = arguments[i] != null ? arguments[i] : {}; | |||||
| if (i % 2) { | |||||
| ownKeys(Object(source), true).forEach(function (key) { | |||||
| _defineProperty(target, key, source[key]); | |||||
| }); | |||||
| } else if (Object.getOwnPropertyDescriptors) { | |||||
| Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); | |||||
| } else { | |||||
| ownKeys(Object(source)).forEach(function (key) { | |||||
| Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); | |||||
| }); | |||||
| } | |||||
| } | |||||
| return target; | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Constants | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| var NAME = 'toast'; | |||||
| var VERSION = '4.4.1'; | |||||
| var DATA_KEY = 'bs.toast'; | |||||
| var EVENT_KEY = "." + DATA_KEY; | |||||
| var JQUERY_NO_CONFLICT = $.fn[NAME]; | |||||
| var Event = { | |||||
| CLICK_DISMISS: "click.dismiss" + EVENT_KEY, | |||||
| HIDE: "hide" + EVENT_KEY, | |||||
| HIDDEN: "hidden" + EVENT_KEY, | |||||
| SHOW: "show" + EVENT_KEY, | |||||
| SHOWN: "shown" + EVENT_KEY | |||||
| }; | |||||
| var ClassName = { | |||||
| FADE: 'fade', | |||||
| HIDE: 'hide', | |||||
| SHOW: 'show', | |||||
| SHOWING: 'showing' | |||||
| }; | |||||
| var DefaultType = { | |||||
| animation: 'boolean', | |||||
| autohide: 'boolean', | |||||
| delay: 'number' | |||||
| }; | |||||
| var Default = { | |||||
| animation: true, | |||||
| autohide: true, | |||||
| delay: 500 | |||||
| }; | |||||
| var Selector = { | |||||
| DATA_DISMISS: '[data-dismiss="toast"]' | |||||
| }; | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Class Definition | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| var Toast = | |||||
| /*#__PURE__*/ | |||||
| function () { | |||||
| function Toast(element, config) { | |||||
| this._element = element; | |||||
| this._config = this._getConfig(config); | |||||
| this._timeout = null; | |||||
| this._setListeners(); | |||||
| } // Getters | |||||
| var _proto = Toast.prototype; | |||||
| // Public | |||||
| _proto.show = function show() { | |||||
| var _this = this; | |||||
| var showEvent = $.Event(Event.SHOW); | |||||
| $(this._element).trigger(showEvent); | |||||
| if (showEvent.isDefaultPrevented()) { | |||||
| return; | |||||
| } | |||||
| if (this._config.animation) { | |||||
| this._element.classList.add(ClassName.FADE); | |||||
| } | |||||
| var complete = function complete() { | |||||
| _this._element.classList.remove(ClassName.SHOWING); | |||||
| _this._element.classList.add(ClassName.SHOW); | |||||
| $(_this._element).trigger(Event.SHOWN); | |||||
| if (_this._config.autohide) { | |||||
| _this._timeout = setTimeout(function () { | |||||
| _this.hide(); | |||||
| }, _this._config.delay); | |||||
| } | |||||
| }; | |||||
| this._element.classList.remove(ClassName.HIDE); | |||||
| Util.reflow(this._element); | |||||
| this._element.classList.add(ClassName.SHOWING); | |||||
| if (this._config.animation) { | |||||
| var transitionDuration = Util.getTransitionDurationFromElement(this._element); | |||||
| $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration); | |||||
| } else { | |||||
| complete(); | |||||
| } | |||||
| }; | |||||
| _proto.hide = function hide() { | |||||
| if (!this._element.classList.contains(ClassName.SHOW)) { | |||||
| return; | |||||
| } | |||||
| var hideEvent = $.Event(Event.HIDE); | |||||
| $(this._element).trigger(hideEvent); | |||||
| if (hideEvent.isDefaultPrevented()) { | |||||
| return; | |||||
| } | |||||
| this._close(); | |||||
| }; | |||||
| _proto.dispose = function dispose() { | |||||
| clearTimeout(this._timeout); | |||||
| this._timeout = null; | |||||
| if (this._element.classList.contains(ClassName.SHOW)) { | |||||
| this._element.classList.remove(ClassName.SHOW); | |||||
| } | |||||
| $(this._element).off(Event.CLICK_DISMISS); | |||||
| $.removeData(this._element, DATA_KEY); | |||||
| this._element = null; | |||||
| this._config = null; | |||||
| } // Private | |||||
| ; | |||||
| _proto._getConfig = function _getConfig(config) { | |||||
| config = _objectSpread2({}, Default, {}, $(this._element).data(), {}, typeof config === 'object' && config ? config : {}); | |||||
| Util.typeCheckConfig(NAME, config, this.constructor.DefaultType); | |||||
| return config; | |||||
| }; | |||||
| _proto._setListeners = function _setListeners() { | |||||
| var _this2 = this; | |||||
| $(this._element).on(Event.CLICK_DISMISS, Selector.DATA_DISMISS, function () { | |||||
| return _this2.hide(); | |||||
| }); | |||||
| }; | |||||
| _proto._close = function _close() { | |||||
| var _this3 = this; | |||||
| var complete = function complete() { | |||||
| _this3._element.classList.add(ClassName.HIDE); | |||||
| $(_this3._element).trigger(Event.HIDDEN); | |||||
| }; | |||||
| this._element.classList.remove(ClassName.SHOW); | |||||
| if (this._config.animation) { | |||||
| var transitionDuration = Util.getTransitionDurationFromElement(this._element); | |||||
| $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration); | |||||
| } else { | |||||
| complete(); | |||||
| } | |||||
| } // Static | |||||
| ; | |||||
| Toast._jQueryInterface = function _jQueryInterface(config) { | |||||
| return this.each(function () { | |||||
| var $element = $(this); | |||||
| var data = $element.data(DATA_KEY); | |||||
| var _config = typeof config === 'object' && config; | |||||
| if (!data) { | |||||
| data = new Toast(this, _config); | |||||
| $element.data(DATA_KEY, data); | |||||
| } | |||||
| if (typeof config === 'string') { | |||||
| if (typeof data[config] === 'undefined') { | |||||
| throw new TypeError("No method named \"" + config + "\""); | |||||
| } | |||||
| data[config](this); | |||||
| } | |||||
| }); | |||||
| }; | |||||
| _createClass(Toast, null, [{ | |||||
| key: "VERSION", | |||||
| get: function get() { | |||||
| return VERSION; | |||||
| } | |||||
| }, { | |||||
| key: "DefaultType", | |||||
| get: function get() { | |||||
| return DefaultType; | |||||
| } | |||||
| }, { | |||||
| key: "Default", | |||||
| get: function get() { | |||||
| return Default; | |||||
| } | |||||
| }]); | |||||
| return Toast; | |||||
| }(); | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * jQuery | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $.fn[NAME] = Toast._jQueryInterface; | |||||
| $.fn[NAME].Constructor = Toast; | |||||
| $.fn[NAME].noConflict = function () { | |||||
| $.fn[NAME] = JQUERY_NO_CONFLICT; | |||||
| return Toast._jQueryInterface; | |||||
| }; | |||||
| return Toast; | |||||
| }))); | |||||
| //# sourceMappingURL=toast.js.map | |||||
| @ -0,0 +1,929 @@ | |||||
| /*! | |||||
| * Bootstrap tooltip.js v4.4.1 (https://getbootstrap.com/) | |||||
| * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| */ | |||||
| (function (global, factory) { | |||||
| typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('popper.js'), require('./util.js')) : | |||||
| typeof define === 'function' && define.amd ? define(['jquery', 'popper.js', './util.js'], factory) : | |||||
| (global = global || self, global.Tooltip = factory(global.jQuery, global.Popper, global.Util)); | |||||
| }(this, (function ($, Popper, Util) { 'use strict'; | |||||
| $ = $ && $.hasOwnProperty('default') ? $['default'] : $; | |||||
| Popper = Popper && Popper.hasOwnProperty('default') ? Popper['default'] : Popper; | |||||
| Util = Util && Util.hasOwnProperty('default') ? Util['default'] : Util; | |||||
| function _defineProperties(target, props) { | |||||
| for (var i = 0; i < props.length; i++) { | |||||
| var descriptor = props[i]; | |||||
| descriptor.enumerable = descriptor.enumerable || false; | |||||
| descriptor.configurable = true; | |||||
| if ("value" in descriptor) descriptor.writable = true; | |||||
| Object.defineProperty(target, descriptor.key, descriptor); | |||||
| } | |||||
| } | |||||
| function _createClass(Constructor, protoProps, staticProps) { | |||||
| if (protoProps) _defineProperties(Constructor.prototype, protoProps); | |||||
| if (staticProps) _defineProperties(Constructor, staticProps); | |||||
| return Constructor; | |||||
| } | |||||
| function _defineProperty(obj, key, value) { | |||||
| if (key in obj) { | |||||
| Object.defineProperty(obj, key, { | |||||
| value: value, | |||||
| enumerable: true, | |||||
| configurable: true, | |||||
| writable: true | |||||
| }); | |||||
| } else { | |||||
| obj[key] = value; | |||||
| } | |||||
| return obj; | |||||
| } | |||||
| function ownKeys(object, enumerableOnly) { | |||||
| var keys = Object.keys(object); | |||||
| if (Object.getOwnPropertySymbols) { | |||||
| var symbols = Object.getOwnPropertySymbols(object); | |||||
| if (enumerableOnly) symbols = symbols.filter(function (sym) { | |||||
| return Object.getOwnPropertyDescriptor(object, sym).enumerable; | |||||
| }); | |||||
| keys.push.apply(keys, symbols); | |||||
| } | |||||
| return keys; | |||||
| } | |||||
| function _objectSpread2(target) { | |||||
| for (var i = 1; i < arguments.length; i++) { | |||||
| var source = arguments[i] != null ? arguments[i] : {}; | |||||
| if (i % 2) { | |||||
| ownKeys(Object(source), true).forEach(function (key) { | |||||
| _defineProperty(target, key, source[key]); | |||||
| }); | |||||
| } else if (Object.getOwnPropertyDescriptors) { | |||||
| Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); | |||||
| } else { | |||||
| ownKeys(Object(source)).forEach(function (key) { | |||||
| Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); | |||||
| }); | |||||
| } | |||||
| } | |||||
| return target; | |||||
| } | |||||
| /** | |||||
| * -------------------------------------------------------------------------- | |||||
| * Bootstrap (v4.4.1): tools/sanitizer.js | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| * -------------------------------------------------------------------------- | |||||
| */ | |||||
| var uriAttrs = ['background', 'cite', 'href', 'itemtype', 'longdesc', 'poster', 'src', 'xlink:href']; | |||||
| var ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i; | |||||
| var DefaultWhitelist = { | |||||
| // Global attributes allowed on any supplied element below. | |||||
| '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN], | |||||
| a: ['target', 'href', 'title', 'rel'], | |||||
| area: [], | |||||
| b: [], | |||||
| br: [], | |||||
| col: [], | |||||
| code: [], | |||||
| div: [], | |||||
| em: [], | |||||
| hr: [], | |||||
| h1: [], | |||||
| h2: [], | |||||
| h3: [], | |||||
| h4: [], | |||||
| h5: [], | |||||
| h6: [], | |||||
| i: [], | |||||
| img: ['src', 'alt', 'title', 'width', 'height'], | |||||
| li: [], | |||||
| ol: [], | |||||
| p: [], | |||||
| pre: [], | |||||
| s: [], | |||||
| small: [], | |||||
| span: [], | |||||
| sub: [], | |||||
| sup: [], | |||||
| strong: [], | |||||
| u: [], | |||||
| ul: [] | |||||
| }; | |||||
| /** | |||||
| * A pattern that recognizes a commonly useful subset of URLs that are safe. | |||||
| * | |||||
| * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts | |||||
| */ | |||||
| var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi; | |||||
| /** | |||||
| * A pattern that matches safe data URLs. Only matches image, video and audio types. | |||||
| * | |||||
| * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts | |||||
| */ | |||||
| var DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i; | |||||
| function allowedAttribute(attr, allowedAttributeList) { | |||||
| var attrName = attr.nodeName.toLowerCase(); | |||||
| if (allowedAttributeList.indexOf(attrName) !== -1) { | |||||
| if (uriAttrs.indexOf(attrName) !== -1) { | |||||
| return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN)); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| var regExp = allowedAttributeList.filter(function (attrRegex) { | |||||
| return attrRegex instanceof RegExp; | |||||
| }); // Check if a regular expression validates the attribute. | |||||
| for (var i = 0, l = regExp.length; i < l; i++) { | |||||
| if (attrName.match(regExp[i])) { | |||||
| return true; | |||||
| } | |||||
| } | |||||
| return false; | |||||
| } | |||||
| function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) { | |||||
| if (unsafeHtml.length === 0) { | |||||
| return unsafeHtml; | |||||
| } | |||||
| if (sanitizeFn && typeof sanitizeFn === 'function') { | |||||
| return sanitizeFn(unsafeHtml); | |||||
| } | |||||
| var domParser = new window.DOMParser(); | |||||
| var createdDocument = domParser.parseFromString(unsafeHtml, 'text/html'); | |||||
| var whitelistKeys = Object.keys(whiteList); | |||||
| var elements = [].slice.call(createdDocument.body.querySelectorAll('*')); | |||||
| var _loop = function _loop(i, len) { | |||||
| var el = elements[i]; | |||||
| var elName = el.nodeName.toLowerCase(); | |||||
| if (whitelistKeys.indexOf(el.nodeName.toLowerCase()) === -1) { | |||||
| el.parentNode.removeChild(el); | |||||
| return "continue"; | |||||
| } | |||||
| var attributeList = [].slice.call(el.attributes); | |||||
| var whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || []); | |||||
| attributeList.forEach(function (attr) { | |||||
| if (!allowedAttribute(attr, whitelistedAttributes)) { | |||||
| el.removeAttribute(attr.nodeName); | |||||
| } | |||||
| }); | |||||
| }; | |||||
| for (var i = 0, len = elements.length; i < len; i++) { | |||||
| var _ret = _loop(i); | |||||
| if (_ret === "continue") continue; | |||||
| } | |||||
| return createdDocument.body.innerHTML; | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Constants | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| var NAME = 'tooltip'; | |||||
| var VERSION = '4.4.1'; | |||||
| var DATA_KEY = 'bs.tooltip'; | |||||
| var EVENT_KEY = "." + DATA_KEY; | |||||
| var JQUERY_NO_CONFLICT = $.fn[NAME]; | |||||
| var CLASS_PREFIX = 'bs-tooltip'; | |||||
| var BSCLS_PREFIX_REGEX = new RegExp("(^|\\s)" + CLASS_PREFIX + "\\S+", 'g'); | |||||
| var DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn']; | |||||
| var DefaultType = { | |||||
| animation: 'boolean', | |||||
| template: 'string', | |||||
| title: '(string|element|function)', | |||||
| trigger: 'string', | |||||
| delay: '(number|object)', | |||||
| html: 'boolean', | |||||
| selector: '(string|boolean)', | |||||
| placement: '(string|function)', | |||||
| offset: '(number|string|function)', | |||||
| container: '(string|element|boolean)', | |||||
| fallbackPlacement: '(string|array)', | |||||
| boundary: '(string|element)', | |||||
| sanitize: 'boolean', | |||||
| sanitizeFn: '(null|function)', | |||||
| whiteList: 'object', | |||||
| popperConfig: '(null|object)' | |||||
| }; | |||||
| var AttachmentMap = { | |||||
| AUTO: 'auto', | |||||
| TOP: 'top', | |||||
| RIGHT: 'right', | |||||
| BOTTOM: 'bottom', | |||||
| LEFT: 'left' | |||||
| }; | |||||
| var Default = { | |||||
| animation: true, | |||||
| template: '<div class="tooltip" role="tooltip">' + '<div class="arrow"></div>' + '<div class="tooltip-inner"></div></div>', | |||||
| trigger: 'hover focus', | |||||
| title: '', | |||||
| delay: 0, | |||||
| html: false, | |||||
| selector: false, | |||||
| placement: 'top', | |||||
| offset: 0, | |||||
| container: false, | |||||
| fallbackPlacement: 'flip', | |||||
| boundary: 'scrollParent', | |||||
| sanitize: true, | |||||
| sanitizeFn: null, | |||||
| whiteList: DefaultWhitelist, | |||||
| popperConfig: null | |||||
| }; | |||||
| var HoverState = { | |||||
| SHOW: 'show', | |||||
| OUT: 'out' | |||||
| }; | |||||
| var Event = { | |||||
| HIDE: "hide" + EVENT_KEY, | |||||
| HIDDEN: "hidden" + EVENT_KEY, | |||||
| SHOW: "show" + EVENT_KEY, | |||||
| SHOWN: "shown" + EVENT_KEY, | |||||
| INSERTED: "inserted" + EVENT_KEY, | |||||
| CLICK: "click" + EVENT_KEY, | |||||
| FOCUSIN: "focusin" + EVENT_KEY, | |||||
| FOCUSOUT: "focusout" + EVENT_KEY, | |||||
| MOUSEENTER: "mouseenter" + EVENT_KEY, | |||||
| MOUSELEAVE: "mouseleave" + EVENT_KEY | |||||
| }; | |||||
| var ClassName = { | |||||
| FADE: 'fade', | |||||
| SHOW: 'show' | |||||
| }; | |||||
| var Selector = { | |||||
| TOOLTIP: '.tooltip', | |||||
| TOOLTIP_INNER: '.tooltip-inner', | |||||
| ARROW: '.arrow' | |||||
| }; | |||||
| var Trigger = { | |||||
| HOVER: 'hover', | |||||
| FOCUS: 'focus', | |||||
| CLICK: 'click', | |||||
| MANUAL: 'manual' | |||||
| }; | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Class Definition | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| var Tooltip = | |||||
| /*#__PURE__*/ | |||||
| function () { | |||||
| function Tooltip(element, config) { | |||||
| if (typeof Popper === 'undefined') { | |||||
| throw new TypeError('Bootstrap\'s tooltips require Popper.js (https://popper.js.org/)'); | |||||
| } // private | |||||
| this._isEnabled = true; | |||||
| this._timeout = 0; | |||||
| this._hoverState = ''; | |||||
| this._activeTrigger = {}; | |||||
| this._popper = null; // Protected | |||||
| this.element = element; | |||||
| this.config = this._getConfig(config); | |||||
| this.tip = null; | |||||
| this._setListeners(); | |||||
| } // Getters | |||||
| var _proto = Tooltip.prototype; | |||||
| // Public | |||||
| _proto.enable = function enable() { | |||||
| this._isEnabled = true; | |||||
| }; | |||||
| _proto.disable = function disable() { | |||||
| this._isEnabled = false; | |||||
| }; | |||||
| _proto.toggleEnabled = function toggleEnabled() { | |||||
| this._isEnabled = !this._isEnabled; | |||||
| }; | |||||
| _proto.toggle = function toggle(event) { | |||||
| if (!this._isEnabled) { | |||||
| return; | |||||
| } | |||||
| if (event) { | |||||
| var dataKey = this.constructor.DATA_KEY; | |||||
| var context = $(event.currentTarget).data(dataKey); | |||||
| if (!context) { | |||||
| context = new this.constructor(event.currentTarget, this._getDelegateConfig()); | |||||
| $(event.currentTarget).data(dataKey, context); | |||||
| } | |||||
| context._activeTrigger.click = !context._activeTrigger.click; | |||||
| if (context._isWithActiveTrigger()) { | |||||
| context._enter(null, context); | |||||
| } else { | |||||
| context._leave(null, context); | |||||
| } | |||||
| } else { | |||||
| if ($(this.getTipElement()).hasClass(ClassName.SHOW)) { | |||||
| this._leave(null, this); | |||||
| return; | |||||
| } | |||||
| this._enter(null, this); | |||||
| } | |||||
| }; | |||||
| _proto.dispose = function dispose() { | |||||
| clearTimeout(this._timeout); | |||||
| $.removeData(this.element, this.constructor.DATA_KEY); | |||||
| $(this.element).off(this.constructor.EVENT_KEY); | |||||
| $(this.element).closest('.modal').off('hide.bs.modal', this._hideModalHandler); | |||||
| if (this.tip) { | |||||
| $(this.tip).remove(); | |||||
| } | |||||
| this._isEnabled = null; | |||||
| this._timeout = null; | |||||
| this._hoverState = null; | |||||
| this._activeTrigger = null; | |||||
| if (this._popper) { | |||||
| this._popper.destroy(); | |||||
| } | |||||
| this._popper = null; | |||||
| this.element = null; | |||||
| this.config = null; | |||||
| this.tip = null; | |||||
| }; | |||||
| _proto.show = function show() { | |||||
| var _this = this; | |||||
| if ($(this.element).css('display') === 'none') { | |||||
| throw new Error('Please use show on visible elements'); | |||||
| } | |||||
| var showEvent = $.Event(this.constructor.Event.SHOW); | |||||
| if (this.isWithContent() && this._isEnabled) { | |||||
| $(this.element).trigger(showEvent); | |||||
| var shadowRoot = Util.findShadowRoot(this.element); | |||||
| var isInTheDom = $.contains(shadowRoot !== null ? shadowRoot : this.element.ownerDocument.documentElement, this.element); | |||||
| if (showEvent.isDefaultPrevented() || !isInTheDom) { | |||||
| return; | |||||
| } | |||||
| var tip = this.getTipElement(); | |||||
| var tipId = Util.getUID(this.constructor.NAME); | |||||
| tip.setAttribute('id', tipId); | |||||
| this.element.setAttribute('aria-describedby', tipId); | |||||
| this.setContent(); | |||||
| if (this.config.animation) { | |||||
| $(tip).addClass(ClassName.FADE); | |||||
| } | |||||
| var placement = typeof this.config.placement === 'function' ? this.config.placement.call(this, tip, this.element) : this.config.placement; | |||||
| var attachment = this._getAttachment(placement); | |||||
| this.addAttachmentClass(attachment); | |||||
| var container = this._getContainer(); | |||||
| $(tip).data(this.constructor.DATA_KEY, this); | |||||
| if (!$.contains(this.element.ownerDocument.documentElement, this.tip)) { | |||||
| $(tip).appendTo(container); | |||||
| } | |||||
| $(this.element).trigger(this.constructor.Event.INSERTED); | |||||
| this._popper = new Popper(this.element, tip, this._getPopperConfig(attachment)); | |||||
| $(tip).addClass(ClassName.SHOW); // If this is a touch-enabled device we add extra | |||||
| // empty mouseover listeners to the body's immediate children; | |||||
| // only needed because of broken event delegation on iOS | |||||
| // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html | |||||
| if ('ontouchstart' in document.documentElement) { | |||||
| $(document.body).children().on('mouseover', null, $.noop); | |||||
| } | |||||
| var complete = function complete() { | |||||
| if (_this.config.animation) { | |||||
| _this._fixTransition(); | |||||
| } | |||||
| var prevHoverState = _this._hoverState; | |||||
| _this._hoverState = null; | |||||
| $(_this.element).trigger(_this.constructor.Event.SHOWN); | |||||
| if (prevHoverState === HoverState.OUT) { | |||||
| _this._leave(null, _this); | |||||
| } | |||||
| }; | |||||
| if ($(this.tip).hasClass(ClassName.FADE)) { | |||||
| var transitionDuration = Util.getTransitionDurationFromElement(this.tip); | |||||
| $(this.tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration); | |||||
| } else { | |||||
| complete(); | |||||
| } | |||||
| } | |||||
| }; | |||||
| _proto.hide = function hide(callback) { | |||||
| var _this2 = this; | |||||
| var tip = this.getTipElement(); | |||||
| var hideEvent = $.Event(this.constructor.Event.HIDE); | |||||
| var complete = function complete() { | |||||
| if (_this2._hoverState !== HoverState.SHOW && tip.parentNode) { | |||||
| tip.parentNode.removeChild(tip); | |||||
| } | |||||
| _this2._cleanTipClass(); | |||||
| _this2.element.removeAttribute('aria-describedby'); | |||||
| $(_this2.element).trigger(_this2.constructor.Event.HIDDEN); | |||||
| if (_this2._popper !== null) { | |||||
| _this2._popper.destroy(); | |||||
| } | |||||
| if (callback) { | |||||
| callback(); | |||||
| } | |||||
| }; | |||||
| $(this.element).trigger(hideEvent); | |||||
| if (hideEvent.isDefaultPrevented()) { | |||||
| return; | |||||
| } | |||||
| $(tip).removeClass(ClassName.SHOW); // If this is a touch-enabled device we remove the extra | |||||
| // empty mouseover listeners we added for iOS support | |||||
| if ('ontouchstart' in document.documentElement) { | |||||
| $(document.body).children().off('mouseover', null, $.noop); | |||||
| } | |||||
| this._activeTrigger[Trigger.CLICK] = false; | |||||
| this._activeTrigger[Trigger.FOCUS] = false; | |||||
| this._activeTrigger[Trigger.HOVER] = false; | |||||
| if ($(this.tip).hasClass(ClassName.FADE)) { | |||||
| var transitionDuration = Util.getTransitionDurationFromElement(tip); | |||||
| $(tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration); | |||||
| } else { | |||||
| complete(); | |||||
| } | |||||
| this._hoverState = ''; | |||||
| }; | |||||
| _proto.update = function update() { | |||||
| if (this._popper !== null) { | |||||
| this._popper.scheduleUpdate(); | |||||
| } | |||||
| } // Protected | |||||
| ; | |||||
| _proto.isWithContent = function isWithContent() { | |||||
| return Boolean(this.getTitle()); | |||||
| }; | |||||
| _proto.addAttachmentClass = function addAttachmentClass(attachment) { | |||||
| $(this.getTipElement()).addClass(CLASS_PREFIX + "-" + attachment); | |||||
| }; | |||||
| _proto.getTipElement = function getTipElement() { | |||||
| this.tip = this.tip || $(this.config.template)[0]; | |||||
| return this.tip; | |||||
| }; | |||||
| _proto.setContent = function setContent() { | |||||
| var tip = this.getTipElement(); | |||||
| this.setElementContent($(tip.querySelectorAll(Selector.TOOLTIP_INNER)), this.getTitle()); | |||||
| $(tip).removeClass(ClassName.FADE + " " + ClassName.SHOW); | |||||
| }; | |||||
| _proto.setElementContent = function setElementContent($element, content) { | |||||
| if (typeof content === 'object' && (content.nodeType || content.jquery)) { | |||||
| // Content is a DOM node or a jQuery | |||||
| if (this.config.html) { | |||||
| if (!$(content).parent().is($element)) { | |||||
| $element.empty().append(content); | |||||
| } | |||||
| } else { | |||||
| $element.text($(content).text()); | |||||
| } | |||||
| return; | |||||
| } | |||||
| if (this.config.html) { | |||||
| if (this.config.sanitize) { | |||||
| content = sanitizeHtml(content, this.config.whiteList, this.config.sanitizeFn); | |||||
| } | |||||
| $element.html(content); | |||||
| } else { | |||||
| $element.text(content); | |||||
| } | |||||
| }; | |||||
| _proto.getTitle = function getTitle() { | |||||
| var title = this.element.getAttribute('data-original-title'); | |||||
| if (!title) { | |||||
| title = typeof this.config.title === 'function' ? this.config.title.call(this.element) : this.config.title; | |||||
| } | |||||
| return title; | |||||
| } // Private | |||||
| ; | |||||
| _proto._getPopperConfig = function _getPopperConfig(attachment) { | |||||
| var _this3 = this; | |||||
| var defaultBsConfig = { | |||||
| placement: attachment, | |||||
| modifiers: { | |||||
| offset: this._getOffset(), | |||||
| flip: { | |||||
| behavior: this.config.fallbackPlacement | |||||
| }, | |||||
| arrow: { | |||||
| element: Selector.ARROW | |||||
| }, | |||||
| preventOverflow: { | |||||
| boundariesElement: this.config.boundary | |||||
| } | |||||
| }, | |||||
| onCreate: function onCreate(data) { | |||||
| if (data.originalPlacement !== data.placement) { | |||||
| _this3._handlePopperPlacementChange(data); | |||||
| } | |||||
| }, | |||||
| onUpdate: function onUpdate(data) { | |||||
| return _this3._handlePopperPlacementChange(data); | |||||
| } | |||||
| }; | |||||
| return _objectSpread2({}, defaultBsConfig, {}, this.config.popperConfig); | |||||
| }; | |||||
| _proto._getOffset = function _getOffset() { | |||||
| var _this4 = this; | |||||
| var offset = {}; | |||||
| if (typeof this.config.offset === 'function') { | |||||
| offset.fn = function (data) { | |||||
| data.offsets = _objectSpread2({}, data.offsets, {}, _this4.config.offset(data.offsets, _this4.element) || {}); | |||||
| return data; | |||||
| }; | |||||
| } else { | |||||
| offset.offset = this.config.offset; | |||||
| } | |||||
| return offset; | |||||
| }; | |||||
| _proto._getContainer = function _getContainer() { | |||||
| if (this.config.container === false) { | |||||
| return document.body; | |||||
| } | |||||
| if (Util.isElement(this.config.container)) { | |||||
| return $(this.config.container); | |||||
| } | |||||
| return $(document).find(this.config.container); | |||||
| }; | |||||
| _proto._getAttachment = function _getAttachment(placement) { | |||||
| return AttachmentMap[placement.toUpperCase()]; | |||||
| }; | |||||
| _proto._setListeners = function _setListeners() { | |||||
| var _this5 = this; | |||||
| var triggers = this.config.trigger.split(' '); | |||||
| triggers.forEach(function (trigger) { | |||||
| if (trigger === 'click') { | |||||
| $(_this5.element).on(_this5.constructor.Event.CLICK, _this5.config.selector, function (event) { | |||||
| return _this5.toggle(event); | |||||
| }); | |||||
| } else if (trigger !== Trigger.MANUAL) { | |||||
| var eventIn = trigger === Trigger.HOVER ? _this5.constructor.Event.MOUSEENTER : _this5.constructor.Event.FOCUSIN; | |||||
| var eventOut = trigger === Trigger.HOVER ? _this5.constructor.Event.MOUSELEAVE : _this5.constructor.Event.FOCUSOUT; | |||||
| $(_this5.element).on(eventIn, _this5.config.selector, function (event) { | |||||
| return _this5._enter(event); | |||||
| }).on(eventOut, _this5.config.selector, function (event) { | |||||
| return _this5._leave(event); | |||||
| }); | |||||
| } | |||||
| }); | |||||
| this._hideModalHandler = function () { | |||||
| if (_this5.element) { | |||||
| _this5.hide(); | |||||
| } | |||||
| }; | |||||
| $(this.element).closest('.modal').on('hide.bs.modal', this._hideModalHandler); | |||||
| if (this.config.selector) { | |||||
| this.config = _objectSpread2({}, this.config, { | |||||
| trigger: 'manual', | |||||
| selector: '' | |||||
| }); | |||||
| } else { | |||||
| this._fixTitle(); | |||||
| } | |||||
| }; | |||||
| _proto._fixTitle = function _fixTitle() { | |||||
| var titleType = typeof this.element.getAttribute('data-original-title'); | |||||
| if (this.element.getAttribute('title') || titleType !== 'string') { | |||||
| this.element.setAttribute('data-original-title', this.element.getAttribute('title') || ''); | |||||
| this.element.setAttribute('title', ''); | |||||
| } | |||||
| }; | |||||
| _proto._enter = function _enter(event, context) { | |||||
| var dataKey = this.constructor.DATA_KEY; | |||||
| context = context || $(event.currentTarget).data(dataKey); | |||||
| if (!context) { | |||||
| context = new this.constructor(event.currentTarget, this._getDelegateConfig()); | |||||
| $(event.currentTarget).data(dataKey, context); | |||||
| } | |||||
| if (event) { | |||||
| context._activeTrigger[event.type === 'focusin' ? Trigger.FOCUS : Trigger.HOVER] = true; | |||||
| } | |||||
| if ($(context.getTipElement()).hasClass(ClassName.SHOW) || context._hoverState === HoverState.SHOW) { | |||||
| context._hoverState = HoverState.SHOW; | |||||
| return; | |||||
| } | |||||
| clearTimeout(context._timeout); | |||||
| context._hoverState = HoverState.SHOW; | |||||
| if (!context.config.delay || !context.config.delay.show) { | |||||
| context.show(); | |||||
| return; | |||||
| } | |||||
| context._timeout = setTimeout(function () { | |||||
| if (context._hoverState === HoverState.SHOW) { | |||||
| context.show(); | |||||
| } | |||||
| }, context.config.delay.show); | |||||
| }; | |||||
| _proto._leave = function _leave(event, context) { | |||||
| var dataKey = this.constructor.DATA_KEY; | |||||
| context = context || $(event.currentTarget).data(dataKey); | |||||
| if (!context) { | |||||
| context = new this.constructor(event.currentTarget, this._getDelegateConfig()); | |||||
| $(event.currentTarget).data(dataKey, context); | |||||
| } | |||||
| if (event) { | |||||
| context._activeTrigger[event.type === 'focusout' ? Trigger.FOCUS : Trigger.HOVER] = false; | |||||
| } | |||||
| if (context._isWithActiveTrigger()) { | |||||
| return; | |||||
| } | |||||
| clearTimeout(context._timeout); | |||||
| context._hoverState = HoverState.OUT; | |||||
| if (!context.config.delay || !context.config.delay.hide) { | |||||
| context.hide(); | |||||
| return; | |||||
| } | |||||
| context._timeout = setTimeout(function () { | |||||
| if (context._hoverState === HoverState.OUT) { | |||||
| context.hide(); | |||||
| } | |||||
| }, context.config.delay.hide); | |||||
| }; | |||||
| _proto._isWithActiveTrigger = function _isWithActiveTrigger() { | |||||
| for (var trigger in this._activeTrigger) { | |||||
| if (this._activeTrigger[trigger]) { | |||||
| return true; | |||||
| } | |||||
| } | |||||
| return false; | |||||
| }; | |||||
| _proto._getConfig = function _getConfig(config) { | |||||
| var dataAttributes = $(this.element).data(); | |||||
| Object.keys(dataAttributes).forEach(function (dataAttr) { | |||||
| if (DISALLOWED_ATTRIBUTES.indexOf(dataAttr) !== -1) { | |||||
| delete dataAttributes[dataAttr]; | |||||
| } | |||||
| }); | |||||
| config = _objectSpread2({}, this.constructor.Default, {}, dataAttributes, {}, typeof config === 'object' && config ? config : {}); | |||||
| if (typeof config.delay === 'number') { | |||||
| config.delay = { | |||||
| show: config.delay, | |||||
| hide: config.delay | |||||
| }; | |||||
| } | |||||
| if (typeof config.title === 'number') { | |||||
| config.title = config.title.toString(); | |||||
| } | |||||
| if (typeof config.content === 'number') { | |||||
| config.content = config.content.toString(); | |||||
| } | |||||
| Util.typeCheckConfig(NAME, config, this.constructor.DefaultType); | |||||
| if (config.sanitize) { | |||||
| config.template = sanitizeHtml(config.template, config.whiteList, config.sanitizeFn); | |||||
| } | |||||
| return config; | |||||
| }; | |||||
| _proto._getDelegateConfig = function _getDelegateConfig() { | |||||
| var config = {}; | |||||
| if (this.config) { | |||||
| for (var key in this.config) { | |||||
| if (this.constructor.Default[key] !== this.config[key]) { | |||||
| config[key] = this.config[key]; | |||||
| } | |||||
| } | |||||
| } | |||||
| return config; | |||||
| }; | |||||
| _proto._cleanTipClass = function _cleanTipClass() { | |||||
| var $tip = $(this.getTipElement()); | |||||
| var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX); | |||||
| if (tabClass !== null && tabClass.length) { | |||||
| $tip.removeClass(tabClass.join('')); | |||||
| } | |||||
| }; | |||||
| _proto._handlePopperPlacementChange = function _handlePopperPlacementChange(popperData) { | |||||
| var popperInstance = popperData.instance; | |||||
| this.tip = popperInstance.popper; | |||||
| this._cleanTipClass(); | |||||
| this.addAttachmentClass(this._getAttachment(popperData.placement)); | |||||
| }; | |||||
| _proto._fixTransition = function _fixTransition() { | |||||
| var tip = this.getTipElement(); | |||||
| var initConfigAnimation = this.config.animation; | |||||
| if (tip.getAttribute('x-placement') !== null) { | |||||
| return; | |||||
| } | |||||
| $(tip).removeClass(ClassName.FADE); | |||||
| this.config.animation = false; | |||||
| this.hide(); | |||||
| this.show(); | |||||
| this.config.animation = initConfigAnimation; | |||||
| } // Static | |||||
| ; | |||||
| Tooltip._jQueryInterface = function _jQueryInterface(config) { | |||||
| return this.each(function () { | |||||
| var data = $(this).data(DATA_KEY); | |||||
| var _config = typeof config === 'object' && config; | |||||
| if (!data && /dispose|hide/.test(config)) { | |||||
| return; | |||||
| } | |||||
| if (!data) { | |||||
| data = new Tooltip(this, _config); | |||||
| $(this).data(DATA_KEY, data); | |||||
| } | |||||
| if (typeof config === 'string') { | |||||
| if (typeof data[config] === 'undefined') { | |||||
| throw new TypeError("No method named \"" + config + "\""); | |||||
| } | |||||
| data[config](); | |||||
| } | |||||
| }); | |||||
| }; | |||||
| _createClass(Tooltip, null, [{ | |||||
| key: "VERSION", | |||||
| get: function get() { | |||||
| return VERSION; | |||||
| } | |||||
| }, { | |||||
| key: "Default", | |||||
| get: function get() { | |||||
| return Default; | |||||
| } | |||||
| }, { | |||||
| key: "NAME", | |||||
| get: function get() { | |||||
| return NAME; | |||||
| } | |||||
| }, { | |||||
| key: "DATA_KEY", | |||||
| get: function get() { | |||||
| return DATA_KEY; | |||||
| } | |||||
| }, { | |||||
| key: "Event", | |||||
| get: function get() { | |||||
| return Event; | |||||
| } | |||||
| }, { | |||||
| key: "EVENT_KEY", | |||||
| get: function get() { | |||||
| return EVENT_KEY; | |||||
| } | |||||
| }, { | |||||
| key: "DefaultType", | |||||
| get: function get() { | |||||
| return DefaultType; | |||||
| } | |||||
| }]); | |||||
| return Tooltip; | |||||
| }(); | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * jQuery | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $.fn[NAME] = Tooltip._jQueryInterface; | |||||
| $.fn[NAME].Constructor = Tooltip; | |||||
| $.fn[NAME].noConflict = function () { | |||||
| $.fn[NAME] = JQUERY_NO_CONFLICT; | |||||
| return Tooltip._jQueryInterface; | |||||
| }; | |||||
| return Tooltip; | |||||
| }))); | |||||
| //# sourceMappingURL=tooltip.js.map | |||||
| @ -0,0 +1,189 @@ | |||||
| /*! | |||||
| * Bootstrap util.js v4.4.1 (https://getbootstrap.com/) | |||||
| * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| */ | |||||
| (function (global, factory) { | |||||
| typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery')) : | |||||
| typeof define === 'function' && define.amd ? define(['jquery'], factory) : | |||||
| (global = global || self, global.Util = factory(global.jQuery)); | |||||
| }(this, (function ($) { 'use strict'; | |||||
| $ = $ && $.hasOwnProperty('default') ? $['default'] : $; | |||||
| /** | |||||
| * -------------------------------------------------------------------------- | |||||
| * Bootstrap (v4.4.1): util.js | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| * -------------------------------------------------------------------------- | |||||
| */ | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Private TransitionEnd Helpers | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| var TRANSITION_END = 'transitionend'; | |||||
| var MAX_UID = 1000000; | |||||
| var MILLISECONDS_MULTIPLIER = 1000; // Shoutout AngusCroll (https://goo.gl/pxwQGp) | |||||
| function toType(obj) { | |||||
| return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase(); | |||||
| } | |||||
| function getSpecialTransitionEndEvent() { | |||||
| return { | |||||
| bindType: TRANSITION_END, | |||||
| delegateType: TRANSITION_END, | |||||
| handle: function handle(event) { | |||||
| if ($(event.target).is(this)) { | |||||
| return event.handleObj.handler.apply(this, arguments); // eslint-disable-line prefer-rest-params | |||||
| } | |||||
| return undefined; // eslint-disable-line no-undefined | |||||
| } | |||||
| }; | |||||
| } | |||||
| function transitionEndEmulator(duration) { | |||||
| var _this = this; | |||||
| var called = false; | |||||
| $(this).one(Util.TRANSITION_END, function () { | |||||
| called = true; | |||||
| }); | |||||
| setTimeout(function () { | |||||
| if (!called) { | |||||
| Util.triggerTransitionEnd(_this); | |||||
| } | |||||
| }, duration); | |||||
| return this; | |||||
| } | |||||
| function setTransitionEndSupport() { | |||||
| $.fn.emulateTransitionEnd = transitionEndEmulator; | |||||
| $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent(); | |||||
| } | |||||
| /** | |||||
| * -------------------------------------------------------------------------- | |||||
| * Public Util Api | |||||
| * -------------------------------------------------------------------------- | |||||
| */ | |||||
| var Util = { | |||||
| TRANSITION_END: 'bsTransitionEnd', | |||||
| getUID: function getUID(prefix) { | |||||
| do { | |||||
| // eslint-disable-next-line no-bitwise | |||||
| prefix += ~~(Math.random() * MAX_UID); // "~~" acts like a faster Math.floor() here | |||||
| } while (document.getElementById(prefix)); | |||||
| return prefix; | |||||
| }, | |||||
| getSelectorFromElement: function getSelectorFromElement(element) { | |||||
| var selector = element.getAttribute('data-target'); | |||||
| if (!selector || selector === '#') { | |||||
| var hrefAttr = element.getAttribute('href'); | |||||
| selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : ''; | |||||
| } | |||||
| try { | |||||
| return document.querySelector(selector) ? selector : null; | |||||
| } catch (err) { | |||||
| return null; | |||||
| } | |||||
| }, | |||||
| getTransitionDurationFromElement: function getTransitionDurationFromElement(element) { | |||||
| if (!element) { | |||||
| return 0; | |||||
| } // Get transition-duration of the element | |||||
| var transitionDuration = $(element).css('transition-duration'); | |||||
| var transitionDelay = $(element).css('transition-delay'); | |||||
| var floatTransitionDuration = parseFloat(transitionDuration); | |||||
| var floatTransitionDelay = parseFloat(transitionDelay); // Return 0 if element or transition duration is not found | |||||
| if (!floatTransitionDuration && !floatTransitionDelay) { | |||||
| return 0; | |||||
| } // If multiple durations are defined, take the first | |||||
| transitionDuration = transitionDuration.split(',')[0]; | |||||
| transitionDelay = transitionDelay.split(',')[0]; | |||||
| return (parseFloat(transitionDuration) + parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER; | |||||
| }, | |||||
| reflow: function reflow(element) { | |||||
| return element.offsetHeight; | |||||
| }, | |||||
| triggerTransitionEnd: function triggerTransitionEnd(element) { | |||||
| $(element).trigger(TRANSITION_END); | |||||
| }, | |||||
| // TODO: Remove in v5 | |||||
| supportsTransitionEnd: function supportsTransitionEnd() { | |||||
| return Boolean(TRANSITION_END); | |||||
| }, | |||||
| isElement: function isElement(obj) { | |||||
| return (obj[0] || obj).nodeType; | |||||
| }, | |||||
| typeCheckConfig: function typeCheckConfig(componentName, config, configTypes) { | |||||
| for (var property in configTypes) { | |||||
| if (Object.prototype.hasOwnProperty.call(configTypes, property)) { | |||||
| var expectedTypes = configTypes[property]; | |||||
| var value = config[property]; | |||||
| var valueType = value && Util.isElement(value) ? 'element' : toType(value); | |||||
| if (!new RegExp(expectedTypes).test(valueType)) { | |||||
| throw new Error(componentName.toUpperCase() + ": " + ("Option \"" + property + "\" provided type \"" + valueType + "\" ") + ("but expected type \"" + expectedTypes + "\".")); | |||||
| } | |||||
| } | |||||
| } | |||||
| }, | |||||
| findShadowRoot: function findShadowRoot(element) { | |||||
| if (!document.documentElement.attachShadow) { | |||||
| return null; | |||||
| } // Can find the shadow root otherwise it'll return the document | |||||
| if (typeof element.getRootNode === 'function') { | |||||
| var root = element.getRootNode(); | |||||
| return root instanceof ShadowRoot ? root : null; | |||||
| } | |||||
| if (element instanceof ShadowRoot) { | |||||
| return element; | |||||
| } // when we don't find a shadow root | |||||
| if (!element.parentNode) { | |||||
| return null; | |||||
| } | |||||
| return Util.findShadowRoot(element.parentNode); | |||||
| }, | |||||
| jQueryDetection: function jQueryDetection() { | |||||
| if (typeof $ === 'undefined') { | |||||
| throw new TypeError('Bootstrap\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\'s JavaScript.'); | |||||
| } | |||||
| var version = $.fn.jquery.split(' ')[0].split('.'); | |||||
| var minMajor = 1; | |||||
| var ltMajor = 2; | |||||
| var minMinor = 9; | |||||
| var minPatch = 1; | |||||
| var maxMajor = 4; | |||||
| if (version[0] < ltMajor && version[1] < minMinor || version[0] === minMajor && version[1] === minMinor && version[2] < minPatch || version[0] >= maxMajor) { | |||||
| throw new Error('Bootstrap\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0'); | |||||
| } | |||||
| } | |||||
| }; | |||||
| Util.jQueryDetection(); | |||||
| setTransitionEndSupport(); | |||||
| return Util; | |||||
| }))); | |||||
| //# sourceMappingURL=util.js.map | |||||
| @ -0,0 +1,179 @@ | |||||
| /** | |||||
| * -------------------------------------------------------------------------- | |||||
| * Bootstrap (v4.4.1): alert.js | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| * -------------------------------------------------------------------------- | |||||
| */ | |||||
| import $ from 'jquery' | |||||
| import Util from './util' | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Constants | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| const NAME = 'alert' | |||||
| const VERSION = '4.4.1' | |||||
| const DATA_KEY = 'bs.alert' | |||||
| const EVENT_KEY = `.${DATA_KEY}` | |||||
| const DATA_API_KEY = '.data-api' | |||||
| const JQUERY_NO_CONFLICT = $.fn[NAME] | |||||
| const Selector = { | |||||
| DISMISS : '[data-dismiss="alert"]' | |||||
| } | |||||
| const Event = { | |||||
| CLOSE : `close${EVENT_KEY}`, | |||||
| CLOSED : `closed${EVENT_KEY}`, | |||||
| CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}` | |||||
| } | |||||
| const ClassName = { | |||||
| ALERT : 'alert', | |||||
| FADE : 'fade', | |||||
| SHOW : 'show' | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Class Definition | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| class Alert { | |||||
| constructor(element) { | |||||
| this._element = element | |||||
| } | |||||
| // Getters | |||||
| static get VERSION() { | |||||
| return VERSION | |||||
| } | |||||
| // Public | |||||
| close(element) { | |||||
| let rootElement = this._element | |||||
| if (element) { | |||||
| rootElement = this._getRootElement(element) | |||||
| } | |||||
| const customEvent = this._triggerCloseEvent(rootElement) | |||||
| if (customEvent.isDefaultPrevented()) { | |||||
| return | |||||
| } | |||||
| this._removeElement(rootElement) | |||||
| } | |||||
| dispose() { | |||||
| $.removeData(this._element, DATA_KEY) | |||||
| this._element = null | |||||
| } | |||||
| // Private | |||||
| _getRootElement(element) { | |||||
| const selector = Util.getSelectorFromElement(element) | |||||
| let parent = false | |||||
| if (selector) { | |||||
| parent = document.querySelector(selector) | |||||
| } | |||||
| if (!parent) { | |||||
| parent = $(element).closest(`.${ClassName.ALERT}`)[0] | |||||
| } | |||||
| return parent | |||||
| } | |||||
| _triggerCloseEvent(element) { | |||||
| const closeEvent = $.Event(Event.CLOSE) | |||||
| $(element).trigger(closeEvent) | |||||
| return closeEvent | |||||
| } | |||||
| _removeElement(element) { | |||||
| $(element).removeClass(ClassName.SHOW) | |||||
| if (!$(element).hasClass(ClassName.FADE)) { | |||||
| this._destroyElement(element) | |||||
| return | |||||
| } | |||||
| const transitionDuration = Util.getTransitionDurationFromElement(element) | |||||
| $(element) | |||||
| .one(Util.TRANSITION_END, (event) => this._destroyElement(element, event)) | |||||
| .emulateTransitionEnd(transitionDuration) | |||||
| } | |||||
| _destroyElement(element) { | |||||
| $(element) | |||||
| .detach() | |||||
| .trigger(Event.CLOSED) | |||||
| .remove() | |||||
| } | |||||
| // Static | |||||
| static _jQueryInterface(config) { | |||||
| return this.each(function () { | |||||
| const $element = $(this) | |||||
| let data = $element.data(DATA_KEY) | |||||
| if (!data) { | |||||
| data = new Alert(this) | |||||
| $element.data(DATA_KEY, data) | |||||
| } | |||||
| if (config === 'close') { | |||||
| data[config](this) | |||||
| } | |||||
| }) | |||||
| } | |||||
| static _handleDismiss(alertInstance) { | |||||
| return function (event) { | |||||
| if (event) { | |||||
| event.preventDefault() | |||||
| } | |||||
| alertInstance.close(this) | |||||
| } | |||||
| } | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Data Api implementation | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $(document).on( | |||||
| Event.CLICK_DATA_API, | |||||
| Selector.DISMISS, | |||||
| Alert._handleDismiss(new Alert()) | |||||
| ) | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * jQuery | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $.fn[NAME] = Alert._jQueryInterface | |||||
| $.fn[NAME].Constructor = Alert | |||||
| $.fn[NAME].noConflict = () => { | |||||
| $.fn[NAME] = JQUERY_NO_CONFLICT | |||||
| return Alert._jQueryInterface | |||||
| } | |||||
| export default Alert | |||||
| @ -0,0 +1,213 @@ | |||||
| /** | |||||
| * -------------------------------------------------------------------------- | |||||
| * Bootstrap (v4.4.1): button.js | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| * -------------------------------------------------------------------------- | |||||
| */ | |||||
| import $ from 'jquery' | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Constants | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| const NAME = 'button' | |||||
| const VERSION = '4.4.1' | |||||
| const DATA_KEY = 'bs.button' | |||||
| const EVENT_KEY = `.${DATA_KEY}` | |||||
| const DATA_API_KEY = '.data-api' | |||||
| const JQUERY_NO_CONFLICT = $.fn[NAME] | |||||
| const ClassName = { | |||||
| ACTIVE : 'active', | |||||
| BUTTON : 'btn', | |||||
| FOCUS : 'focus' | |||||
| } | |||||
| const Selector = { | |||||
| DATA_TOGGLE_CARROT : '[data-toggle^="button"]', | |||||
| DATA_TOGGLES : '[data-toggle="buttons"]', | |||||
| DATA_TOGGLE : '[data-toggle="button"]', | |||||
| DATA_TOGGLES_BUTTONS : '[data-toggle="buttons"] .btn', | |||||
| INPUT : 'input:not([type="hidden"])', | |||||
| ACTIVE : '.active', | |||||
| BUTTON : '.btn' | |||||
| } | |||||
| const Event = { | |||||
| CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`, | |||||
| FOCUS_BLUR_DATA_API : `focus${EVENT_KEY}${DATA_API_KEY} ` + | |||||
| `blur${EVENT_KEY}${DATA_API_KEY}`, | |||||
| LOAD_DATA_API : `load${EVENT_KEY}${DATA_API_KEY}` | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Class Definition | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| class Button { | |||||
| constructor(element) { | |||||
| this._element = element | |||||
| } | |||||
| // Getters | |||||
| static get VERSION() { | |||||
| return VERSION | |||||
| } | |||||
| // Public | |||||
| toggle() { | |||||
| let triggerChangeEvent = true | |||||
| let addAriaPressed = true | |||||
| const rootElement = $(this._element).closest( | |||||
| Selector.DATA_TOGGLES | |||||
| )[0] | |||||
| if (rootElement) { | |||||
| const input = this._element.querySelector(Selector.INPUT) | |||||
| if (input) { | |||||
| if (input.type === 'radio') { | |||||
| if (input.checked && | |||||
| this._element.classList.contains(ClassName.ACTIVE)) { | |||||
| triggerChangeEvent = false | |||||
| } else { | |||||
| const activeElement = rootElement.querySelector(Selector.ACTIVE) | |||||
| if (activeElement) { | |||||
| $(activeElement).removeClass(ClassName.ACTIVE) | |||||
| } | |||||
| } | |||||
| } else if (input.type === 'checkbox') { | |||||
| if (this._element.tagName === 'LABEL' && input.checked === this._element.classList.contains(ClassName.ACTIVE)) { | |||||
| triggerChangeEvent = false | |||||
| } | |||||
| } else { | |||||
| // if it's not a radio button or checkbox don't add a pointless/invalid checked property to the input | |||||
| triggerChangeEvent = false | |||||
| } | |||||
| if (triggerChangeEvent) { | |||||
| input.checked = !this._element.classList.contains(ClassName.ACTIVE) | |||||
| $(input).trigger('change') | |||||
| } | |||||
| input.focus() | |||||
| addAriaPressed = false | |||||
| } | |||||
| } | |||||
| if (!(this._element.hasAttribute('disabled') || this._element.classList.contains('disabled'))) { | |||||
| if (addAriaPressed) { | |||||
| this._element.setAttribute('aria-pressed', | |||||
| !this._element.classList.contains(ClassName.ACTIVE)) | |||||
| } | |||||
| if (triggerChangeEvent) { | |||||
| $(this._element).toggleClass(ClassName.ACTIVE) | |||||
| } | |||||
| } | |||||
| } | |||||
| dispose() { | |||||
| $.removeData(this._element, DATA_KEY) | |||||
| this._element = null | |||||
| } | |||||
| // Static | |||||
| static _jQueryInterface(config) { | |||||
| return this.each(function () { | |||||
| let data = $(this).data(DATA_KEY) | |||||
| if (!data) { | |||||
| data = new Button(this) | |||||
| $(this).data(DATA_KEY, data) | |||||
| } | |||||
| if (config === 'toggle') { | |||||
| data[config]() | |||||
| } | |||||
| }) | |||||
| } | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Data Api implementation | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $(document) | |||||
| .on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, (event) => { | |||||
| let button = event.target | |||||
| if (!$(button).hasClass(ClassName.BUTTON)) { | |||||
| button = $(button).closest(Selector.BUTTON)[0] | |||||
| } | |||||
| if (!button || button.hasAttribute('disabled') || button.classList.contains('disabled')) { | |||||
| event.preventDefault() // work around Firefox bug #1540995 | |||||
| } else { | |||||
| const inputBtn = button.querySelector(Selector.INPUT) | |||||
| if (inputBtn && (inputBtn.hasAttribute('disabled') || inputBtn.classList.contains('disabled'))) { | |||||
| event.preventDefault() // work around Firefox bug #1540995 | |||||
| return | |||||
| } | |||||
| Button._jQueryInterface.call($(button), 'toggle') | |||||
| } | |||||
| }) | |||||
| .on(Event.FOCUS_BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, (event) => { | |||||
| const button = $(event.target).closest(Selector.BUTTON)[0] | |||||
| $(button).toggleClass(ClassName.FOCUS, /^focus(in)?$/.test(event.type)) | |||||
| }) | |||||
| $(window).on(Event.LOAD_DATA_API, () => { | |||||
| // ensure correct active class is set to match the controls' actual values/states | |||||
| // find all checkboxes/readio buttons inside data-toggle groups | |||||
| let buttons = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLES_BUTTONS)) | |||||
| for (let i = 0, len = buttons.length; i < len; i++) { | |||||
| const button = buttons[i] | |||||
| const input = button.querySelector(Selector.INPUT) | |||||
| if (input.checked || input.hasAttribute('checked')) { | |||||
| button.classList.add(ClassName.ACTIVE) | |||||
| } else { | |||||
| button.classList.remove(ClassName.ACTIVE) | |||||
| } | |||||
| } | |||||
| // find all button toggles | |||||
| buttons = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE)) | |||||
| for (let i = 0, len = buttons.length; i < len; i++) { | |||||
| const button = buttons[i] | |||||
| if (button.getAttribute('aria-pressed') === 'true') { | |||||
| button.classList.add(ClassName.ACTIVE) | |||||
| } else { | |||||
| button.classList.remove(ClassName.ACTIVE) | |||||
| } | |||||
| } | |||||
| }) | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * jQuery | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $.fn[NAME] = Button._jQueryInterface | |||||
| $.fn[NAME].Constructor = Button | |||||
| $.fn[NAME].noConflict = () => { | |||||
| $.fn[NAME] = JQUERY_NO_CONFLICT | |||||
| return Button._jQueryInterface | |||||
| } | |||||
| export default Button | |||||
| @ -0,0 +1,608 @@ | |||||
| /** | |||||
| * -------------------------------------------------------------------------- | |||||
| * Bootstrap (v4.4.1): carousel.js | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| * -------------------------------------------------------------------------- | |||||
| */ | |||||
| import $ from 'jquery' | |||||
| import Util from './util' | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Constants | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| const NAME = 'carousel' | |||||
| const VERSION = '4.4.1' | |||||
| const DATA_KEY = 'bs.carousel' | |||||
| const EVENT_KEY = `.${DATA_KEY}` | |||||
| const DATA_API_KEY = '.data-api' | |||||
| const JQUERY_NO_CONFLICT = $.fn[NAME] | |||||
| const ARROW_LEFT_KEYCODE = 37 // KeyboardEvent.which value for left arrow key | |||||
| const ARROW_RIGHT_KEYCODE = 39 // KeyboardEvent.which value for right arrow key | |||||
| const TOUCHEVENT_COMPAT_WAIT = 500 // Time for mouse compat events to fire after touch | |||||
| const SWIPE_THRESHOLD = 40 | |||||
| const Default = { | |||||
| interval : 5000, | |||||
| keyboard : true, | |||||
| slide : false, | |||||
| pause : 'hover', | |||||
| wrap : true, | |||||
| touch : true | |||||
| } | |||||
| const DefaultType = { | |||||
| interval : '(number|boolean)', | |||||
| keyboard : 'boolean', | |||||
| slide : '(boolean|string)', | |||||
| pause : '(string|boolean)', | |||||
| wrap : 'boolean', | |||||
| touch : 'boolean' | |||||
| } | |||||
| const Direction = { | |||||
| NEXT : 'next', | |||||
| PREV : 'prev', | |||||
| LEFT : 'left', | |||||
| RIGHT : 'right' | |||||
| } | |||||
| const Event = { | |||||
| SLIDE : `slide${EVENT_KEY}`, | |||||
| SLID : `slid${EVENT_KEY}`, | |||||
| KEYDOWN : `keydown${EVENT_KEY}`, | |||||
| MOUSEENTER : `mouseenter${EVENT_KEY}`, | |||||
| MOUSELEAVE : `mouseleave${EVENT_KEY}`, | |||||
| TOUCHSTART : `touchstart${EVENT_KEY}`, | |||||
| TOUCHMOVE : `touchmove${EVENT_KEY}`, | |||||
| TOUCHEND : `touchend${EVENT_KEY}`, | |||||
| POINTERDOWN : `pointerdown${EVENT_KEY}`, | |||||
| POINTERUP : `pointerup${EVENT_KEY}`, | |||||
| DRAG_START : `dragstart${EVENT_KEY}`, | |||||
| LOAD_DATA_API : `load${EVENT_KEY}${DATA_API_KEY}`, | |||||
| CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}` | |||||
| } | |||||
| const ClassName = { | |||||
| CAROUSEL : 'carousel', | |||||
| ACTIVE : 'active', | |||||
| SLIDE : 'slide', | |||||
| RIGHT : 'carousel-item-right', | |||||
| LEFT : 'carousel-item-left', | |||||
| NEXT : 'carousel-item-next', | |||||
| PREV : 'carousel-item-prev', | |||||
| ITEM : 'carousel-item', | |||||
| POINTER_EVENT : 'pointer-event' | |||||
| } | |||||
| const Selector = { | |||||
| ACTIVE : '.active', | |||||
| ACTIVE_ITEM : '.active.carousel-item', | |||||
| ITEM : '.carousel-item', | |||||
| ITEM_IMG : '.carousel-item img', | |||||
| NEXT_PREV : '.carousel-item-next, .carousel-item-prev', | |||||
| INDICATORS : '.carousel-indicators', | |||||
| DATA_SLIDE : '[data-slide], [data-slide-to]', | |||||
| DATA_RIDE : '[data-ride="carousel"]' | |||||
| } | |||||
| const PointerType = { | |||||
| TOUCH : 'touch', | |||||
| PEN : 'pen' | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Class Definition | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| class Carousel { | |||||
| constructor(element, config) { | |||||
| this._items = null | |||||
| this._interval = null | |||||
| this._activeElement = null | |||||
| this._isPaused = false | |||||
| this._isSliding = false | |||||
| this.touchTimeout = null | |||||
| this.touchStartX = 0 | |||||
| this.touchDeltaX = 0 | |||||
| this._config = this._getConfig(config) | |||||
| this._element = element | |||||
| this._indicatorsElement = this._element.querySelector(Selector.INDICATORS) | |||||
| this._touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0 | |||||
| this._pointerEvent = Boolean(window.PointerEvent || window.MSPointerEvent) | |||||
| this._addEventListeners() | |||||
| } | |||||
| // Getters | |||||
| static get VERSION() { | |||||
| return VERSION | |||||
| } | |||||
| static get Default() { | |||||
| return Default | |||||
| } | |||||
| // Public | |||||
| next() { | |||||
| if (!this._isSliding) { | |||||
| this._slide(Direction.NEXT) | |||||
| } | |||||
| } | |||||
| nextWhenVisible() { | |||||
| // Don't call next when the page isn't visible | |||||
| // or the carousel or its parent isn't visible | |||||
| if (!document.hidden && | |||||
| ($(this._element).is(':visible') && $(this._element).css('visibility') !== 'hidden')) { | |||||
| this.next() | |||||
| } | |||||
| } | |||||
| prev() { | |||||
| if (!this._isSliding) { | |||||
| this._slide(Direction.PREV) | |||||
| } | |||||
| } | |||||
| pause(event) { | |||||
| if (!event) { | |||||
| this._isPaused = true | |||||
| } | |||||
| if (this._element.querySelector(Selector.NEXT_PREV)) { | |||||
| Util.triggerTransitionEnd(this._element) | |||||
| this.cycle(true) | |||||
| } | |||||
| clearInterval(this._interval) | |||||
| this._interval = null | |||||
| } | |||||
| cycle(event) { | |||||
| if (!event) { | |||||
| this._isPaused = false | |||||
| } | |||||
| if (this._interval) { | |||||
| clearInterval(this._interval) | |||||
| this._interval = null | |||||
| } | |||||
| if (this._config.interval && !this._isPaused) { | |||||
| this._interval = setInterval( | |||||
| (document.visibilityState ? this.nextWhenVisible : this.next).bind(this), | |||||
| this._config.interval | |||||
| ) | |||||
| } | |||||
| } | |||||
| to(index) { | |||||
| this._activeElement = this._element.querySelector(Selector.ACTIVE_ITEM) | |||||
| const activeIndex = this._getItemIndex(this._activeElement) | |||||
| if (index > this._items.length - 1 || index < 0) { | |||||
| return | |||||
| } | |||||
| if (this._isSliding) { | |||||
| $(this._element).one(Event.SLID, () => this.to(index)) | |||||
| return | |||||
| } | |||||
| if (activeIndex === index) { | |||||
| this.pause() | |||||
| this.cycle() | |||||
| return | |||||
| } | |||||
| const direction = index > activeIndex | |||||
| ? Direction.NEXT | |||||
| : Direction.PREV | |||||
| this._slide(direction, this._items[index]) | |||||
| } | |||||
| dispose() { | |||||
| $(this._element).off(EVENT_KEY) | |||||
| $.removeData(this._element, DATA_KEY) | |||||
| this._items = null | |||||
| this._config = null | |||||
| this._element = null | |||||
| this._interval = null | |||||
| this._isPaused = null | |||||
| this._isSliding = null | |||||
| this._activeElement = null | |||||
| this._indicatorsElement = null | |||||
| } | |||||
| // Private | |||||
| _getConfig(config) { | |||||
| config = { | |||||
| ...Default, | |||||
| ...config | |||||
| } | |||||
| Util.typeCheckConfig(NAME, config, DefaultType) | |||||
| return config | |||||
| } | |||||
| _handleSwipe() { | |||||
| const absDeltax = Math.abs(this.touchDeltaX) | |||||
| if (absDeltax <= SWIPE_THRESHOLD) { | |||||
| return | |||||
| } | |||||
| const direction = absDeltax / this.touchDeltaX | |||||
| this.touchDeltaX = 0 | |||||
| // swipe left | |||||
| if (direction > 0) { | |||||
| this.prev() | |||||
| } | |||||
| // swipe right | |||||
| if (direction < 0) { | |||||
| this.next() | |||||
| } | |||||
| } | |||||
| _addEventListeners() { | |||||
| if (this._config.keyboard) { | |||||
| $(this._element) | |||||
| .on(Event.KEYDOWN, (event) => this._keydown(event)) | |||||
| } | |||||
| if (this._config.pause === 'hover') { | |||||
| $(this._element) | |||||
| .on(Event.MOUSEENTER, (event) => this.pause(event)) | |||||
| .on(Event.MOUSELEAVE, (event) => this.cycle(event)) | |||||
| } | |||||
| if (this._config.touch) { | |||||
| this._addTouchEventListeners() | |||||
| } | |||||
| } | |||||
| _addTouchEventListeners() { | |||||
| if (!this._touchSupported) { | |||||
| return | |||||
| } | |||||
| const start = (event) => { | |||||
| if (this._pointerEvent && PointerType[event.originalEvent.pointerType.toUpperCase()]) { | |||||
| this.touchStartX = event.originalEvent.clientX | |||||
| } else if (!this._pointerEvent) { | |||||
| this.touchStartX = event.originalEvent.touches[0].clientX | |||||
| } | |||||
| } | |||||
| const move = (event) => { | |||||
| // ensure swiping with one touch and not pinching | |||||
| if (event.originalEvent.touches && event.originalEvent.touches.length > 1) { | |||||
| this.touchDeltaX = 0 | |||||
| } else { | |||||
| this.touchDeltaX = event.originalEvent.touches[0].clientX - this.touchStartX | |||||
| } | |||||
| } | |||||
| const end = (event) => { | |||||
| if (this._pointerEvent && PointerType[event.originalEvent.pointerType.toUpperCase()]) { | |||||
| this.touchDeltaX = event.originalEvent.clientX - this.touchStartX | |||||
| } | |||||
| this._handleSwipe() | |||||
| if (this._config.pause === 'hover') { | |||||
| // If it's a touch-enabled device, mouseenter/leave are fired as | |||||
| // part of the mouse compatibility events on first tap - the carousel | |||||
| // would stop cycling until user tapped out of it; | |||||
| // here, we listen for touchend, explicitly pause the carousel | |||||
| // (as if it's the second time we tap on it, mouseenter compat event | |||||
| // is NOT fired) and after a timeout (to allow for mouse compatibility | |||||
| // events to fire) we explicitly restart cycling | |||||
| this.pause() | |||||
| if (this.touchTimeout) { | |||||
| clearTimeout(this.touchTimeout) | |||||
| } | |||||
| this.touchTimeout = setTimeout((event) => this.cycle(event), TOUCHEVENT_COMPAT_WAIT + this._config.interval) | |||||
| } | |||||
| } | |||||
| $(this._element.querySelectorAll(Selector.ITEM_IMG)).on(Event.DRAG_START, (e) => e.preventDefault()) | |||||
| if (this._pointerEvent) { | |||||
| $(this._element).on(Event.POINTERDOWN, (event) => start(event)) | |||||
| $(this._element).on(Event.POINTERUP, (event) => end(event)) | |||||
| this._element.classList.add(ClassName.POINTER_EVENT) | |||||
| } else { | |||||
| $(this._element).on(Event.TOUCHSTART, (event) => start(event)) | |||||
| $(this._element).on(Event.TOUCHMOVE, (event) => move(event)) | |||||
| $(this._element).on(Event.TOUCHEND, (event) => end(event)) | |||||
| } | |||||
| } | |||||
| _keydown(event) { | |||||
| if (/input|textarea/i.test(event.target.tagName)) { | |||||
| return | |||||
| } | |||||
| switch (event.which) { | |||||
| case ARROW_LEFT_KEYCODE: | |||||
| event.preventDefault() | |||||
| this.prev() | |||||
| break | |||||
| case ARROW_RIGHT_KEYCODE: | |||||
| event.preventDefault() | |||||
| this.next() | |||||
| break | |||||
| default: | |||||
| } | |||||
| } | |||||
| _getItemIndex(element) { | |||||
| this._items = element && element.parentNode | |||||
| ? [].slice.call(element.parentNode.querySelectorAll(Selector.ITEM)) | |||||
| : [] | |||||
| return this._items.indexOf(element) | |||||
| } | |||||
| _getItemByDirection(direction, activeElement) { | |||||
| const isNextDirection = direction === Direction.NEXT | |||||
| const isPrevDirection = direction === Direction.PREV | |||||
| const activeIndex = this._getItemIndex(activeElement) | |||||
| const lastItemIndex = this._items.length - 1 | |||||
| const isGoingToWrap = isPrevDirection && activeIndex === 0 || | |||||
| isNextDirection && activeIndex === lastItemIndex | |||||
| if (isGoingToWrap && !this._config.wrap) { | |||||
| return activeElement | |||||
| } | |||||
| const delta = direction === Direction.PREV ? -1 : 1 | |||||
| const itemIndex = (activeIndex + delta) % this._items.length | |||||
| return itemIndex === -1 | |||||
| ? this._items[this._items.length - 1] : this._items[itemIndex] | |||||
| } | |||||
| _triggerSlideEvent(relatedTarget, eventDirectionName) { | |||||
| const targetIndex = this._getItemIndex(relatedTarget) | |||||
| const fromIndex = this._getItemIndex(this._element.querySelector(Selector.ACTIVE_ITEM)) | |||||
| const slideEvent = $.Event(Event.SLIDE, { | |||||
| relatedTarget, | |||||
| direction: eventDirectionName, | |||||
| from: fromIndex, | |||||
| to: targetIndex | |||||
| }) | |||||
| $(this._element).trigger(slideEvent) | |||||
| return slideEvent | |||||
| } | |||||
| _setActiveIndicatorElement(element) { | |||||
| if (this._indicatorsElement) { | |||||
| const indicators = [].slice.call(this._indicatorsElement.querySelectorAll(Selector.ACTIVE)) | |||||
| $(indicators) | |||||
| .removeClass(ClassName.ACTIVE) | |||||
| const nextIndicator = this._indicatorsElement.children[ | |||||
| this._getItemIndex(element) | |||||
| ] | |||||
| if (nextIndicator) { | |||||
| $(nextIndicator).addClass(ClassName.ACTIVE) | |||||
| } | |||||
| } | |||||
| } | |||||
| _slide(direction, element) { | |||||
| const activeElement = this._element.querySelector(Selector.ACTIVE_ITEM) | |||||
| const activeElementIndex = this._getItemIndex(activeElement) | |||||
| const nextElement = element || activeElement && | |||||
| this._getItemByDirection(direction, activeElement) | |||||
| const nextElementIndex = this._getItemIndex(nextElement) | |||||
| const isCycling = Boolean(this._interval) | |||||
| let directionalClassName | |||||
| let orderClassName | |||||
| let eventDirectionName | |||||
| if (direction === Direction.NEXT) { | |||||
| directionalClassName = ClassName.LEFT | |||||
| orderClassName = ClassName.NEXT | |||||
| eventDirectionName = Direction.LEFT | |||||
| } else { | |||||
| directionalClassName = ClassName.RIGHT | |||||
| orderClassName = ClassName.PREV | |||||
| eventDirectionName = Direction.RIGHT | |||||
| } | |||||
| if (nextElement && $(nextElement).hasClass(ClassName.ACTIVE)) { | |||||
| this._isSliding = false | |||||
| return | |||||
| } | |||||
| const slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName) | |||||
| if (slideEvent.isDefaultPrevented()) { | |||||
| return | |||||
| } | |||||
| if (!activeElement || !nextElement) { | |||||
| // Some weirdness is happening, so we bail | |||||
| return | |||||
| } | |||||
| this._isSliding = true | |||||
| if (isCycling) { | |||||
| this.pause() | |||||
| } | |||||
| this._setActiveIndicatorElement(nextElement) | |||||
| const slidEvent = $.Event(Event.SLID, { | |||||
| relatedTarget: nextElement, | |||||
| direction: eventDirectionName, | |||||
| from: activeElementIndex, | |||||
| to: nextElementIndex | |||||
| }) | |||||
| if ($(this._element).hasClass(ClassName.SLIDE)) { | |||||
| $(nextElement).addClass(orderClassName) | |||||
| Util.reflow(nextElement) | |||||
| $(activeElement).addClass(directionalClassName) | |||||
| $(nextElement).addClass(directionalClassName) | |||||
| const nextElementInterval = parseInt(nextElement.getAttribute('data-interval'), 10) | |||||
| if (nextElementInterval) { | |||||
| this._config.defaultInterval = this._config.defaultInterval || this._config.interval | |||||
| this._config.interval = nextElementInterval | |||||
| } else { | |||||
| this._config.interval = this._config.defaultInterval || this._config.interval | |||||
| } | |||||
| const transitionDuration = Util.getTransitionDurationFromElement(activeElement) | |||||
| $(activeElement) | |||||
| .one(Util.TRANSITION_END, () => { | |||||
| $(nextElement) | |||||
| .removeClass(`${directionalClassName} ${orderClassName}`) | |||||
| .addClass(ClassName.ACTIVE) | |||||
| $(activeElement).removeClass(`${ClassName.ACTIVE} ${orderClassName} ${directionalClassName}`) | |||||
| this._isSliding = false | |||||
| setTimeout(() => $(this._element).trigger(slidEvent), 0) | |||||
| }) | |||||
| .emulateTransitionEnd(transitionDuration) | |||||
| } else { | |||||
| $(activeElement).removeClass(ClassName.ACTIVE) | |||||
| $(nextElement).addClass(ClassName.ACTIVE) | |||||
| this._isSliding = false | |||||
| $(this._element).trigger(slidEvent) | |||||
| } | |||||
| if (isCycling) { | |||||
| this.cycle() | |||||
| } | |||||
| } | |||||
| // Static | |||||
| static _jQueryInterface(config) { | |||||
| return this.each(function () { | |||||
| let data = $(this).data(DATA_KEY) | |||||
| let _config = { | |||||
| ...Default, | |||||
| ...$(this).data() | |||||
| } | |||||
| if (typeof config === 'object') { | |||||
| _config = { | |||||
| ..._config, | |||||
| ...config | |||||
| } | |||||
| } | |||||
| const action = typeof config === 'string' ? config : _config.slide | |||||
| if (!data) { | |||||
| data = new Carousel(this, _config) | |||||
| $(this).data(DATA_KEY, data) | |||||
| } | |||||
| if (typeof config === 'number') { | |||||
| data.to(config) | |||||
| } else if (typeof action === 'string') { | |||||
| if (typeof data[action] === 'undefined') { | |||||
| throw new TypeError(`No method named "${action}"`) | |||||
| } | |||||
| data[action]() | |||||
| } else if (_config.interval && _config.ride) { | |||||
| data.pause() | |||||
| data.cycle() | |||||
| } | |||||
| }) | |||||
| } | |||||
| static _dataApiClickHandler(event) { | |||||
| const selector = Util.getSelectorFromElement(this) | |||||
| if (!selector) { | |||||
| return | |||||
| } | |||||
| const target = $(selector)[0] | |||||
| if (!target || !$(target).hasClass(ClassName.CAROUSEL)) { | |||||
| return | |||||
| } | |||||
| const config = { | |||||
| ...$(target).data(), | |||||
| ...$(this).data() | |||||
| } | |||||
| const slideIndex = this.getAttribute('data-slide-to') | |||||
| if (slideIndex) { | |||||
| config.interval = false | |||||
| } | |||||
| Carousel._jQueryInterface.call($(target), config) | |||||
| if (slideIndex) { | |||||
| $(target).data(DATA_KEY).to(slideIndex) | |||||
| } | |||||
| event.preventDefault() | |||||
| } | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Data Api implementation | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $(document) | |||||
| .on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler) | |||||
| $(window).on(Event.LOAD_DATA_API, () => { | |||||
| const carousels = [].slice.call(document.querySelectorAll(Selector.DATA_RIDE)) | |||||
| for (let i = 0, len = carousels.length; i < len; i++) { | |||||
| const $carousel = $(carousels[i]) | |||||
| Carousel._jQueryInterface.call($carousel, $carousel.data()) | |||||
| } | |||||
| }) | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * jQuery | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $.fn[NAME] = Carousel._jQueryInterface | |||||
| $.fn[NAME].Constructor = Carousel | |||||
| $.fn[NAME].noConflict = () => { | |||||
| $.fn[NAME] = JQUERY_NO_CONFLICT | |||||
| return Carousel._jQueryInterface | |||||
| } | |||||
| export default Carousel | |||||
| @ -0,0 +1,402 @@ | |||||
| /** | |||||
| * -------------------------------------------------------------------------- | |||||
| * Bootstrap (v4.4.1): collapse.js | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| * -------------------------------------------------------------------------- | |||||
| */ | |||||
| import $ from 'jquery' | |||||
| import Util from './util' | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Constants | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| const NAME = 'collapse' | |||||
| const VERSION = '4.4.1' | |||||
| const DATA_KEY = 'bs.collapse' | |||||
| const EVENT_KEY = `.${DATA_KEY}` | |||||
| const DATA_API_KEY = '.data-api' | |||||
| const JQUERY_NO_CONFLICT = $.fn[NAME] | |||||
| const Default = { | |||||
| toggle : true, | |||||
| parent : '' | |||||
| } | |||||
| const DefaultType = { | |||||
| toggle : 'boolean', | |||||
| parent : '(string|element)' | |||||
| } | |||||
| const Event = { | |||||
| SHOW : `show${EVENT_KEY}`, | |||||
| SHOWN : `shown${EVENT_KEY}`, | |||||
| HIDE : `hide${EVENT_KEY}`, | |||||
| HIDDEN : `hidden${EVENT_KEY}`, | |||||
| CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}` | |||||
| } | |||||
| const ClassName = { | |||||
| SHOW : 'show', | |||||
| COLLAPSE : 'collapse', | |||||
| COLLAPSING : 'collapsing', | |||||
| COLLAPSED : 'collapsed' | |||||
| } | |||||
| const Dimension = { | |||||
| WIDTH : 'width', | |||||
| HEIGHT : 'height' | |||||
| } | |||||
| const Selector = { | |||||
| ACTIVES : '.show, .collapsing', | |||||
| DATA_TOGGLE : '[data-toggle="collapse"]' | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Class Definition | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| class Collapse { | |||||
| constructor(element, config) { | |||||
| this._isTransitioning = false | |||||
| this._element = element | |||||
| this._config = this._getConfig(config) | |||||
| this._triggerArray = [].slice.call(document.querySelectorAll( | |||||
| `[data-toggle="collapse"][href="#${element.id}"],` + | |||||
| `[data-toggle="collapse"][data-target="#${element.id}"]` | |||||
| )) | |||||
| const toggleList = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE)) | |||||
| for (let i = 0, len = toggleList.length; i < len; i++) { | |||||
| const elem = toggleList[i] | |||||
| const selector = Util.getSelectorFromElement(elem) | |||||
| const filterElement = [].slice.call(document.querySelectorAll(selector)) | |||||
| .filter((foundElem) => foundElem === element) | |||||
| if (selector !== null && filterElement.length > 0) { | |||||
| this._selector = selector | |||||
| this._triggerArray.push(elem) | |||||
| } | |||||
| } | |||||
| this._parent = this._config.parent ? this._getParent() : null | |||||
| if (!this._config.parent) { | |||||
| this._addAriaAndCollapsedClass(this._element, this._triggerArray) | |||||
| } | |||||
| if (this._config.toggle) { | |||||
| this.toggle() | |||||
| } | |||||
| } | |||||
| // Getters | |||||
| static get VERSION() { | |||||
| return VERSION | |||||
| } | |||||
| static get Default() { | |||||
| return Default | |||||
| } | |||||
| // Public | |||||
| toggle() { | |||||
| if ($(this._element).hasClass(ClassName.SHOW)) { | |||||
| this.hide() | |||||
| } else { | |||||
| this.show() | |||||
| } | |||||
| } | |||||
| show() { | |||||
| if (this._isTransitioning || | |||||
| $(this._element).hasClass(ClassName.SHOW)) { | |||||
| return | |||||
| } | |||||
| let actives | |||||
| let activesData | |||||
| if (this._parent) { | |||||
| actives = [].slice.call(this._parent.querySelectorAll(Selector.ACTIVES)) | |||||
| .filter((elem) => { | |||||
| if (typeof this._config.parent === 'string') { | |||||
| return elem.getAttribute('data-parent') === this._config.parent | |||||
| } | |||||
| return elem.classList.contains(ClassName.COLLAPSE) | |||||
| }) | |||||
| if (actives.length === 0) { | |||||
| actives = null | |||||
| } | |||||
| } | |||||
| if (actives) { | |||||
| activesData = $(actives).not(this._selector).data(DATA_KEY) | |||||
| if (activesData && activesData._isTransitioning) { | |||||
| return | |||||
| } | |||||
| } | |||||
| const startEvent = $.Event(Event.SHOW) | |||||
| $(this._element).trigger(startEvent) | |||||
| if (startEvent.isDefaultPrevented()) { | |||||
| return | |||||
| } | |||||
| if (actives) { | |||||
| Collapse._jQueryInterface.call($(actives).not(this._selector), 'hide') | |||||
| if (!activesData) { | |||||
| $(actives).data(DATA_KEY, null) | |||||
| } | |||||
| } | |||||
| const dimension = this._getDimension() | |||||
| $(this._element) | |||||
| .removeClass(ClassName.COLLAPSE) | |||||
| .addClass(ClassName.COLLAPSING) | |||||
| this._element.style[dimension] = 0 | |||||
| if (this._triggerArray.length) { | |||||
| $(this._triggerArray) | |||||
| .removeClass(ClassName.COLLAPSED) | |||||
| .attr('aria-expanded', true) | |||||
| } | |||||
| this.setTransitioning(true) | |||||
| const complete = () => { | |||||
| $(this._element) | |||||
| .removeClass(ClassName.COLLAPSING) | |||||
| .addClass(ClassName.COLLAPSE) | |||||
| .addClass(ClassName.SHOW) | |||||
| this._element.style[dimension] = '' | |||||
| this.setTransitioning(false) | |||||
| $(this._element).trigger(Event.SHOWN) | |||||
| } | |||||
| const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1) | |||||
| const scrollSize = `scroll${capitalizedDimension}` | |||||
| const transitionDuration = Util.getTransitionDurationFromElement(this._element) | |||||
| $(this._element) | |||||
| .one(Util.TRANSITION_END, complete) | |||||
| .emulateTransitionEnd(transitionDuration) | |||||
| this._element.style[dimension] = `${this._element[scrollSize]}px` | |||||
| } | |||||
| hide() { | |||||
| if (this._isTransitioning || | |||||
| !$(this._element).hasClass(ClassName.SHOW)) { | |||||
| return | |||||
| } | |||||
| const startEvent = $.Event(Event.HIDE) | |||||
| $(this._element).trigger(startEvent) | |||||
| if (startEvent.isDefaultPrevented()) { | |||||
| return | |||||
| } | |||||
| const dimension = this._getDimension() | |||||
| this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px` | |||||
| Util.reflow(this._element) | |||||
| $(this._element) | |||||
| .addClass(ClassName.COLLAPSING) | |||||
| .removeClass(ClassName.COLLAPSE) | |||||
| .removeClass(ClassName.SHOW) | |||||
| const triggerArrayLength = this._triggerArray.length | |||||
| if (triggerArrayLength > 0) { | |||||
| for (let i = 0; i < triggerArrayLength; i++) { | |||||
| const trigger = this._triggerArray[i] | |||||
| const selector = Util.getSelectorFromElement(trigger) | |||||
| if (selector !== null) { | |||||
| const $elem = $([].slice.call(document.querySelectorAll(selector))) | |||||
| if (!$elem.hasClass(ClassName.SHOW)) { | |||||
| $(trigger).addClass(ClassName.COLLAPSED) | |||||
| .attr('aria-expanded', false) | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| this.setTransitioning(true) | |||||
| const complete = () => { | |||||
| this.setTransitioning(false) | |||||
| $(this._element) | |||||
| .removeClass(ClassName.COLLAPSING) | |||||
| .addClass(ClassName.COLLAPSE) | |||||
| .trigger(Event.HIDDEN) | |||||
| } | |||||
| this._element.style[dimension] = '' | |||||
| const transitionDuration = Util.getTransitionDurationFromElement(this._element) | |||||
| $(this._element) | |||||
| .one(Util.TRANSITION_END, complete) | |||||
| .emulateTransitionEnd(transitionDuration) | |||||
| } | |||||
| setTransitioning(isTransitioning) { | |||||
| this._isTransitioning = isTransitioning | |||||
| } | |||||
| dispose() { | |||||
| $.removeData(this._element, DATA_KEY) | |||||
| this._config = null | |||||
| this._parent = null | |||||
| this._element = null | |||||
| this._triggerArray = null | |||||
| this._isTransitioning = null | |||||
| } | |||||
| // Private | |||||
| _getConfig(config) { | |||||
| config = { | |||||
| ...Default, | |||||
| ...config | |||||
| } | |||||
| config.toggle = Boolean(config.toggle) // Coerce string values | |||||
| Util.typeCheckConfig(NAME, config, DefaultType) | |||||
| return config | |||||
| } | |||||
| _getDimension() { | |||||
| const hasWidth = $(this._element).hasClass(Dimension.WIDTH) | |||||
| return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT | |||||
| } | |||||
| _getParent() { | |||||
| let parent | |||||
| if (Util.isElement(this._config.parent)) { | |||||
| parent = this._config.parent | |||||
| // It's a jQuery object | |||||
| if (typeof this._config.parent.jquery !== 'undefined') { | |||||
| parent = this._config.parent[0] | |||||
| } | |||||
| } else { | |||||
| parent = document.querySelector(this._config.parent) | |||||
| } | |||||
| const selector = | |||||
| `[data-toggle="collapse"][data-parent="${this._config.parent}"]` | |||||
| const children = [].slice.call(parent.querySelectorAll(selector)) | |||||
| $(children).each((i, element) => { | |||||
| this._addAriaAndCollapsedClass( | |||||
| Collapse._getTargetFromElement(element), | |||||
| [element] | |||||
| ) | |||||
| }) | |||||
| return parent | |||||
| } | |||||
| _addAriaAndCollapsedClass(element, triggerArray) { | |||||
| const isOpen = $(element).hasClass(ClassName.SHOW) | |||||
| if (triggerArray.length) { | |||||
| $(triggerArray) | |||||
| .toggleClass(ClassName.COLLAPSED, !isOpen) | |||||
| .attr('aria-expanded', isOpen) | |||||
| } | |||||
| } | |||||
| // Static | |||||
| static _getTargetFromElement(element) { | |||||
| const selector = Util.getSelectorFromElement(element) | |||||
| return selector ? document.querySelector(selector) : null | |||||
| } | |||||
| static _jQueryInterface(config) { | |||||
| return this.each(function () { | |||||
| const $this = $(this) | |||||
| let data = $this.data(DATA_KEY) | |||||
| const _config = { | |||||
| ...Default, | |||||
| ...$this.data(), | |||||
| ...typeof config === 'object' && config ? config : {} | |||||
| } | |||||
| if (!data && _config.toggle && /show|hide/.test(config)) { | |||||
| _config.toggle = false | |||||
| } | |||||
| if (!data) { | |||||
| data = new Collapse(this, _config) | |||||
| $this.data(DATA_KEY, data) | |||||
| } | |||||
| if (typeof config === 'string') { | |||||
| if (typeof data[config] === 'undefined') { | |||||
| throw new TypeError(`No method named "${config}"`) | |||||
| } | |||||
| data[config]() | |||||
| } | |||||
| }) | |||||
| } | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Data Api implementation | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { | |||||
| // preventDefault only for <a> elements (which change the URL) not inside the collapsible element | |||||
| if (event.currentTarget.tagName === 'A') { | |||||
| event.preventDefault() | |||||
| } | |||||
| const $trigger = $(this) | |||||
| const selector = Util.getSelectorFromElement(this) | |||||
| const selectors = [].slice.call(document.querySelectorAll(selector)) | |||||
| $(selectors).each(function () { | |||||
| const $target = $(this) | |||||
| const data = $target.data(DATA_KEY) | |||||
| const config = data ? 'toggle' : $trigger.data() | |||||
| Collapse._jQueryInterface.call($target, config) | |||||
| }) | |||||
| }) | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * jQuery | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $.fn[NAME] = Collapse._jQueryInterface | |||||
| $.fn[NAME].Constructor = Collapse | |||||
| $.fn[NAME].noConflict = () => { | |||||
| $.fn[NAME] = JQUERY_NO_CONFLICT | |||||
| return Collapse._jQueryInterface | |||||
| } | |||||
| export default Collapse | |||||
| @ -0,0 +1,548 @@ | |||||
| /** | |||||
| * -------------------------------------------------------------------------- | |||||
| * Bootstrap (v4.4.1): dropdown.js | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| * -------------------------------------------------------------------------- | |||||
| */ | |||||
| import $ from 'jquery' | |||||
| import Popper from 'popper.js' | |||||
| import Util from './util' | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Constants | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| const NAME = 'dropdown' | |||||
| const VERSION = '4.4.1' | |||||
| const DATA_KEY = 'bs.dropdown' | |||||
| const EVENT_KEY = `.${DATA_KEY}` | |||||
| const DATA_API_KEY = '.data-api' | |||||
| const JQUERY_NO_CONFLICT = $.fn[NAME] | |||||
| const ESCAPE_KEYCODE = 27 // KeyboardEvent.which value for Escape (Esc) key | |||||
| const SPACE_KEYCODE = 32 // KeyboardEvent.which value for space key | |||||
| const TAB_KEYCODE = 9 // KeyboardEvent.which value for tab key | |||||
| const ARROW_UP_KEYCODE = 38 // KeyboardEvent.which value for up arrow key | |||||
| const ARROW_DOWN_KEYCODE = 40 // KeyboardEvent.which value for down arrow key | |||||
| const RIGHT_MOUSE_BUTTON_WHICH = 3 // MouseEvent.which value for the right button (assuming a right-handed mouse) | |||||
| const REGEXP_KEYDOWN = new RegExp(`${ARROW_UP_KEYCODE}|${ARROW_DOWN_KEYCODE}|${ESCAPE_KEYCODE}`) | |||||
| const Event = { | |||||
| HIDE : `hide${EVENT_KEY}`, | |||||
| HIDDEN : `hidden${EVENT_KEY}`, | |||||
| SHOW : `show${EVENT_KEY}`, | |||||
| SHOWN : `shown${EVENT_KEY}`, | |||||
| CLICK : `click${EVENT_KEY}`, | |||||
| CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`, | |||||
| KEYDOWN_DATA_API : `keydown${EVENT_KEY}${DATA_API_KEY}`, | |||||
| KEYUP_DATA_API : `keyup${EVENT_KEY}${DATA_API_KEY}` | |||||
| } | |||||
| const ClassName = { | |||||
| DISABLED : 'disabled', | |||||
| SHOW : 'show', | |||||
| DROPUP : 'dropup', | |||||
| DROPRIGHT : 'dropright', | |||||
| DROPLEFT : 'dropleft', | |||||
| MENURIGHT : 'dropdown-menu-right', | |||||
| MENULEFT : 'dropdown-menu-left', | |||||
| POSITION_STATIC : 'position-static' | |||||
| } | |||||
| const Selector = { | |||||
| DATA_TOGGLE : '[data-toggle="dropdown"]', | |||||
| FORM_CHILD : '.dropdown form', | |||||
| MENU : '.dropdown-menu', | |||||
| NAVBAR_NAV : '.navbar-nav', | |||||
| VISIBLE_ITEMS : '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)' | |||||
| } | |||||
| const AttachmentMap = { | |||||
| TOP : 'top-start', | |||||
| TOPEND : 'top-end', | |||||
| BOTTOM : 'bottom-start', | |||||
| BOTTOMEND : 'bottom-end', | |||||
| RIGHT : 'right-start', | |||||
| RIGHTEND : 'right-end', | |||||
| LEFT : 'left-start', | |||||
| LEFTEND : 'left-end' | |||||
| } | |||||
| const Default = { | |||||
| offset : 0, | |||||
| flip : true, | |||||
| boundary : 'scrollParent', | |||||
| reference : 'toggle', | |||||
| display : 'dynamic', | |||||
| popperConfig : null | |||||
| } | |||||
| const DefaultType = { | |||||
| offset : '(number|string|function)', | |||||
| flip : 'boolean', | |||||
| boundary : '(string|element)', | |||||
| reference : '(string|element)', | |||||
| display : 'string', | |||||
| popperConfig : '(null|object)' | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Class Definition | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| class Dropdown { | |||||
| constructor(element, config) { | |||||
| this._element = element | |||||
| this._popper = null | |||||
| this._config = this._getConfig(config) | |||||
| this._menu = this._getMenuElement() | |||||
| this._inNavbar = this._detectNavbar() | |||||
| this._addEventListeners() | |||||
| } | |||||
| // Getters | |||||
| static get VERSION() { | |||||
| return VERSION | |||||
| } | |||||
| static get Default() { | |||||
| return Default | |||||
| } | |||||
| static get DefaultType() { | |||||
| return DefaultType | |||||
| } | |||||
| // Public | |||||
| toggle() { | |||||
| if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED)) { | |||||
| return | |||||
| } | |||||
| const isActive = $(this._menu).hasClass(ClassName.SHOW) | |||||
| Dropdown._clearMenus() | |||||
| if (isActive) { | |||||
| return | |||||
| } | |||||
| this.show(true) | |||||
| } | |||||
| show(usePopper = false) { | |||||
| if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED) || $(this._menu).hasClass(ClassName.SHOW)) { | |||||
| return | |||||
| } | |||||
| const relatedTarget = { | |||||
| relatedTarget: this._element | |||||
| } | |||||
| const showEvent = $.Event(Event.SHOW, relatedTarget) | |||||
| const parent = Dropdown._getParentFromElement(this._element) | |||||
| $(parent).trigger(showEvent) | |||||
| if (showEvent.isDefaultPrevented()) { | |||||
| return | |||||
| } | |||||
| // Disable totally Popper.js for Dropdown in Navbar | |||||
| if (!this._inNavbar && usePopper) { | |||||
| /** | |||||
| * Check for Popper dependency | |||||
| * Popper - https://popper.js.org | |||||
| */ | |||||
| if (typeof Popper === 'undefined') { | |||||
| throw new TypeError('Bootstrap\'s dropdowns require Popper.js (https://popper.js.org/)') | |||||
| } | |||||
| let referenceElement = this._element | |||||
| if (this._config.reference === 'parent') { | |||||
| referenceElement = parent | |||||
| } else if (Util.isElement(this._config.reference)) { | |||||
| referenceElement = this._config.reference | |||||
| // Check if it's jQuery element | |||||
| if (typeof this._config.reference.jquery !== 'undefined') { | |||||
| referenceElement = this._config.reference[0] | |||||
| } | |||||
| } | |||||
| // If boundary is not `scrollParent`, then set position to `static` | |||||
| // to allow the menu to "escape" the scroll parent's boundaries | |||||
| // https://github.com/twbs/bootstrap/issues/24251 | |||||
| if (this._config.boundary !== 'scrollParent') { | |||||
| $(parent).addClass(ClassName.POSITION_STATIC) | |||||
| } | |||||
| this._popper = new Popper(referenceElement, this._menu, this._getPopperConfig()) | |||||
| } | |||||
| // If this is a touch-enabled device we add extra | |||||
| // empty mouseover listeners to the body's immediate children; | |||||
| // only needed because of broken event delegation on iOS | |||||
| // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html | |||||
| if ('ontouchstart' in document.documentElement && | |||||
| $(parent).closest(Selector.NAVBAR_NAV).length === 0) { | |||||
| $(document.body).children().on('mouseover', null, $.noop) | |||||
| } | |||||
| this._element.focus() | |||||
| this._element.setAttribute('aria-expanded', true) | |||||
| $(this._menu).toggleClass(ClassName.SHOW) | |||||
| $(parent) | |||||
| .toggleClass(ClassName.SHOW) | |||||
| .trigger($.Event(Event.SHOWN, relatedTarget)) | |||||
| } | |||||
| hide() { | |||||
| if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED) || !$(this._menu).hasClass(ClassName.SHOW)) { | |||||
| return | |||||
| } | |||||
| const relatedTarget = { | |||||
| relatedTarget: this._element | |||||
| } | |||||
| const hideEvent = $.Event(Event.HIDE, relatedTarget) | |||||
| const parent = Dropdown._getParentFromElement(this._element) | |||||
| $(parent).trigger(hideEvent) | |||||
| if (hideEvent.isDefaultPrevented()) { | |||||
| return | |||||
| } | |||||
| if (this._popper) { | |||||
| this._popper.destroy() | |||||
| } | |||||
| $(this._menu).toggleClass(ClassName.SHOW) | |||||
| $(parent) | |||||
| .toggleClass(ClassName.SHOW) | |||||
| .trigger($.Event(Event.HIDDEN, relatedTarget)) | |||||
| } | |||||
| dispose() { | |||||
| $.removeData(this._element, DATA_KEY) | |||||
| $(this._element).off(EVENT_KEY) | |||||
| this._element = null | |||||
| this._menu = null | |||||
| if (this._popper !== null) { | |||||
| this._popper.destroy() | |||||
| this._popper = null | |||||
| } | |||||
| } | |||||
| update() { | |||||
| this._inNavbar = this._detectNavbar() | |||||
| if (this._popper !== null) { | |||||
| this._popper.scheduleUpdate() | |||||
| } | |||||
| } | |||||
| // Private | |||||
| _addEventListeners() { | |||||
| $(this._element).on(Event.CLICK, (event) => { | |||||
| event.preventDefault() | |||||
| event.stopPropagation() | |||||
| this.toggle() | |||||
| }) | |||||
| } | |||||
| _getConfig(config) { | |||||
| config = { | |||||
| ...this.constructor.Default, | |||||
| ...$(this._element).data(), | |||||
| ...config | |||||
| } | |||||
| Util.typeCheckConfig( | |||||
| NAME, | |||||
| config, | |||||
| this.constructor.DefaultType | |||||
| ) | |||||
| return config | |||||
| } | |||||
| _getMenuElement() { | |||||
| if (!this._menu) { | |||||
| const parent = Dropdown._getParentFromElement(this._element) | |||||
| if (parent) { | |||||
| this._menu = parent.querySelector(Selector.MENU) | |||||
| } | |||||
| } | |||||
| return this._menu | |||||
| } | |||||
| _getPlacement() { | |||||
| const $parentDropdown = $(this._element.parentNode) | |||||
| let placement = AttachmentMap.BOTTOM | |||||
| // Handle dropup | |||||
| if ($parentDropdown.hasClass(ClassName.DROPUP)) { | |||||
| placement = AttachmentMap.TOP | |||||
| if ($(this._menu).hasClass(ClassName.MENURIGHT)) { | |||||
| placement = AttachmentMap.TOPEND | |||||
| } | |||||
| } else if ($parentDropdown.hasClass(ClassName.DROPRIGHT)) { | |||||
| placement = AttachmentMap.RIGHT | |||||
| } else if ($parentDropdown.hasClass(ClassName.DROPLEFT)) { | |||||
| placement = AttachmentMap.LEFT | |||||
| } else if ($(this._menu).hasClass(ClassName.MENURIGHT)) { | |||||
| placement = AttachmentMap.BOTTOMEND | |||||
| } | |||||
| return placement | |||||
| } | |||||
| _detectNavbar() { | |||||
| return $(this._element).closest('.navbar').length > 0 | |||||
| } | |||||
| _getOffset() { | |||||
| const offset = {} | |||||
| if (typeof this._config.offset === 'function') { | |||||
| offset.fn = (data) => { | |||||
| data.offsets = { | |||||
| ...data.offsets, | |||||
| ...this._config.offset(data.offsets, this._element) || {} | |||||
| } | |||||
| return data | |||||
| } | |||||
| } else { | |||||
| offset.offset = this._config.offset | |||||
| } | |||||
| return offset | |||||
| } | |||||
| _getPopperConfig() { | |||||
| const popperConfig = { | |||||
| placement: this._getPlacement(), | |||||
| modifiers: { | |||||
| offset: this._getOffset(), | |||||
| flip: { | |||||
| enabled: this._config.flip | |||||
| }, | |||||
| preventOverflow: { | |||||
| boundariesElement: this._config.boundary | |||||
| } | |||||
| } | |||||
| } | |||||
| // Disable Popper.js if we have a static display | |||||
| if (this._config.display === 'static') { | |||||
| popperConfig.modifiers.applyStyle = { | |||||
| enabled: false | |||||
| } | |||||
| } | |||||
| return { | |||||
| ...popperConfig, | |||||
| ...this._config.popperConfig | |||||
| } | |||||
| } | |||||
| // Static | |||||
| static _jQueryInterface(config) { | |||||
| return this.each(function () { | |||||
| let data = $(this).data(DATA_KEY) | |||||
| const _config = typeof config === 'object' ? config : null | |||||
| if (!data) { | |||||
| data = new Dropdown(this, _config) | |||||
| $(this).data(DATA_KEY, data) | |||||
| } | |||||
| if (typeof config === 'string') { | |||||
| if (typeof data[config] === 'undefined') { | |||||
| throw new TypeError(`No method named "${config}"`) | |||||
| } | |||||
| data[config]() | |||||
| } | |||||
| }) | |||||
| } | |||||
| static _clearMenus(event) { | |||||
| if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH || | |||||
| event.type === 'keyup' && event.which !== TAB_KEYCODE)) { | |||||
| return | |||||
| } | |||||
| const toggles = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE)) | |||||
| for (let i = 0, len = toggles.length; i < len; i++) { | |||||
| const parent = Dropdown._getParentFromElement(toggles[i]) | |||||
| const context = $(toggles[i]).data(DATA_KEY) | |||||
| const relatedTarget = { | |||||
| relatedTarget: toggles[i] | |||||
| } | |||||
| if (event && event.type === 'click') { | |||||
| relatedTarget.clickEvent = event | |||||
| } | |||||
| if (!context) { | |||||
| continue | |||||
| } | |||||
| const dropdownMenu = context._menu | |||||
| if (!$(parent).hasClass(ClassName.SHOW)) { | |||||
| continue | |||||
| } | |||||
| if (event && (event.type === 'click' && | |||||
| /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) && | |||||
| $.contains(parent, event.target)) { | |||||
| continue | |||||
| } | |||||
| const hideEvent = $.Event(Event.HIDE, relatedTarget) | |||||
| $(parent).trigger(hideEvent) | |||||
| if (hideEvent.isDefaultPrevented()) { | |||||
| continue | |||||
| } | |||||
| // If this is a touch-enabled device we remove the extra | |||||
| // empty mouseover listeners we added for iOS support | |||||
| if ('ontouchstart' in document.documentElement) { | |||||
| $(document.body).children().off('mouseover', null, $.noop) | |||||
| } | |||||
| toggles[i].setAttribute('aria-expanded', 'false') | |||||
| if (context._popper) { | |||||
| context._popper.destroy() | |||||
| } | |||||
| $(dropdownMenu).removeClass(ClassName.SHOW) | |||||
| $(parent) | |||||
| .removeClass(ClassName.SHOW) | |||||
| .trigger($.Event(Event.HIDDEN, relatedTarget)) | |||||
| } | |||||
| } | |||||
| static _getParentFromElement(element) { | |||||
| let parent | |||||
| const selector = Util.getSelectorFromElement(element) | |||||
| if (selector) { | |||||
| parent = document.querySelector(selector) | |||||
| } | |||||
| return parent || element.parentNode | |||||
| } | |||||
| // eslint-disable-next-line complexity | |||||
| static _dataApiKeydownHandler(event) { | |||||
| // If not input/textarea: | |||||
| // - And not a key in REGEXP_KEYDOWN => not a dropdown command | |||||
| // If input/textarea: | |||||
| // - If space key => not a dropdown command | |||||
| // - If key is other than escape | |||||
| // - If key is not up or down => not a dropdown command | |||||
| // - If trigger inside the menu => not a dropdown command | |||||
| if (/input|textarea/i.test(event.target.tagName) | |||||
| ? event.which === SPACE_KEYCODE || event.which !== ESCAPE_KEYCODE && | |||||
| (event.which !== ARROW_DOWN_KEYCODE && event.which !== ARROW_UP_KEYCODE || | |||||
| $(event.target).closest(Selector.MENU).length) : !REGEXP_KEYDOWN.test(event.which)) { | |||||
| return | |||||
| } | |||||
| event.preventDefault() | |||||
| event.stopPropagation() | |||||
| if (this.disabled || $(this).hasClass(ClassName.DISABLED)) { | |||||
| return | |||||
| } | |||||
| const parent = Dropdown._getParentFromElement(this) | |||||
| const isActive = $(parent).hasClass(ClassName.SHOW) | |||||
| if (!isActive && event.which === ESCAPE_KEYCODE) { | |||||
| return | |||||
| } | |||||
| if (!isActive || isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) { | |||||
| if (event.which === ESCAPE_KEYCODE) { | |||||
| const toggle = parent.querySelector(Selector.DATA_TOGGLE) | |||||
| $(toggle).trigger('focus') | |||||
| } | |||||
| $(this).trigger('click') | |||||
| return | |||||
| } | |||||
| const items = [].slice.call(parent.querySelectorAll(Selector.VISIBLE_ITEMS)) | |||||
| .filter((item) => $(item).is(':visible')) | |||||
| if (items.length === 0) { | |||||
| return | |||||
| } | |||||
| let index = items.indexOf(event.target) | |||||
| if (event.which === ARROW_UP_KEYCODE && index > 0) { // Up | |||||
| index-- | |||||
| } | |||||
| if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) { // Down | |||||
| index++ | |||||
| } | |||||
| if (index < 0) { | |||||
| index = 0 | |||||
| } | |||||
| items[index].focus() | |||||
| } | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Data Api implementation | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $(document) | |||||
| .on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler) | |||||
| .on(Event.KEYDOWN_DATA_API, Selector.MENU, Dropdown._dataApiKeydownHandler) | |||||
| .on(`${Event.CLICK_DATA_API} ${Event.KEYUP_DATA_API}`, Dropdown._clearMenus) | |||||
| .on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { | |||||
| event.preventDefault() | |||||
| event.stopPropagation() | |||||
| Dropdown._jQueryInterface.call($(this), 'toggle') | |||||
| }) | |||||
| .on(Event.CLICK_DATA_API, Selector.FORM_CHILD, (e) => { | |||||
| e.stopPropagation() | |||||
| }) | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * jQuery | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $.fn[NAME] = Dropdown._jQueryInterface | |||||
| $.fn[NAME].Constructor = Dropdown | |||||
| $.fn[NAME].noConflict = () => { | |||||
| $.fn[NAME] = JQUERY_NO_CONFLICT | |||||
| return Dropdown._jQueryInterface | |||||
| } | |||||
| export default Dropdown | |||||
| @ -0,0 +1,34 @@ | |||||
| import Alert from './alert' | |||||
| import Button from './button' | |||||
| import Carousel from './carousel' | |||||
| import Collapse from './collapse' | |||||
| import Dropdown from './dropdown' | |||||
| import Modal from './modal' | |||||
| import Popover from './popover' | |||||
| import Scrollspy from './scrollspy' | |||||
| import Tab from './tab' | |||||
| import Toast from './toast' | |||||
| import Tooltip from './tooltip' | |||||
| import Util from './util' | |||||
| /** | |||||
| * -------------------------------------------------------------------------- | |||||
| * Bootstrap (v4.4.1): index.js | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| * -------------------------------------------------------------------------- | |||||
| */ | |||||
| export { | |||||
| Util, | |||||
| Alert, | |||||
| Button, | |||||
| Carousel, | |||||
| Collapse, | |||||
| Dropdown, | |||||
| Modal, | |||||
| Popover, | |||||
| Scrollspy, | |||||
| Tab, | |||||
| Toast, | |||||
| Tooltip | |||||
| } | |||||
| @ -0,0 +1,616 @@ | |||||
| /** | |||||
| * -------------------------------------------------------------------------- | |||||
| * Bootstrap (v4.4.1): modal.js | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| * -------------------------------------------------------------------------- | |||||
| */ | |||||
| import $ from 'jquery' | |||||
| import Util from './util' | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Constants | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| const NAME = 'modal' | |||||
| const VERSION = '4.4.1' | |||||
| const DATA_KEY = 'bs.modal' | |||||
| const EVENT_KEY = `.${DATA_KEY}` | |||||
| const DATA_API_KEY = '.data-api' | |||||
| const JQUERY_NO_CONFLICT = $.fn[NAME] | |||||
| const ESCAPE_KEYCODE = 27 // KeyboardEvent.which value for Escape (Esc) key | |||||
| const Default = { | |||||
| backdrop : true, | |||||
| keyboard : true, | |||||
| focus : true, | |||||
| show : true | |||||
| } | |||||
| const DefaultType = { | |||||
| backdrop : '(boolean|string)', | |||||
| keyboard : 'boolean', | |||||
| focus : 'boolean', | |||||
| show : 'boolean' | |||||
| } | |||||
| const Event = { | |||||
| HIDE : `hide${EVENT_KEY}`, | |||||
| HIDE_PREVENTED : `hidePrevented${EVENT_KEY}`, | |||||
| HIDDEN : `hidden${EVENT_KEY}`, | |||||
| SHOW : `show${EVENT_KEY}`, | |||||
| SHOWN : `shown${EVENT_KEY}`, | |||||
| FOCUSIN : `focusin${EVENT_KEY}`, | |||||
| RESIZE : `resize${EVENT_KEY}`, | |||||
| CLICK_DISMISS : `click.dismiss${EVENT_KEY}`, | |||||
| KEYDOWN_DISMISS : `keydown.dismiss${EVENT_KEY}`, | |||||
| MOUSEUP_DISMISS : `mouseup.dismiss${EVENT_KEY}`, | |||||
| MOUSEDOWN_DISMISS : `mousedown.dismiss${EVENT_KEY}`, | |||||
| CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}` | |||||
| } | |||||
| const ClassName = { | |||||
| SCROLLABLE : 'modal-dialog-scrollable', | |||||
| SCROLLBAR_MEASURER : 'modal-scrollbar-measure', | |||||
| BACKDROP : 'modal-backdrop', | |||||
| OPEN : 'modal-open', | |||||
| FADE : 'fade', | |||||
| SHOW : 'show', | |||||
| STATIC : 'modal-static' | |||||
| } | |||||
| const Selector = { | |||||
| DIALOG : '.modal-dialog', | |||||
| MODAL_BODY : '.modal-body', | |||||
| DATA_TOGGLE : '[data-toggle="modal"]', | |||||
| DATA_DISMISS : '[data-dismiss="modal"]', | |||||
| FIXED_CONTENT : '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top', | |||||
| STICKY_CONTENT : '.sticky-top' | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Class Definition | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| class Modal { | |||||
| constructor(element, config) { | |||||
| this._config = this._getConfig(config) | |||||
| this._element = element | |||||
| this._dialog = element.querySelector(Selector.DIALOG) | |||||
| this._backdrop = null | |||||
| this._isShown = false | |||||
| this._isBodyOverflowing = false | |||||
| this._ignoreBackdropClick = false | |||||
| this._isTransitioning = false | |||||
| this._scrollbarWidth = 0 | |||||
| } | |||||
| // Getters | |||||
| static get VERSION() { | |||||
| return VERSION | |||||
| } | |||||
| static get Default() { | |||||
| return Default | |||||
| } | |||||
| // Public | |||||
| toggle(relatedTarget) { | |||||
| return this._isShown ? this.hide() : this.show(relatedTarget) | |||||
| } | |||||
| show(relatedTarget) { | |||||
| if (this._isShown || this._isTransitioning) { | |||||
| return | |||||
| } | |||||
| if ($(this._element).hasClass(ClassName.FADE)) { | |||||
| this._isTransitioning = true | |||||
| } | |||||
| const showEvent = $.Event(Event.SHOW, { | |||||
| relatedTarget | |||||
| }) | |||||
| $(this._element).trigger(showEvent) | |||||
| if (this._isShown || showEvent.isDefaultPrevented()) { | |||||
| return | |||||
| } | |||||
| this._isShown = true | |||||
| this._checkScrollbar() | |||||
| this._setScrollbar() | |||||
| this._adjustDialog() | |||||
| this._setEscapeEvent() | |||||
| this._setResizeEvent() | |||||
| $(this._element).on( | |||||
| Event.CLICK_DISMISS, | |||||
| Selector.DATA_DISMISS, | |||||
| (event) => this.hide(event) | |||||
| ) | |||||
| $(this._dialog).on(Event.MOUSEDOWN_DISMISS, () => { | |||||
| $(this._element).one(Event.MOUSEUP_DISMISS, (event) => { | |||||
| if ($(event.target).is(this._element)) { | |||||
| this._ignoreBackdropClick = true | |||||
| } | |||||
| }) | |||||
| }) | |||||
| this._showBackdrop(() => this._showElement(relatedTarget)) | |||||
| } | |||||
| hide(event) { | |||||
| if (event) { | |||||
| event.preventDefault() | |||||
| } | |||||
| if (!this._isShown || this._isTransitioning) { | |||||
| return | |||||
| } | |||||
| const hideEvent = $.Event(Event.HIDE) | |||||
| $(this._element).trigger(hideEvent) | |||||
| if (!this._isShown || hideEvent.isDefaultPrevented()) { | |||||
| return | |||||
| } | |||||
| this._isShown = false | |||||
| const transition = $(this._element).hasClass(ClassName.FADE) | |||||
| if (transition) { | |||||
| this._isTransitioning = true | |||||
| } | |||||
| this._setEscapeEvent() | |||||
| this._setResizeEvent() | |||||
| $(document).off(Event.FOCUSIN) | |||||
| $(this._element).removeClass(ClassName.SHOW) | |||||
| $(this._element).off(Event.CLICK_DISMISS) | |||||
| $(this._dialog).off(Event.MOUSEDOWN_DISMISS) | |||||
| if (transition) { | |||||
| const transitionDuration = Util.getTransitionDurationFromElement(this._element) | |||||
| $(this._element) | |||||
| .one(Util.TRANSITION_END, (event) => this._hideModal(event)) | |||||
| .emulateTransitionEnd(transitionDuration) | |||||
| } else { | |||||
| this._hideModal() | |||||
| } | |||||
| } | |||||
| dispose() { | |||||
| [window, this._element, this._dialog] | |||||
| .forEach((htmlElement) => $(htmlElement).off(EVENT_KEY)) | |||||
| /** | |||||
| * `document` has 2 events `Event.FOCUSIN` and `Event.CLICK_DATA_API` | |||||
| * Do not move `document` in `htmlElements` array | |||||
| * It will remove `Event.CLICK_DATA_API` event that should remain | |||||
| */ | |||||
| $(document).off(Event.FOCUSIN) | |||||
| $.removeData(this._element, DATA_KEY) | |||||
| this._config = null | |||||
| this._element = null | |||||
| this._dialog = null | |||||
| this._backdrop = null | |||||
| this._isShown = null | |||||
| this._isBodyOverflowing = null | |||||
| this._ignoreBackdropClick = null | |||||
| this._isTransitioning = null | |||||
| this._scrollbarWidth = null | |||||
| } | |||||
| handleUpdate() { | |||||
| this._adjustDialog() | |||||
| } | |||||
| // Private | |||||
| _getConfig(config) { | |||||
| config = { | |||||
| ...Default, | |||||
| ...config | |||||
| } | |||||
| Util.typeCheckConfig(NAME, config, DefaultType) | |||||
| return config | |||||
| } | |||||
| _triggerBackdropTransition() { | |||||
| if (this._config.backdrop === 'static') { | |||||
| const hideEventPrevented = $.Event(Event.HIDE_PREVENTED) | |||||
| $(this._element).trigger(hideEventPrevented) | |||||
| if (hideEventPrevented.defaultPrevented) { | |||||
| return | |||||
| } | |||||
| this._element.classList.add(ClassName.STATIC) | |||||
| const modalTransitionDuration = Util.getTransitionDurationFromElement(this._element) | |||||
| $(this._element).one(Util.TRANSITION_END, () => { | |||||
| this._element.classList.remove(ClassName.STATIC) | |||||
| }) | |||||
| .emulateTransitionEnd(modalTransitionDuration) | |||||
| this._element.focus() | |||||
| } else { | |||||
| this.hide() | |||||
| } | |||||
| } | |||||
| _showElement(relatedTarget) { | |||||
| const transition = $(this._element).hasClass(ClassName.FADE) | |||||
| const modalBody = this._dialog ? this._dialog.querySelector(Selector.MODAL_BODY) : null | |||||
| if (!this._element.parentNode || | |||||
| this._element.parentNode.nodeType !== Node.ELEMENT_NODE) { | |||||
| // Don't move modal's DOM position | |||||
| document.body.appendChild(this._element) | |||||
| } | |||||
| this._element.style.display = 'block' | |||||
| this._element.removeAttribute('aria-hidden') | |||||
| this._element.setAttribute('aria-modal', true) | |||||
| if ($(this._dialog).hasClass(ClassName.SCROLLABLE) && modalBody) { | |||||
| modalBody.scrollTop = 0 | |||||
| } else { | |||||
| this._element.scrollTop = 0 | |||||
| } | |||||
| if (transition) { | |||||
| Util.reflow(this._element) | |||||
| } | |||||
| $(this._element).addClass(ClassName.SHOW) | |||||
| if (this._config.focus) { | |||||
| this._enforceFocus() | |||||
| } | |||||
| const shownEvent = $.Event(Event.SHOWN, { | |||||
| relatedTarget | |||||
| }) | |||||
| const transitionComplete = () => { | |||||
| if (this._config.focus) { | |||||
| this._element.focus() | |||||
| } | |||||
| this._isTransitioning = false | |||||
| $(this._element).trigger(shownEvent) | |||||
| } | |||||
| if (transition) { | |||||
| const transitionDuration = Util.getTransitionDurationFromElement(this._dialog) | |||||
| $(this._dialog) | |||||
| .one(Util.TRANSITION_END, transitionComplete) | |||||
| .emulateTransitionEnd(transitionDuration) | |||||
| } else { | |||||
| transitionComplete() | |||||
| } | |||||
| } | |||||
| _enforceFocus() { | |||||
| $(document) | |||||
| .off(Event.FOCUSIN) // Guard against infinite focus loop | |||||
| .on(Event.FOCUSIN, (event) => { | |||||
| if (document !== event.target && | |||||
| this._element !== event.target && | |||||
| $(this._element).has(event.target).length === 0) { | |||||
| this._element.focus() | |||||
| } | |||||
| }) | |||||
| } | |||||
| _setEscapeEvent() { | |||||
| if (this._isShown && this._config.keyboard) { | |||||
| $(this._element).on(Event.KEYDOWN_DISMISS, (event) => { | |||||
| if (event.which === ESCAPE_KEYCODE) { | |||||
| this._triggerBackdropTransition() | |||||
| } | |||||
| }) | |||||
| } else if (!this._isShown) { | |||||
| $(this._element).off(Event.KEYDOWN_DISMISS) | |||||
| } | |||||
| } | |||||
| _setResizeEvent() { | |||||
| if (this._isShown) { | |||||
| $(window).on(Event.RESIZE, (event) => this.handleUpdate(event)) | |||||
| } else { | |||||
| $(window).off(Event.RESIZE) | |||||
| } | |||||
| } | |||||
| _hideModal() { | |||||
| this._element.style.display = 'none' | |||||
| this._element.setAttribute('aria-hidden', true) | |||||
| this._element.removeAttribute('aria-modal') | |||||
| this._isTransitioning = false | |||||
| this._showBackdrop(() => { | |||||
| $(document.body).removeClass(ClassName.OPEN) | |||||
| this._resetAdjustments() | |||||
| this._resetScrollbar() | |||||
| $(this._element).trigger(Event.HIDDEN) | |||||
| }) | |||||
| } | |||||
| _removeBackdrop() { | |||||
| if (this._backdrop) { | |||||
| $(this._backdrop).remove() | |||||
| this._backdrop = null | |||||
| } | |||||
| } | |||||
| _showBackdrop(callback) { | |||||
| const animate = $(this._element).hasClass(ClassName.FADE) | |||||
| ? ClassName.FADE : '' | |||||
| if (this._isShown && this._config.backdrop) { | |||||
| this._backdrop = document.createElement('div') | |||||
| this._backdrop.className = ClassName.BACKDROP | |||||
| if (animate) { | |||||
| this._backdrop.classList.add(animate) | |||||
| } | |||||
| $(this._backdrop).appendTo(document.body) | |||||
| $(this._element).on(Event.CLICK_DISMISS, (event) => { | |||||
| if (this._ignoreBackdropClick) { | |||||
| this._ignoreBackdropClick = false | |||||
| return | |||||
| } | |||||
| if (event.target !== event.currentTarget) { | |||||
| return | |||||
| } | |||||
| this._triggerBackdropTransition() | |||||
| }) | |||||
| if (animate) { | |||||
| Util.reflow(this._backdrop) | |||||
| } | |||||
| $(this._backdrop).addClass(ClassName.SHOW) | |||||
| if (!callback) { | |||||
| return | |||||
| } | |||||
| if (!animate) { | |||||
| callback() | |||||
| return | |||||
| } | |||||
| const backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop) | |||||
| $(this._backdrop) | |||||
| .one(Util.TRANSITION_END, callback) | |||||
| .emulateTransitionEnd(backdropTransitionDuration) | |||||
| } else if (!this._isShown && this._backdrop) { | |||||
| $(this._backdrop).removeClass(ClassName.SHOW) | |||||
| const callbackRemove = () => { | |||||
| this._removeBackdrop() | |||||
| if (callback) { | |||||
| callback() | |||||
| } | |||||
| } | |||||
| if ($(this._element).hasClass(ClassName.FADE)) { | |||||
| const backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop) | |||||
| $(this._backdrop) | |||||
| .one(Util.TRANSITION_END, callbackRemove) | |||||
| .emulateTransitionEnd(backdropTransitionDuration) | |||||
| } else { | |||||
| callbackRemove() | |||||
| } | |||||
| } else if (callback) { | |||||
| callback() | |||||
| } | |||||
| } | |||||
| // ---------------------------------------------------------------------- | |||||
| // the following methods are used to handle overflowing modals | |||||
| // todo (fat): these should probably be refactored out of modal.js | |||||
| // ---------------------------------------------------------------------- | |||||
| _adjustDialog() { | |||||
| const isModalOverflowing = | |||||
| this._element.scrollHeight > document.documentElement.clientHeight | |||||
| if (!this._isBodyOverflowing && isModalOverflowing) { | |||||
| this._element.style.paddingLeft = `${this._scrollbarWidth}px` | |||||
| } | |||||
| if (this._isBodyOverflowing && !isModalOverflowing) { | |||||
| this._element.style.paddingRight = `${this._scrollbarWidth}px` | |||||
| } | |||||
| } | |||||
| _resetAdjustments() { | |||||
| this._element.style.paddingLeft = '' | |||||
| this._element.style.paddingRight = '' | |||||
| } | |||||
| _checkScrollbar() { | |||||
| const rect = document.body.getBoundingClientRect() | |||||
| this._isBodyOverflowing = rect.left + rect.right < window.innerWidth | |||||
| this._scrollbarWidth = this._getScrollbarWidth() | |||||
| } | |||||
| _setScrollbar() { | |||||
| if (this._isBodyOverflowing) { | |||||
| // Note: DOMNode.style.paddingRight returns the actual value or '' if not set | |||||
| // while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set | |||||
| const fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT)) | |||||
| const stickyContent = [].slice.call(document.querySelectorAll(Selector.STICKY_CONTENT)) | |||||
| // Adjust fixed content padding | |||||
| $(fixedContent).each((index, element) => { | |||||
| const actualPadding = element.style.paddingRight | |||||
| const calculatedPadding = $(element).css('padding-right') | |||||
| $(element) | |||||
| .data('padding-right', actualPadding) | |||||
| .css('padding-right', `${parseFloat(calculatedPadding) + this._scrollbarWidth}px`) | |||||
| }) | |||||
| // Adjust sticky content margin | |||||
| $(stickyContent).each((index, element) => { | |||||
| const actualMargin = element.style.marginRight | |||||
| const calculatedMargin = $(element).css('margin-right') | |||||
| $(element) | |||||
| .data('margin-right', actualMargin) | |||||
| .css('margin-right', `${parseFloat(calculatedMargin) - this._scrollbarWidth}px`) | |||||
| }) | |||||
| // Adjust body padding | |||||
| const actualPadding = document.body.style.paddingRight | |||||
| const calculatedPadding = $(document.body).css('padding-right') | |||||
| $(document.body) | |||||
| .data('padding-right', actualPadding) | |||||
| .css('padding-right', `${parseFloat(calculatedPadding) + this._scrollbarWidth}px`) | |||||
| } | |||||
| $(document.body).addClass(ClassName.OPEN) | |||||
| } | |||||
| _resetScrollbar() { | |||||
| // Restore fixed content padding | |||||
| const fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT)) | |||||
| $(fixedContent).each((index, element) => { | |||||
| const padding = $(element).data('padding-right') | |||||
| $(element).removeData('padding-right') | |||||
| element.style.paddingRight = padding ? padding : '' | |||||
| }) | |||||
| // Restore sticky content | |||||
| const elements = [].slice.call(document.querySelectorAll(`${Selector.STICKY_CONTENT}`)) | |||||
| $(elements).each((index, element) => { | |||||
| const margin = $(element).data('margin-right') | |||||
| if (typeof margin !== 'undefined') { | |||||
| $(element).css('margin-right', margin).removeData('margin-right') | |||||
| } | |||||
| }) | |||||
| // Restore body padding | |||||
| const padding = $(document.body).data('padding-right') | |||||
| $(document.body).removeData('padding-right') | |||||
| document.body.style.paddingRight = padding ? padding : '' | |||||
| } | |||||
| _getScrollbarWidth() { // thx d.walsh | |||||
| const scrollDiv = document.createElement('div') | |||||
| scrollDiv.className = ClassName.SCROLLBAR_MEASURER | |||||
| document.body.appendChild(scrollDiv) | |||||
| const scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth | |||||
| document.body.removeChild(scrollDiv) | |||||
| return scrollbarWidth | |||||
| } | |||||
| // Static | |||||
| static _jQueryInterface(config, relatedTarget) { | |||||
| return this.each(function () { | |||||
| let data = $(this).data(DATA_KEY) | |||||
| const _config = { | |||||
| ...Default, | |||||
| ...$(this).data(), | |||||
| ...typeof config === 'object' && config ? config : {} | |||||
| } | |||||
| if (!data) { | |||||
| data = new Modal(this, _config) | |||||
| $(this).data(DATA_KEY, data) | |||||
| } | |||||
| if (typeof config === 'string') { | |||||
| if (typeof data[config] === 'undefined') { | |||||
| throw new TypeError(`No method named "${config}"`) | |||||
| } | |||||
| data[config](relatedTarget) | |||||
| } else if (_config.show) { | |||||
| data.show(relatedTarget) | |||||
| } | |||||
| }) | |||||
| } | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Data Api implementation | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { | |||||
| let target | |||||
| const selector = Util.getSelectorFromElement(this) | |||||
| if (selector) { | |||||
| target = document.querySelector(selector) | |||||
| } | |||||
| const config = $(target).data(DATA_KEY) | |||||
| ? 'toggle' : { | |||||
| ...$(target).data(), | |||||
| ...$(this).data() | |||||
| } | |||||
| if (this.tagName === 'A' || this.tagName === 'AREA') { | |||||
| event.preventDefault() | |||||
| } | |||||
| const $target = $(target).one(Event.SHOW, (showEvent) => { | |||||
| if (showEvent.isDefaultPrevented()) { | |||||
| // Only register focus restorer if modal will actually get shown | |||||
| return | |||||
| } | |||||
| $target.one(Event.HIDDEN, () => { | |||||
| if ($(this).is(':visible')) { | |||||
| this.focus() | |||||
| } | |||||
| }) | |||||
| }) | |||||
| Modal._jQueryInterface.call($(target), config, this) | |||||
| }) | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * jQuery | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $.fn[NAME] = Modal._jQueryInterface | |||||
| $.fn[NAME].Constructor = Modal | |||||
| $.fn[NAME].noConflict = () => { | |||||
| $.fn[NAME] = JQUERY_NO_CONFLICT | |||||
| return Modal._jQueryInterface | |||||
| } | |||||
| export default Modal | |||||
| @ -0,0 +1,184 @@ | |||||
| /** | |||||
| * -------------------------------------------------------------------------- | |||||
| * Bootstrap (v4.4.1): popover.js | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| * -------------------------------------------------------------------------- | |||||
| */ | |||||
| import $ from 'jquery' | |||||
| import Tooltip from './tooltip' | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Constants | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| const NAME = 'popover' | |||||
| const VERSION = '4.4.1' | |||||
| const DATA_KEY = 'bs.popover' | |||||
| const EVENT_KEY = `.${DATA_KEY}` | |||||
| const JQUERY_NO_CONFLICT = $.fn[NAME] | |||||
| const CLASS_PREFIX = 'bs-popover' | |||||
| const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\s)${CLASS_PREFIX}\\S+`, 'g') | |||||
| const Default = { | |||||
| ...Tooltip.Default, | |||||
| placement : 'right', | |||||
| trigger : 'click', | |||||
| content : '', | |||||
| template : '<div class="popover" role="tooltip">' + | |||||
| '<div class="arrow"></div>' + | |||||
| '<h3 class="popover-header"></h3>' + | |||||
| '<div class="popover-body"></div></div>' | |||||
| } | |||||
| const DefaultType = { | |||||
| ...Tooltip.DefaultType, | |||||
| content : '(string|element|function)' | |||||
| } | |||||
| const ClassName = { | |||||
| FADE : 'fade', | |||||
| SHOW : 'show' | |||||
| } | |||||
| const Selector = { | |||||
| TITLE : '.popover-header', | |||||
| CONTENT : '.popover-body' | |||||
| } | |||||
| const Event = { | |||||
| HIDE : `hide${EVENT_KEY}`, | |||||
| HIDDEN : `hidden${EVENT_KEY}`, | |||||
| SHOW : `show${EVENT_KEY}`, | |||||
| SHOWN : `shown${EVENT_KEY}`, | |||||
| INSERTED : `inserted${EVENT_KEY}`, | |||||
| CLICK : `click${EVENT_KEY}`, | |||||
| FOCUSIN : `focusin${EVENT_KEY}`, | |||||
| FOCUSOUT : `focusout${EVENT_KEY}`, | |||||
| MOUSEENTER : `mouseenter${EVENT_KEY}`, | |||||
| MOUSELEAVE : `mouseleave${EVENT_KEY}` | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Class Definition | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| class Popover extends Tooltip { | |||||
| // Getters | |||||
| static get VERSION() { | |||||
| return VERSION | |||||
| } | |||||
| static get Default() { | |||||
| return Default | |||||
| } | |||||
| static get NAME() { | |||||
| return NAME | |||||
| } | |||||
| static get DATA_KEY() { | |||||
| return DATA_KEY | |||||
| } | |||||
| static get Event() { | |||||
| return Event | |||||
| } | |||||
| static get EVENT_KEY() { | |||||
| return EVENT_KEY | |||||
| } | |||||
| static get DefaultType() { | |||||
| return DefaultType | |||||
| } | |||||
| // Overrides | |||||
| isWithContent() { | |||||
| return this.getTitle() || this._getContent() | |||||
| } | |||||
| addAttachmentClass(attachment) { | |||||
| $(this.getTipElement()).addClass(`${CLASS_PREFIX}-${attachment}`) | |||||
| } | |||||
| getTipElement() { | |||||
| this.tip = this.tip || $(this.config.template)[0] | |||||
| return this.tip | |||||
| } | |||||
| setContent() { | |||||
| const $tip = $(this.getTipElement()) | |||||
| // We use append for html objects to maintain js events | |||||
| this.setElementContent($tip.find(Selector.TITLE), this.getTitle()) | |||||
| let content = this._getContent() | |||||
| if (typeof content === 'function') { | |||||
| content = content.call(this.element) | |||||
| } | |||||
| this.setElementContent($tip.find(Selector.CONTENT), content) | |||||
| $tip.removeClass(`${ClassName.FADE} ${ClassName.SHOW}`) | |||||
| } | |||||
| // Private | |||||
| _getContent() { | |||||
| return this.element.getAttribute('data-content') || | |||||
| this.config.content | |||||
| } | |||||
| _cleanTipClass() { | |||||
| const $tip = $(this.getTipElement()) | |||||
| const tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX) | |||||
| if (tabClass !== null && tabClass.length > 0) { | |||||
| $tip.removeClass(tabClass.join('')) | |||||
| } | |||||
| } | |||||
| // Static | |||||
| static _jQueryInterface(config) { | |||||
| return this.each(function () { | |||||
| let data = $(this).data(DATA_KEY) | |||||
| const _config = typeof config === 'object' ? config : null | |||||
| if (!data && /dispose|hide/.test(config)) { | |||||
| return | |||||
| } | |||||
| if (!data) { | |||||
| data = new Popover(this, _config) | |||||
| $(this).data(DATA_KEY, data) | |||||
| } | |||||
| if (typeof config === 'string') { | |||||
| if (typeof data[config] === 'undefined') { | |||||
| throw new TypeError(`No method named "${config}"`) | |||||
| } | |||||
| data[config]() | |||||
| } | |||||
| }) | |||||
| } | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * jQuery | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $.fn[NAME] = Popover._jQueryInterface | |||||
| $.fn[NAME].Constructor = Popover | |||||
| $.fn[NAME].noConflict = () => { | |||||
| $.fn[NAME] = JQUERY_NO_CONFLICT | |||||
| return Popover._jQueryInterface | |||||
| } | |||||
| export default Popover | |||||
| @ -0,0 +1,326 @@ | |||||
| /** | |||||
| * -------------------------------------------------------------------------- | |||||
| * Bootstrap (v4.4.1): scrollspy.js | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| * -------------------------------------------------------------------------- | |||||
| */ | |||||
| import $ from 'jquery' | |||||
| import Util from './util' | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Constants | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| const NAME = 'scrollspy' | |||||
| const VERSION = '4.4.1' | |||||
| const DATA_KEY = 'bs.scrollspy' | |||||
| const EVENT_KEY = `.${DATA_KEY}` | |||||
| const DATA_API_KEY = '.data-api' | |||||
| const JQUERY_NO_CONFLICT = $.fn[NAME] | |||||
| const Default = { | |||||
| offset : 10, | |||||
| method : 'auto', | |||||
| target : '' | |||||
| } | |||||
| const DefaultType = { | |||||
| offset : 'number', | |||||
| method : 'string', | |||||
| target : '(string|element)' | |||||
| } | |||||
| const Event = { | |||||
| ACTIVATE : `activate${EVENT_KEY}`, | |||||
| SCROLL : `scroll${EVENT_KEY}`, | |||||
| LOAD_DATA_API : `load${EVENT_KEY}${DATA_API_KEY}` | |||||
| } | |||||
| const ClassName = { | |||||
| DROPDOWN_ITEM : 'dropdown-item', | |||||
| DROPDOWN_MENU : 'dropdown-menu', | |||||
| ACTIVE : 'active' | |||||
| } | |||||
| const Selector = { | |||||
| DATA_SPY : '[data-spy="scroll"]', | |||||
| ACTIVE : '.active', | |||||
| NAV_LIST_GROUP : '.nav, .list-group', | |||||
| NAV_LINKS : '.nav-link', | |||||
| NAV_ITEMS : '.nav-item', | |||||
| LIST_ITEMS : '.list-group-item', | |||||
| DROPDOWN : '.dropdown', | |||||
| DROPDOWN_ITEMS : '.dropdown-item', | |||||
| DROPDOWN_TOGGLE : '.dropdown-toggle' | |||||
| } | |||||
| const OffsetMethod = { | |||||
| OFFSET : 'offset', | |||||
| POSITION : 'position' | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Class Definition | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| class ScrollSpy { | |||||
| constructor(element, config) { | |||||
| this._element = element | |||||
| this._scrollElement = element.tagName === 'BODY' ? window : element | |||||
| this._config = this._getConfig(config) | |||||
| this._selector = `${this._config.target} ${Selector.NAV_LINKS},` + | |||||
| `${this._config.target} ${Selector.LIST_ITEMS},` + | |||||
| `${this._config.target} ${Selector.DROPDOWN_ITEMS}` | |||||
| this._offsets = [] | |||||
| this._targets = [] | |||||
| this._activeTarget = null | |||||
| this._scrollHeight = 0 | |||||
| $(this._scrollElement).on(Event.SCROLL, (event) => this._process(event)) | |||||
| this.refresh() | |||||
| this._process() | |||||
| } | |||||
| // Getters | |||||
| static get VERSION() { | |||||
| return VERSION | |||||
| } | |||||
| static get Default() { | |||||
| return Default | |||||
| } | |||||
| // Public | |||||
| refresh() { | |||||
| const autoMethod = this._scrollElement === this._scrollElement.window | |||||
| ? OffsetMethod.OFFSET : OffsetMethod.POSITION | |||||
| const offsetMethod = this._config.method === 'auto' | |||||
| ? autoMethod : this._config.method | |||||
| const offsetBase = offsetMethod === OffsetMethod.POSITION | |||||
| ? this._getScrollTop() : 0 | |||||
| this._offsets = [] | |||||
| this._targets = [] | |||||
| this._scrollHeight = this._getScrollHeight() | |||||
| const targets = [].slice.call(document.querySelectorAll(this._selector)) | |||||
| targets | |||||
| .map((element) => { | |||||
| let target | |||||
| const targetSelector = Util.getSelectorFromElement(element) | |||||
| if (targetSelector) { | |||||
| target = document.querySelector(targetSelector) | |||||
| } | |||||
| if (target) { | |||||
| const targetBCR = target.getBoundingClientRect() | |||||
| if (targetBCR.width || targetBCR.height) { | |||||
| // TODO (fat): remove sketch reliance on jQuery position/offset | |||||
| return [ | |||||
| $(target)[offsetMethod]().top + offsetBase, | |||||
| targetSelector | |||||
| ] | |||||
| } | |||||
| } | |||||
| return null | |||||
| }) | |||||
| .filter((item) => item) | |||||
| .sort((a, b) => a[0] - b[0]) | |||||
| .forEach((item) => { | |||||
| this._offsets.push(item[0]) | |||||
| this._targets.push(item[1]) | |||||
| }) | |||||
| } | |||||
| dispose() { | |||||
| $.removeData(this._element, DATA_KEY) | |||||
| $(this._scrollElement).off(EVENT_KEY) | |||||
| this._element = null | |||||
| this._scrollElement = null | |||||
| this._config = null | |||||
| this._selector = null | |||||
| this._offsets = null | |||||
| this._targets = null | |||||
| this._activeTarget = null | |||||
| this._scrollHeight = null | |||||
| } | |||||
| // Private | |||||
| _getConfig(config) { | |||||
| config = { | |||||
| ...Default, | |||||
| ...typeof config === 'object' && config ? config : {} | |||||
| } | |||||
| if (typeof config.target !== 'string') { | |||||
| let id = $(config.target).attr('id') | |||||
| if (!id) { | |||||
| id = Util.getUID(NAME) | |||||
| $(config.target).attr('id', id) | |||||
| } | |||||
| config.target = `#${id}` | |||||
| } | |||||
| Util.typeCheckConfig(NAME, config, DefaultType) | |||||
| return config | |||||
| } | |||||
| _getScrollTop() { | |||||
| return this._scrollElement === window | |||||
| ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop | |||||
| } | |||||
| _getScrollHeight() { | |||||
| return this._scrollElement.scrollHeight || Math.max( | |||||
| document.body.scrollHeight, | |||||
| document.documentElement.scrollHeight | |||||
| ) | |||||
| } | |||||
| _getOffsetHeight() { | |||||
| return this._scrollElement === window | |||||
| ? window.innerHeight : this._scrollElement.getBoundingClientRect().height | |||||
| } | |||||
| _process() { | |||||
| const scrollTop = this._getScrollTop() + this._config.offset | |||||
| const scrollHeight = this._getScrollHeight() | |||||
| const maxScroll = this._config.offset + | |||||
| scrollHeight - | |||||
| this._getOffsetHeight() | |||||
| if (this._scrollHeight !== scrollHeight) { | |||||
| this.refresh() | |||||
| } | |||||
| if (scrollTop >= maxScroll) { | |||||
| const target = this._targets[this._targets.length - 1] | |||||
| if (this._activeTarget !== target) { | |||||
| this._activate(target) | |||||
| } | |||||
| return | |||||
| } | |||||
| if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) { | |||||
| this._activeTarget = null | |||||
| this._clear() | |||||
| return | |||||
| } | |||||
| const offsetLength = this._offsets.length | |||||
| for (let i = offsetLength; i--;) { | |||||
| const isActiveTarget = this._activeTarget !== this._targets[i] && | |||||
| scrollTop >= this._offsets[i] && | |||||
| (typeof this._offsets[i + 1] === 'undefined' || | |||||
| scrollTop < this._offsets[i + 1]) | |||||
| if (isActiveTarget) { | |||||
| this._activate(this._targets[i]) | |||||
| } | |||||
| } | |||||
| } | |||||
| _activate(target) { | |||||
| this._activeTarget = target | |||||
| this._clear() | |||||
| const queries = this._selector | |||||
| .split(',') | |||||
| .map((selector) => `${selector}[data-target="${target}"],${selector}[href="${target}"]`) | |||||
| const $link = $([].slice.call(document.querySelectorAll(queries.join(',')))) | |||||
| if ($link.hasClass(ClassName.DROPDOWN_ITEM)) { | |||||
| $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE) | |||||
| $link.addClass(ClassName.ACTIVE) | |||||
| } else { | |||||
| // Set triggered link as active | |||||
| $link.addClass(ClassName.ACTIVE) | |||||
| // Set triggered links parents as active | |||||
| // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor | |||||
| $link.parents(Selector.NAV_LIST_GROUP).prev(`${Selector.NAV_LINKS}, ${Selector.LIST_ITEMS}`).addClass(ClassName.ACTIVE) | |||||
| // Handle special case when .nav-link is inside .nav-item | |||||
| $link.parents(Selector.NAV_LIST_GROUP).prev(Selector.NAV_ITEMS).children(Selector.NAV_LINKS).addClass(ClassName.ACTIVE) | |||||
| } | |||||
| $(this._scrollElement).trigger(Event.ACTIVATE, { | |||||
| relatedTarget: target | |||||
| }) | |||||
| } | |||||
| _clear() { | |||||
| [].slice.call(document.querySelectorAll(this._selector)) | |||||
| .filter((node) => node.classList.contains(ClassName.ACTIVE)) | |||||
| .forEach((node) => node.classList.remove(ClassName.ACTIVE)) | |||||
| } | |||||
| // Static | |||||
| static _jQueryInterface(config) { | |||||
| return this.each(function () { | |||||
| let data = $(this).data(DATA_KEY) | |||||
| const _config = typeof config === 'object' && config | |||||
| if (!data) { | |||||
| data = new ScrollSpy(this, _config) | |||||
| $(this).data(DATA_KEY, data) | |||||
| } | |||||
| if (typeof config === 'string') { | |||||
| if (typeof data[config] === 'undefined') { | |||||
| throw new TypeError(`No method named "${config}"`) | |||||
| } | |||||
| data[config]() | |||||
| } | |||||
| }) | |||||
| } | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Data Api implementation | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $(window).on(Event.LOAD_DATA_API, () => { | |||||
| const scrollSpys = [].slice.call(document.querySelectorAll(Selector.DATA_SPY)) | |||||
| const scrollSpysLength = scrollSpys.length | |||||
| for (let i = scrollSpysLength; i--;) { | |||||
| const $spy = $(scrollSpys[i]) | |||||
| ScrollSpy._jQueryInterface.call($spy, $spy.data()) | |||||
| } | |||||
| }) | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * jQuery | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $.fn[NAME] = ScrollSpy._jQueryInterface | |||||
| $.fn[NAME].Constructor = ScrollSpy | |||||
| $.fn[NAME].noConflict = () => { | |||||
| $.fn[NAME] = JQUERY_NO_CONFLICT | |||||
| return ScrollSpy._jQueryInterface | |||||
| } | |||||
| export default ScrollSpy | |||||
| @ -0,0 +1,260 @@ | |||||
| /** | |||||
| * -------------------------------------------------------------------------- | |||||
| * Bootstrap (v4.4.1): tab.js | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| * -------------------------------------------------------------------------- | |||||
| */ | |||||
| import $ from 'jquery' | |||||
| import Util from './util' | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Constants | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| const NAME = 'tab' | |||||
| const VERSION = '4.4.1' | |||||
| const DATA_KEY = 'bs.tab' | |||||
| const EVENT_KEY = `.${DATA_KEY}` | |||||
| const DATA_API_KEY = '.data-api' | |||||
| const JQUERY_NO_CONFLICT = $.fn[NAME] | |||||
| const Event = { | |||||
| HIDE : `hide${EVENT_KEY}`, | |||||
| HIDDEN : `hidden${EVENT_KEY}`, | |||||
| SHOW : `show${EVENT_KEY}`, | |||||
| SHOWN : `shown${EVENT_KEY}`, | |||||
| CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}` | |||||
| } | |||||
| const ClassName = { | |||||
| DROPDOWN_MENU : 'dropdown-menu', | |||||
| ACTIVE : 'active', | |||||
| DISABLED : 'disabled', | |||||
| FADE : 'fade', | |||||
| SHOW : 'show' | |||||
| } | |||||
| const Selector = { | |||||
| DROPDOWN : '.dropdown', | |||||
| NAV_LIST_GROUP : '.nav, .list-group', | |||||
| ACTIVE : '.active', | |||||
| ACTIVE_UL : '> li > .active', | |||||
| DATA_TOGGLE : '[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]', | |||||
| DROPDOWN_TOGGLE : '.dropdown-toggle', | |||||
| DROPDOWN_ACTIVE_CHILD : '> .dropdown-menu .active' | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Class Definition | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| class Tab { | |||||
| constructor(element) { | |||||
| this._element = element | |||||
| } | |||||
| // Getters | |||||
| static get VERSION() { | |||||
| return VERSION | |||||
| } | |||||
| // Public | |||||
| show() { | |||||
| if (this._element.parentNode && | |||||
| this._element.parentNode.nodeType === Node.ELEMENT_NODE && | |||||
| $(this._element).hasClass(ClassName.ACTIVE) || | |||||
| $(this._element).hasClass(ClassName.DISABLED)) { | |||||
| return | |||||
| } | |||||
| let target | |||||
| let previous | |||||
| const listElement = $(this._element).closest(Selector.NAV_LIST_GROUP)[0] | |||||
| const selector = Util.getSelectorFromElement(this._element) | |||||
| if (listElement) { | |||||
| const itemSelector = listElement.nodeName === 'UL' || listElement.nodeName === 'OL' ? Selector.ACTIVE_UL : Selector.ACTIVE | |||||
| previous = $.makeArray($(listElement).find(itemSelector)) | |||||
| previous = previous[previous.length - 1] | |||||
| } | |||||
| const hideEvent = $.Event(Event.HIDE, { | |||||
| relatedTarget: this._element | |||||
| }) | |||||
| const showEvent = $.Event(Event.SHOW, { | |||||
| relatedTarget: previous | |||||
| }) | |||||
| if (previous) { | |||||
| $(previous).trigger(hideEvent) | |||||
| } | |||||
| $(this._element).trigger(showEvent) | |||||
| if (showEvent.isDefaultPrevented() || | |||||
| hideEvent.isDefaultPrevented()) { | |||||
| return | |||||
| } | |||||
| if (selector) { | |||||
| target = document.querySelector(selector) | |||||
| } | |||||
| this._activate( | |||||
| this._element, | |||||
| listElement | |||||
| ) | |||||
| const complete = () => { | |||||
| const hiddenEvent = $.Event(Event.HIDDEN, { | |||||
| relatedTarget: this._element | |||||
| }) | |||||
| const shownEvent = $.Event(Event.SHOWN, { | |||||
| relatedTarget: previous | |||||
| }) | |||||
| $(previous).trigger(hiddenEvent) | |||||
| $(this._element).trigger(shownEvent) | |||||
| } | |||||
| if (target) { | |||||
| this._activate(target, target.parentNode, complete) | |||||
| } else { | |||||
| complete() | |||||
| } | |||||
| } | |||||
| dispose() { | |||||
| $.removeData(this._element, DATA_KEY) | |||||
| this._element = null | |||||
| } | |||||
| // Private | |||||
| _activate(element, container, callback) { | |||||
| const activeElements = container && (container.nodeName === 'UL' || container.nodeName === 'OL') | |||||
| ? $(container).find(Selector.ACTIVE_UL) | |||||
| : $(container).children(Selector.ACTIVE) | |||||
| const active = activeElements[0] | |||||
| const isTransitioning = callback && (active && $(active).hasClass(ClassName.FADE)) | |||||
| const complete = () => this._transitionComplete( | |||||
| element, | |||||
| active, | |||||
| callback | |||||
| ) | |||||
| if (active && isTransitioning) { | |||||
| const transitionDuration = Util.getTransitionDurationFromElement(active) | |||||
| $(active) | |||||
| .removeClass(ClassName.SHOW) | |||||
| .one(Util.TRANSITION_END, complete) | |||||
| .emulateTransitionEnd(transitionDuration) | |||||
| } else { | |||||
| complete() | |||||
| } | |||||
| } | |||||
| _transitionComplete(element, active, callback) { | |||||
| if (active) { | |||||
| $(active).removeClass(ClassName.ACTIVE) | |||||
| const dropdownChild = $(active.parentNode).find( | |||||
| Selector.DROPDOWN_ACTIVE_CHILD | |||||
| )[0] | |||||
| if (dropdownChild) { | |||||
| $(dropdownChild).removeClass(ClassName.ACTIVE) | |||||
| } | |||||
| if (active.getAttribute('role') === 'tab') { | |||||
| active.setAttribute('aria-selected', false) | |||||
| } | |||||
| } | |||||
| $(element).addClass(ClassName.ACTIVE) | |||||
| if (element.getAttribute('role') === 'tab') { | |||||
| element.setAttribute('aria-selected', true) | |||||
| } | |||||
| Util.reflow(element) | |||||
| if (element.classList.contains(ClassName.FADE)) { | |||||
| element.classList.add(ClassName.SHOW) | |||||
| } | |||||
| if (element.parentNode && $(element.parentNode).hasClass(ClassName.DROPDOWN_MENU)) { | |||||
| const dropdownElement = $(element).closest(Selector.DROPDOWN)[0] | |||||
| if (dropdownElement) { | |||||
| const dropdownToggleList = [].slice.call(dropdownElement.querySelectorAll(Selector.DROPDOWN_TOGGLE)) | |||||
| $(dropdownToggleList).addClass(ClassName.ACTIVE) | |||||
| } | |||||
| element.setAttribute('aria-expanded', true) | |||||
| } | |||||
| if (callback) { | |||||
| callback() | |||||
| } | |||||
| } | |||||
| // Static | |||||
| static _jQueryInterface(config) { | |||||
| return this.each(function () { | |||||
| const $this = $(this) | |||||
| let data = $this.data(DATA_KEY) | |||||
| if (!data) { | |||||
| data = new Tab(this) | |||||
| $this.data(DATA_KEY, data) | |||||
| } | |||||
| if (typeof config === 'string') { | |||||
| if (typeof data[config] === 'undefined') { | |||||
| throw new TypeError(`No method named "${config}"`) | |||||
| } | |||||
| data[config]() | |||||
| } | |||||
| }) | |||||
| } | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Data Api implementation | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $(document) | |||||
| .on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { | |||||
| event.preventDefault() | |||||
| Tab._jQueryInterface.call($(this), 'show') | |||||
| }) | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * jQuery | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $.fn[NAME] = Tab._jQueryInterface | |||||
| $.fn[NAME].Constructor = Tab | |||||
| $.fn[NAME].noConflict = () => { | |||||
| $.fn[NAME] = JQUERY_NO_CONFLICT | |||||
| return Tab._jQueryInterface | |||||
| } | |||||
| export default Tab | |||||
| @ -0,0 +1,234 @@ | |||||
| /** | |||||
| * -------------------------------------------------------------------------- | |||||
| * Bootstrap (v4.4.1): toast.js | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| * -------------------------------------------------------------------------- | |||||
| */ | |||||
| import $ from 'jquery' | |||||
| import Util from './util' | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Constants | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| const NAME = 'toast' | |||||
| const VERSION = '4.4.1' | |||||
| const DATA_KEY = 'bs.toast' | |||||
| const EVENT_KEY = `.${DATA_KEY}` | |||||
| const JQUERY_NO_CONFLICT = $.fn[NAME] | |||||
| const Event = { | |||||
| CLICK_DISMISS : `click.dismiss${EVENT_KEY}`, | |||||
| HIDE : `hide${EVENT_KEY}`, | |||||
| HIDDEN : `hidden${EVENT_KEY}`, | |||||
| SHOW : `show${EVENT_KEY}`, | |||||
| SHOWN : `shown${EVENT_KEY}` | |||||
| } | |||||
| const ClassName = { | |||||
| FADE : 'fade', | |||||
| HIDE : 'hide', | |||||
| SHOW : 'show', | |||||
| SHOWING : 'showing' | |||||
| } | |||||
| const DefaultType = { | |||||
| animation : 'boolean', | |||||
| autohide : 'boolean', | |||||
| delay : 'number' | |||||
| } | |||||
| const Default = { | |||||
| animation : true, | |||||
| autohide : true, | |||||
| delay : 500 | |||||
| } | |||||
| const Selector = { | |||||
| DATA_DISMISS : '[data-dismiss="toast"]' | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Class Definition | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| class Toast { | |||||
| constructor(element, config) { | |||||
| this._element = element | |||||
| this._config = this._getConfig(config) | |||||
| this._timeout = null | |||||
| this._setListeners() | |||||
| } | |||||
| // Getters | |||||
| static get VERSION() { | |||||
| return VERSION | |||||
| } | |||||
| static get DefaultType() { | |||||
| return DefaultType | |||||
| } | |||||
| static get Default() { | |||||
| return Default | |||||
| } | |||||
| // Public | |||||
| show() { | |||||
| const showEvent = $.Event(Event.SHOW) | |||||
| $(this._element).trigger(showEvent) | |||||
| if (showEvent.isDefaultPrevented()) { | |||||
| return | |||||
| } | |||||
| if (this._config.animation) { | |||||
| this._element.classList.add(ClassName.FADE) | |||||
| } | |||||
| const complete = () => { | |||||
| this._element.classList.remove(ClassName.SHOWING) | |||||
| this._element.classList.add(ClassName.SHOW) | |||||
| $(this._element).trigger(Event.SHOWN) | |||||
| if (this._config.autohide) { | |||||
| this._timeout = setTimeout(() => { | |||||
| this.hide() | |||||
| }, this._config.delay) | |||||
| } | |||||
| } | |||||
| this._element.classList.remove(ClassName.HIDE) | |||||
| Util.reflow(this._element) | |||||
| this._element.classList.add(ClassName.SHOWING) | |||||
| if (this._config.animation) { | |||||
| const transitionDuration = Util.getTransitionDurationFromElement(this._element) | |||||
| $(this._element) | |||||
| .one(Util.TRANSITION_END, complete) | |||||
| .emulateTransitionEnd(transitionDuration) | |||||
| } else { | |||||
| complete() | |||||
| } | |||||
| } | |||||
| hide() { | |||||
| if (!this._element.classList.contains(ClassName.SHOW)) { | |||||
| return | |||||
| } | |||||
| const hideEvent = $.Event(Event.HIDE) | |||||
| $(this._element).trigger(hideEvent) | |||||
| if (hideEvent.isDefaultPrevented()) { | |||||
| return | |||||
| } | |||||
| this._close() | |||||
| } | |||||
| dispose() { | |||||
| clearTimeout(this._timeout) | |||||
| this._timeout = null | |||||
| if (this._element.classList.contains(ClassName.SHOW)) { | |||||
| this._element.classList.remove(ClassName.SHOW) | |||||
| } | |||||
| $(this._element).off(Event.CLICK_DISMISS) | |||||
| $.removeData(this._element, DATA_KEY) | |||||
| this._element = null | |||||
| this._config = null | |||||
| } | |||||
| // Private | |||||
| _getConfig(config) { | |||||
| config = { | |||||
| ...Default, | |||||
| ...$(this._element).data(), | |||||
| ...typeof config === 'object' && config ? config : {} | |||||
| } | |||||
| Util.typeCheckConfig( | |||||
| NAME, | |||||
| config, | |||||
| this.constructor.DefaultType | |||||
| ) | |||||
| return config | |||||
| } | |||||
| _setListeners() { | |||||
| $(this._element).on( | |||||
| Event.CLICK_DISMISS, | |||||
| Selector.DATA_DISMISS, | |||||
| () => this.hide() | |||||
| ) | |||||
| } | |||||
| _close() { | |||||
| const complete = () => { | |||||
| this._element.classList.add(ClassName.HIDE) | |||||
| $(this._element).trigger(Event.HIDDEN) | |||||
| } | |||||
| this._element.classList.remove(ClassName.SHOW) | |||||
| if (this._config.animation) { | |||||
| const transitionDuration = Util.getTransitionDurationFromElement(this._element) | |||||
| $(this._element) | |||||
| .one(Util.TRANSITION_END, complete) | |||||
| .emulateTransitionEnd(transitionDuration) | |||||
| } else { | |||||
| complete() | |||||
| } | |||||
| } | |||||
| // Static | |||||
| static _jQueryInterface(config) { | |||||
| return this.each(function () { | |||||
| const $element = $(this) | |||||
| let data = $element.data(DATA_KEY) | |||||
| const _config = typeof config === 'object' && config | |||||
| if (!data) { | |||||
| data = new Toast(this, _config) | |||||
| $element.data(DATA_KEY, data) | |||||
| } | |||||
| if (typeof config === 'string') { | |||||
| if (typeof data[config] === 'undefined') { | |||||
| throw new TypeError(`No method named "${config}"`) | |||||
| } | |||||
| data[config](this) | |||||
| } | |||||
| }) | |||||
| } | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * jQuery | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $.fn[NAME] = Toast._jQueryInterface | |||||
| $.fn[NAME].Constructor = Toast | |||||
| $.fn[NAME].noConflict = () => { | |||||
| $.fn[NAME] = JQUERY_NO_CONFLICT | |||||
| return Toast._jQueryInterface | |||||
| } | |||||
| export default Toast | |||||
| @ -0,0 +1,127 @@ | |||||
| /** | |||||
| * -------------------------------------------------------------------------- | |||||
| * Bootstrap (v4.4.1): tools/sanitizer.js | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| * -------------------------------------------------------------------------- | |||||
| */ | |||||
| const uriAttrs = [ | |||||
| 'background', | |||||
| 'cite', | |||||
| 'href', | |||||
| 'itemtype', | |||||
| 'longdesc', | |||||
| 'poster', | |||||
| 'src', | |||||
| 'xlink:href' | |||||
| ] | |||||
| const ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i | |||||
| export const DefaultWhitelist = { | |||||
| // Global attributes allowed on any supplied element below. | |||||
| '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN], | |||||
| a: ['target', 'href', 'title', 'rel'], | |||||
| area: [], | |||||
| b: [], | |||||
| br: [], | |||||
| col: [], | |||||
| code: [], | |||||
| div: [], | |||||
| em: [], | |||||
| hr: [], | |||||
| h1: [], | |||||
| h2: [], | |||||
| h3: [], | |||||
| h4: [], | |||||
| h5: [], | |||||
| h6: [], | |||||
| i: [], | |||||
| img: ['src', 'alt', 'title', 'width', 'height'], | |||||
| li: [], | |||||
| ol: [], | |||||
| p: [], | |||||
| pre: [], | |||||
| s: [], | |||||
| small: [], | |||||
| span: [], | |||||
| sub: [], | |||||
| sup: [], | |||||
| strong: [], | |||||
| u: [], | |||||
| ul: [] | |||||
| } | |||||
| /** | |||||
| * A pattern that recognizes a commonly useful subset of URLs that are safe. | |||||
| * | |||||
| * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts | |||||
| */ | |||||
| const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi | |||||
| /** | |||||
| * A pattern that matches safe data URLs. Only matches image, video and audio types. | |||||
| * | |||||
| * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts | |||||
| */ | |||||
| const DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i | |||||
| function allowedAttribute(attr, allowedAttributeList) { | |||||
| const attrName = attr.nodeName.toLowerCase() | |||||
| if (allowedAttributeList.indexOf(attrName) !== -1) { | |||||
| if (uriAttrs.indexOf(attrName) !== -1) { | |||||
| return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN)) | |||||
| } | |||||
| return true | |||||
| } | |||||
| const regExp = allowedAttributeList.filter((attrRegex) => attrRegex instanceof RegExp) | |||||
| // Check if a regular expression validates the attribute. | |||||
| for (let i = 0, l = regExp.length; i < l; i++) { | |||||
| if (attrName.match(regExp[i])) { | |||||
| return true | |||||
| } | |||||
| } | |||||
| return false | |||||
| } | |||||
| export function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) { | |||||
| if (unsafeHtml.length === 0) { | |||||
| return unsafeHtml | |||||
| } | |||||
| if (sanitizeFn && typeof sanitizeFn === 'function') { | |||||
| return sanitizeFn(unsafeHtml) | |||||
| } | |||||
| const domParser = new window.DOMParser() | |||||
| const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html') | |||||
| const whitelistKeys = Object.keys(whiteList) | |||||
| const elements = [].slice.call(createdDocument.body.querySelectorAll('*')) | |||||
| for (let i = 0, len = elements.length; i < len; i++) { | |||||
| const el = elements[i] | |||||
| const elName = el.nodeName.toLowerCase() | |||||
| if (whitelistKeys.indexOf(el.nodeName.toLowerCase()) === -1) { | |||||
| el.parentNode.removeChild(el) | |||||
| continue | |||||
| } | |||||
| const attributeList = [].slice.call(el.attributes) | |||||
| const whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || []) | |||||
| attributeList.forEach((attr) => { | |||||
| if (!allowedAttribute(attr, whitelistedAttributes)) { | |||||
| el.removeAttribute(attr.nodeName) | |||||
| } | |||||
| }) | |||||
| } | |||||
| return createdDocument.body.innerHTML | |||||
| } | |||||
| @ -0,0 +1,794 @@ | |||||
| /** | |||||
| * -------------------------------------------------------------------------- | |||||
| * Bootstrap (v4.4.1): tooltip.js | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| * -------------------------------------------------------------------------- | |||||
| */ | |||||
| import { | |||||
| DefaultWhitelist, | |||||
| sanitizeHtml | |||||
| } from './tools/sanitizer' | |||||
| import $ from 'jquery' | |||||
| import Popper from 'popper.js' | |||||
| import Util from './util' | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Constants | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| const NAME = 'tooltip' | |||||
| const VERSION = '4.4.1' | |||||
| const DATA_KEY = 'bs.tooltip' | |||||
| const EVENT_KEY = `.${DATA_KEY}` | |||||
| const JQUERY_NO_CONFLICT = $.fn[NAME] | |||||
| const CLASS_PREFIX = 'bs-tooltip' | |||||
| const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\s)${CLASS_PREFIX}\\S+`, 'g') | |||||
| const DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn'] | |||||
| const DefaultType = { | |||||
| animation : 'boolean', | |||||
| template : 'string', | |||||
| title : '(string|element|function)', | |||||
| trigger : 'string', | |||||
| delay : '(number|object)', | |||||
| html : 'boolean', | |||||
| selector : '(string|boolean)', | |||||
| placement : '(string|function)', | |||||
| offset : '(number|string|function)', | |||||
| container : '(string|element|boolean)', | |||||
| fallbackPlacement : '(string|array)', | |||||
| boundary : '(string|element)', | |||||
| sanitize : 'boolean', | |||||
| sanitizeFn : '(null|function)', | |||||
| whiteList : 'object', | |||||
| popperConfig : '(null|object)' | |||||
| } | |||||
| const AttachmentMap = { | |||||
| AUTO : 'auto', | |||||
| TOP : 'top', | |||||
| RIGHT : 'right', | |||||
| BOTTOM : 'bottom', | |||||
| LEFT : 'left' | |||||
| } | |||||
| const Default = { | |||||
| animation : true, | |||||
| template : '<div class="tooltip" role="tooltip">' + | |||||
| '<div class="arrow"></div>' + | |||||
| '<div class="tooltip-inner"></div></div>', | |||||
| trigger : 'hover focus', | |||||
| title : '', | |||||
| delay : 0, | |||||
| html : false, | |||||
| selector : false, | |||||
| placement : 'top', | |||||
| offset : 0, | |||||
| container : false, | |||||
| fallbackPlacement : 'flip', | |||||
| boundary : 'scrollParent', | |||||
| sanitize : true, | |||||
| sanitizeFn : null, | |||||
| whiteList : DefaultWhitelist, | |||||
| popperConfig : null | |||||
| } | |||||
| const HoverState = { | |||||
| SHOW : 'show', | |||||
| OUT : 'out' | |||||
| } | |||||
| const Event = { | |||||
| HIDE : `hide${EVENT_KEY}`, | |||||
| HIDDEN : `hidden${EVENT_KEY}`, | |||||
| SHOW : `show${EVENT_KEY}`, | |||||
| SHOWN : `shown${EVENT_KEY}`, | |||||
| INSERTED : `inserted${EVENT_KEY}`, | |||||
| CLICK : `click${EVENT_KEY}`, | |||||
| FOCUSIN : `focusin${EVENT_KEY}`, | |||||
| FOCUSOUT : `focusout${EVENT_KEY}`, | |||||
| MOUSEENTER : `mouseenter${EVENT_KEY}`, | |||||
| MOUSELEAVE : `mouseleave${EVENT_KEY}` | |||||
| } | |||||
| const ClassName = { | |||||
| FADE : 'fade', | |||||
| SHOW : 'show' | |||||
| } | |||||
| const Selector = { | |||||
| TOOLTIP : '.tooltip', | |||||
| TOOLTIP_INNER : '.tooltip-inner', | |||||
| ARROW : '.arrow' | |||||
| } | |||||
| const Trigger = { | |||||
| HOVER : 'hover', | |||||
| FOCUS : 'focus', | |||||
| CLICK : 'click', | |||||
| MANUAL : 'manual' | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Class Definition | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| class Tooltip { | |||||
| constructor(element, config) { | |||||
| if (typeof Popper === 'undefined') { | |||||
| throw new TypeError('Bootstrap\'s tooltips require Popper.js (https://popper.js.org/)') | |||||
| } | |||||
| // private | |||||
| this._isEnabled = true | |||||
| this._timeout = 0 | |||||
| this._hoverState = '' | |||||
| this._activeTrigger = {} | |||||
| this._popper = null | |||||
| // Protected | |||||
| this.element = element | |||||
| this.config = this._getConfig(config) | |||||
| this.tip = null | |||||
| this._setListeners() | |||||
| } | |||||
| // Getters | |||||
| static get VERSION() { | |||||
| return VERSION | |||||
| } | |||||
| static get Default() { | |||||
| return Default | |||||
| } | |||||
| static get NAME() { | |||||
| return NAME | |||||
| } | |||||
| static get DATA_KEY() { | |||||
| return DATA_KEY | |||||
| } | |||||
| static get Event() { | |||||
| return Event | |||||
| } | |||||
| static get EVENT_KEY() { | |||||
| return EVENT_KEY | |||||
| } | |||||
| static get DefaultType() { | |||||
| return DefaultType | |||||
| } | |||||
| // Public | |||||
| enable() { | |||||
| this._isEnabled = true | |||||
| } | |||||
| disable() { | |||||
| this._isEnabled = false | |||||
| } | |||||
| toggleEnabled() { | |||||
| this._isEnabled = !this._isEnabled | |||||
| } | |||||
| toggle(event) { | |||||
| if (!this._isEnabled) { | |||||
| return | |||||
| } | |||||
| if (event) { | |||||
| const dataKey = this.constructor.DATA_KEY | |||||
| let context = $(event.currentTarget).data(dataKey) | |||||
| if (!context) { | |||||
| context = new this.constructor( | |||||
| event.currentTarget, | |||||
| this._getDelegateConfig() | |||||
| ) | |||||
| $(event.currentTarget).data(dataKey, context) | |||||
| } | |||||
| context._activeTrigger.click = !context._activeTrigger.click | |||||
| if (context._isWithActiveTrigger()) { | |||||
| context._enter(null, context) | |||||
| } else { | |||||
| context._leave(null, context) | |||||
| } | |||||
| } else { | |||||
| if ($(this.getTipElement()).hasClass(ClassName.SHOW)) { | |||||
| this._leave(null, this) | |||||
| return | |||||
| } | |||||
| this._enter(null, this) | |||||
| } | |||||
| } | |||||
| dispose() { | |||||
| clearTimeout(this._timeout) | |||||
| $.removeData(this.element, this.constructor.DATA_KEY) | |||||
| $(this.element).off(this.constructor.EVENT_KEY) | |||||
| $(this.element).closest('.modal').off('hide.bs.modal', this._hideModalHandler) | |||||
| if (this.tip) { | |||||
| $(this.tip).remove() | |||||
| } | |||||
| this._isEnabled = null | |||||
| this._timeout = null | |||||
| this._hoverState = null | |||||
| this._activeTrigger = null | |||||
| if (this._popper) { | |||||
| this._popper.destroy() | |||||
| } | |||||
| this._popper = null | |||||
| this.element = null | |||||
| this.config = null | |||||
| this.tip = null | |||||
| } | |||||
| show() { | |||||
| if ($(this.element).css('display') === 'none') { | |||||
| throw new Error('Please use show on visible elements') | |||||
| } | |||||
| const showEvent = $.Event(this.constructor.Event.SHOW) | |||||
| if (this.isWithContent() && this._isEnabled) { | |||||
| $(this.element).trigger(showEvent) | |||||
| const shadowRoot = Util.findShadowRoot(this.element) | |||||
| const isInTheDom = $.contains( | |||||
| shadowRoot !== null ? shadowRoot : this.element.ownerDocument.documentElement, | |||||
| this.element | |||||
| ) | |||||
| if (showEvent.isDefaultPrevented() || !isInTheDom) { | |||||
| return | |||||
| } | |||||
| const tip = this.getTipElement() | |||||
| const tipId = Util.getUID(this.constructor.NAME) | |||||
| tip.setAttribute('id', tipId) | |||||
| this.element.setAttribute('aria-describedby', tipId) | |||||
| this.setContent() | |||||
| if (this.config.animation) { | |||||
| $(tip).addClass(ClassName.FADE) | |||||
| } | |||||
| const placement = typeof this.config.placement === 'function' | |||||
| ? this.config.placement.call(this, tip, this.element) | |||||
| : this.config.placement | |||||
| const attachment = this._getAttachment(placement) | |||||
| this.addAttachmentClass(attachment) | |||||
| const container = this._getContainer() | |||||
| $(tip).data(this.constructor.DATA_KEY, this) | |||||
| if (!$.contains(this.element.ownerDocument.documentElement, this.tip)) { | |||||
| $(tip).appendTo(container) | |||||
| } | |||||
| $(this.element).trigger(this.constructor.Event.INSERTED) | |||||
| this._popper = new Popper(this.element, tip, this._getPopperConfig(attachment)) | |||||
| $(tip).addClass(ClassName.SHOW) | |||||
| // If this is a touch-enabled device we add extra | |||||
| // empty mouseover listeners to the body's immediate children; | |||||
| // only needed because of broken event delegation on iOS | |||||
| // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html | |||||
| if ('ontouchstart' in document.documentElement) { | |||||
| $(document.body).children().on('mouseover', null, $.noop) | |||||
| } | |||||
| const complete = () => { | |||||
| if (this.config.animation) { | |||||
| this._fixTransition() | |||||
| } | |||||
| const prevHoverState = this._hoverState | |||||
| this._hoverState = null | |||||
| $(this.element).trigger(this.constructor.Event.SHOWN) | |||||
| if (prevHoverState === HoverState.OUT) { | |||||
| this._leave(null, this) | |||||
| } | |||||
| } | |||||
| if ($(this.tip).hasClass(ClassName.FADE)) { | |||||
| const transitionDuration = Util.getTransitionDurationFromElement(this.tip) | |||||
| $(this.tip) | |||||
| .one(Util.TRANSITION_END, complete) | |||||
| .emulateTransitionEnd(transitionDuration) | |||||
| } else { | |||||
| complete() | |||||
| } | |||||
| } | |||||
| } | |||||
| hide(callback) { | |||||
| const tip = this.getTipElement() | |||||
| const hideEvent = $.Event(this.constructor.Event.HIDE) | |||||
| const complete = () => { | |||||
| if (this._hoverState !== HoverState.SHOW && tip.parentNode) { | |||||
| tip.parentNode.removeChild(tip) | |||||
| } | |||||
| this._cleanTipClass() | |||||
| this.element.removeAttribute('aria-describedby') | |||||
| $(this.element).trigger(this.constructor.Event.HIDDEN) | |||||
| if (this._popper !== null) { | |||||
| this._popper.destroy() | |||||
| } | |||||
| if (callback) { | |||||
| callback() | |||||
| } | |||||
| } | |||||
| $(this.element).trigger(hideEvent) | |||||
| if (hideEvent.isDefaultPrevented()) { | |||||
| return | |||||
| } | |||||
| $(tip).removeClass(ClassName.SHOW) | |||||
| // If this is a touch-enabled device we remove the extra | |||||
| // empty mouseover listeners we added for iOS support | |||||
| if ('ontouchstart' in document.documentElement) { | |||||
| $(document.body).children().off('mouseover', null, $.noop) | |||||
| } | |||||
| this._activeTrigger[Trigger.CLICK] = false | |||||
| this._activeTrigger[Trigger.FOCUS] = false | |||||
| this._activeTrigger[Trigger.HOVER] = false | |||||
| if ($(this.tip).hasClass(ClassName.FADE)) { | |||||
| const transitionDuration = Util.getTransitionDurationFromElement(tip) | |||||
| $(tip) | |||||
| .one(Util.TRANSITION_END, complete) | |||||
| .emulateTransitionEnd(transitionDuration) | |||||
| } else { | |||||
| complete() | |||||
| } | |||||
| this._hoverState = '' | |||||
| } | |||||
| update() { | |||||
| if (this._popper !== null) { | |||||
| this._popper.scheduleUpdate() | |||||
| } | |||||
| } | |||||
| // Protected | |||||
| isWithContent() { | |||||
| return Boolean(this.getTitle()) | |||||
| } | |||||
| addAttachmentClass(attachment) { | |||||
| $(this.getTipElement()).addClass(`${CLASS_PREFIX}-${attachment}`) | |||||
| } | |||||
| getTipElement() { | |||||
| this.tip = this.tip || $(this.config.template)[0] | |||||
| return this.tip | |||||
| } | |||||
| setContent() { | |||||
| const tip = this.getTipElement() | |||||
| this.setElementContent($(tip.querySelectorAll(Selector.TOOLTIP_INNER)), this.getTitle()) | |||||
| $(tip).removeClass(`${ClassName.FADE} ${ClassName.SHOW}`) | |||||
| } | |||||
| setElementContent($element, content) { | |||||
| if (typeof content === 'object' && (content.nodeType || content.jquery)) { | |||||
| // Content is a DOM node or a jQuery | |||||
| if (this.config.html) { | |||||
| if (!$(content).parent().is($element)) { | |||||
| $element.empty().append(content) | |||||
| } | |||||
| } else { | |||||
| $element.text($(content).text()) | |||||
| } | |||||
| return | |||||
| } | |||||
| if (this.config.html) { | |||||
| if (this.config.sanitize) { | |||||
| content = sanitizeHtml(content, this.config.whiteList, this.config.sanitizeFn) | |||||
| } | |||||
| $element.html(content) | |||||
| } else { | |||||
| $element.text(content) | |||||
| } | |||||
| } | |||||
| getTitle() { | |||||
| let title = this.element.getAttribute('data-original-title') | |||||
| if (!title) { | |||||
| title = typeof this.config.title === 'function' | |||||
| ? this.config.title.call(this.element) | |||||
| : this.config.title | |||||
| } | |||||
| return title | |||||
| } | |||||
| // Private | |||||
| _getPopperConfig(attachment) { | |||||
| const defaultBsConfig = { | |||||
| placement: attachment, | |||||
| modifiers: { | |||||
| offset: this._getOffset(), | |||||
| flip: { | |||||
| behavior: this.config.fallbackPlacement | |||||
| }, | |||||
| arrow: { | |||||
| element: Selector.ARROW | |||||
| }, | |||||
| preventOverflow: { | |||||
| boundariesElement: this.config.boundary | |||||
| } | |||||
| }, | |||||
| onCreate: (data) => { | |||||
| if (data.originalPlacement !== data.placement) { | |||||
| this._handlePopperPlacementChange(data) | |||||
| } | |||||
| }, | |||||
| onUpdate: (data) => this._handlePopperPlacementChange(data) | |||||
| } | |||||
| return { | |||||
| ...defaultBsConfig, | |||||
| ...this.config.popperConfig | |||||
| } | |||||
| } | |||||
| _getOffset() { | |||||
| const offset = {} | |||||
| if (typeof this.config.offset === 'function') { | |||||
| offset.fn = (data) => { | |||||
| data.offsets = { | |||||
| ...data.offsets, | |||||
| ...this.config.offset(data.offsets, this.element) || {} | |||||
| } | |||||
| return data | |||||
| } | |||||
| } else { | |||||
| offset.offset = this.config.offset | |||||
| } | |||||
| return offset | |||||
| } | |||||
| _getContainer() { | |||||
| if (this.config.container === false) { | |||||
| return document.body | |||||
| } | |||||
| if (Util.isElement(this.config.container)) { | |||||
| return $(this.config.container) | |||||
| } | |||||
| return $(document).find(this.config.container) | |||||
| } | |||||
| _getAttachment(placement) { | |||||
| return AttachmentMap[placement.toUpperCase()] | |||||
| } | |||||
| _setListeners() { | |||||
| const triggers = this.config.trigger.split(' ') | |||||
| triggers.forEach((trigger) => { | |||||
| if (trigger === 'click') { | |||||
| $(this.element).on( | |||||
| this.constructor.Event.CLICK, | |||||
| this.config.selector, | |||||
| (event) => this.toggle(event) | |||||
| ) | |||||
| } else if (trigger !== Trigger.MANUAL) { | |||||
| const eventIn = trigger === Trigger.HOVER | |||||
| ? this.constructor.Event.MOUSEENTER | |||||
| : this.constructor.Event.FOCUSIN | |||||
| const eventOut = trigger === Trigger.HOVER | |||||
| ? this.constructor.Event.MOUSELEAVE | |||||
| : this.constructor.Event.FOCUSOUT | |||||
| $(this.element) | |||||
| .on( | |||||
| eventIn, | |||||
| this.config.selector, | |||||
| (event) => this._enter(event) | |||||
| ) | |||||
| .on( | |||||
| eventOut, | |||||
| this.config.selector, | |||||
| (event) => this._leave(event) | |||||
| ) | |||||
| } | |||||
| }) | |||||
| this._hideModalHandler = () => { | |||||
| if (this.element) { | |||||
| this.hide() | |||||
| } | |||||
| } | |||||
| $(this.element).closest('.modal').on( | |||||
| 'hide.bs.modal', | |||||
| this._hideModalHandler | |||||
| ) | |||||
| if (this.config.selector) { | |||||
| this.config = { | |||||
| ...this.config, | |||||
| trigger: 'manual', | |||||
| selector: '' | |||||
| } | |||||
| } else { | |||||
| this._fixTitle() | |||||
| } | |||||
| } | |||||
| _fixTitle() { | |||||
| const titleType = typeof this.element.getAttribute('data-original-title') | |||||
| if (this.element.getAttribute('title') || titleType !== 'string') { | |||||
| this.element.setAttribute( | |||||
| 'data-original-title', | |||||
| this.element.getAttribute('title') || '' | |||||
| ) | |||||
| this.element.setAttribute('title', '') | |||||
| } | |||||
| } | |||||
| _enter(event, context) { | |||||
| const dataKey = this.constructor.DATA_KEY | |||||
| context = context || $(event.currentTarget).data(dataKey) | |||||
| if (!context) { | |||||
| context = new this.constructor( | |||||
| event.currentTarget, | |||||
| this._getDelegateConfig() | |||||
| ) | |||||
| $(event.currentTarget).data(dataKey, context) | |||||
| } | |||||
| if (event) { | |||||
| context._activeTrigger[ | |||||
| event.type === 'focusin' ? Trigger.FOCUS : Trigger.HOVER | |||||
| ] = true | |||||
| } | |||||
| if ($(context.getTipElement()).hasClass(ClassName.SHOW) || context._hoverState === HoverState.SHOW) { | |||||
| context._hoverState = HoverState.SHOW | |||||
| return | |||||
| } | |||||
| clearTimeout(context._timeout) | |||||
| context._hoverState = HoverState.SHOW | |||||
| if (!context.config.delay || !context.config.delay.show) { | |||||
| context.show() | |||||
| return | |||||
| } | |||||
| context._timeout = setTimeout(() => { | |||||
| if (context._hoverState === HoverState.SHOW) { | |||||
| context.show() | |||||
| } | |||||
| }, context.config.delay.show) | |||||
| } | |||||
| _leave(event, context) { | |||||
| const dataKey = this.constructor.DATA_KEY | |||||
| context = context || $(event.currentTarget).data(dataKey) | |||||
| if (!context) { | |||||
| context = new this.constructor( | |||||
| event.currentTarget, | |||||
| this._getDelegateConfig() | |||||
| ) | |||||
| $(event.currentTarget).data(dataKey, context) | |||||
| } | |||||
| if (event) { | |||||
| context._activeTrigger[ | |||||
| event.type === 'focusout' ? Trigger.FOCUS : Trigger.HOVER | |||||
| ] = false | |||||
| } | |||||
| if (context._isWithActiveTrigger()) { | |||||
| return | |||||
| } | |||||
| clearTimeout(context._timeout) | |||||
| context._hoverState = HoverState.OUT | |||||
| if (!context.config.delay || !context.config.delay.hide) { | |||||
| context.hide() | |||||
| return | |||||
| } | |||||
| context._timeout = setTimeout(() => { | |||||
| if (context._hoverState === HoverState.OUT) { | |||||
| context.hide() | |||||
| } | |||||
| }, context.config.delay.hide) | |||||
| } | |||||
| _isWithActiveTrigger() { | |||||
| for (const trigger in this._activeTrigger) { | |||||
| if (this._activeTrigger[trigger]) { | |||||
| return true | |||||
| } | |||||
| } | |||||
| return false | |||||
| } | |||||
| _getConfig(config) { | |||||
| const dataAttributes = $(this.element).data() | |||||
| Object.keys(dataAttributes) | |||||
| .forEach((dataAttr) => { | |||||
| if (DISALLOWED_ATTRIBUTES.indexOf(dataAttr) !== -1) { | |||||
| delete dataAttributes[dataAttr] | |||||
| } | |||||
| }) | |||||
| config = { | |||||
| ...this.constructor.Default, | |||||
| ...dataAttributes, | |||||
| ...typeof config === 'object' && config ? config : {} | |||||
| } | |||||
| if (typeof config.delay === 'number') { | |||||
| config.delay = { | |||||
| show: config.delay, | |||||
| hide: config.delay | |||||
| } | |||||
| } | |||||
| if (typeof config.title === 'number') { | |||||
| config.title = config.title.toString() | |||||
| } | |||||
| if (typeof config.content === 'number') { | |||||
| config.content = config.content.toString() | |||||
| } | |||||
| Util.typeCheckConfig( | |||||
| NAME, | |||||
| config, | |||||
| this.constructor.DefaultType | |||||
| ) | |||||
| if (config.sanitize) { | |||||
| config.template = sanitizeHtml(config.template, config.whiteList, config.sanitizeFn) | |||||
| } | |||||
| return config | |||||
| } | |||||
| _getDelegateConfig() { | |||||
| const config = {} | |||||
| if (this.config) { | |||||
| for (const key in this.config) { | |||||
| if (this.constructor.Default[key] !== this.config[key]) { | |||||
| config[key] = this.config[key] | |||||
| } | |||||
| } | |||||
| } | |||||
| return config | |||||
| } | |||||
| _cleanTipClass() { | |||||
| const $tip = $(this.getTipElement()) | |||||
| const tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX) | |||||
| if (tabClass !== null && tabClass.length) { | |||||
| $tip.removeClass(tabClass.join('')) | |||||
| } | |||||
| } | |||||
| _handlePopperPlacementChange(popperData) { | |||||
| const popperInstance = popperData.instance | |||||
| this.tip = popperInstance.popper | |||||
| this._cleanTipClass() | |||||
| this.addAttachmentClass(this._getAttachment(popperData.placement)) | |||||
| } | |||||
| _fixTransition() { | |||||
| const tip = this.getTipElement() | |||||
| const initConfigAnimation = this.config.animation | |||||
| if (tip.getAttribute('x-placement') !== null) { | |||||
| return | |||||
| } | |||||
| $(tip).removeClass(ClassName.FADE) | |||||
| this.config.animation = false | |||||
| this.hide() | |||||
| this.show() | |||||
| this.config.animation = initConfigAnimation | |||||
| } | |||||
| // Static | |||||
| static _jQueryInterface(config) { | |||||
| return this.each(function () { | |||||
| let data = $(this).data(DATA_KEY) | |||||
| const _config = typeof config === 'object' && config | |||||
| if (!data && /dispose|hide/.test(config)) { | |||||
| return | |||||
| } | |||||
| if (!data) { | |||||
| data = new Tooltip(this, _config) | |||||
| $(this).data(DATA_KEY, data) | |||||
| } | |||||
| if (typeof config === 'string') { | |||||
| if (typeof data[config] === 'undefined') { | |||||
| throw new TypeError(`No method named "${config}"`) | |||||
| } | |||||
| data[config]() | |||||
| } | |||||
| }) | |||||
| } | |||||
| } | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * jQuery | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| $.fn[NAME] = Tooltip._jQueryInterface | |||||
| $.fn[NAME].Constructor = Tooltip | |||||
| $.fn[NAME].noConflict = () => { | |||||
| $.fn[NAME] = JQUERY_NO_CONFLICT | |||||
| return Tooltip._jQueryInterface | |||||
| } | |||||
| export default Tooltip | |||||
| @ -0,0 +1,195 @@ | |||||
| /** | |||||
| * -------------------------------------------------------------------------- | |||||
| * Bootstrap (v4.4.1): util.js | |||||
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |||||
| * -------------------------------------------------------------------------- | |||||
| */ | |||||
| import $ from 'jquery' | |||||
| /** | |||||
| * ------------------------------------------------------------------------ | |||||
| * Private TransitionEnd Helpers | |||||
| * ------------------------------------------------------------------------ | |||||
| */ | |||||
| const TRANSITION_END = 'transitionend' | |||||
| const MAX_UID = 1000000 | |||||
| const MILLISECONDS_MULTIPLIER = 1000 | |||||
| // Shoutout AngusCroll (https://goo.gl/pxwQGp) | |||||
| function toType(obj) { | |||||
| return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase() | |||||
| } | |||||
| function getSpecialTransitionEndEvent() { | |||||
| return { | |||||
| bindType: TRANSITION_END, | |||||
| delegateType: TRANSITION_END, | |||||
| handle(event) { | |||||
| if ($(event.target).is(this)) { | |||||
| return event.handleObj.handler.apply(this, arguments) // eslint-disable-line prefer-rest-params | |||||
| } | |||||
| return undefined // eslint-disable-line no-undefined | |||||
| } | |||||
| } | |||||
| } | |||||
| function transitionEndEmulator(duration) { | |||||
| let called = false | |||||
| $(this).one(Util.TRANSITION_END, () => { | |||||
| called = true | |||||
| }) | |||||
| setTimeout(() => { | |||||
| if (!called) { | |||||
| Util.triggerTransitionEnd(this) | |||||
| } | |||||
| }, duration) | |||||
| return this | |||||
| } | |||||
| function setTransitionEndSupport() { | |||||
| $.fn.emulateTransitionEnd = transitionEndEmulator | |||||
| $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent() | |||||
| } | |||||
| /** | |||||
| * -------------------------------------------------------------------------- | |||||
| * Public Util Api | |||||
| * -------------------------------------------------------------------------- | |||||
| */ | |||||
| const Util = { | |||||
| TRANSITION_END: 'bsTransitionEnd', | |||||
| getUID(prefix) { | |||||
| do { | |||||
| // eslint-disable-next-line no-bitwise | |||||
| prefix += ~~(Math.random() * MAX_UID) // "~~" acts like a faster Math.floor() here | |||||
| } while (document.getElementById(prefix)) | |||||
| return prefix | |||||
| }, | |||||
| getSelectorFromElement(element) { | |||||
| let selector = element.getAttribute('data-target') | |||||
| if (!selector || selector === '#') { | |||||
| const hrefAttr = element.getAttribute('href') | |||||
| selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : '' | |||||
| } | |||||
| try { | |||||
| return document.querySelector(selector) ? selector : null | |||||
| } catch (err) { | |||||
| return null | |||||
| } | |||||
| }, | |||||
| getTransitionDurationFromElement(element) { | |||||
| if (!element) { | |||||
| return 0 | |||||
| } | |||||
| // Get transition-duration of the element | |||||
| let transitionDuration = $(element).css('transition-duration') | |||||
| let transitionDelay = $(element).css('transition-delay') | |||||
| const floatTransitionDuration = parseFloat(transitionDuration) | |||||
| const floatTransitionDelay = parseFloat(transitionDelay) | |||||
| // Return 0 if element or transition duration is not found | |||||
| if (!floatTransitionDuration && !floatTransitionDelay) { | |||||
| return 0 | |||||
| } | |||||
| // If multiple durations are defined, take the first | |||||
| transitionDuration = transitionDuration.split(',')[0] | |||||
| transitionDelay = transitionDelay.split(',')[0] | |||||
| return (parseFloat(transitionDuration) + parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER | |||||
| }, | |||||
| reflow(element) { | |||||
| return element.offsetHeight | |||||
| }, | |||||
| triggerTransitionEnd(element) { | |||||
| $(element).trigger(TRANSITION_END) | |||||
| }, | |||||
| // TODO: Remove in v5 | |||||
| supportsTransitionEnd() { | |||||
| return Boolean(TRANSITION_END) | |||||
| }, | |||||
| isElement(obj) { | |||||
| return (obj[0] || obj).nodeType | |||||
| }, | |||||
| typeCheckConfig(componentName, config, configTypes) { | |||||
| for (const property in configTypes) { | |||||
| if (Object.prototype.hasOwnProperty.call(configTypes, property)) { | |||||
| const expectedTypes = configTypes[property] | |||||
| const value = config[property] | |||||
| const valueType = value && Util.isElement(value) | |||||
| ? 'element' : toType(value) | |||||
| if (!new RegExp(expectedTypes).test(valueType)) { | |||||
| throw new Error( | |||||
| `${componentName.toUpperCase()}: ` + | |||||
| `Option "${property}" provided type "${valueType}" ` + | |||||
| `but expected type "${expectedTypes}".`) | |||||
| } | |||||
| } | |||||
| } | |||||
| }, | |||||
| findShadowRoot(element) { | |||||
| if (!document.documentElement.attachShadow) { | |||||
| return null | |||||
| } | |||||
| // Can find the shadow root otherwise it'll return the document | |||||
| if (typeof element.getRootNode === 'function') { | |||||
| const root = element.getRootNode() | |||||
| return root instanceof ShadowRoot ? root : null | |||||
| } | |||||
| if (element instanceof ShadowRoot) { | |||||
| return element | |||||
| } | |||||
| // when we don't find a shadow root | |||||
| if (!element.parentNode) { | |||||
| return null | |||||
| } | |||||
| return Util.findShadowRoot(element.parentNode) | |||||
| }, | |||||
| jQueryDetection() { | |||||
| if (typeof $ === 'undefined') { | |||||
| throw new TypeError('Bootstrap\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\'s JavaScript.') | |||||
| } | |||||
| const version = $.fn.jquery.split(' ')[0].split('.') | |||||
| const minMajor = 1 | |||||
| const ltMajor = 2 | |||||
| const minMinor = 9 | |||||
| const minPatch = 1 | |||||
| const maxMajor = 4 | |||||
| if (version[0] < ltMajor && version[1] < minMinor || version[0] === minMajor && version[1] === minMinor && version[2] < minPatch || version[0] >= maxMajor) { | |||||
| throw new Error('Bootstrap\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0') | |||||
| } | |||||
| } | |||||
| } | |||||
| Util.jQueryDetection() | |||||
| setTransitionEndSupport() | |||||
| export default Util | |||||
| @ -0,0 +1,214 @@ | |||||
| { | |||||
| "_from": "bootstrap", | |||||
| "_id": "bootstrap@4.4.1", | |||||
| "_inBundle": false, | |||||
| "_integrity": "sha512-tbx5cHubwE6e2ZG7nqM3g/FZ5PQEDMWmMGNrCUBVRPHXTJaH7CBDdsLeu3eCh3B1tzAxTnAbtmrzvWEvT2NNEA==", | |||||
| "_location": "/bootstrap", | |||||
| "_phantomChildren": {}, | |||||
| "_requested": { | |||||
| "type": "tag", | |||||
| "registry": true, | |||||
| "raw": "bootstrap", | |||||
| "name": "bootstrap", | |||||
| "escapedName": "bootstrap", | |||||
| "rawSpec": "", | |||||
| "saveSpec": null, | |||||
| "fetchSpec": "latest" | |||||
| }, | |||||
| "_requiredBy": [ | |||||
| "#USER", | |||||
| "/" | |||||
| ], | |||||
| "_resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.4.1.tgz", | |||||
| "_shasum": "8582960eea0c5cd2bede84d8b0baf3789c3e8b01", | |||||
| "_spec": "bootstrap", | |||||
| "_where": "/app", | |||||
| "author": { | |||||
| "name": "The Bootstrap Authors", | |||||
| "url": "https://github.com/twbs/bootstrap/graphs/contributors" | |||||
| }, | |||||
| "bugs": { | |||||
| "url": "https://github.com/twbs/bootstrap/issues" | |||||
| }, | |||||
| "bundleDependencies": false, | |||||
| "contributors": [ | |||||
| { | |||||
| "name": "Twitter, Inc." | |||||
| } | |||||
| ], | |||||
| "dependencies": {}, | |||||
| "deprecated": false, | |||||
| "description": "The most popular front-end framework for developing responsive, mobile first projects on the web.", | |||||
| "devDependencies": { | |||||
| "@babel/cli": "^7.7.4", | |||||
| "@babel/core": "^7.7.4", | |||||
| "@babel/plugin-proposal-object-rest-spread": "^7.7.4", | |||||
| "@babel/preset-env": "^7.7.4", | |||||
| "autoprefixer": "^9.7.2", | |||||
| "babel-eslint": "^10.0.3", | |||||
| "babel-plugin-istanbul": "^5.2.0", | |||||
| "broken-link-checker": "^0.7.8", | |||||
| "bundlesize": "^0.18.0", | |||||
| "clean-css-cli": "^4.3.0", | |||||
| "cross-env": "^5.2.1", | |||||
| "eslint": "^5.16.0", | |||||
| "find-unused-sass-variables": "^0.6.0", | |||||
| "glob": "^7.1.6", | |||||
| "hammer-simulator": "0.0.1", | |||||
| "http-server": "^0.11.1", | |||||
| "ip": "^1.1.5", | |||||
| "jquery": "^3.4.1", | |||||
| "karma": "^3.1.4", | |||||
| "karma-browserstack-launcher": "1.4.0", | |||||
| "karma-chrome-launcher": "^3.1.0", | |||||
| "karma-coverage-istanbul-reporter": "^2.1.1", | |||||
| "karma-detect-browsers": "^2.3.3", | |||||
| "karma-firefox-launcher": "^1.2.0", | |||||
| "karma-qunit": "^3.1.3", | |||||
| "karma-sinon": "^1.0.5", | |||||
| "node-sass": "^4.13.0", | |||||
| "nodemon": "^1.19.4", | |||||
| "npm-run-all": "^4.1.5", | |||||
| "popper.js": "^1.16.0", | |||||
| "postcss-cli": "^6.1.3", | |||||
| "qunit": "2.9.2", | |||||
| "rollup": "1.26.5", | |||||
| "rollup-plugin-babel": "^4.3.3", | |||||
| "rollup-plugin-commonjs": "^10.1.0", | |||||
| "rollup-plugin-node-resolve": "^5.2.0", | |||||
| "shelljs": "^0.8.3", | |||||
| "shx": "^0.3.2", | |||||
| "sinon": "^7.5.0", | |||||
| "stylelint": "^9.10.1", | |||||
| "stylelint-config-twbs-bootstrap": "^0.5.0", | |||||
| "uglify-js": "^3.6.9", | |||||
| "vnu-jar": "19.9.4" | |||||
| }, | |||||
| "engines": { | |||||
| "node": ">=6" | |||||
| }, | |||||
| "files": [ | |||||
| "dist/{css,js}/*.{css,js,map}", | |||||
| "js/{src,dist}/**/*.{js,map}", | |||||
| "scss/**/*.scss" | |||||
| ], | |||||
| "funding": { | |||||
| "type": "opencollective", | |||||
| "url": "https://opencollective.com/bootstrap" | |||||
| }, | |||||
| "homepage": "https://getbootstrap.com/", | |||||
| "jspm": { | |||||
| "registry": "npm", | |||||
| "main": "js/bootstrap", | |||||
| "directories": { | |||||
| "lib": "dist" | |||||
| }, | |||||
| "shim": { | |||||
| "js/bootstrap": { | |||||
| "deps": [ | |||||
| "jquery", | |||||
| "popper.js" | |||||
| ], | |||||
| "exports": "$" | |||||
| } | |||||
| }, | |||||
| "dependencies": {}, | |||||
| "peerDependencies": { | |||||
| "jquery": "1.9.1 - 3", | |||||
| "popper.js": "^1.16.0" | |||||
| } | |||||
| }, | |||||
| "keywords": [ | |||||
| "css", | |||||
| "sass", | |||||
| "mobile-first", | |||||
| "responsive", | |||||
| "front-end", | |||||
| "framework", | |||||
| "web" | |||||
| ], | |||||
| "license": "MIT", | |||||
| "main": "dist/js/bootstrap", | |||||
| "name": "bootstrap", | |||||
| "peerDependencies": { | |||||
| "jquery": "1.9.1 - 3", | |||||
| "popper.js": "^1.16.0" | |||||
| }, | |||||
| "repository": { | |||||
| "type": "git", | |||||
| "url": "git+https://github.com/twbs/bootstrap.git" | |||||
| }, | |||||
| "sass": "scss/bootstrap.scss", | |||||
| "scripts": { | |||||
| "blc": "blc --exclude-external --filter-level 3 --follow --get --ordered --recursive --host-requests 4 --input http://localhost:3000/", | |||||
| "bundlesize": "bundlesize", | |||||
| "check-broken-links": "npm-run-all --parallel --race \"http-server -- _gh_pages/\" blc", | |||||
| "css": "npm-run-all css-compile css-prefix css-minify css-copy", | |||||
| "css-compile": "npm-run-all --parallel css-compile-*", | |||||
| "css-compile-docs": "cross-env-shell node-sass --output-style expanded --source-map true --source-map-contents true --precision 6 site/docs/$npm_package_version_short/assets/scss/docs.scss site/docs/$npm_package_version_short/assets/css/docs.min.css", | |||||
| "css-compile-main": "node-sass --output-style expanded --source-map true --source-map-contents true --precision 6 scss/ -o dist/css/ && npm run css-copy", | |||||
| "css-copy": "cross-env-shell shx mkdir -p site/docs/$npm_package_version_short/dist/ && cross-env-shell shx cp -r dist/css/ site/docs/$npm_package_version_short/dist/", | |||||
| "css-docs": "npm-run-all css-compile-docs css-prefix-docs css-minify-docs", | |||||
| "css-lint": "npm-run-all --continue-on-error --parallel css-lint-*", | |||||
| "css-lint-docs": "stylelint \"site/docs/**/assets/scss/*.scss\" \"site/docs/**/*.css\" --cache --cache-location .cache/.stylelintcache", | |||||
| "css-lint-main": "stylelint \"scss/**/*.scss\" --cache --cache-location .cache/.stylelintcache", | |||||
| "css-lint-vars": "fusv scss/ site/docs/", | |||||
| "css-main": "npm-run-all css-lint css-compile-main css-prefix-main css-minify-main css-copy", | |||||
| "css-minify": "npm-run-all --parallel css-minify-*", | |||||
| "css-minify-docs": "cross-env-shell cleancss --level 1 --format breakWith=lf --source-map --source-map-inline-sources --output site/docs/$npm_package_version_short/assets/css/docs.min.css site/docs/$npm_package_version_short/assets/css/docs.min.css", | |||||
| "css-minify-main": "cleancss --level 1 --format breakWith=lf --source-map --source-map-inline-sources --output dist/css/bootstrap.min.css dist/css/bootstrap.css && cleancss --level 1 --format breakWith=lf --source-map --source-map-inline-sources --output dist/css/bootstrap-grid.min.css dist/css/bootstrap-grid.css && cleancss --level 1 --format breakWith=lf --source-map --source-map-inline-sources --output dist/css/bootstrap-reboot.min.css dist/css/bootstrap-reboot.css", | |||||
| "css-prefix": "npm-run-all --parallel css-prefix-*", | |||||
| "css-prefix-docs": "postcss --config build/postcss.config.js --replace \"site/docs/**/*.css\"", | |||||
| "css-prefix-main": "postcss --config build/postcss.config.js --replace \"dist/css/*.css\" \"!dist/css/*.min.css\"", | |||||
| "dist": "npm-run-all --parallel css js", | |||||
| "docs": "npm-run-all css-docs js-docs docs-compile docs-lint", | |||||
| "docs-compile": "bundle exec jekyll build", | |||||
| "docs-lint": "node build/vnu-jar.js", | |||||
| "docs-netlify": "cross-env JEKYLL_ENV=netlify npm run docs-compile", | |||||
| "docs-production": "cross-env JEKYLL_ENV=production npm run docs-compile", | |||||
| "docs-serve": "bundle exec jekyll serve", | |||||
| "docs-serve-only": "npm run docs-serve -- --skip-initial-build --no-watch", | |||||
| "http-server": "http-server --silent -p 3000", | |||||
| "js": "npm-run-all js-compile js-minify js-copy", | |||||
| "js-compile": "npm-run-all --parallel js-compile-* --sequential js-copy", | |||||
| "js-compile-bundle": "rollup --environment BUNDLE:true --config build/rollup.config.js --sourcemap", | |||||
| "js-compile-plugins": "node build/build-plugins.js", | |||||
| "js-compile-plugins-coverage": "cross-env NODE_ENV=test node build/build-plugins.js", | |||||
| "js-compile-standalone": "rollup --environment BUNDLE:false --config build/rollup.config.js --sourcemap", | |||||
| "js-copy": "cross-env-shell shx mkdir -p site/docs/$npm_package_version_short/dist/ && cross-env-shell shx cp -r dist/js/ site/docs/$npm_package_version_short/dist/", | |||||
| "js-docs": "npm-run-all js-lint-docs js-minify-docs", | |||||
| "js-lint": "npm-run-all --continue-on-error --parallel js-lint-*", | |||||
| "js-lint-docs": "eslint --cache --cache-location .cache/.eslintcache site/", | |||||
| "js-lint-main": "eslint --cache --cache-location .cache/.eslintcache js/src js/tests build/", | |||||
| "js-main": "npm-run-all js-lint js-compile js-minify-main", | |||||
| "js-minify": "npm-run-all --parallel js-minify-main js-minify-docs", | |||||
| "js-minify-bundle": "uglifyjs --compress typeofs=false --mangle --comments \"/^!/\" --source-map \"content=dist/js/bootstrap.bundle.js.map,includeSources,url=bootstrap.bundle.min.js.map\" --output dist/js/bootstrap.bundle.min.js dist/js/bootstrap.bundle.js", | |||||
| "js-minify-docs": "cross-env-shell uglifyjs --mangle --comments \\\"/^!/\\\" --output site/docs/$npm_package_version_short/assets/js/docs.min.js site/docs/$npm_package_version_short/assets/js/vendor/anchor.min.js site/docs/$npm_package_version_short/assets/js/vendor/clipboard.min.js site/docs/$npm_package_version_short/assets/js/vendor/bs-custom-file-input.min.js \"site/docs/$npm_package_version_short/assets/js/src/*.js\"", | |||||
| "js-minify-main": "npm-run-all js-minify-standalone js-minify-bundle", | |||||
| "js-minify-standalone": "uglifyjs --compress typeofs=false --mangle --comments \"/^!/\" --source-map \"content=dist/js/bootstrap.js.map,includeSources,url=bootstrap.min.js.map\" --output dist/js/bootstrap.min.js dist/js/bootstrap.js", | |||||
| "js-test": "npm-run-all js-test-karma* js-test-integration", | |||||
| "js-test-cloud": "cross-env BROWSER=true npm run js-test-karma", | |||||
| "js-test-integration": "rollup --config js/tests/integration/rollup.bundle.js", | |||||
| "js-test-karma": "karma start js/tests/karma.conf.js", | |||||
| "js-test-karma-bundle": "cross-env BUNDLE=true npm run js-test-karma", | |||||
| "js-test-karma-bundle-old": "cross-env BUNDLE=true USE_OLD_JQUERY=true npm run js-test-karma", | |||||
| "js-test-karma-old": "cross-env USE_OLD_JQUERY=true npm run js-test-karma", | |||||
| "lint": "npm-run-all --parallel js-lint css-lint", | |||||
| "netlify": "npm-run-all dist release-sri docs-netlify", | |||||
| "release": "npm-run-all dist release-sri release-zip docs-production", | |||||
| "release-sri": "node build/generate-sri.js", | |||||
| "release-version": "node build/change-version.js", | |||||
| "release-zip": "cross-env-shell \"shx rm -rf bootstrap-$npm_package_version-dist && shx cp -r dist/ bootstrap-$npm_package_version-dist && zip -r9 bootstrap-$npm_package_version-dist.zip bootstrap-$npm_package_version-dist && shx rm -rf bootstrap-$npm_package_version-dist\"", | |||||
| "start": "npm-run-all --parallel watch docs-serve", | |||||
| "test": "npm-run-all lint dist js-test docs-compile docs-lint", | |||||
| "update-deps": "ncu -a -x \"cross-env,eslint,find-unused-sass-variables,karma,karma-browserstack-launcher,karma-qunit,nodemon,qunit,rollup,stylelint,stylelint-config-twbs-bootstrap\" && npm update && bundle update && cross-env-shell echo Manually update \\\"site/docs/$npm_package_version_short/assets/js/vendor/\\\"", | |||||
| "watch": "npm-run-all --parallel watch-*", | |||||
| "watch-css-docs": "nodemon --watch \"site/docs/**/assets/scss/\" --ext scss --exec \"npm run css-docs\"", | |||||
| "watch-css-main": "nodemon --watch scss/ --ext scss --exec \"npm run css-main\"", | |||||
| "watch-js-docs": "nodemon --watch \"site/docs/**/assets/js/src/\" --ext js --exec \"npm run js-docs\"", | |||||
| "watch-js-main": "nodemon --watch js/src/ --ext js --exec \"npm run js-compile\"" | |||||
| }, | |||||
| "style": "dist/css/bootstrap.css", | |||||
| "version": "4.4.1", | |||||
| "version_short": "4.4" | |||||
| } | |||||
| @ -0,0 +1,51 @@ | |||||
| // | |||||
| // Base styles | |||||
| // | |||||
| .alert { | |||||
| position: relative; | |||||
| padding: $alert-padding-y $alert-padding-x; | |||||
| margin-bottom: $alert-margin-bottom; | |||||
| border: $alert-border-width solid transparent; | |||||
| @include border-radius($alert-border-radius); | |||||
| } | |||||
| // Headings for larger alerts | |||||
| .alert-heading { | |||||
| // Specified to prevent conflicts of changing $headings-color | |||||
| color: inherit; | |||||
| } | |||||
| // Provide class for links that match alerts | |||||
| .alert-link { | |||||
| font-weight: $alert-link-font-weight; | |||||
| } | |||||
| // Dismissible alerts | |||||
| // | |||||
| // Expand the right padding and account for the close button's positioning. | |||||
| .alert-dismissible { | |||||
| padding-right: $close-font-size + $alert-padding-x * 2; | |||||
| // Adjust close link position | |||||
| .close { | |||||
| position: absolute; | |||||
| top: 0; | |||||
| right: 0; | |||||
| padding: $alert-padding-y $alert-padding-x; | |||||
| color: inherit; | |||||
| } | |||||
| } | |||||
| // Alternate styles | |||||
| // | |||||
| // Generate contextual modifier classes for colorizing the alert. | |||||
| @each $color, $value in $theme-colors { | |||||
| .alert-#{$color} { | |||||
| @include alert-variant(theme-color-level($color, $alert-bg-level), theme-color-level($color, $alert-border-level), theme-color-level($color, $alert-color-level)); | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,54 @@ | |||||
| // Base class | |||||
| // | |||||
| // Requires one of the contextual, color modifier classes for `color` and | |||||
| // `background-color`. | |||||
| .badge { | |||||
| display: inline-block; | |||||
| padding: $badge-padding-y $badge-padding-x; | |||||
| @include font-size($badge-font-size); | |||||
| font-weight: $badge-font-weight; | |||||
| line-height: 1; | |||||
| text-align: center; | |||||
| white-space: nowrap; | |||||
| vertical-align: baseline; | |||||
| @include border-radius($badge-border-radius); | |||||
| @include transition($badge-transition); | |||||
| @at-root a#{&} { | |||||
| @include hover-focus() { | |||||
| text-decoration: none; | |||||
| } | |||||
| } | |||||
| // Empty badges collapse automatically | |||||
| &:empty { | |||||
| display: none; | |||||
| } | |||||
| } | |||||
| // Quick fix for badges in buttons | |||||
| .btn .badge { | |||||
| position: relative; | |||||
| top: -1px; | |||||
| } | |||||
| // Pill badges | |||||
| // | |||||
| // Make them extra rounded with a modifier to replace v3's badges. | |||||
| .badge-pill { | |||||
| padding-right: $badge-pill-padding-x; | |||||
| padding-left: $badge-pill-padding-x; | |||||
| @include border-radius($badge-pill-border-radius); | |||||
| } | |||||
| // Colors | |||||
| // | |||||
| // Contextual variations (linked badges get darker on :hover). | |||||
| @each $color, $value in $theme-colors { | |||||
| .badge-#{$color} { | |||||
| @include badge-variant($value); | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,42 @@ | |||||
| .breadcrumb { | |||||
| display: flex; | |||||
| flex-wrap: wrap; | |||||
| padding: $breadcrumb-padding-y $breadcrumb-padding-x; | |||||
| margin-bottom: $breadcrumb-margin-bottom; | |||||
| @include font-size($breadcrumb-font-size); | |||||
| list-style: none; | |||||
| background-color: $breadcrumb-bg; | |||||
| @include border-radius($breadcrumb-border-radius); | |||||
| } | |||||
| .breadcrumb-item { | |||||
| // The separator between breadcrumbs (by default, a forward-slash: "/") | |||||
| + .breadcrumb-item { | |||||
| padding-left: $breadcrumb-item-padding; | |||||
| &::before { | |||||
| display: inline-block; // Suppress underlining of the separator in modern browsers | |||||
| padding-right: $breadcrumb-item-padding; | |||||
| color: $breadcrumb-divider-color; | |||||
| content: escape-svg($breadcrumb-divider); | |||||
| } | |||||
| } | |||||
| // IE9-11 hack to properly handle hyperlink underlines for breadcrumbs built | |||||
| // without `<ul>`s. The `::before` pseudo-element generates an element | |||||
| // *within* the .breadcrumb-item and thereby inherits the `text-decoration`. | |||||
| // | |||||
| // To trick IE into suppressing the underline, we give the pseudo-element an | |||||
| // underline and then immediately remove it. | |||||
| + .breadcrumb-item:hover::before { | |||||
| text-decoration: underline; | |||||
| } | |||||
| // stylelint-disable-next-line no-duplicate-selectors | |||||
| + .breadcrumb-item:hover::before { | |||||
| text-decoration: none; | |||||
| } | |||||
| &.active { | |||||
| color: $breadcrumb-active-color; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,163 @@ | |||||
| // stylelint-disable selector-no-qualifying-type | |||||
| // Make the div behave like a button | |||||
| .btn-group, | |||||
| .btn-group-vertical { | |||||
| position: relative; | |||||
| display: inline-flex; | |||||
| vertical-align: middle; // match .btn alignment given font-size hack above | |||||
| > .btn { | |||||
| position: relative; | |||||
| flex: 1 1 auto; | |||||
| // Bring the hover, focused, and "active" buttons to the front to overlay | |||||
| // the borders properly | |||||
| @include hover() { | |||||
| z-index: 1; | |||||
| } | |||||
| &:focus, | |||||
| &:active, | |||||
| &.active { | |||||
| z-index: 1; | |||||
| } | |||||
| } | |||||
| } | |||||
| // Optional: Group multiple button groups together for a toolbar | |||||
| .btn-toolbar { | |||||
| display: flex; | |||||
| flex-wrap: wrap; | |||||
| justify-content: flex-start; | |||||
| .input-group { | |||||
| width: auto; | |||||
| } | |||||
| } | |||||
| .btn-group { | |||||
| // Prevent double borders when buttons are next to each other | |||||
| > .btn:not(:first-child), | |||||
| > .btn-group:not(:first-child) { | |||||
| margin-left: -$btn-border-width; | |||||
| } | |||||
| // Reset rounded corners | |||||
| > .btn:not(:last-child):not(.dropdown-toggle), | |||||
| > .btn-group:not(:last-child) > .btn { | |||||
| @include border-right-radius(0); | |||||
| } | |||||
| > .btn:not(:first-child), | |||||
| > .btn-group:not(:first-child) > .btn { | |||||
| @include border-left-radius(0); | |||||
| } | |||||
| } | |||||
| // Sizing | |||||
| // | |||||
| // Remix the default button sizing classes into new ones for easier manipulation. | |||||
| .btn-group-sm > .btn { @extend .btn-sm; } | |||||
| .btn-group-lg > .btn { @extend .btn-lg; } | |||||
| // | |||||
| // Split button dropdowns | |||||
| // | |||||
| .dropdown-toggle-split { | |||||
| padding-right: $btn-padding-x * .75; | |||||
| padding-left: $btn-padding-x * .75; | |||||
| &::after, | |||||
| .dropup &::after, | |||||
| .dropright &::after { | |||||
| margin-left: 0; | |||||
| } | |||||
| .dropleft &::before { | |||||
| margin-right: 0; | |||||
| } | |||||
| } | |||||
| .btn-sm + .dropdown-toggle-split { | |||||
| padding-right: $btn-padding-x-sm * .75; | |||||
| padding-left: $btn-padding-x-sm * .75; | |||||
| } | |||||
| .btn-lg + .dropdown-toggle-split { | |||||
| padding-right: $btn-padding-x-lg * .75; | |||||
| padding-left: $btn-padding-x-lg * .75; | |||||
| } | |||||
| // The clickable button for toggling the menu | |||||
| // Set the same inset shadow as the :active state | |||||
| .btn-group.show .dropdown-toggle { | |||||
| @include box-shadow($btn-active-box-shadow); | |||||
| // Show no shadow for `.btn-link` since it has no other button styles. | |||||
| &.btn-link { | |||||
| @include box-shadow(none); | |||||
| } | |||||
| } | |||||
| // | |||||
| // Vertical button groups | |||||
| // | |||||
| .btn-group-vertical { | |||||
| flex-direction: column; | |||||
| align-items: flex-start; | |||||
| justify-content: center; | |||||
| > .btn, | |||||
| > .btn-group { | |||||
| width: 100%; | |||||
| } | |||||
| > .btn:not(:first-child), | |||||
| > .btn-group:not(:first-child) { | |||||
| margin-top: -$btn-border-width; | |||||
| } | |||||
| // Reset rounded corners | |||||
| > .btn:not(:last-child):not(.dropdown-toggle), | |||||
| > .btn-group:not(:last-child) > .btn { | |||||
| @include border-bottom-radius(0); | |||||
| } | |||||
| > .btn:not(:first-child), | |||||
| > .btn-group:not(:first-child) > .btn { | |||||
| @include border-top-radius(0); | |||||
| } | |||||
| } | |||||
| // Checkbox and radio options | |||||
| // | |||||
| // In order to support the browser's form validation feedback, powered by the | |||||
| // `required` attribute, we have to "hide" the inputs via `clip`. We cannot use | |||||
| // `display: none;` or `visibility: hidden;` as that also hides the popover. | |||||
| // Simply visually hiding the inputs via `opacity` would leave them clickable in | |||||
| // certain cases which is prevented by using `clip` and `pointer-events`. | |||||
| // This way, we ensure a DOM element is visible to position the popover from. | |||||
| // | |||||
| // See https://github.com/twbs/bootstrap/pull/12794 and | |||||
| // https://github.com/twbs/bootstrap/pull/14559 for more information. | |||||
| .btn-group-toggle { | |||||
| > .btn, | |||||
| > .btn-group > .btn { | |||||
| margin-bottom: 0; // Override default `<label>` value | |||||
| input[type="radio"], | |||||
| input[type="checkbox"] { | |||||
| position: absolute; | |||||
| clip: rect(0, 0, 0, 0); | |||||
| pointer-events: none; | |||||
| } | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,139 @@ | |||||
| // stylelint-disable selector-no-qualifying-type | |||||
| // | |||||
| // Base styles | |||||
| // | |||||
| .btn { | |||||
| display: inline-block; | |||||
| font-family: $btn-font-family; | |||||
| font-weight: $btn-font-weight; | |||||
| color: $body-color; | |||||
| text-align: center; | |||||
| white-space: $btn-white-space; | |||||
| vertical-align: middle; | |||||
| cursor: if($enable-pointer-cursor-for-buttons, pointer, null); | |||||
| user-select: none; | |||||
| background-color: transparent; | |||||
| border: $btn-border-width solid transparent; | |||||
| @include button-size($btn-padding-y, $btn-padding-x, $btn-font-size, $btn-line-height, $btn-border-radius); | |||||
| @include transition($btn-transition); | |||||
| @include hover() { | |||||
| color: $body-color; | |||||
| text-decoration: none; | |||||
| } | |||||
| &:focus, | |||||
| &.focus { | |||||
| outline: 0; | |||||
| box-shadow: $btn-focus-box-shadow; | |||||
| } | |||||
| // Disabled comes first so active can properly restyle | |||||
| &.disabled, | |||||
| &:disabled { | |||||
| opacity: $btn-disabled-opacity; | |||||
| @include box-shadow(none); | |||||
| } | |||||
| &:not(:disabled):not(.disabled):active, | |||||
| &:not(:disabled):not(.disabled).active { | |||||
| @include box-shadow($btn-active-box-shadow); | |||||
| &:focus { | |||||
| @include box-shadow($btn-focus-box-shadow, $btn-active-box-shadow); | |||||
| } | |||||
| } | |||||
| } | |||||
| // Future-proof disabling of clicks on `<a>` elements | |||||
| a.btn.disabled, | |||||
| fieldset:disabled a.btn { | |||||
| pointer-events: none; | |||||
| } | |||||
| // | |||||
| // Alternate buttons | |||||
| // | |||||
| @each $color, $value in $theme-colors { | |||||
| .btn-#{$color} { | |||||
| @include button-variant($value, $value); | |||||
| } | |||||
| } | |||||
| @each $color, $value in $theme-colors { | |||||
| .btn-outline-#{$color} { | |||||
| @include button-outline-variant($value); | |||||
| } | |||||
| } | |||||
| // | |||||
| // Link buttons | |||||
| // | |||||
| // Make a button look and behave like a link | |||||
| .btn-link { | |||||
| font-weight: $font-weight-normal; | |||||
| color: $link-color; | |||||
| text-decoration: $link-decoration; | |||||
| @include hover() { | |||||
| color: $link-hover-color; | |||||
| text-decoration: $link-hover-decoration; | |||||
| } | |||||
| &:focus, | |||||
| &.focus { | |||||
| text-decoration: $link-hover-decoration; | |||||
| box-shadow: none; | |||||
| } | |||||
| &:disabled, | |||||
| &.disabled { | |||||
| color: $btn-link-disabled-color; | |||||
| pointer-events: none; | |||||
| } | |||||
| // No need for an active state here | |||||
| } | |||||
| // | |||||
| // Button Sizes | |||||
| // | |||||
| .btn-lg { | |||||
| @include button-size($btn-padding-y-lg, $btn-padding-x-lg, $btn-font-size-lg, $btn-line-height-lg, $btn-border-radius-lg); | |||||
| } | |||||
| .btn-sm { | |||||
| @include button-size($btn-padding-y-sm, $btn-padding-x-sm, $btn-font-size-sm, $btn-line-height-sm, $btn-border-radius-sm); | |||||
| } | |||||
| // | |||||
| // Block button | |||||
| // | |||||
| .btn-block { | |||||
| display: block; | |||||
| width: 100%; | |||||
| // Vertically space out multiple block buttons | |||||
| + .btn-block { | |||||
| margin-top: $btn-block-spacing-y; | |||||
| } | |||||
| } | |||||
| // Specificity overrides | |||||
| input[type="submit"], | |||||
| input[type="reset"], | |||||
| input[type="button"] { | |||||
| &.btn-block { | |||||
| width: 100%; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,278 @@ | |||||
| // | |||||
| // Base styles | |||||
| // | |||||
| .card { | |||||
| position: relative; | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| min-width: 0; // See https://github.com/twbs/bootstrap/pull/22740#issuecomment-305868106 | |||||
| height: $card-height; | |||||
| word-wrap: break-word; | |||||
| background-color: $card-bg; | |||||
| background-clip: border-box; | |||||
| border: $card-border-width solid $card-border-color; | |||||
| @include border-radius($card-border-radius); | |||||
| > hr { | |||||
| margin-right: 0; | |||||
| margin-left: 0; | |||||
| } | |||||
| > .list-group:first-child { | |||||
| .list-group-item:first-child { | |||||
| @include border-top-radius($card-border-radius); | |||||
| } | |||||
| } | |||||
| > .list-group:last-child { | |||||
| .list-group-item:last-child { | |||||
| @include border-bottom-radius($card-border-radius); | |||||
| } | |||||
| } | |||||
| } | |||||
| .card-body { | |||||
| // Enable `flex-grow: 1` for decks and groups so that card blocks take up | |||||
| // as much space as possible, ensuring footers are aligned to the bottom. | |||||
| flex: 1 1 auto; | |||||
| // Workaround for the image size bug in IE | |||||
| // See: https://github.com/twbs/bootstrap/pull/28855 | |||||
| min-height: 1px; | |||||
| padding: $card-spacer-x; | |||||
| color: $card-color; | |||||
| } | |||||
| .card-title { | |||||
| margin-bottom: $card-spacer-y; | |||||
| } | |||||
| .card-subtitle { | |||||
| margin-top: -$card-spacer-y / 2; | |||||
| margin-bottom: 0; | |||||
| } | |||||
| .card-text:last-child { | |||||
| margin-bottom: 0; | |||||
| } | |||||
| .card-link { | |||||
| @include hover() { | |||||
| text-decoration: none; | |||||
| } | |||||
| + .card-link { | |||||
| margin-left: $card-spacer-x; | |||||
| } | |||||
| } | |||||
| // | |||||
| // Optional textual caps | |||||
| // | |||||
| .card-header { | |||||
| padding: $card-spacer-y $card-spacer-x; | |||||
| margin-bottom: 0; // Removes the default margin-bottom of <hN> | |||||
| color: $card-cap-color; | |||||
| background-color: $card-cap-bg; | |||||
| border-bottom: $card-border-width solid $card-border-color; | |||||
| &:first-child { | |||||
| @include border-radius($card-inner-border-radius $card-inner-border-radius 0 0); | |||||
| } | |||||
| + .list-group { | |||||
| .list-group-item:first-child { | |||||
| border-top: 0; | |||||
| } | |||||
| } | |||||
| } | |||||
| .card-footer { | |||||
| padding: $card-spacer-y $card-spacer-x; | |||||
| background-color: $card-cap-bg; | |||||
| border-top: $card-border-width solid $card-border-color; | |||||
| &:last-child { | |||||
| @include border-radius(0 0 $card-inner-border-radius $card-inner-border-radius); | |||||
| } | |||||
| } | |||||
| // | |||||
| // Header navs | |||||
| // | |||||
| .card-header-tabs { | |||||
| margin-right: -$card-spacer-x / 2; | |||||
| margin-bottom: -$card-spacer-y; | |||||
| margin-left: -$card-spacer-x / 2; | |||||
| border-bottom: 0; | |||||
| } | |||||
| .card-header-pills { | |||||
| margin-right: -$card-spacer-x / 2; | |||||
| margin-left: -$card-spacer-x / 2; | |||||
| } | |||||
| // Card image | |||||
| .card-img-overlay { | |||||
| position: absolute; | |||||
| top: 0; | |||||
| right: 0; | |||||
| bottom: 0; | |||||
| left: 0; | |||||
| padding: $card-img-overlay-padding; | |||||
| } | |||||
| .card-img, | |||||
| .card-img-top, | |||||
| .card-img-bottom { | |||||
| flex-shrink: 0; // For IE: https://github.com/twbs/bootstrap/issues/29396 | |||||
| width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch | |||||
| } | |||||
| .card-img, | |||||
| .card-img-top { | |||||
| @include border-top-radius($card-inner-border-radius); | |||||
| } | |||||
| .card-img, | |||||
| .card-img-bottom { | |||||
| @include border-bottom-radius($card-inner-border-radius); | |||||
| } | |||||
| // Card deck | |||||
| .card-deck { | |||||
| .card { | |||||
| margin-bottom: $card-deck-margin; | |||||
| } | |||||
| @include media-breakpoint-up(sm) { | |||||
| display: flex; | |||||
| flex-flow: row wrap; | |||||
| margin-right: -$card-deck-margin; | |||||
| margin-left: -$card-deck-margin; | |||||
| .card { | |||||
| // Flexbugs #4: https://github.com/philipwalton/flexbugs#flexbug-4 | |||||
| flex: 1 0 0%; | |||||
| margin-right: $card-deck-margin; | |||||
| margin-bottom: 0; // Override the default | |||||
| margin-left: $card-deck-margin; | |||||
| } | |||||
| } | |||||
| } | |||||
| // | |||||
| // Card groups | |||||
| // | |||||
| .card-group { | |||||
| // The child selector allows nested `.card` within `.card-group` | |||||
| // to display properly. | |||||
| > .card { | |||||
| margin-bottom: $card-group-margin; | |||||
| } | |||||
| @include media-breakpoint-up(sm) { | |||||
| display: flex; | |||||
| flex-flow: row wrap; | |||||
| // The child selector allows nested `.card` within `.card-group` | |||||
| // to display properly. | |||||
| > .card { | |||||
| // Flexbugs #4: https://github.com/philipwalton/flexbugs#flexbug-4 | |||||
| flex: 1 0 0%; | |||||
| margin-bottom: 0; | |||||
| + .card { | |||||
| margin-left: 0; | |||||
| border-left: 0; | |||||
| } | |||||
| // Handle rounded corners | |||||
| @if $enable-rounded { | |||||
| &:not(:last-child) { | |||||
| @include border-right-radius(0); | |||||
| .card-img-top, | |||||
| .card-header { | |||||
| // stylelint-disable-next-line property-blacklist | |||||
| border-top-right-radius: 0; | |||||
| } | |||||
| .card-img-bottom, | |||||
| .card-footer { | |||||
| // stylelint-disable-next-line property-blacklist | |||||
| border-bottom-right-radius: 0; | |||||
| } | |||||
| } | |||||
| &:not(:first-child) { | |||||
| @include border-left-radius(0); | |||||
| .card-img-top, | |||||
| .card-header { | |||||
| // stylelint-disable-next-line property-blacklist | |||||
| border-top-left-radius: 0; | |||||
| } | |||||
| .card-img-bottom, | |||||
| .card-footer { | |||||
| // stylelint-disable-next-line property-blacklist | |||||
| border-bottom-left-radius: 0; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| // | |||||
| // Columns | |||||
| // | |||||
| .card-columns { | |||||
| .card { | |||||
| margin-bottom: $card-columns-margin; | |||||
| } | |||||
| @include media-breakpoint-up(sm) { | |||||
| column-count: $card-columns-count; | |||||
| column-gap: $card-columns-gap; | |||||
| orphans: 1; | |||||
| widows: 1; | |||||
| .card { | |||||
| display: inline-block; // Don't let them vertically span multiple columns | |||||
| width: 100%; // Don't let their width change | |||||
| } | |||||
| } | |||||
| } | |||||
| // | |||||
| // Accordion | |||||
| // | |||||
| .accordion { | |||||
| > .card { | |||||
| overflow: hidden; | |||||
| &:not(:last-of-type) { | |||||
| border-bottom: 0; | |||||
| @include border-bottom-radius(0); | |||||
| } | |||||
| &:not(:first-of-type) { | |||||
| @include border-top-radius(0); | |||||
| } | |||||
| > .card-header { | |||||
| @include border-radius(0); | |||||
| margin-bottom: -$card-border-width; | |||||
| } | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,197 @@ | |||||
| // Notes on the classes: | |||||
| // | |||||
| // 1. .carousel.pointer-event should ideally be pan-y (to allow for users to scroll vertically) | |||||
| // even when their scroll action started on a carousel, but for compatibility (with Firefox) | |||||
| // we're preventing all actions instead | |||||
| // 2. The .carousel-item-left and .carousel-item-right is used to indicate where | |||||
| // the active slide is heading. | |||||
| // 3. .active.carousel-item is the current slide. | |||||
| // 4. .active.carousel-item-left and .active.carousel-item-right is the current | |||||
| // slide in its in-transition state. Only one of these occurs at a time. | |||||
| // 5. .carousel-item-next.carousel-item-left and .carousel-item-prev.carousel-item-right | |||||
| // is the upcoming slide in transition. | |||||
| .carousel { | |||||
| position: relative; | |||||
| } | |||||
| .carousel.pointer-event { | |||||
| touch-action: pan-y; | |||||
| } | |||||
| .carousel-inner { | |||||
| position: relative; | |||||
| width: 100%; | |||||
| overflow: hidden; | |||||
| @include clearfix(); | |||||
| } | |||||
| .carousel-item { | |||||
| position: relative; | |||||
| display: none; | |||||
| float: left; | |||||
| width: 100%; | |||||
| margin-right: -100%; | |||||
| backface-visibility: hidden; | |||||
| @include transition($carousel-transition); | |||||
| } | |||||
| .carousel-item.active, | |||||
| .carousel-item-next, | |||||
| .carousel-item-prev { | |||||
| display: block; | |||||
| } | |||||
| .carousel-item-next:not(.carousel-item-left), | |||||
| .active.carousel-item-right { | |||||
| transform: translateX(100%); | |||||
| } | |||||
| .carousel-item-prev:not(.carousel-item-right), | |||||
| .active.carousel-item-left { | |||||
| transform: translateX(-100%); | |||||
| } | |||||
| // | |||||
| // Alternate transitions | |||||
| // | |||||
| .carousel-fade { | |||||
| .carousel-item { | |||||
| opacity: 0; | |||||
| transition-property: opacity; | |||||
| transform: none; | |||||
| } | |||||
| .carousel-item.active, | |||||
| .carousel-item-next.carousel-item-left, | |||||
| .carousel-item-prev.carousel-item-right { | |||||
| z-index: 1; | |||||
| opacity: 1; | |||||
| } | |||||
| .active.carousel-item-left, | |||||
| .active.carousel-item-right { | |||||
| z-index: 0; | |||||
| opacity: 0; | |||||
| @include transition(opacity 0s $carousel-transition-duration); | |||||
| } | |||||
| } | |||||
| // | |||||
| // Left/right controls for nav | |||||
| // | |||||
| .carousel-control-prev, | |||||
| .carousel-control-next { | |||||
| position: absolute; | |||||
| top: 0; | |||||
| bottom: 0; | |||||
| z-index: 1; | |||||
| // Use flex for alignment (1-3) | |||||
| display: flex; // 1. allow flex styles | |||||
| align-items: center; // 2. vertically center contents | |||||
| justify-content: center; // 3. horizontally center contents | |||||
| width: $carousel-control-width; | |||||
| color: $carousel-control-color; | |||||
| text-align: center; | |||||
| opacity: $carousel-control-opacity; | |||||
| @include transition($carousel-control-transition); | |||||
| // Hover/focus state | |||||
| @include hover-focus() { | |||||
| color: $carousel-control-color; | |||||
| text-decoration: none; | |||||
| outline: 0; | |||||
| opacity: $carousel-control-hover-opacity; | |||||
| } | |||||
| } | |||||
| .carousel-control-prev { | |||||
| left: 0; | |||||
| @if $enable-gradients { | |||||
| background-image: linear-gradient(90deg, rgba($black, .25), rgba($black, .001)); | |||||
| } | |||||
| } | |||||
| .carousel-control-next { | |||||
| right: 0; | |||||
| @if $enable-gradients { | |||||
| background-image: linear-gradient(270deg, rgba($black, .25), rgba($black, .001)); | |||||
| } | |||||
| } | |||||
| // Icons for within | |||||
| .carousel-control-prev-icon, | |||||
| .carousel-control-next-icon { | |||||
| display: inline-block; | |||||
| width: $carousel-control-icon-width; | |||||
| height: $carousel-control-icon-width; | |||||
| background: no-repeat 50% / 100% 100%; | |||||
| } | |||||
| .carousel-control-prev-icon { | |||||
| background-image: escape-svg($carousel-control-prev-icon-bg); | |||||
| } | |||||
| .carousel-control-next-icon { | |||||
| background-image: escape-svg($carousel-control-next-icon-bg); | |||||
| } | |||||
| // Optional indicator pips | |||||
| // | |||||
| // Add an ordered list with the following class and add a list item for each | |||||
| // slide your carousel holds. | |||||
| .carousel-indicators { | |||||
| position: absolute; | |||||
| right: 0; | |||||
| bottom: 0; | |||||
| left: 0; | |||||
| z-index: 15; | |||||
| display: flex; | |||||
| justify-content: center; | |||||
| padding-left: 0; // override <ol> default | |||||
| // Use the .carousel-control's width as margin so we don't overlay those | |||||
| margin-right: $carousel-control-width; | |||||
| margin-left: $carousel-control-width; | |||||
| list-style: none; | |||||
| li { | |||||
| box-sizing: content-box; | |||||
| flex: 0 1 auto; | |||||
| width: $carousel-indicator-width; | |||||
| height: $carousel-indicator-height; | |||||
| margin-right: $carousel-indicator-spacer; | |||||
| margin-left: $carousel-indicator-spacer; | |||||
| text-indent: -999px; | |||||
| cursor: pointer; | |||||
| background-color: $carousel-indicator-active-bg; | |||||
| background-clip: padding-box; | |||||
| // Use transparent borders to increase the hit area by 10px on top and bottom. | |||||
| border-top: $carousel-indicator-hit-area-height solid transparent; | |||||
| border-bottom: $carousel-indicator-hit-area-height solid transparent; | |||||
| opacity: .5; | |||||
| @include transition($carousel-indicator-transition); | |||||
| } | |||||
| .active { | |||||
| opacity: 1; | |||||
| } | |||||
| } | |||||
| // Optional captions | |||||
| // | |||||
| // | |||||
| .carousel-caption { | |||||
| position: absolute; | |||||
| right: (100% - $carousel-caption-width) / 2; | |||||
| bottom: 20px; | |||||
| left: (100% - $carousel-caption-width) / 2; | |||||
| z-index: 10; | |||||
| padding-top: 20px; | |||||
| padding-bottom: 20px; | |||||
| color: $carousel-caption-color; | |||||
| text-align: center; | |||||
| } | |||||
| @ -0,0 +1,41 @@ | |||||
| .close { | |||||
| float: right; | |||||
| @include font-size($close-font-size); | |||||
| font-weight: $close-font-weight; | |||||
| line-height: 1; | |||||
| color: $close-color; | |||||
| text-shadow: $close-text-shadow; | |||||
| opacity: .5; | |||||
| // Override <a>'s hover style | |||||
| @include hover() { | |||||
| color: $close-color; | |||||
| text-decoration: none; | |||||
| } | |||||
| &:not(:disabled):not(.disabled) { | |||||
| @include hover-focus() { | |||||
| opacity: .75; | |||||
| } | |||||
| } | |||||
| } | |||||
| // Additional properties for button version | |||||
| // iOS requires the button element instead of an anchor tag. | |||||
| // If you want the anchor version, it requires `href="#"`. | |||||
| // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile | |||||
| // stylelint-disable-next-line selector-no-qualifying-type | |||||
| button.close { | |||||
| padding: 0; | |||||
| background-color: transparent; | |||||
| border: 0; | |||||
| appearance: none; | |||||
| } | |||||
| // Future-proof disabling of clicks on `<a>` elements | |||||
| // stylelint-disable-next-line selector-no-qualifying-type | |||||
| a.close.disabled { | |||||
| pointer-events: none; | |||||
| } | |||||
| @ -0,0 +1,48 @@ | |||||
| // Inline code | |||||
| code { | |||||
| @include font-size($code-font-size); | |||||
| color: $code-color; | |||||
| word-wrap: break-word; | |||||
| // Streamline the style when inside anchors to avoid broken underline and more | |||||
| a > & { | |||||
| color: inherit; | |||||
| } | |||||
| } | |||||
| // User input typically entered via keyboard | |||||
| kbd { | |||||
| padding: $kbd-padding-y $kbd-padding-x; | |||||
| @include font-size($kbd-font-size); | |||||
| color: $kbd-color; | |||||
| background-color: $kbd-bg; | |||||
| @include border-radius($border-radius-sm); | |||||
| @include box-shadow($kbd-box-shadow); | |||||
| kbd { | |||||
| padding: 0; | |||||
| @include font-size(100%); | |||||
| font-weight: $nested-kbd-font-weight; | |||||
| @include box-shadow(none); | |||||
| } | |||||
| } | |||||
| // Blocks of code | |||||
| pre { | |||||
| display: block; | |||||
| @include font-size($code-font-size); | |||||
| color: $pre-color; | |||||
| // Account for some code outputs that place code tags in pre tags | |||||
| code { | |||||
| @include font-size(inherit); | |||||
| color: inherit; | |||||
| word-break: normal; | |||||
| } | |||||
| } | |||||
| // Enable scrollable blocks of code | |||||
| .pre-scrollable { | |||||
| max-height: $pre-scrollable-max-height; | |||||
| overflow-y: scroll; | |||||
| } | |||||
| @ -0,0 +1,521 @@ | |||||
| // Embedded icons from Open Iconic. | |||||
| // Released under MIT and copyright 2014 Waybury. | |||||
| // https://useiconic.com/open | |||||
| // Checkboxes and radios | |||||
| // | |||||
| // Base class takes care of all the key behavioral aspects. | |||||
| .custom-control { | |||||
| position: relative; | |||||
| display: block; | |||||
| min-height: $font-size-base * $line-height-base; | |||||
| padding-left: $custom-control-gutter + $custom-control-indicator-size; | |||||
| } | |||||
| .custom-control-inline { | |||||
| display: inline-flex; | |||||
| margin-right: $custom-control-spacer-x; | |||||
| } | |||||
| .custom-control-input { | |||||
| position: absolute; | |||||
| left: 0; | |||||
| z-index: -1; // Put the input behind the label so it doesn't overlay text | |||||
| width: $custom-control-indicator-size; | |||||
| height: ($font-size-base * $line-height-base + $custom-control-indicator-size) / 2; | |||||
| opacity: 0; | |||||
| &:checked ~ .custom-control-label::before { | |||||
| color: $custom-control-indicator-checked-color; | |||||
| border-color: $custom-control-indicator-checked-border-color; | |||||
| @include gradient-bg($custom-control-indicator-checked-bg); | |||||
| @include box-shadow($custom-control-indicator-checked-box-shadow); | |||||
| } | |||||
| &:focus ~ .custom-control-label::before { | |||||
| // the mixin is not used here to make sure there is feedback | |||||
| @if $enable-shadows { | |||||
| box-shadow: $input-box-shadow, $input-focus-box-shadow; | |||||
| } @else { | |||||
| box-shadow: $custom-control-indicator-focus-box-shadow; | |||||
| } | |||||
| } | |||||
| &:focus:not(:checked) ~ .custom-control-label::before { | |||||
| border-color: $custom-control-indicator-focus-border-color; | |||||
| } | |||||
| &:not(:disabled):active ~ .custom-control-label::before { | |||||
| color: $custom-control-indicator-active-color; | |||||
| background-color: $custom-control-indicator-active-bg; | |||||
| border-color: $custom-control-indicator-active-border-color; | |||||
| @include box-shadow($custom-control-indicator-active-box-shadow); | |||||
| } | |||||
| // Use [disabled] and :disabled to work around https://github.com/twbs/bootstrap/issues/28247 | |||||
| &[disabled], | |||||
| &:disabled { | |||||
| ~ .custom-control-label { | |||||
| color: $custom-control-label-disabled-color; | |||||
| &::before { | |||||
| background-color: $custom-control-indicator-disabled-bg; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| // Custom control indicators | |||||
| // | |||||
| // Build the custom controls out of pseudo-elements. | |||||
| .custom-control-label { | |||||
| position: relative; | |||||
| margin-bottom: 0; | |||||
| color: $custom-control-label-color; | |||||
| vertical-align: top; | |||||
| cursor: $custom-control-cursor; | |||||
| // Background-color and (when enabled) gradient | |||||
| &::before { | |||||
| position: absolute; | |||||
| top: ($font-size-base * $line-height-base - $custom-control-indicator-size) / 2; | |||||
| left: -($custom-control-gutter + $custom-control-indicator-size); | |||||
| display: block; | |||||
| width: $custom-control-indicator-size; | |||||
| height: $custom-control-indicator-size; | |||||
| pointer-events: none; | |||||
| content: ""; | |||||
| background-color: $custom-control-indicator-bg; | |||||
| border: $custom-control-indicator-border-color solid $custom-control-indicator-border-width; | |||||
| @include box-shadow($custom-control-indicator-box-shadow); | |||||
| } | |||||
| // Foreground (icon) | |||||
| &::after { | |||||
| position: absolute; | |||||
| top: ($font-size-base * $line-height-base - $custom-control-indicator-size) / 2; | |||||
| left: -($custom-control-gutter + $custom-control-indicator-size); | |||||
| display: block; | |||||
| width: $custom-control-indicator-size; | |||||
| height: $custom-control-indicator-size; | |||||
| content: ""; | |||||
| background: no-repeat 50% / #{$custom-control-indicator-bg-size}; | |||||
| } | |||||
| } | |||||
| // Checkboxes | |||||
| // | |||||
| // Tweak just a few things for checkboxes. | |||||
| .custom-checkbox { | |||||
| .custom-control-label::before { | |||||
| @include border-radius($custom-checkbox-indicator-border-radius); | |||||
| } | |||||
| .custom-control-input:checked ~ .custom-control-label { | |||||
| &::after { | |||||
| background-image: escape-svg($custom-checkbox-indicator-icon-checked); | |||||
| } | |||||
| } | |||||
| .custom-control-input:indeterminate ~ .custom-control-label { | |||||
| &::before { | |||||
| border-color: $custom-checkbox-indicator-indeterminate-border-color; | |||||
| @include gradient-bg($custom-checkbox-indicator-indeterminate-bg); | |||||
| @include box-shadow($custom-checkbox-indicator-indeterminate-box-shadow); | |||||
| } | |||||
| &::after { | |||||
| background-image: escape-svg($custom-checkbox-indicator-icon-indeterminate); | |||||
| } | |||||
| } | |||||
| .custom-control-input:disabled { | |||||
| &:checked ~ .custom-control-label::before { | |||||
| background-color: $custom-control-indicator-checked-disabled-bg; | |||||
| } | |||||
| &:indeterminate ~ .custom-control-label::before { | |||||
| background-color: $custom-control-indicator-checked-disabled-bg; | |||||
| } | |||||
| } | |||||
| } | |||||
| // Radios | |||||
| // | |||||
| // Tweak just a few things for radios. | |||||
| .custom-radio { | |||||
| .custom-control-label::before { | |||||
| // stylelint-disable-next-line property-blacklist | |||||
| border-radius: $custom-radio-indicator-border-radius; | |||||
| } | |||||
| .custom-control-input:checked ~ .custom-control-label { | |||||
| &::after { | |||||
| background-image: escape-svg($custom-radio-indicator-icon-checked); | |||||
| } | |||||
| } | |||||
| .custom-control-input:disabled { | |||||
| &:checked ~ .custom-control-label::before { | |||||
| background-color: $custom-control-indicator-checked-disabled-bg; | |||||
| } | |||||
| } | |||||
| } | |||||
| // switches | |||||
| // | |||||
| // Tweak a few things for switches | |||||
| .custom-switch { | |||||
| padding-left: $custom-switch-width + $custom-control-gutter; | |||||
| .custom-control-label { | |||||
| &::before { | |||||
| left: -($custom-switch-width + $custom-control-gutter); | |||||
| width: $custom-switch-width; | |||||
| pointer-events: all; | |||||
| // stylelint-disable-next-line property-blacklist | |||||
| border-radius: $custom-switch-indicator-border-radius; | |||||
| } | |||||
| &::after { | |||||
| top: add(($font-size-base * $line-height-base - $custom-control-indicator-size) / 2, $custom-control-indicator-border-width * 2); | |||||
| left: add(-($custom-switch-width + $custom-control-gutter), $custom-control-indicator-border-width * 2); | |||||
| width: $custom-switch-indicator-size; | |||||
| height: $custom-switch-indicator-size; | |||||
| background-color: $custom-control-indicator-border-color; | |||||
| // stylelint-disable-next-line property-blacklist | |||||
| border-radius: $custom-switch-indicator-border-radius; | |||||
| @include transition(transform .15s ease-in-out, $custom-forms-transition); | |||||
| } | |||||
| } | |||||
| .custom-control-input:checked ~ .custom-control-label { | |||||
| &::after { | |||||
| background-color: $custom-control-indicator-bg; | |||||
| transform: translateX($custom-switch-width - $custom-control-indicator-size); | |||||
| } | |||||
| } | |||||
| .custom-control-input:disabled { | |||||
| &:checked ~ .custom-control-label::before { | |||||
| background-color: $custom-control-indicator-checked-disabled-bg; | |||||
| } | |||||
| } | |||||
| } | |||||
| // Select | |||||
| // | |||||
| // Replaces the browser default select with a custom one, mostly pulled from | |||||
| // https://primer.github.io/. | |||||
| // | |||||
| .custom-select { | |||||
| display: inline-block; | |||||
| width: 100%; | |||||
| height: $custom-select-height; | |||||
| padding: $custom-select-padding-y ($custom-select-padding-x + $custom-select-indicator-padding) $custom-select-padding-y $custom-select-padding-x; | |||||
| font-family: $custom-select-font-family; | |||||
| @include font-size($custom-select-font-size); | |||||
| font-weight: $custom-select-font-weight; | |||||
| line-height: $custom-select-line-height; | |||||
| color: $custom-select-color; | |||||
| vertical-align: middle; | |||||
| background: $custom-select-bg $custom-select-background; | |||||
| border: $custom-select-border-width solid $custom-select-border-color; | |||||
| @include border-radius($custom-select-border-radius, 0); | |||||
| @include box-shadow($custom-select-box-shadow); | |||||
| appearance: none; | |||||
| &:focus { | |||||
| border-color: $custom-select-focus-border-color; | |||||
| outline: 0; | |||||
| @if $enable-shadows { | |||||
| box-shadow: $custom-select-box-shadow, $custom-select-focus-box-shadow; | |||||
| } @else { | |||||
| box-shadow: $custom-select-focus-box-shadow; | |||||
| } | |||||
| &::-ms-value { | |||||
| // For visual consistency with other platforms/browsers, | |||||
| // suppress the default white text on blue background highlight given to | |||||
| // the selected option text when the (still closed) <select> receives focus | |||||
| // in IE and (under certain conditions) Edge. | |||||
| // See https://github.com/twbs/bootstrap/issues/19398. | |||||
| color: $input-color; | |||||
| background-color: $input-bg; | |||||
| } | |||||
| } | |||||
| &[multiple], | |||||
| &[size]:not([size="1"]) { | |||||
| height: auto; | |||||
| padding-right: $custom-select-padding-x; | |||||
| background-image: none; | |||||
| } | |||||
| &:disabled { | |||||
| color: $custom-select-disabled-color; | |||||
| background-color: $custom-select-disabled-bg; | |||||
| } | |||||
| // Hides the default caret in IE11 | |||||
| &::-ms-expand { | |||||
| display: none; | |||||
| } | |||||
| // Remove outline from select box in FF | |||||
| &:-moz-focusring { | |||||
| color: transparent; | |||||
| text-shadow: 0 0 0 $custom-select-color; | |||||
| } | |||||
| } | |||||
| .custom-select-sm { | |||||
| height: $custom-select-height-sm; | |||||
| padding-top: $custom-select-padding-y-sm; | |||||
| padding-bottom: $custom-select-padding-y-sm; | |||||
| padding-left: $custom-select-padding-x-sm; | |||||
| @include font-size($custom-select-font-size-sm); | |||||
| } | |||||
| .custom-select-lg { | |||||
| height: $custom-select-height-lg; | |||||
| padding-top: $custom-select-padding-y-lg; | |||||
| padding-bottom: $custom-select-padding-y-lg; | |||||
| padding-left: $custom-select-padding-x-lg; | |||||
| @include font-size($custom-select-font-size-lg); | |||||
| } | |||||
| // File | |||||
| // | |||||
| // Custom file input. | |||||
| .custom-file { | |||||
| position: relative; | |||||
| display: inline-block; | |||||
| width: 100%; | |||||
| height: $custom-file-height; | |||||
| margin-bottom: 0; | |||||
| } | |||||
| .custom-file-input { | |||||
| position: relative; | |||||
| z-index: 2; | |||||
| width: 100%; | |||||
| height: $custom-file-height; | |||||
| margin: 0; | |||||
| opacity: 0; | |||||
| &:focus ~ .custom-file-label { | |||||
| border-color: $custom-file-focus-border-color; | |||||
| box-shadow: $custom-file-focus-box-shadow; | |||||
| } | |||||
| // Use [disabled] and :disabled to work around https://github.com/twbs/bootstrap/issues/28247 | |||||
| &[disabled] ~ .custom-file-label, | |||||
| &:disabled ~ .custom-file-label { | |||||
| background-color: $custom-file-disabled-bg; | |||||
| } | |||||
| @each $lang, $value in $custom-file-text { | |||||
| &:lang(#{$lang}) ~ .custom-file-label::after { | |||||
| content: $value; | |||||
| } | |||||
| } | |||||
| ~ .custom-file-label[data-browse]::after { | |||||
| content: attr(data-browse); | |||||
| } | |||||
| } | |||||
| .custom-file-label { | |||||
| position: absolute; | |||||
| top: 0; | |||||
| right: 0; | |||||
| left: 0; | |||||
| z-index: 1; | |||||
| height: $custom-file-height; | |||||
| padding: $custom-file-padding-y $custom-file-padding-x; | |||||
| font-family: $custom-file-font-family; | |||||
| font-weight: $custom-file-font-weight; | |||||
| line-height: $custom-file-line-height; | |||||
| color: $custom-file-color; | |||||
| background-color: $custom-file-bg; | |||||
| border: $custom-file-border-width solid $custom-file-border-color; | |||||
| @include border-radius($custom-file-border-radius); | |||||
| @include box-shadow($custom-file-box-shadow); | |||||
| &::after { | |||||
| position: absolute; | |||||
| top: 0; | |||||
| right: 0; | |||||
| bottom: 0; | |||||
| z-index: 3; | |||||
| display: block; | |||||
| height: $custom-file-height-inner; | |||||
| padding: $custom-file-padding-y $custom-file-padding-x; | |||||
| line-height: $custom-file-line-height; | |||||
| color: $custom-file-button-color; | |||||
| content: "Browse"; | |||||
| @include gradient-bg($custom-file-button-bg); | |||||
| border-left: inherit; | |||||
| @include border-radius(0 $custom-file-border-radius $custom-file-border-radius 0); | |||||
| } | |||||
| } | |||||
| // Range | |||||
| // | |||||
| // Style range inputs the same across browsers. Vendor-specific rules for pseudo | |||||
| // elements cannot be mixed. As such, there are no shared styles for focus or | |||||
| // active states on prefixed selectors. | |||||
| .custom-range { | |||||
| width: 100%; | |||||
| height: add($custom-range-thumb-height, $custom-range-thumb-focus-box-shadow-width * 2); | |||||
| padding: 0; // Need to reset padding | |||||
| background-color: transparent; | |||||
| appearance: none; | |||||
| &:focus { | |||||
| outline: none; | |||||
| // Pseudo-elements must be split across multiple rulesets to have an effect. | |||||
| // No box-shadow() mixin for focus accessibility. | |||||
| &::-webkit-slider-thumb { box-shadow: $custom-range-thumb-focus-box-shadow; } | |||||
| &::-moz-range-thumb { box-shadow: $custom-range-thumb-focus-box-shadow; } | |||||
| &::-ms-thumb { box-shadow: $custom-range-thumb-focus-box-shadow; } | |||||
| } | |||||
| &::-moz-focus-outer { | |||||
| border: 0; | |||||
| } | |||||
| &::-webkit-slider-thumb { | |||||
| width: $custom-range-thumb-width; | |||||
| height: $custom-range-thumb-height; | |||||
| margin-top: ($custom-range-track-height - $custom-range-thumb-height) / 2; // Webkit specific | |||||
| @include gradient-bg($custom-range-thumb-bg); | |||||
| border: $custom-range-thumb-border; | |||||
| @include border-radius($custom-range-thumb-border-radius); | |||||
| @include box-shadow($custom-range-thumb-box-shadow); | |||||
| @include transition($custom-forms-transition); | |||||
| appearance: none; | |||||
| &:active { | |||||
| @include gradient-bg($custom-range-thumb-active-bg); | |||||
| } | |||||
| } | |||||
| &::-webkit-slider-runnable-track { | |||||
| width: $custom-range-track-width; | |||||
| height: $custom-range-track-height; | |||||
| color: transparent; // Why? | |||||
| cursor: $custom-range-track-cursor; | |||||
| background-color: $custom-range-track-bg; | |||||
| border-color: transparent; | |||||
| @include border-radius($custom-range-track-border-radius); | |||||
| @include box-shadow($custom-range-track-box-shadow); | |||||
| } | |||||
| &::-moz-range-thumb { | |||||
| width: $custom-range-thumb-width; | |||||
| height: $custom-range-thumb-height; | |||||
| @include gradient-bg($custom-range-thumb-bg); | |||||
| border: $custom-range-thumb-border; | |||||
| @include border-radius($custom-range-thumb-border-radius); | |||||
| @include box-shadow($custom-range-thumb-box-shadow); | |||||
| @include transition($custom-forms-transition); | |||||
| appearance: none; | |||||
| &:active { | |||||
| @include gradient-bg($custom-range-thumb-active-bg); | |||||
| } | |||||
| } | |||||
| &::-moz-range-track { | |||||
| width: $custom-range-track-width; | |||||
| height: $custom-range-track-height; | |||||
| color: transparent; | |||||
| cursor: $custom-range-track-cursor; | |||||
| background-color: $custom-range-track-bg; | |||||
| border-color: transparent; // Firefox specific? | |||||
| @include border-radius($custom-range-track-border-radius); | |||||
| @include box-shadow($custom-range-track-box-shadow); | |||||
| } | |||||
| &::-ms-thumb { | |||||
| width: $custom-range-thumb-width; | |||||
| height: $custom-range-thumb-height; | |||||
| margin-top: 0; // Edge specific | |||||
| margin-right: $custom-range-thumb-focus-box-shadow-width; // Workaround that overflowed box-shadow is hidden. | |||||
| margin-left: $custom-range-thumb-focus-box-shadow-width; // Workaround that overflowed box-shadow is hidden. | |||||
| @include gradient-bg($custom-range-thumb-bg); | |||||
| border: $custom-range-thumb-border; | |||||
| @include border-radius($custom-range-thumb-border-radius); | |||||
| @include box-shadow($custom-range-thumb-box-shadow); | |||||
| @include transition($custom-forms-transition); | |||||
| appearance: none; | |||||
| &:active { | |||||
| @include gradient-bg($custom-range-thumb-active-bg); | |||||
| } | |||||
| } | |||||
| &::-ms-track { | |||||
| width: $custom-range-track-width; | |||||
| height: $custom-range-track-height; | |||||
| color: transparent; | |||||
| cursor: $custom-range-track-cursor; | |||||
| background-color: transparent; | |||||
| border-color: transparent; | |||||
| border-width: $custom-range-thumb-height / 2; | |||||
| @include box-shadow($custom-range-track-box-shadow); | |||||
| } | |||||
| &::-ms-fill-lower { | |||||
| background-color: $custom-range-track-bg; | |||||
| @include border-radius($custom-range-track-border-radius); | |||||
| } | |||||
| &::-ms-fill-upper { | |||||
| margin-right: 15px; // arbitrary? | |||||
| background-color: $custom-range-track-bg; | |||||
| @include border-radius($custom-range-track-border-radius); | |||||
| } | |||||
| &:disabled { | |||||
| &::-webkit-slider-thumb { | |||||
| background-color: $custom-range-thumb-disabled-bg; | |||||
| } | |||||
| &::-webkit-slider-runnable-track { | |||||
| cursor: default; | |||||
| } | |||||
| &::-moz-range-thumb { | |||||
| background-color: $custom-range-thumb-disabled-bg; | |||||
| } | |||||
| &::-moz-range-track { | |||||
| cursor: default; | |||||
| } | |||||
| &::-ms-thumb { | |||||
| background-color: $custom-range-thumb-disabled-bg; | |||||
| } | |||||
| } | |||||
| } | |||||
| .custom-control-label::before, | |||||
| .custom-file-label, | |||||
| .custom-select { | |||||
| @include transition($custom-forms-transition); | |||||
| } | |||||
| @ -0,0 +1,191 @@ | |||||
| // The dropdown wrapper (`<div>`) | |||||
| .dropup, | |||||
| .dropright, | |||||
| .dropdown, | |||||
| .dropleft { | |||||
| position: relative; | |||||
| } | |||||
| .dropdown-toggle { | |||||
| white-space: nowrap; | |||||
| // Generate the caret automatically | |||||
| @include caret(); | |||||
| } | |||||
| // The dropdown menu | |||||
| .dropdown-menu { | |||||
| position: absolute; | |||||
| top: 100%; | |||||
| left: 0; | |||||
| z-index: $zindex-dropdown; | |||||
| display: none; // none by default, but block on "open" of the menu | |||||
| float: left; | |||||
| min-width: $dropdown-min-width; | |||||
| padding: $dropdown-padding-y 0; | |||||
| margin: $dropdown-spacer 0 0; // override default ul | |||||
| @include font-size($dropdown-font-size); | |||||
| color: $dropdown-color; | |||||
| text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer) | |||||
| list-style: none; | |||||
| background-color: $dropdown-bg; | |||||
| background-clip: padding-box; | |||||
| border: $dropdown-border-width solid $dropdown-border-color; | |||||
| @include border-radius($dropdown-border-radius); | |||||
| @include box-shadow($dropdown-box-shadow); | |||||
| } | |||||
| @each $breakpoint in map-keys($grid-breakpoints) { | |||||
| @include media-breakpoint-up($breakpoint) { | |||||
| $infix: breakpoint-infix($breakpoint, $grid-breakpoints); | |||||
| .dropdown-menu#{$infix}-left { | |||||
| right: auto; | |||||
| left: 0; | |||||
| } | |||||
| .dropdown-menu#{$infix}-right { | |||||
| right: 0; | |||||
| left: auto; | |||||
| } | |||||
| } | |||||
| } | |||||
| // Allow for dropdowns to go bottom up (aka, dropup-menu) | |||||
| // Just add .dropup after the standard .dropdown class and you're set. | |||||
| .dropup { | |||||
| .dropdown-menu { | |||||
| top: auto; | |||||
| bottom: 100%; | |||||
| margin-top: 0; | |||||
| margin-bottom: $dropdown-spacer; | |||||
| } | |||||
| .dropdown-toggle { | |||||
| @include caret(up); | |||||
| } | |||||
| } | |||||
| .dropright { | |||||
| .dropdown-menu { | |||||
| top: 0; | |||||
| right: auto; | |||||
| left: 100%; | |||||
| margin-top: 0; | |||||
| margin-left: $dropdown-spacer; | |||||
| } | |||||
| .dropdown-toggle { | |||||
| @include caret(right); | |||||
| &::after { | |||||
| vertical-align: 0; | |||||
| } | |||||
| } | |||||
| } | |||||
| .dropleft { | |||||
| .dropdown-menu { | |||||
| top: 0; | |||||
| right: 100%; | |||||
| left: auto; | |||||
| margin-top: 0; | |||||
| margin-right: $dropdown-spacer; | |||||
| } | |||||
| .dropdown-toggle { | |||||
| @include caret(left); | |||||
| &::before { | |||||
| vertical-align: 0; | |||||
| } | |||||
| } | |||||
| } | |||||
| // When enabled Popper.js, reset basic dropdown position | |||||
| // stylelint-disable-next-line no-duplicate-selectors | |||||
| .dropdown-menu { | |||||
| &[x-placement^="top"], | |||||
| &[x-placement^="right"], | |||||
| &[x-placement^="bottom"], | |||||
| &[x-placement^="left"] { | |||||
| right: auto; | |||||
| bottom: auto; | |||||
| } | |||||
| } | |||||
| // Dividers (basically an `<hr>`) within the dropdown | |||||
| .dropdown-divider { | |||||
| @include nav-divider($dropdown-divider-bg, $dropdown-divider-margin-y, true); | |||||
| } | |||||
| // Links, buttons, and more within the dropdown menu | |||||
| // | |||||
| // `<button>`-specific styles are denoted with `// For <button>s` | |||||
| .dropdown-item { | |||||
| display: block; | |||||
| width: 100%; // For `<button>`s | |||||
| padding: $dropdown-item-padding-y $dropdown-item-padding-x; | |||||
| clear: both; | |||||
| font-weight: $font-weight-normal; | |||||
| color: $dropdown-link-color; | |||||
| text-align: inherit; // For `<button>`s | |||||
| white-space: nowrap; // prevent links from randomly breaking onto new lines | |||||
| background-color: transparent; // For `<button>`s | |||||
| border: 0; // For `<button>`s | |||||
| // Prevent dropdown overflow if there's no padding | |||||
| // See https://github.com/twbs/bootstrap/pull/27703 | |||||
| @if $dropdown-padding-y == 0 { | |||||
| &:first-child { | |||||
| @include border-top-radius($dropdown-inner-border-radius); | |||||
| } | |||||
| &:last-child { | |||||
| @include border-bottom-radius($dropdown-inner-border-radius); | |||||
| } | |||||
| } | |||||
| @include hover-focus() { | |||||
| color: $dropdown-link-hover-color; | |||||
| text-decoration: none; | |||||
| @include gradient-bg($dropdown-link-hover-bg); | |||||
| } | |||||
| &.active, | |||||
| &:active { | |||||
| color: $dropdown-link-active-color; | |||||
| text-decoration: none; | |||||
| @include gradient-bg($dropdown-link-active-bg); | |||||
| } | |||||
| &.disabled, | |||||
| &:disabled { | |||||
| color: $dropdown-link-disabled-color; | |||||
| pointer-events: none; | |||||
| background-color: transparent; | |||||
| // Remove CSS gradients if they're enabled | |||||
| @if $enable-gradients { | |||||
| background-image: none; | |||||
| } | |||||
| } | |||||
| } | |||||
| .dropdown-menu.show { | |||||
| display: block; | |||||
| } | |||||
| // Dropdown section headers | |||||
| .dropdown-header { | |||||
| display: block; | |||||
| padding: $dropdown-padding-y $dropdown-item-padding-x; | |||||
| margin-bottom: 0; // for use with heading elements | |||||
| @include font-size($font-size-sm); | |||||
| color: $dropdown-header-color; | |||||
| white-space: nowrap; // as with > li > a | |||||
| } | |||||
| // Dropdown text | |||||
| .dropdown-item-text { | |||||
| display: block; | |||||
| padding: $dropdown-item-padding-y $dropdown-item-padding-x; | |||||
| color: $dropdown-link-color; | |||||
| } | |||||
| @ -0,0 +1,338 @@ | |||||
| // stylelint-disable selector-no-qualifying-type | |||||
| // | |||||
| // Textual form controls | |||||
| // | |||||
| .form-control { | |||||
| display: block; | |||||
| width: 100%; | |||||
| height: $input-height; | |||||
| padding: $input-padding-y $input-padding-x; | |||||
| font-family: $input-font-family; | |||||
| @include font-size($input-font-size); | |||||
| font-weight: $input-font-weight; | |||||
| line-height: $input-line-height; | |||||
| color: $input-color; | |||||
| background-color: $input-bg; | |||||
| background-clip: padding-box; | |||||
| border: $input-border-width solid $input-border-color; | |||||
| // Note: This has no effect on <select>s in some browsers, due to the limited stylability of `<select>`s in CSS. | |||||
| @include border-radius($input-border-radius, 0); | |||||
| @include box-shadow($input-box-shadow); | |||||
| @include transition($input-transition); | |||||
| // Unstyle the caret on `<select>`s in IE10+. | |||||
| &::-ms-expand { | |||||
| background-color: transparent; | |||||
| border: 0; | |||||
| } | |||||
| // Remove select outline from select box in FF | |||||
| &:-moz-focusring { | |||||
| color: transparent; | |||||
| text-shadow: 0 0 0 $input-color; | |||||
| } | |||||
| // Customize the `:focus` state to imitate native WebKit styles. | |||||
| @include form-control-focus($ignore-warning: true); | |||||
| // Placeholder | |||||
| &::placeholder { | |||||
| color: $input-placeholder-color; | |||||
| // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526. | |||||
| opacity: 1; | |||||
| } | |||||
| // Disabled and read-only inputs | |||||
| // | |||||
| // HTML5 says that controls under a fieldset > legend:first-child won't be | |||||
| // disabled if the fieldset is disabled. Due to implementation difficulty, we | |||||
| // don't honor that edge case; we style them as disabled anyway. | |||||
| &:disabled, | |||||
| &[readonly] { | |||||
| background-color: $input-disabled-bg; | |||||
| // iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655. | |||||
| opacity: 1; | |||||
| } | |||||
| } | |||||
| select.form-control { | |||||
| &:focus::-ms-value { | |||||
| // Suppress the nested default white text on blue background highlight given to | |||||
| // the selected option text when the (still closed) <select> receives focus | |||||
| // in IE and (under certain conditions) Edge, as it looks bad and cannot be made to | |||||
| // match the appearance of the native widget. | |||||
| // See https://github.com/twbs/bootstrap/issues/19398. | |||||
| color: $input-color; | |||||
| background-color: $input-bg; | |||||
| } | |||||
| } | |||||
| // Make file inputs better match text inputs by forcing them to new lines. | |||||
| .form-control-file, | |||||
| .form-control-range { | |||||
| display: block; | |||||
| width: 100%; | |||||
| } | |||||
| // | |||||
| // Labels | |||||
| // | |||||
| // For use with horizontal and inline forms, when you need the label (or legend) | |||||
| // text to align with the form controls. | |||||
| .col-form-label { | |||||
| padding-top: add($input-padding-y, $input-border-width); | |||||
| padding-bottom: add($input-padding-y, $input-border-width); | |||||
| margin-bottom: 0; // Override the `<label>/<legend>` default | |||||
| @include font-size(inherit); // Override the `<legend>` default | |||||
| line-height: $input-line-height; | |||||
| } | |||||
| .col-form-label-lg { | |||||
| padding-top: add($input-padding-y-lg, $input-border-width); | |||||
| padding-bottom: add($input-padding-y-lg, $input-border-width); | |||||
| @include font-size($input-font-size-lg); | |||||
| line-height: $input-line-height-lg; | |||||
| } | |||||
| .col-form-label-sm { | |||||
| padding-top: add($input-padding-y-sm, $input-border-width); | |||||
| padding-bottom: add($input-padding-y-sm, $input-border-width); | |||||
| @include font-size($input-font-size-sm); | |||||
| line-height: $input-line-height-sm; | |||||
| } | |||||
| // Readonly controls as plain text | |||||
| // | |||||
| // Apply class to a readonly input to make it appear like regular plain | |||||
| // text (without any border, background color, focus indicator) | |||||
| .form-control-plaintext { | |||||
| display: block; | |||||
| width: 100%; | |||||
| padding: $input-padding-y 0; | |||||
| margin-bottom: 0; // match inputs if this class comes on inputs with default margins | |||||
| @include font-size($input-font-size); | |||||
| line-height: $input-line-height; | |||||
| color: $input-plaintext-color; | |||||
| background-color: transparent; | |||||
| border: solid transparent; | |||||
| border-width: $input-border-width 0; | |||||
| &.form-control-sm, | |||||
| &.form-control-lg { | |||||
| padding-right: 0; | |||||
| padding-left: 0; | |||||
| } | |||||
| } | |||||
| // Form control sizing | |||||
| // | |||||
| // Build on `.form-control` with modifier classes to decrease or increase the | |||||
| // height and font-size of form controls. | |||||
| // | |||||
| // Repeated in `_input_group.scss` to avoid Sass extend issues. | |||||
| .form-control-sm { | |||||
| height: $input-height-sm; | |||||
| padding: $input-padding-y-sm $input-padding-x-sm; | |||||
| @include font-size($input-font-size-sm); | |||||
| line-height: $input-line-height-sm; | |||||
| @include border-radius($input-border-radius-sm); | |||||
| } | |||||
| .form-control-lg { | |||||
| height: $input-height-lg; | |||||
| padding: $input-padding-y-lg $input-padding-x-lg; | |||||
| @include font-size($input-font-size-lg); | |||||
| line-height: $input-line-height-lg; | |||||
| @include border-radius($input-border-radius-lg); | |||||
| } | |||||
| // stylelint-disable-next-line no-duplicate-selectors | |||||
| select.form-control { | |||||
| &[size], | |||||
| &[multiple] { | |||||
| height: auto; | |||||
| } | |||||
| } | |||||
| textarea.form-control { | |||||
| height: auto; | |||||
| } | |||||
| // Form groups | |||||
| // | |||||
| // Designed to help with the organization and spacing of vertical forms. For | |||||
| // horizontal forms, use the predefined grid classes. | |||||
| .form-group { | |||||
| margin-bottom: $form-group-margin-bottom; | |||||
| } | |||||
| .form-text { | |||||
| display: block; | |||||
| margin-top: $form-text-margin-top; | |||||
| } | |||||
| // Form grid | |||||
| // | |||||
| // Special replacement for our grid system's `.row` for tighter form layouts. | |||||
| .form-row { | |||||
| display: flex; | |||||
| flex-wrap: wrap; | |||||
| margin-right: -$form-grid-gutter-width / 2; | |||||
| margin-left: -$form-grid-gutter-width / 2; | |||||
| > .col, | |||||
| > [class*="col-"] { | |||||
| padding-right: $form-grid-gutter-width / 2; | |||||
| padding-left: $form-grid-gutter-width / 2; | |||||
| } | |||||
| } | |||||
| // Checkboxes and radios | |||||
| // | |||||
| // Indent the labels to position radios/checkboxes as hanging controls. | |||||
| .form-check { | |||||
| position: relative; | |||||
| display: block; | |||||
| padding-left: $form-check-input-gutter; | |||||
| } | |||||
| .form-check-input { | |||||
| position: absolute; | |||||
| margin-top: $form-check-input-margin-y; | |||||
| margin-left: -$form-check-input-gutter; | |||||
| // Use [disabled] and :disabled for workaround https://github.com/twbs/bootstrap/issues/28247 | |||||
| &[disabled] ~ .form-check-label, | |||||
| &:disabled ~ .form-check-label { | |||||
| color: $text-muted; | |||||
| } | |||||
| } | |||||
| .form-check-label { | |||||
| margin-bottom: 0; // Override default `<label>` bottom margin | |||||
| } | |||||
| .form-check-inline { | |||||
| display: inline-flex; | |||||
| align-items: center; | |||||
| padding-left: 0; // Override base .form-check | |||||
| margin-right: $form-check-inline-margin-x; | |||||
| // Undo .form-check-input defaults and add some `margin-right`. | |||||
| .form-check-input { | |||||
| position: static; | |||||
| margin-top: 0; | |||||
| margin-right: $form-check-inline-input-margin-x; | |||||
| margin-left: 0; | |||||
| } | |||||
| } | |||||
| // Form validation | |||||
| // | |||||
| // Provide feedback to users when form field values are valid or invalid. Works | |||||
| // primarily for client-side validation via scoped `:invalid` and `:valid` | |||||
| // pseudo-classes but also includes `.is-invalid` and `.is-valid` classes for | |||||
| // server side validation. | |||||
| @each $state, $data in $form-validation-states { | |||||
| @include form-validation-state($state, map-get($data, color), map-get($data, icon)); | |||||
| } | |||||
| // Inline forms | |||||
| // | |||||
| // Make forms appear inline(-block) by adding the `.form-inline` class. Inline | |||||
| // forms begin stacked on extra small (mobile) devices and then go inline when | |||||
| // viewports reach <768px. | |||||
| // | |||||
| // Requires wrapping inputs and labels with `.form-group` for proper display of | |||||
| // default HTML form controls and our custom form controls (e.g., input groups). | |||||
| .form-inline { | |||||
| display: flex; | |||||
| flex-flow: row wrap; | |||||
| align-items: center; // Prevent shorter elements from growing to same height as others (e.g., small buttons growing to normal sized button height) | |||||
| // Because we use flex, the initial sizing of checkboxes is collapsed and | |||||
| // doesn't occupy the full-width (which is what we want for xs grid tier), | |||||
| // so we force that here. | |||||
| .form-check { | |||||
| width: 100%; | |||||
| } | |||||
| // Kick in the inline | |||||
| @include media-breakpoint-up(sm) { | |||||
| label { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| margin-bottom: 0; | |||||
| } | |||||
| // Inline-block all the things for "inline" | |||||
| .form-group { | |||||
| display: flex; | |||||
| flex: 0 0 auto; | |||||
| flex-flow: row wrap; | |||||
| align-items: center; | |||||
| margin-bottom: 0; | |||||
| } | |||||
| // Allow folks to *not* use `.form-group` | |||||
| .form-control { | |||||
| display: inline-block; | |||||
| width: auto; // Prevent labels from stacking above inputs in `.form-group` | |||||
| vertical-align: middle; | |||||
| } | |||||
| // Make static controls behave like regular ones | |||||
| .form-control-plaintext { | |||||
| display: inline-block; | |||||
| } | |||||
| .input-group, | |||||
| .custom-select { | |||||
| width: auto; | |||||
| } | |||||
| // Remove default margin on radios/checkboxes that were used for stacking, and | |||||
| // then undo the floating of radios and checkboxes to match. | |||||
| .form-check { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| width: auto; | |||||
| padding-left: 0; | |||||
| } | |||||
| .form-check-input { | |||||
| position: relative; | |||||
| flex-shrink: 0; | |||||
| margin-top: 0; | |||||
| margin-right: $form-check-input-margin-x; | |||||
| margin-left: 0; | |||||
| } | |||||
| .custom-control { | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| } | |||||
| .custom-control-label { | |||||
| margin-bottom: 0; | |||||
| } | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,134 @@ | |||||
| // Bootstrap functions | |||||
| // | |||||
| // Utility mixins and functions for evaluating source code across our variables, maps, and mixins. | |||||
| // Ascending | |||||
| // Used to evaluate Sass maps like our grid breakpoints. | |||||
| @mixin _assert-ascending($map, $map-name) { | |||||
| $prev-key: null; | |||||
| $prev-num: null; | |||||
| @each $key, $num in $map { | |||||
| @if $prev-num == null or unit($num) == "%" or unit($prev-num) == "%" { | |||||
| // Do nothing | |||||
| } @else if not comparable($prev-num, $num) { | |||||
| @warn "Potentially invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} whose unit makes it incomparable to #{$prev-num}, the value of the previous key '#{$prev-key}' !"; | |||||
| } @else if $prev-num >= $num { | |||||
| @warn "Invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} which isn't greater than #{$prev-num}, the value of the previous key '#{$prev-key}' !"; | |||||
| } | |||||
| $prev-key: $key; | |||||
| $prev-num: $num; | |||||
| } | |||||
| } | |||||
| // Starts at zero | |||||
| // Used to ensure the min-width of the lowest breakpoint starts at 0. | |||||
| @mixin _assert-starts-at-zero($map, $map-name: "$grid-breakpoints") { | |||||
| $values: map-values($map); | |||||
| $first-value: nth($values, 1); | |||||
| @if $first-value != 0 { | |||||
| @warn "First breakpoint in #{$map-name} must start at 0, but starts at #{$first-value}."; | |||||
| } | |||||
| } | |||||
| // Replace `$search` with `$replace` in `$string` | |||||
| // Used on our SVG icon backgrounds for custom forms. | |||||
| // | |||||
| // @author Hugo Giraudel | |||||
| // @param {String} $string - Initial string | |||||
| // @param {String} $search - Substring to replace | |||||
| // @param {String} $replace ('') - New value | |||||
| // @return {String} - Updated string | |||||
| @function str-replace($string, $search, $replace: "") { | |||||
| $index: str-index($string, $search); | |||||
| @if $index { | |||||
| @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace); | |||||
| } | |||||
| @return $string; | |||||
| } | |||||
| // See https://codepen.io/kevinweber/pen/dXWoRw | |||||
| @function escape-svg($string) { | |||||
| @if str-index($string, "data:image/svg+xml") { | |||||
| @each $char, $encoded in $escaped-characters { | |||||
| $string: str-replace($string, $char, $encoded); | |||||
| } | |||||
| } | |||||
| @return $string; | |||||
| } | |||||
| // Color contrast | |||||
| @function color-yiq($color, $dark: $yiq-text-dark, $light: $yiq-text-light) { | |||||
| $r: red($color); | |||||
| $g: green($color); | |||||
| $b: blue($color); | |||||
| $yiq: (($r * 299) + ($g * 587) + ($b * 114)) / 1000; | |||||
| @if ($yiq >= $yiq-contrasted-threshold) { | |||||
| @return $dark; | |||||
| } @else { | |||||
| @return $light; | |||||
| } | |||||
| } | |||||
| // Retrieve color Sass maps | |||||
| @function color($key: "blue") { | |||||
| @return map-get($colors, $key); | |||||
| } | |||||
| @function theme-color($key: "primary") { | |||||
| @return map-get($theme-colors, $key); | |||||
| } | |||||
| @function gray($key: "100") { | |||||
| @return map-get($grays, $key); | |||||
| } | |||||
| // Request a theme color level | |||||
| @function theme-color-level($color-name: "primary", $level: 0) { | |||||
| $color: theme-color($color-name); | |||||
| $color-base: if($level > 0, $black, $white); | |||||
| $level: abs($level); | |||||
| @return mix($color-base, $color, $level * $theme-color-interval); | |||||
| } | |||||
| // Return valid calc | |||||
| @function add($value1, $value2, $return-calc: true) { | |||||
| @if $value1 == null { | |||||
| @return $value2; | |||||
| } | |||||
| @if $value2 == null { | |||||
| @return $value1; | |||||
| } | |||||
| @if type-of($value1) == number and type-of($value2) == number and comparable($value1, $value2) { | |||||
| @return $value1 + $value2; | |||||
| } | |||||
| @return if($return-calc == true, calc(#{$value1} + #{$value2}), $value1 + unquote(" + ") + $value2); | |||||
| } | |||||
| @function subtract($value1, $value2, $return-calc: true) { | |||||
| @if $value1 == null and $value2 == null { | |||||
| @return null; | |||||
| } | |||||
| @if $value1 == null { | |||||
| @return -$value2; | |||||
| } | |||||
| @if $value2 == null { | |||||
| @return $value1; | |||||
| } | |||||
| @if type-of($value1) == number and type-of($value2) == number and comparable($value1, $value2) { | |||||
| @return $value1 - $value2; | |||||
| } | |||||
| @return if($return-calc == true, calc(#{$value1} - #{$value2}), $value1 + unquote(" - ") + $value2); | |||||
| } | |||||
| @ -0,0 +1,69 @@ | |||||
| // Container widths | |||||
| // | |||||
| // Set the container width, and override it for fixed navbars in media queries. | |||||
| @if $enable-grid-classes { | |||||
| // Single container class with breakpoint max-widths | |||||
| .container { | |||||
| @include make-container(); | |||||
| @include make-container-max-widths(); | |||||
| } | |||||
| // 100% wide container at all breakpoints | |||||
| .container-fluid { | |||||
| @include make-container(); | |||||
| } | |||||
| // Responsive containers that are 100% wide until a breakpoint | |||||
| @each $breakpoint, $container-max-width in $container-max-widths { | |||||
| .container-#{$breakpoint} { | |||||
| @extend .container-fluid; | |||||
| } | |||||
| @include media-breakpoint-up($breakpoint, $grid-breakpoints) { | |||||
| %responsive-container-#{$breakpoint} { | |||||
| max-width: $container-max-width; | |||||
| } | |||||
| @each $name, $width in $grid-breakpoints { | |||||
| @if ($container-max-width > $width or $breakpoint == $name) { | |||||
| .container#{breakpoint-infix($name, $grid-breakpoints)} { | |||||
| @extend %responsive-container-#{$breakpoint}; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| // Row | |||||
| // | |||||
| // Rows contain your columns. | |||||
| @if $enable-grid-classes { | |||||
| .row { | |||||
| @include make-row(); | |||||
| } | |||||
| // Remove the negative margin from default .row, then the horizontal padding | |||||
| // from all immediate children columns (to prevent runaway style inheritance). | |||||
| .no-gutters { | |||||
| margin-right: 0; | |||||
| margin-left: 0; | |||||
| > .col, | |||||
| > [class*="col-"] { | |||||
| padding-right: 0; | |||||
| padding-left: 0; | |||||
| } | |||||
| } | |||||
| } | |||||
| // Columns | |||||
| // | |||||
| // Common styles for small and large grid columns | |||||
| @if $enable-grid-classes { | |||||
| @include make-grid-columns(); | |||||
| } | |||||
| @ -0,0 +1,42 @@ | |||||
| // Responsive images (ensure images don't scale beyond their parents) | |||||
| // | |||||
| // This is purposefully opt-in via an explicit class rather than being the default for all `<img>`s. | |||||
| // We previously tried the "images are responsive by default" approach in Bootstrap v2, | |||||
| // and abandoned it in Bootstrap v3 because it breaks lots of third-party widgets (including Google Maps) | |||||
| // which weren't expecting the images within themselves to be involuntarily resized. | |||||
| // See also https://github.com/twbs/bootstrap/issues/18178 | |||||
| .img-fluid { | |||||
| @include img-fluid(); | |||||
| } | |||||
| // Image thumbnails | |||||
| .img-thumbnail { | |||||
| padding: $thumbnail-padding; | |||||
| background-color: $thumbnail-bg; | |||||
| border: $thumbnail-border-width solid $thumbnail-border-color; | |||||
| @include border-radius($thumbnail-border-radius); | |||||
| @include box-shadow($thumbnail-box-shadow); | |||||
| // Keep them at most 100% wide | |||||
| @include img-fluid(); | |||||
| } | |||||
| // | |||||
| // Figures | |||||
| // | |||||
| .figure { | |||||
| // Ensures the caption's text aligns with the image. | |||||
| display: inline-block; | |||||
| } | |||||
| .figure-img { | |||||
| margin-bottom: $spacer / 2; | |||||
| line-height: 1; | |||||
| } | |||||
| .figure-caption { | |||||
| @include font-size($figure-caption-font-size); | |||||
| color: $figure-caption-color; | |||||
| } | |||||
| @ -0,0 +1,191 @@ | |||||
| // stylelint-disable selector-no-qualifying-type | |||||
| // | |||||
| // Base styles | |||||
| // | |||||
| .input-group { | |||||
| position: relative; | |||||
| display: flex; | |||||
| flex-wrap: wrap; // For form validation feedback | |||||
| align-items: stretch; | |||||
| width: 100%; | |||||
| > .form-control, | |||||
| > .form-control-plaintext, | |||||
| > .custom-select, | |||||
| > .custom-file { | |||||
| position: relative; // For focus state's z-index | |||||
| flex: 1 1 0%; | |||||
| min-width: 0; // https://stackoverflow.com/questions/36247140/why-dont-flex-items-shrink-past-content-size | |||||
| margin-bottom: 0; | |||||
| + .form-control, | |||||
| + .custom-select, | |||||
| + .custom-file { | |||||
| margin-left: -$input-border-width; | |||||
| } | |||||
| } | |||||
| // Bring the "active" form control to the top of surrounding elements | |||||
| > .form-control:focus, | |||||
| > .custom-select:focus, | |||||
| > .custom-file .custom-file-input:focus ~ .custom-file-label { | |||||
| z-index: 3; | |||||
| } | |||||
| // Bring the custom file input above the label | |||||
| > .custom-file .custom-file-input:focus { | |||||
| z-index: 4; | |||||
| } | |||||
| > .form-control, | |||||
| > .custom-select { | |||||
| &:not(:last-child) { @include border-right-radius(0); } | |||||
| &:not(:first-child) { @include border-left-radius(0); } | |||||
| } | |||||
| // Custom file inputs have more complex markup, thus requiring different | |||||
| // border-radius overrides. | |||||
| > .custom-file { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| &:not(:last-child) .custom-file-label, | |||||
| &:not(:last-child) .custom-file-label::after { @include border-right-radius(0); } | |||||
| &:not(:first-child) .custom-file-label { @include border-left-radius(0); } | |||||
| } | |||||
| } | |||||
| // Prepend and append | |||||
| // | |||||
| // While it requires one extra layer of HTML for each, dedicated prepend and | |||||
| // append elements allow us to 1) be less clever, 2) simplify our selectors, and | |||||
| // 3) support HTML5 form validation. | |||||
| .input-group-prepend, | |||||
| .input-group-append { | |||||
| display: flex; | |||||
| // Ensure buttons are always above inputs for more visually pleasing borders. | |||||
| // This isn't needed for `.input-group-text` since it shares the same border-color | |||||
| // as our inputs. | |||||
| .btn { | |||||
| position: relative; | |||||
| z-index: 2; | |||||
| &:focus { | |||||
| z-index: 3; | |||||
| } | |||||
| } | |||||
| .btn + .btn, | |||||
| .btn + .input-group-text, | |||||
| .input-group-text + .input-group-text, | |||||
| .input-group-text + .btn { | |||||
| margin-left: -$input-border-width; | |||||
| } | |||||
| } | |||||
| .input-group-prepend { margin-right: -$input-border-width; } | |||||
| .input-group-append { margin-left: -$input-border-width; } | |||||
| // Textual addons | |||||
| // | |||||
| // Serves as a catch-all element for any text or radio/checkbox input you wish | |||||
| // to prepend or append to an input. | |||||
| .input-group-text { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| padding: $input-padding-y $input-padding-x; | |||||
| margin-bottom: 0; // Allow use of <label> elements by overriding our default margin-bottom | |||||
| @include font-size($input-font-size); // Match inputs | |||||
| font-weight: $font-weight-normal; | |||||
| line-height: $input-line-height; | |||||
| color: $input-group-addon-color; | |||||
| text-align: center; | |||||
| white-space: nowrap; | |||||
| background-color: $input-group-addon-bg; | |||||
| border: $input-border-width solid $input-group-addon-border-color; | |||||
| @include border-radius($input-border-radius); | |||||
| // Nuke default margins from checkboxes and radios to vertically center within. | |||||
| input[type="radio"], | |||||
| input[type="checkbox"] { | |||||
| margin-top: 0; | |||||
| } | |||||
| } | |||||
| // Sizing | |||||
| // | |||||
| // Remix the default form control sizing classes into new ones for easier | |||||
| // manipulation. | |||||
| .input-group-lg > .form-control:not(textarea), | |||||
| .input-group-lg > .custom-select { | |||||
| height: $input-height-lg; | |||||
| } | |||||
| .input-group-lg > .form-control, | |||||
| .input-group-lg > .custom-select, | |||||
| .input-group-lg > .input-group-prepend > .input-group-text, | |||||
| .input-group-lg > .input-group-append > .input-group-text, | |||||
| .input-group-lg > .input-group-prepend > .btn, | |||||
| .input-group-lg > .input-group-append > .btn { | |||||
| padding: $input-padding-y-lg $input-padding-x-lg; | |||||
| @include font-size($input-font-size-lg); | |||||
| line-height: $input-line-height-lg; | |||||
| @include border-radius($input-border-radius-lg); | |||||
| } | |||||
| .input-group-sm > .form-control:not(textarea), | |||||
| .input-group-sm > .custom-select { | |||||
| height: $input-height-sm; | |||||
| } | |||||
| .input-group-sm > .form-control, | |||||
| .input-group-sm > .custom-select, | |||||
| .input-group-sm > .input-group-prepend > .input-group-text, | |||||
| .input-group-sm > .input-group-append > .input-group-text, | |||||
| .input-group-sm > .input-group-prepend > .btn, | |||||
| .input-group-sm > .input-group-append > .btn { | |||||
| padding: $input-padding-y-sm $input-padding-x-sm; | |||||
| @include font-size($input-font-size-sm); | |||||
| line-height: $input-line-height-sm; | |||||
| @include border-radius($input-border-radius-sm); | |||||
| } | |||||
| .input-group-lg > .custom-select, | |||||
| .input-group-sm > .custom-select { | |||||
| padding-right: $custom-select-padding-x + $custom-select-indicator-padding; | |||||
| } | |||||
| // Prepend and append rounded corners | |||||
| // | |||||
| // These rulesets must come after the sizing ones to properly override sm and lg | |||||
| // border-radius values when extending. They're more specific than we'd like | |||||
| // with the `.input-group >` part, but without it, we cannot override the sizing. | |||||
| .input-group > .input-group-prepend > .btn, | |||||
| .input-group > .input-group-prepend > .input-group-text, | |||||
| .input-group > .input-group-append:not(:last-child) > .btn, | |||||
| .input-group > .input-group-append:not(:last-child) > .input-group-text, | |||||
| .input-group > .input-group-append:last-child > .btn:not(:last-child):not(.dropdown-toggle), | |||||
| .input-group > .input-group-append:last-child > .input-group-text:not(:last-child) { | |||||
| @include border-right-radius(0); | |||||
| } | |||||
| .input-group > .input-group-append > .btn, | |||||
| .input-group > .input-group-append > .input-group-text, | |||||
| .input-group > .input-group-prepend:not(:first-child) > .btn, | |||||
| .input-group > .input-group-prepend:not(:first-child) > .input-group-text, | |||||
| .input-group > .input-group-prepend:first-child > .btn:not(:first-child), | |||||
| .input-group > .input-group-prepend:first-child > .input-group-text:not(:first-child) { | |||||
| @include border-left-radius(0); | |||||
| } | |||||
| @ -0,0 +1,17 @@ | |||||
| .jumbotron { | |||||
| padding: $jumbotron-padding ($jumbotron-padding / 2); | |||||
| margin-bottom: $jumbotron-padding; | |||||
| color: $jumbotron-color; | |||||
| background-color: $jumbotron-bg; | |||||
| @include border-radius($border-radius-lg); | |||||
| @include media-breakpoint-up(sm) { | |||||
| padding: ($jumbotron-padding * 2) $jumbotron-padding; | |||||
| } | |||||
| } | |||||
| .jumbotron-fluid { | |||||
| padding-right: 0; | |||||
| padding-left: 0; | |||||
| @include border-radius(0); | |||||
| } | |||||
| @ -0,0 +1,158 @@ | |||||
| // Base class | |||||
| // | |||||
| // Easily usable on <ul>, <ol>, or <div>. | |||||
| .list-group { | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| // No need to set list-style: none; since .list-group-item is block level | |||||
| padding-left: 0; // reset padding because ul and ol | |||||
| margin-bottom: 0; | |||||
| } | |||||
| // Interactive list items | |||||
| // | |||||
| // Use anchor or button elements instead of `li`s or `div`s to create interactive | |||||
| // list items. Includes an extra `.active` modifier class for selected items. | |||||
| .list-group-item-action { | |||||
| width: 100%; // For `<button>`s (anchors become 100% by default though) | |||||
| color: $list-group-action-color; | |||||
| text-align: inherit; // For `<button>`s (anchors inherit) | |||||
| // Hover state | |||||
| @include hover-focus() { | |||||
| z-index: 1; // Place hover/focus items above their siblings for proper border styling | |||||
| color: $list-group-action-hover-color; | |||||
| text-decoration: none; | |||||
| background-color: $list-group-hover-bg; | |||||
| } | |||||
| &:active { | |||||
| color: $list-group-action-active-color; | |||||
| background-color: $list-group-action-active-bg; | |||||
| } | |||||
| } | |||||
| // Individual list items | |||||
| // | |||||
| // Use on `li`s or `div`s within the `.list-group` parent. | |||||
| .list-group-item { | |||||
| position: relative; | |||||
| display: block; | |||||
| padding: $list-group-item-padding-y $list-group-item-padding-x; | |||||
| color: $list-group-color; | |||||
| background-color: $list-group-bg; | |||||
| border: $list-group-border-width solid $list-group-border-color; | |||||
| &:first-child { | |||||
| @include border-top-radius($list-group-border-radius); | |||||
| } | |||||
| &:last-child { | |||||
| @include border-bottom-radius($list-group-border-radius); | |||||
| } | |||||
| &.disabled, | |||||
| &:disabled { | |||||
| color: $list-group-disabled-color; | |||||
| pointer-events: none; | |||||
| background-color: $list-group-disabled-bg; | |||||
| } | |||||
| // Include both here for `<a>`s and `<button>`s | |||||
| &.active { | |||||
| z-index: 2; // Place active items above their siblings for proper border styling | |||||
| color: $list-group-active-color; | |||||
| background-color: $list-group-active-bg; | |||||
| border-color: $list-group-active-border-color; | |||||
| } | |||||
| & + & { | |||||
| border-top-width: 0; | |||||
| &.active { | |||||
| margin-top: -$list-group-border-width; | |||||
| border-top-width: $list-group-border-width; | |||||
| } | |||||
| } | |||||
| } | |||||
| // Horizontal | |||||
| // | |||||
| // Change the layout of list group items from vertical (default) to horizontal. | |||||
| @each $breakpoint in map-keys($grid-breakpoints) { | |||||
| @include media-breakpoint-up($breakpoint) { | |||||
| $infix: breakpoint-infix($breakpoint, $grid-breakpoints); | |||||
| .list-group-horizontal#{$infix} { | |||||
| flex-direction: row; | |||||
| .list-group-item { | |||||
| &:first-child { | |||||
| @include border-bottom-left-radius($list-group-border-radius); | |||||
| @include border-top-right-radius(0); | |||||
| } | |||||
| &:last-child { | |||||
| @include border-top-right-radius($list-group-border-radius); | |||||
| @include border-bottom-left-radius(0); | |||||
| } | |||||
| &.active { | |||||
| margin-top: 0; | |||||
| } | |||||
| & + .list-group-item { | |||||
| border-top-width: $list-group-border-width; | |||||
| border-left-width: 0; | |||||
| &.active { | |||||
| margin-left: -$list-group-border-width; | |||||
| border-left-width: $list-group-border-width; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| // Flush list items | |||||
| // | |||||
| // Remove borders and border-radius to keep list group items edge-to-edge. Most | |||||
| // useful within other components (e.g., cards). | |||||
| .list-group-flush { | |||||
| .list-group-item { | |||||
| border-right-width: 0; | |||||
| border-left-width: 0; | |||||
| @include border-radius(0); | |||||
| &:first-child { | |||||
| border-top-width: 0; | |||||
| } | |||||
| } | |||||
| &:last-child { | |||||
| .list-group-item:last-child { | |||||
| border-bottom-width: 0; | |||||
| } | |||||
| } | |||||
| } | |||||
| // Contextual variants | |||||
| // | |||||
| // Add modifier classes to change text and background color on individual items. | |||||
| // Organizationally, this must come after the `:hover` states. | |||||
| @each $color, $value in $theme-colors { | |||||
| @include list-group-item-variant($color, theme-color-level($color, -9), theme-color-level($color, 6)); | |||||
| } | |||||
| @ -0,0 +1,8 @@ | |||||
| .media { | |||||
| display: flex; | |||||
| align-items: flex-start; | |||||
| } | |||||
| .media-body { | |||||
| flex: 1; | |||||
| } | |||||
| @ -0,0 +1,47 @@ | |||||
| // Toggles | |||||
| // | |||||
| // Used in conjunction with global variables to enable certain theme features. | |||||
| // Vendor | |||||
| @import "vendor/rfs"; | |||||
| // Deprecate | |||||
| @import "mixins/deprecate"; | |||||
| // Utilities | |||||
| @import "mixins/breakpoints"; | |||||
| @import "mixins/hover"; | |||||
| @import "mixins/image"; | |||||
| @import "mixins/badge"; | |||||
| @import "mixins/resize"; | |||||
| @import "mixins/screen-reader"; | |||||
| @import "mixins/size"; | |||||
| @import "mixins/reset-text"; | |||||
| @import "mixins/text-emphasis"; | |||||
| @import "mixins/text-hide"; | |||||
| @import "mixins/text-truncate"; | |||||
| @import "mixins/visibility"; | |||||
| // Components | |||||
| @import "mixins/alert"; | |||||
| @import "mixins/buttons"; | |||||
| @import "mixins/caret"; | |||||
| @import "mixins/pagination"; | |||||
| @import "mixins/lists"; | |||||
| @import "mixins/list-group"; | |||||
| @import "mixins/nav-divider"; | |||||
| @import "mixins/forms"; | |||||
| @import "mixins/table-row"; | |||||
| // Skins | |||||
| @import "mixins/background-variant"; | |||||
| @import "mixins/border-radius"; | |||||
| @import "mixins/box-shadow"; | |||||
| @import "mixins/gradients"; | |||||
| @import "mixins/transition"; | |||||
| // Layout | |||||
| @import "mixins/clearfix"; | |||||
| @import "mixins/grid-framework"; | |||||
| @import "mixins/grid"; | |||||
| @import "mixins/float"; | |||||
| @ -0,0 +1,239 @@ | |||||
| // .modal-open - body class for killing the scroll | |||||
| // .modal - container to scroll within | |||||
| // .modal-dialog - positioning shell for the actual modal | |||||
| // .modal-content - actual modal w/ bg and corners and stuff | |||||
| .modal-open { | |||||
| // Kill the scroll on the body | |||||
| overflow: hidden; | |||||
| .modal { | |||||
| overflow-x: hidden; | |||||
| overflow-y: auto; | |||||
| } | |||||
| } | |||||
| // Container that the modal scrolls within | |||||
| .modal { | |||||
| position: fixed; | |||||
| top: 0; | |||||
| left: 0; | |||||
| z-index: $zindex-modal; | |||||
| display: none; | |||||
| width: 100%; | |||||
| height: 100%; | |||||
| overflow: hidden; | |||||
| // Prevent Chrome on Windows from adding a focus outline. For details, see | |||||
| // https://github.com/twbs/bootstrap/pull/10951. | |||||
| outline: 0; | |||||
| // We deliberately don't use `-webkit-overflow-scrolling: touch;` due to a | |||||
| // gnarly iOS Safari bug: https://bugs.webkit.org/show_bug.cgi?id=158342 | |||||
| // See also https://github.com/twbs/bootstrap/issues/17695 | |||||
| } | |||||
| // Shell div to position the modal with bottom padding | |||||
| .modal-dialog { | |||||
| position: relative; | |||||
| width: auto; | |||||
| margin: $modal-dialog-margin; | |||||
| // allow clicks to pass through for custom click handling to close modal | |||||
| pointer-events: none; | |||||
| // When fading in the modal, animate it to slide down | |||||
| .modal.fade & { | |||||
| @include transition($modal-transition); | |||||
| transform: $modal-fade-transform; | |||||
| } | |||||
| .modal.show & { | |||||
| transform: $modal-show-transform; | |||||
| } | |||||
| // When trying to close, animate focus to scale | |||||
| .modal.modal-static & { | |||||
| transform: $modal-scale-transform; | |||||
| } | |||||
| } | |||||
| .modal-dialog-scrollable { | |||||
| display: flex; // IE10/11 | |||||
| max-height: subtract(100%, $modal-dialog-margin * 2); | |||||
| .modal-content { | |||||
| max-height: subtract(100vh, $modal-dialog-margin * 2); // IE10/11 | |||||
| overflow: hidden; | |||||
| } | |||||
| .modal-header, | |||||
| .modal-footer { | |||||
| flex-shrink: 0; | |||||
| } | |||||
| .modal-body { | |||||
| overflow-y: auto; | |||||
| } | |||||
| } | |||||
| .modal-dialog-centered { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| min-height: subtract(100%, $modal-dialog-margin * 2); | |||||
| // Ensure `modal-dialog-centered` extends the full height of the view (IE10/11) | |||||
| &::before { | |||||
| display: block; // IE10 | |||||
| height: subtract(100vh, $modal-dialog-margin * 2); | |||||
| content: ""; | |||||
| } | |||||
| // Ensure `.modal-body` shows scrollbar (IE10/11) | |||||
| &.modal-dialog-scrollable { | |||||
| flex-direction: column; | |||||
| justify-content: center; | |||||
| height: 100%; | |||||
| .modal-content { | |||||
| max-height: none; | |||||
| } | |||||
| &::before { | |||||
| content: none; | |||||
| } | |||||
| } | |||||
| } | |||||
| // Actual modal | |||||
| .modal-content { | |||||
| position: relative; | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| width: 100%; // Ensure `.modal-content` extends the full width of the parent `.modal-dialog` | |||||
| // counteract the pointer-events: none; in the .modal-dialog | |||||
| color: $modal-content-color; | |||||
| pointer-events: auto; | |||||
| background-color: $modal-content-bg; | |||||
| background-clip: padding-box; | |||||
| border: $modal-content-border-width solid $modal-content-border-color; | |||||
| @include border-radius($modal-content-border-radius); | |||||
| @include box-shadow($modal-content-box-shadow-xs); | |||||
| // Remove focus outline from opened modal | |||||
| outline: 0; | |||||
| } | |||||
| // Modal background | |||||
| .modal-backdrop { | |||||
| position: fixed; | |||||
| top: 0; | |||||
| left: 0; | |||||
| z-index: $zindex-modal-backdrop; | |||||
| width: 100vw; | |||||
| height: 100vh; | |||||
| background-color: $modal-backdrop-bg; | |||||
| // Fade for backdrop | |||||
| &.fade { opacity: 0; } | |||||
| &.show { opacity: $modal-backdrop-opacity; } | |||||
| } | |||||
| // Modal header | |||||
| // Top section of the modal w/ title and dismiss | |||||
| .modal-header { | |||||
| display: flex; | |||||
| align-items: flex-start; // so the close btn always stays on the upper right corner | |||||
| justify-content: space-between; // Put modal header elements (title and dismiss) on opposite ends | |||||
| padding: $modal-header-padding; | |||||
| border-bottom: $modal-header-border-width solid $modal-header-border-color; | |||||
| @include border-top-radius($modal-content-inner-border-radius); | |||||
| .close { | |||||
| padding: $modal-header-padding; | |||||
| // auto on the left force icon to the right even when there is no .modal-title | |||||
| margin: (-$modal-header-padding-y) (-$modal-header-padding-x) (-$modal-header-padding-y) auto; | |||||
| } | |||||
| } | |||||
| // Title text within header | |||||
| .modal-title { | |||||
| margin-bottom: 0; | |||||
| line-height: $modal-title-line-height; | |||||
| } | |||||
| // Modal body | |||||
| // Where all modal content resides (sibling of .modal-header and .modal-footer) | |||||
| .modal-body { | |||||
| position: relative; | |||||
| // Enable `flex-grow: 1` so that the body take up as much space as possible | |||||
| // when there should be a fixed height on `.modal-dialog`. | |||||
| flex: 1 1 auto; | |||||
| padding: $modal-inner-padding; | |||||
| } | |||||
| // Footer (for actions) | |||||
| .modal-footer { | |||||
| display: flex; | |||||
| flex-wrap: wrap; | |||||
| align-items: center; // vertically center | |||||
| justify-content: flex-end; // Right align buttons with flex property because text-align doesn't work on flex items | |||||
| padding: $modal-inner-padding - $modal-footer-margin-between / 2; | |||||
| border-top: $modal-footer-border-width solid $modal-footer-border-color; | |||||
| @include border-bottom-radius($modal-content-inner-border-radius); | |||||
| // Place margin between footer elements | |||||
| // This solution is far from ideal because of the universal selector usage, | |||||
| // but is needed to fix https://github.com/twbs/bootstrap/issues/24800 | |||||
| // stylelint-disable-next-line selector-max-universal | |||||
| > * { | |||||
| margin: $modal-footer-margin-between / 2; | |||||
| } | |||||
| } | |||||
| // Measure scrollbar width for padding body during modal show/hide | |||||
| .modal-scrollbar-measure { | |||||
| position: absolute; | |||||
| top: -9999px; | |||||
| width: 50px; | |||||
| height: 50px; | |||||
| overflow: scroll; | |||||
| } | |||||
| // Scale up the modal | |||||
| @include media-breakpoint-up(sm) { | |||||
| // Automatically set modal's width for larger viewports | |||||
| .modal-dialog { | |||||
| max-width: $modal-md; | |||||
| margin: $modal-dialog-margin-y-sm-up auto; | |||||
| } | |||||
| .modal-dialog-scrollable { | |||||
| max-height: subtract(100%, $modal-dialog-margin-y-sm-up * 2); | |||||
| .modal-content { | |||||
| max-height: subtract(100vh, $modal-dialog-margin-y-sm-up * 2); | |||||
| } | |||||
| } | |||||
| .modal-dialog-centered { | |||||
| min-height: subtract(100%, $modal-dialog-margin-y-sm-up * 2); | |||||
| &::before { | |||||
| height: subtract(100vh, $modal-dialog-margin-y-sm-up * 2); | |||||
| } | |||||
| } | |||||
| .modal-content { | |||||
| @include box-shadow($modal-content-box-shadow-sm-up); | |||||
| } | |||||
| .modal-sm { max-width: $modal-sm; } | |||||
| } | |||||
| @include media-breakpoint-up(lg) { | |||||
| .modal-lg, | |||||
| .modal-xl { | |||||
| max-width: $modal-lg; | |||||
| } | |||||
| } | |||||
| @include media-breakpoint-up(xl) { | |||||
| .modal-xl { max-width: $modal-xl; } | |||||
| } | |||||
| @ -0,0 +1,120 @@ | |||||
| // Base class | |||||
| // | |||||
| // Kickstart any navigation component with a set of style resets. Works with | |||||
| // `<nav>`s, `<ul>`s or `<ol>`s. | |||||
| .nav { | |||||
| display: flex; | |||||
| flex-wrap: wrap; | |||||
| padding-left: 0; | |||||
| margin-bottom: 0; | |||||
| list-style: none; | |||||
| } | |||||
| .nav-link { | |||||
| display: block; | |||||
| padding: $nav-link-padding-y $nav-link-padding-x; | |||||
| @include hover-focus() { | |||||
| text-decoration: none; | |||||
| } | |||||
| // Disabled state lightens text | |||||
| &.disabled { | |||||
| color: $nav-link-disabled-color; | |||||
| pointer-events: none; | |||||
| cursor: default; | |||||
| } | |||||
| } | |||||
| // | |||||
| // Tabs | |||||
| // | |||||
| .nav-tabs { | |||||
| border-bottom: $nav-tabs-border-width solid $nav-tabs-border-color; | |||||
| .nav-item { | |||||
| margin-bottom: -$nav-tabs-border-width; | |||||
| } | |||||
| .nav-link { | |||||
| border: $nav-tabs-border-width solid transparent; | |||||
| @include border-top-radius($nav-tabs-border-radius); | |||||
| @include hover-focus() { | |||||
| border-color: $nav-tabs-link-hover-border-color; | |||||
| } | |||||
| &.disabled { | |||||
| color: $nav-link-disabled-color; | |||||
| background-color: transparent; | |||||
| border-color: transparent; | |||||
| } | |||||
| } | |||||
| .nav-link.active, | |||||
| .nav-item.show .nav-link { | |||||
| color: $nav-tabs-link-active-color; | |||||
| background-color: $nav-tabs-link-active-bg; | |||||
| border-color: $nav-tabs-link-active-border-color; | |||||
| } | |||||
| .dropdown-menu { | |||||
| // Make dropdown border overlap tab border | |||||
| margin-top: -$nav-tabs-border-width; | |||||
| // Remove the top rounded corners here since there is a hard edge above the menu | |||||
| @include border-top-radius(0); | |||||
| } | |||||
| } | |||||
| // | |||||
| // Pills | |||||
| // | |||||
| .nav-pills { | |||||
| .nav-link { | |||||
| @include border-radius($nav-pills-border-radius); | |||||
| } | |||||
| .nav-link.active, | |||||
| .show > .nav-link { | |||||
| color: $nav-pills-link-active-color; | |||||
| background-color: $nav-pills-link-active-bg; | |||||
| } | |||||
| } | |||||
| // | |||||
| // Justified variants | |||||
| // | |||||
| .nav-fill { | |||||
| .nav-item { | |||||
| flex: 1 1 auto; | |||||
| text-align: center; | |||||
| } | |||||
| } | |||||
| .nav-justified { | |||||
| .nav-item { | |||||
| flex-basis: 0; | |||||
| flex-grow: 1; | |||||
| text-align: center; | |||||
| } | |||||
| } | |||||
| // Tabbable tabs | |||||
| // | |||||
| // Hide tabbable panes to start, show them when `.active` | |||||
| .tab-content { | |||||
| > .tab-pane { | |||||
| display: none; | |||||
| } | |||||
| > .active { | |||||
| display: block; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,324 @@ | |||||
| // Contents | |||||
| // | |||||
| // Navbar | |||||
| // Navbar brand | |||||
| // Navbar nav | |||||
| // Navbar text | |||||
| // Navbar divider | |||||
| // Responsive navbar | |||||
| // Navbar position | |||||
| // Navbar themes | |||||
| // Navbar | |||||
| // | |||||
| // Provide a static navbar from which we expand to create full-width, fixed, and | |||||
| // other navbar variations. | |||||
| .navbar { | |||||
| position: relative; | |||||
| display: flex; | |||||
| flex-wrap: wrap; // allow us to do the line break for collapsing content | |||||
| align-items: center; | |||||
| justify-content: space-between; // space out brand from logo | |||||
| padding: $navbar-padding-y $navbar-padding-x; | |||||
| // Because flex properties aren't inherited, we need to redeclare these first | |||||
| // few properties so that content nested within behave properly. | |||||
| %container-flex-properties { | |||||
| display: flex; | |||||
| flex-wrap: wrap; | |||||
| align-items: center; | |||||
| justify-content: space-between; | |||||
| } | |||||
| .container, | |||||
| .container-fluid { | |||||
| @extend %container-flex-properties; | |||||
| } | |||||
| @each $breakpoint, $container-max-width in $container-max-widths { | |||||
| > .container#{breakpoint-infix($breakpoint, $container-max-widths)} { | |||||
| @extend %container-flex-properties; | |||||
| } | |||||
| } | |||||
| } | |||||
| // Navbar brand | |||||
| // | |||||
| // Used for brand, project, or site names. | |||||
| .navbar-brand { | |||||
| display: inline-block; | |||||
| padding-top: $navbar-brand-padding-y; | |||||
| padding-bottom: $navbar-brand-padding-y; | |||||
| margin-right: $navbar-padding-x; | |||||
| @include font-size($navbar-brand-font-size); | |||||
| line-height: inherit; | |||||
| white-space: nowrap; | |||||
| @include hover-focus() { | |||||
| text-decoration: none; | |||||
| } | |||||
| } | |||||
| // Navbar nav | |||||
| // | |||||
| // Custom navbar navigation (doesn't require `.nav`, but does make use of `.nav-link`). | |||||
| .navbar-nav { | |||||
| display: flex; | |||||
| flex-direction: column; // cannot use `inherit` to get the `.navbar`s value | |||||
| padding-left: 0; | |||||
| margin-bottom: 0; | |||||
| list-style: none; | |||||
| .nav-link { | |||||
| padding-right: 0; | |||||
| padding-left: 0; | |||||
| } | |||||
| .dropdown-menu { | |||||
| position: static; | |||||
| float: none; | |||||
| } | |||||
| } | |||||
| // Navbar text | |||||
| // | |||||
| // | |||||
| .navbar-text { | |||||
| display: inline-block; | |||||
| padding-top: $nav-link-padding-y; | |||||
| padding-bottom: $nav-link-padding-y; | |||||
| } | |||||
| // Responsive navbar | |||||
| // | |||||
| // Custom styles for responsive collapsing and toggling of navbar contents. | |||||
| // Powered by the collapse Bootstrap JavaScript plugin. | |||||
| // When collapsed, prevent the toggleable navbar contents from appearing in | |||||
| // the default flexbox row orientation. Requires the use of `flex-wrap: wrap` | |||||
| // on the `.navbar` parent. | |||||
| .navbar-collapse { | |||||
| flex-basis: 100%; | |||||
| flex-grow: 1; | |||||
| // For always expanded or extra full navbars, ensure content aligns itself | |||||
| // properly vertically. Can be easily overridden with flex utilities. | |||||
| align-items: center; | |||||
| } | |||||
| // Button for toggling the navbar when in its collapsed state | |||||
| .navbar-toggler { | |||||
| padding: $navbar-toggler-padding-y $navbar-toggler-padding-x; | |||||
| @include font-size($navbar-toggler-font-size); | |||||
| line-height: 1; | |||||
| background-color: transparent; // remove default button style | |||||
| border: $border-width solid transparent; // remove default button style | |||||
| @include border-radius($navbar-toggler-border-radius); | |||||
| @include hover-focus() { | |||||
| text-decoration: none; | |||||
| } | |||||
| } | |||||
| // Keep as a separate element so folks can easily override it with another icon | |||||
| // or image file as needed. | |||||
| .navbar-toggler-icon { | |||||
| display: inline-block; | |||||
| width: 1.5em; | |||||
| height: 1.5em; | |||||
| vertical-align: middle; | |||||
| content: ""; | |||||
| background: no-repeat center center; | |||||
| background-size: 100% 100%; | |||||
| } | |||||
| // Generate series of `.navbar-expand-*` responsive classes for configuring | |||||
| // where your navbar collapses. | |||||
| .navbar-expand { | |||||
| @each $breakpoint in map-keys($grid-breakpoints) { | |||||
| $next: breakpoint-next($breakpoint, $grid-breakpoints); | |||||
| $infix: breakpoint-infix($next, $grid-breakpoints); | |||||
| &#{$infix} { | |||||
| @include media-breakpoint-down($breakpoint) { | |||||
| %container-navbar-expand-#{$breakpoint} { | |||||
| padding-right: 0; | |||||
| padding-left: 0; | |||||
| } | |||||
| > .container, | |||||
| > .container-fluid { | |||||
| @extend %container-navbar-expand-#{$breakpoint}; | |||||
| } | |||||
| @each $size, $container-max-width in $container-max-widths { | |||||
| > .container#{breakpoint-infix($size, $container-max-widths)} { | |||||
| @extend %container-navbar-expand-#{$breakpoint}; | |||||
| } | |||||
| } | |||||
| } | |||||
| @include media-breakpoint-up($next) { | |||||
| flex-flow: row nowrap; | |||||
| justify-content: flex-start; | |||||
| .navbar-nav { | |||||
| flex-direction: row; | |||||
| .dropdown-menu { | |||||
| position: absolute; | |||||
| } | |||||
| .nav-link { | |||||
| padding-right: $navbar-nav-link-padding-x; | |||||
| padding-left: $navbar-nav-link-padding-x; | |||||
| } | |||||
| } | |||||
| // For nesting containers, have to redeclare for alignment purposes | |||||
| %container-nesting-#{$breakpoint} { | |||||
| flex-wrap: nowrap; | |||||
| } | |||||
| > .container, | |||||
| > .container-fluid { | |||||
| @extend %container-nesting-#{$breakpoint}; | |||||
| } | |||||
| @each $size, $container-max-width in $container-max-widths { | |||||
| > .container#{breakpoint-infix($size, $container-max-widths)} { | |||||
| @extend %container-nesting-#{$breakpoint}; | |||||
| } | |||||
| } | |||||
| .navbar-collapse { | |||||
| display: flex !important; // stylelint-disable-line declaration-no-important | |||||
| // Changes flex-bases to auto because of an IE10 bug | |||||
| flex-basis: auto; | |||||
| } | |||||
| .navbar-toggler { | |||||
| display: none; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| // Navbar themes | |||||
| // | |||||
| // Styles for switching between navbars with light or dark background. | |||||
| // Dark links against a light background | |||||
| .navbar-light { | |||||
| .navbar-brand { | |||||
| color: $navbar-light-brand-color; | |||||
| @include hover-focus() { | |||||
| color: $navbar-light-brand-hover-color; | |||||
| } | |||||
| } | |||||
| .navbar-nav { | |||||
| .nav-link { | |||||
| color: $navbar-light-color; | |||||
| @include hover-focus() { | |||||
| color: $navbar-light-hover-color; | |||||
| } | |||||
| &.disabled { | |||||
| color: $navbar-light-disabled-color; | |||||
| } | |||||
| } | |||||
| .show > .nav-link, | |||||
| .active > .nav-link, | |||||
| .nav-link.show, | |||||
| .nav-link.active { | |||||
| color: $navbar-light-active-color; | |||||
| } | |||||
| } | |||||
| .navbar-toggler { | |||||
| color: $navbar-light-color; | |||||
| border-color: $navbar-light-toggler-border-color; | |||||
| } | |||||
| .navbar-toggler-icon { | |||||
| background-image: escape-svg($navbar-light-toggler-icon-bg); | |||||
| } | |||||
| .navbar-text { | |||||
| color: $navbar-light-color; | |||||
| a { | |||||
| color: $navbar-light-active-color; | |||||
| @include hover-focus() { | |||||
| color: $navbar-light-active-color; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| // White links against a dark background | |||||
| .navbar-dark { | |||||
| .navbar-brand { | |||||
| color: $navbar-dark-brand-color; | |||||
| @include hover-focus() { | |||||
| color: $navbar-dark-brand-hover-color; | |||||
| } | |||||
| } | |||||
| .navbar-nav { | |||||
| .nav-link { | |||||
| color: $navbar-dark-color; | |||||
| @include hover-focus() { | |||||
| color: $navbar-dark-hover-color; | |||||
| } | |||||
| &.disabled { | |||||
| color: $navbar-dark-disabled-color; | |||||
| } | |||||
| } | |||||
| .show > .nav-link, | |||||
| .active > .nav-link, | |||||
| .nav-link.show, | |||||
| .nav-link.active { | |||||
| color: $navbar-dark-active-color; | |||||
| } | |||||
| } | |||||
| .navbar-toggler { | |||||
| color: $navbar-dark-color; | |||||
| border-color: $navbar-dark-toggler-border-color; | |||||
| } | |||||
| .navbar-toggler-icon { | |||||
| background-image: escape-svg($navbar-dark-toggler-icon-bg); | |||||
| } | |||||
| .navbar-text { | |||||
| color: $navbar-dark-color; | |||||
| a { | |||||
| color: $navbar-dark-active-color; | |||||
| @include hover-focus() { | |||||
| color: $navbar-dark-active-color; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,73 @@ | |||||
| .pagination { | |||||
| display: flex; | |||||
| @include list-unstyled(); | |||||
| @include border-radius(); | |||||
| } | |||||
| .page-link { | |||||
| position: relative; | |||||
| display: block; | |||||
| padding: $pagination-padding-y $pagination-padding-x; | |||||
| margin-left: -$pagination-border-width; | |||||
| line-height: $pagination-line-height; | |||||
| color: $pagination-color; | |||||
| background-color: $pagination-bg; | |||||
| border: $pagination-border-width solid $pagination-border-color; | |||||
| &:hover { | |||||
| z-index: 2; | |||||
| color: $pagination-hover-color; | |||||
| text-decoration: none; | |||||
| background-color: $pagination-hover-bg; | |||||
| border-color: $pagination-hover-border-color; | |||||
| } | |||||
| &:focus { | |||||
| z-index: 3; | |||||
| outline: $pagination-focus-outline; | |||||
| box-shadow: $pagination-focus-box-shadow; | |||||
| } | |||||
| } | |||||
| .page-item { | |||||
| &:first-child { | |||||
| .page-link { | |||||
| margin-left: 0; | |||||
| @include border-left-radius($border-radius); | |||||
| } | |||||
| } | |||||
| &:last-child { | |||||
| .page-link { | |||||
| @include border-right-radius($border-radius); | |||||
| } | |||||
| } | |||||
| &.active .page-link { | |||||
| z-index: 3; | |||||
| color: $pagination-active-color; | |||||
| background-color: $pagination-active-bg; | |||||
| border-color: $pagination-active-border-color; | |||||
| } | |||||
| &.disabled .page-link { | |||||
| color: $pagination-disabled-color; | |||||
| pointer-events: none; | |||||
| // Opinionated: remove the "hand" cursor set previously for .page-link | |||||
| cursor: auto; | |||||
| background-color: $pagination-disabled-bg; | |||||
| border-color: $pagination-disabled-border-color; | |||||
| } | |||||
| } | |||||
| // | |||||
| // Sizing | |||||
| // | |||||
| .pagination-lg { | |||||
| @include pagination-size($pagination-padding-y-lg, $pagination-padding-x-lg, $font-size-lg, $line-height-lg, $border-radius-lg); | |||||
| } | |||||
| .pagination-sm { | |||||
| @include pagination-size($pagination-padding-y-sm, $pagination-padding-x-sm, $font-size-sm, $line-height-sm, $border-radius-sm); | |||||
| } | |||||
| @ -0,0 +1,170 @@ | |||||
| .popover { | |||||
| position: absolute; | |||||
| top: 0; | |||||
| left: 0; | |||||
| z-index: $zindex-popover; | |||||
| display: block; | |||||
| max-width: $popover-max-width; | |||||
| // Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element. | |||||
| // So reset our font and text properties to avoid inheriting weird values. | |||||
| @include reset-text(); | |||||
| @include font-size($popover-font-size); | |||||
| // Allow breaking very long words so they don't overflow the popover's bounds | |||||
| word-wrap: break-word; | |||||
| background-color: $popover-bg; | |||||
| background-clip: padding-box; | |||||
| border: $popover-border-width solid $popover-border-color; | |||||
| @include border-radius($popover-border-radius); | |||||
| @include box-shadow($popover-box-shadow); | |||||
| .arrow { | |||||
| position: absolute; | |||||
| display: block; | |||||
| width: $popover-arrow-width; | |||||
| height: $popover-arrow-height; | |||||
| margin: 0 $popover-border-radius; | |||||
| &::before, | |||||
| &::after { | |||||
| position: absolute; | |||||
| display: block; | |||||
| content: ""; | |||||
| border-color: transparent; | |||||
| border-style: solid; | |||||
| } | |||||
| } | |||||
| } | |||||
| .bs-popover-top { | |||||
| margin-bottom: $popover-arrow-height; | |||||
| > .arrow { | |||||
| bottom: subtract(-$popover-arrow-height, $popover-border-width); | |||||
| &::before { | |||||
| bottom: 0; | |||||
| border-width: $popover-arrow-height ($popover-arrow-width / 2) 0; | |||||
| border-top-color: $popover-arrow-outer-color; | |||||
| } | |||||
| &::after { | |||||
| bottom: $popover-border-width; | |||||
| border-width: $popover-arrow-height ($popover-arrow-width / 2) 0; | |||||
| border-top-color: $popover-arrow-color; | |||||
| } | |||||
| } | |||||
| } | |||||
| .bs-popover-right { | |||||
| margin-left: $popover-arrow-height; | |||||
| > .arrow { | |||||
| left: subtract(-$popover-arrow-height, $popover-border-width); | |||||
| width: $popover-arrow-height; | |||||
| height: $popover-arrow-width; | |||||
| margin: $popover-border-radius 0; // make sure the arrow does not touch the popover's rounded corners | |||||
| &::before { | |||||
| left: 0; | |||||
| border-width: ($popover-arrow-width / 2) $popover-arrow-height ($popover-arrow-width / 2) 0; | |||||
| border-right-color: $popover-arrow-outer-color; | |||||
| } | |||||
| &::after { | |||||
| left: $popover-border-width; | |||||
| border-width: ($popover-arrow-width / 2) $popover-arrow-height ($popover-arrow-width / 2) 0; | |||||
| border-right-color: $popover-arrow-color; | |||||
| } | |||||
| } | |||||
| } | |||||
| .bs-popover-bottom { | |||||
| margin-top: $popover-arrow-height; | |||||
| > .arrow { | |||||
| top: subtract(-$popover-arrow-height, $popover-border-width); | |||||
| &::before { | |||||
| top: 0; | |||||
| border-width: 0 ($popover-arrow-width / 2) $popover-arrow-height ($popover-arrow-width / 2); | |||||
| border-bottom-color: $popover-arrow-outer-color; | |||||
| } | |||||
| &::after { | |||||
| top: $popover-border-width; | |||||
| border-width: 0 ($popover-arrow-width / 2) $popover-arrow-height ($popover-arrow-width / 2); | |||||
| border-bottom-color: $popover-arrow-color; | |||||
| } | |||||
| } | |||||
| // This will remove the popover-header's border just below the arrow | |||||
| .popover-header::before { | |||||
| position: absolute; | |||||
| top: 0; | |||||
| left: 50%; | |||||
| display: block; | |||||
| width: $popover-arrow-width; | |||||
| margin-left: -$popover-arrow-width / 2; | |||||
| content: ""; | |||||
| border-bottom: $popover-border-width solid $popover-header-bg; | |||||
| } | |||||
| } | |||||
| .bs-popover-left { | |||||
| margin-right: $popover-arrow-height; | |||||
| > .arrow { | |||||
| right: subtract(-$popover-arrow-height, $popover-border-width); | |||||
| width: $popover-arrow-height; | |||||
| height: $popover-arrow-width; | |||||
| margin: $popover-border-radius 0; // make sure the arrow does not touch the popover's rounded corners | |||||
| &::before { | |||||
| right: 0; | |||||
| border-width: ($popover-arrow-width / 2) 0 ($popover-arrow-width / 2) $popover-arrow-height; | |||||
| border-left-color: $popover-arrow-outer-color; | |||||
| } | |||||
| &::after { | |||||
| right: $popover-border-width; | |||||
| border-width: ($popover-arrow-width / 2) 0 ($popover-arrow-width / 2) $popover-arrow-height; | |||||
| border-left-color: $popover-arrow-color; | |||||
| } | |||||
| } | |||||
| } | |||||
| .bs-popover-auto { | |||||
| &[x-placement^="top"] { | |||||
| @extend .bs-popover-top; | |||||
| } | |||||
| &[x-placement^="right"] { | |||||
| @extend .bs-popover-right; | |||||
| } | |||||
| &[x-placement^="bottom"] { | |||||
| @extend .bs-popover-bottom; | |||||
| } | |||||
| &[x-placement^="left"] { | |||||
| @extend .bs-popover-left; | |||||
| } | |||||
| } | |||||
| // Offset the popover to account for the popover arrow | |||||
| .popover-header { | |||||
| padding: $popover-header-padding-y $popover-header-padding-x; | |||||
| margin-bottom: 0; // Reset the default from Reboot | |||||
| @include font-size($font-size-base); | |||||
| color: $popover-header-color; | |||||
| background-color: $popover-header-bg; | |||||
| border-bottom: $popover-border-width solid darken($popover-header-bg, 5%); | |||||
| @include border-top-radius($popover-inner-border-radius); | |||||
| &:empty { | |||||
| display: none; | |||||
| } | |||||
| } | |||||
| .popover-body { | |||||
| padding: $popover-body-padding-y $popover-body-padding-x; | |||||
| color: $popover-body-color; | |||||
| } | |||||
| @ -0,0 +1,141 @@ | |||||
| // stylelint-disable declaration-no-important, selector-no-qualifying-type | |||||
| // Source: https://github.com/h5bp/main.css/blob/master/src/_print.css | |||||
| // ========================================================================== | |||||
| // Print styles. | |||||
| // Inlined to avoid the additional HTTP request: | |||||
| // https://www.phpied.com/delay-loading-your-print-css/ | |||||
| // ========================================================================== | |||||
| @if $enable-print-styles { | |||||
| @media print { | |||||
| *, | |||||
| *::before, | |||||
| *::after { | |||||
| // Bootstrap specific; comment out `color` and `background` | |||||
| //color: $black !important; // Black prints faster | |||||
| text-shadow: none !important; | |||||
| //background: transparent !important; | |||||
| box-shadow: none !important; | |||||
| } | |||||
| a { | |||||
| &:not(.btn) { | |||||
| text-decoration: underline; | |||||
| } | |||||
| } | |||||
| // Bootstrap specific; comment the following selector out | |||||
| //a[href]::after { | |||||
| // content: " (" attr(href) ")"; | |||||
| //} | |||||
| abbr[title]::after { | |||||
| content: " (" attr(title) ")"; | |||||
| } | |||||
| // Bootstrap specific; comment the following selector out | |||||
| // | |||||
| // Don't show links that are fragment identifiers, | |||||
| // or use the `javascript:` pseudo protocol | |||||
| // | |||||
| //a[href^="#"]::after, | |||||
| //a[href^="javascript:"]::after { | |||||
| // content: ""; | |||||
| //} | |||||
| pre { | |||||
| white-space: pre-wrap !important; | |||||
| } | |||||
| pre, | |||||
| blockquote { | |||||
| border: $border-width solid $gray-500; // Bootstrap custom code; using `$border-width` instead of 1px | |||||
| page-break-inside: avoid; | |||||
| } | |||||
| // | |||||
| // Printing Tables: | |||||
| // https://web.archive.org/web/20180815150934/http://css-discuss.incutio.com/wiki/Printing_Tables | |||||
| // | |||||
| thead { | |||||
| display: table-header-group; | |||||
| } | |||||
| tr, | |||||
| img { | |||||
| page-break-inside: avoid; | |||||
| } | |||||
| p, | |||||
| h2, | |||||
| h3 { | |||||
| orphans: 3; | |||||
| widows: 3; | |||||
| } | |||||
| h2, | |||||
| h3 { | |||||
| page-break-after: avoid; | |||||
| } | |||||
| // Bootstrap specific changes start | |||||
| // Specify a size and min-width to make printing closer across browsers. | |||||
| // We don't set margin here because it breaks `size` in Chrome. We also | |||||
| // don't use `!important` on `size` as it breaks in Chrome. | |||||
| @page { | |||||
| size: $print-page-size; | |||||
| } | |||||
| body { | |||||
| min-width: $print-body-min-width !important; | |||||
| } | |||||
| .container { | |||||
| min-width: $print-body-min-width !important; | |||||
| } | |||||
| // Bootstrap components | |||||
| .navbar { | |||||
| display: none; | |||||
| } | |||||
| .badge { | |||||
| border: $border-width solid $black; | |||||
| } | |||||
| .table { | |||||
| border-collapse: collapse !important; | |||||
| td, | |||||
| th { | |||||
| background-color: $white !important; | |||||
| } | |||||
| } | |||||
| .table-bordered { | |||||
| th, | |||||
| td { | |||||
| border: 1px solid $gray-300 !important; | |||||
| } | |||||
| } | |||||
| .table-dark { | |||||
| color: inherit; | |||||
| th, | |||||
| td, | |||||
| thead th, | |||||
| tbody + tbody { | |||||
| border-color: $table-border-color; | |||||
| } | |||||
| } | |||||
| .table .thead-dark th { | |||||
| color: inherit; | |||||
| border-color: $table-border-color; | |||||
| } | |||||
| // Bootstrap specific changes end | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,46 @@ | |||||
| // Disable animation if transitions are disabled | |||||
| @if $enable-transitions { | |||||
| @keyframes progress-bar-stripes { | |||||
| from { background-position: $progress-height 0; } | |||||
| to { background-position: 0 0; } | |||||
| } | |||||
| } | |||||
| .progress { | |||||
| display: flex; | |||||
| height: $progress-height; | |||||
| overflow: hidden; // force rounded corners by cropping it | |||||
| @include font-size($progress-font-size); | |||||
| background-color: $progress-bg; | |||||
| @include border-radius($progress-border-radius); | |||||
| @include box-shadow($progress-box-shadow); | |||||
| } | |||||
| .progress-bar { | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| justify-content: center; | |||||
| overflow: hidden; | |||||
| color: $progress-bar-color; | |||||
| text-align: center; | |||||
| white-space: nowrap; | |||||
| background-color: $progress-bar-bg; | |||||
| @include transition($progress-bar-transition); | |||||
| } | |||||
| .progress-bar-striped { | |||||
| @include gradient-striped(); | |||||
| background-size: $progress-height $progress-height; | |||||
| } | |||||
| @if $enable-transitions { | |||||
| .progress-bar-animated { | |||||
| animation: progress-bar-stripes $progress-bar-animation-timing; | |||||
| @if $enable-prefers-reduced-motion-media-query { | |||||
| @media (prefers-reduced-motion: reduce) { | |||||
| animation: none; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,482 @@ | |||||
| // stylelint-disable at-rule-no-vendor-prefix, declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix | |||||
| // Reboot | |||||
| // | |||||
| // Normalization of HTML elements, manually forked from Normalize.css to remove | |||||
| // styles targeting irrelevant browsers while applying new styles. | |||||
| // | |||||
| // Normalize is licensed MIT. https://github.com/necolas/normalize.css | |||||
| // Document | |||||
| // | |||||
| // 1. Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`. | |||||
| // 2. Change the default font family in all browsers. | |||||
| // 3. Correct the line height in all browsers. | |||||
| // 4. Prevent adjustments of font size after orientation changes in IE on Windows Phone and in iOS. | |||||
| // 5. Change the default tap highlight to be completely transparent in iOS. | |||||
| *, | |||||
| *::before, | |||||
| *::after { | |||||
| box-sizing: border-box; // 1 | |||||
| } | |||||
| html { | |||||
| font-family: sans-serif; // 2 | |||||
| line-height: 1.15; // 3 | |||||
| -webkit-text-size-adjust: 100%; // 4 | |||||
| -webkit-tap-highlight-color: rgba($black, 0); // 5 | |||||
| } | |||||
| // Shim for "new" HTML5 structural elements to display correctly (IE10, older browsers) | |||||
| // TODO: remove in v5 | |||||
| // stylelint-disable-next-line selector-list-comma-newline-after | |||||
| article, aside, figcaption, figure, footer, header, hgroup, main, nav, section { | |||||
| display: block; | |||||
| } | |||||
| // Body | |||||
| // | |||||
| // 1. Remove the margin in all browsers. | |||||
| // 2. As a best practice, apply a default `background-color`. | |||||
| // 3. Set an explicit initial text-align value so that we can later use | |||||
| // the `inherit` value on things like `<th>` elements. | |||||
| body { | |||||
| margin: 0; // 1 | |||||
| font-family: $font-family-base; | |||||
| @include font-size($font-size-base); | |||||
| font-weight: $font-weight-base; | |||||
| line-height: $line-height-base; | |||||
| color: $body-color; | |||||
| text-align: left; // 3 | |||||
| background-color: $body-bg; // 2 | |||||
| } | |||||
| // Future-proof rule: in browsers that support :focus-visible, suppress the focus outline | |||||
| // on elements that programmatically receive focus but wouldn't normally show a visible | |||||
| // focus outline. In general, this would mean that the outline is only applied if the | |||||
| // interaction that led to the element receiving programmatic focus was a keyboard interaction, | |||||
| // or the browser has somehow determined that the user is primarily a keyboard user and/or | |||||
| // wants focus outlines to always be presented. | |||||
| // | |||||
| // See https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-visible | |||||
| // and https://developer.paciellogroup.com/blog/2018/03/focus-visible-and-backwards-compatibility/ | |||||
| [tabindex="-1"]:focus:not(:focus-visible) { | |||||
| outline: 0 !important; | |||||
| } | |||||
| // Content grouping | |||||
| // | |||||
| // 1. Add the correct box sizing in Firefox. | |||||
| // 2. Show the overflow in Edge and IE. | |||||
| hr { | |||||
| box-sizing: content-box; // 1 | |||||
| height: 0; // 1 | |||||
| overflow: visible; // 2 | |||||
| } | |||||
| // | |||||
| // Typography | |||||
| // | |||||
| // Remove top margins from headings | |||||
| // | |||||
| // By default, `<h1>`-`<h6>` all receive top and bottom margins. We nuke the top | |||||
| // margin for easier control within type scales as it avoids margin collapsing. | |||||
| // stylelint-disable-next-line selector-list-comma-newline-after | |||||
| h1, h2, h3, h4, h5, h6 { | |||||
| margin-top: 0; | |||||
| margin-bottom: $headings-margin-bottom; | |||||
| } | |||||
| // Reset margins on paragraphs | |||||
| // | |||||
| // Similarly, the top margin on `<p>`s get reset. However, we also reset the | |||||
| // bottom margin to use `rem` units instead of `em`. | |||||
| p { | |||||
| margin-top: 0; | |||||
| margin-bottom: $paragraph-margin-bottom; | |||||
| } | |||||
| // Abbreviations | |||||
| // | |||||
| // 1. Duplicate behavior to the data-* attribute for our tooltip plugin | |||||
| // 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. | |||||
| // 3. Add explicit cursor to indicate changed behavior. | |||||
| // 4. Remove the bottom border in Firefox 39-. | |||||
| // 5. Prevent the text-decoration to be skipped. | |||||
| abbr[title], | |||||
| abbr[data-original-title] { // 1 | |||||
| text-decoration: underline; // 2 | |||||
| text-decoration: underline dotted; // 2 | |||||
| cursor: help; // 3 | |||||
| border-bottom: 0; // 4 | |||||
| text-decoration-skip-ink: none; // 5 | |||||
| } | |||||
| address { | |||||
| margin-bottom: 1rem; | |||||
| font-style: normal; | |||||
| line-height: inherit; | |||||
| } | |||||
| ol, | |||||
| ul, | |||||
| dl { | |||||
| margin-top: 0; | |||||
| margin-bottom: 1rem; | |||||
| } | |||||
| ol ol, | |||||
| ul ul, | |||||
| ol ul, | |||||
| ul ol { | |||||
| margin-bottom: 0; | |||||
| } | |||||
| dt { | |||||
| font-weight: $dt-font-weight; | |||||
| } | |||||
| dd { | |||||
| margin-bottom: .5rem; | |||||
| margin-left: 0; // Undo browser default | |||||
| } | |||||
| blockquote { | |||||
| margin: 0 0 1rem; | |||||
| } | |||||
| b, | |||||
| strong { | |||||
| font-weight: $font-weight-bolder; // Add the correct font weight in Chrome, Edge, and Safari | |||||
| } | |||||
| small { | |||||
| @include font-size(80%); // Add the correct font size in all browsers | |||||
| } | |||||
| // | |||||
| // Prevent `sub` and `sup` elements from affecting the line height in | |||||
| // all browsers. | |||||
| // | |||||
| sub, | |||||
| sup { | |||||
| position: relative; | |||||
| @include font-size(75%); | |||||
| line-height: 0; | |||||
| vertical-align: baseline; | |||||
| } | |||||
| sub { bottom: -.25em; } | |||||
| sup { top: -.5em; } | |||||
| // | |||||
| // Links | |||||
| // | |||||
| a { | |||||
| color: $link-color; | |||||
| text-decoration: $link-decoration; | |||||
| background-color: transparent; // Remove the gray background on active links in IE 10. | |||||
| @include hover() { | |||||
| color: $link-hover-color; | |||||
| text-decoration: $link-hover-decoration; | |||||
| } | |||||
| } | |||||
| // And undo these styles for placeholder links/named anchors (without href). | |||||
| // It would be more straightforward to just use a[href] in previous block, but that | |||||
| // causes specificity issues in many other styles that are too complex to fix. | |||||
| // See https://github.com/twbs/bootstrap/issues/19402 | |||||
| a:not([href]) { | |||||
| color: inherit; | |||||
| text-decoration: none; | |||||
| @include hover() { | |||||
| color: inherit; | |||||
| text-decoration: none; | |||||
| } | |||||
| } | |||||
| // | |||||
| // Code | |||||
| // | |||||
| pre, | |||||
| code, | |||||
| kbd, | |||||
| samp { | |||||
| font-family: $font-family-monospace; | |||||
| @include font-size(1em); // Correct the odd `em` font sizing in all browsers. | |||||
| } | |||||
| pre { | |||||
| // Remove browser default top margin | |||||
| margin-top: 0; | |||||
| // Reset browser default of `1em` to use `rem`s | |||||
| margin-bottom: 1rem; | |||||
| // Don't allow content to break outside | |||||
| overflow: auto; | |||||
| } | |||||
| // | |||||
| // Figures | |||||
| // | |||||
| figure { | |||||
| // Apply a consistent margin strategy (matches our type styles). | |||||
| margin: 0 0 1rem; | |||||
| } | |||||
| // | |||||
| // Images and content | |||||
| // | |||||
| img { | |||||
| vertical-align: middle; | |||||
| border-style: none; // Remove the border on images inside links in IE 10-. | |||||
| } | |||||
| svg { | |||||
| // Workaround for the SVG overflow bug in IE10/11 is still required. | |||||
| // See https://github.com/twbs/bootstrap/issues/26878 | |||||
| overflow: hidden; | |||||
| vertical-align: middle; | |||||
| } | |||||
| // | |||||
| // Tables | |||||
| // | |||||
| table { | |||||
| border-collapse: collapse; // Prevent double borders | |||||
| } | |||||
| caption { | |||||
| padding-top: $table-cell-padding; | |||||
| padding-bottom: $table-cell-padding; | |||||
| color: $table-caption-color; | |||||
| text-align: left; | |||||
| caption-side: bottom; | |||||
| } | |||||
| th { | |||||
| // Matches default `<td>` alignment by inheriting from the `<body>`, or the | |||||
| // closest parent with a set `text-align`. | |||||
| text-align: inherit; | |||||
| } | |||||
| // | |||||
| // Forms | |||||
| // | |||||
| label { | |||||
| // Allow labels to use `margin` for spacing. | |||||
| display: inline-block; | |||||
| margin-bottom: $label-margin-bottom; | |||||
| } | |||||
| // Remove the default `border-radius` that macOS Chrome adds. | |||||
| // | |||||
| // Details at https://github.com/twbs/bootstrap/issues/24093 | |||||
| button { | |||||
| // stylelint-disable-next-line property-blacklist | |||||
| border-radius: 0; | |||||
| } | |||||
| // Work around a Firefox/IE bug where the transparent `button` background | |||||
| // results in a loss of the default `button` focus styles. | |||||
| // | |||||
| // Credit: https://github.com/suitcss/base/ | |||||
| button:focus { | |||||
| outline: 1px dotted; | |||||
| outline: 5px auto -webkit-focus-ring-color; | |||||
| } | |||||
| input, | |||||
| button, | |||||
| select, | |||||
| optgroup, | |||||
| textarea { | |||||
| margin: 0; // Remove the margin in Firefox and Safari | |||||
| font-family: inherit; | |||||
| @include font-size(inherit); | |||||
| line-height: inherit; | |||||
| } | |||||
| button, | |||||
| input { | |||||
| overflow: visible; // Show the overflow in Edge | |||||
| } | |||||
| button, | |||||
| select { | |||||
| text-transform: none; // Remove the inheritance of text transform in Firefox | |||||
| } | |||||
| // Remove the inheritance of word-wrap in Safari. | |||||
| // | |||||
| // Details at https://github.com/twbs/bootstrap/issues/24990 | |||||
| select { | |||||
| word-wrap: normal; | |||||
| } | |||||
| // 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` | |||||
| // controls in Android 4. | |||||
| // 2. Correct the inability to style clickable types in iOS and Safari. | |||||
| button, | |||||
| [type="button"], // 1 | |||||
| [type="reset"], | |||||
| [type="submit"] { | |||||
| -webkit-appearance: button; // 2 | |||||
| } | |||||
| // Opinionated: add "hand" cursor to non-disabled button elements. | |||||
| @if $enable-pointer-cursor-for-buttons { | |||||
| button, | |||||
| [type="button"], | |||||
| [type="reset"], | |||||
| [type="submit"] { | |||||
| &:not(:disabled) { | |||||
| cursor: pointer; | |||||
| } | |||||
| } | |||||
| } | |||||
| // Remove inner border and padding from Firefox, but don't restore the outline like Normalize. | |||||
| button::-moz-focus-inner, | |||||
| [type="button"]::-moz-focus-inner, | |||||
| [type="reset"]::-moz-focus-inner, | |||||
| [type="submit"]::-moz-focus-inner { | |||||
| padding: 0; | |||||
| border-style: none; | |||||
| } | |||||
| input[type="radio"], | |||||
| input[type="checkbox"] { | |||||
| box-sizing: border-box; // 1. Add the correct box sizing in IE 10- | |||||
| padding: 0; // 2. Remove the padding in IE 10- | |||||
| } | |||||
| input[type="date"], | |||||
| input[type="time"], | |||||
| input[type="datetime-local"], | |||||
| input[type="month"] { | |||||
| // Remove the default appearance of temporal inputs to avoid a Mobile Safari | |||||
| // bug where setting a custom line-height prevents text from being vertically | |||||
| // centered within the input. | |||||
| // See https://bugs.webkit.org/show_bug.cgi?id=139848 | |||||
| // and https://github.com/twbs/bootstrap/issues/11266 | |||||
| -webkit-appearance: listbox; | |||||
| } | |||||
| textarea { | |||||
| overflow: auto; // Remove the default vertical scrollbar in IE. | |||||
| // Textareas should really only resize vertically so they don't break their (horizontal) containers. | |||||
| resize: vertical; | |||||
| } | |||||
| fieldset { | |||||
| // Browsers set a default `min-width: min-content;` on fieldsets, | |||||
| // unlike e.g. `<div>`s, which have `min-width: 0;` by default. | |||||
| // So we reset that to ensure fieldsets behave more like a standard block element. | |||||
| // See https://github.com/twbs/bootstrap/issues/12359 | |||||
| // and https://html.spec.whatwg.org/multipage/#the-fieldset-and-legend-elements | |||||
| min-width: 0; | |||||
| // Reset the default outline behavior of fieldsets so they don't affect page layout. | |||||
| padding: 0; | |||||
| margin: 0; | |||||
| border: 0; | |||||
| } | |||||
| // 1. Correct the text wrapping in Edge and IE. | |||||
| // 2. Correct the color inheritance from `fieldset` elements in IE. | |||||
| legend { | |||||
| display: block; | |||||
| width: 100%; | |||||
| max-width: 100%; // 1 | |||||
| padding: 0; | |||||
| margin-bottom: .5rem; | |||||
| @include font-size(1.5rem); | |||||
| line-height: inherit; | |||||
| color: inherit; // 2 | |||||
| white-space: normal; // 1 | |||||
| } | |||||
| progress { | |||||
| vertical-align: baseline; // Add the correct vertical alignment in Chrome, Firefox, and Opera. | |||||
| } | |||||
| // Correct the cursor style of increment and decrement buttons in Chrome. | |||||
| [type="number"]::-webkit-inner-spin-button, | |||||
| [type="number"]::-webkit-outer-spin-button { | |||||
| height: auto; | |||||
| } | |||||
| [type="search"] { | |||||
| // This overrides the extra rounded corners on search inputs in iOS so that our | |||||
| // `.form-control` class can properly style them. Note that this cannot simply | |||||
| // be added to `.form-control` as it's not specific enough. For details, see | |||||
| // https://github.com/twbs/bootstrap/issues/11586. | |||||
| outline-offset: -2px; // 2. Correct the outline style in Safari. | |||||
| -webkit-appearance: none; | |||||
| } | |||||
| // | |||||
| // Remove the inner padding in Chrome and Safari on macOS. | |||||
| // | |||||
| [type="search"]::-webkit-search-decoration { | |||||
| -webkit-appearance: none; | |||||
| } | |||||
| // | |||||
| // 1. Correct the inability to style clickable types in iOS and Safari. | |||||
| // 2. Change font properties to `inherit` in Safari. | |||||
| // | |||||
| ::-webkit-file-upload-button { | |||||
| font: inherit; // 2 | |||||
| -webkit-appearance: button; // 1 | |||||
| } | |||||
| // | |||||
| // Correct element displays | |||||
| // | |||||
| output { | |||||
| display: inline-block; | |||||
| } | |||||
| summary { | |||||
| display: list-item; // Add the correct display in all browsers | |||||
| cursor: pointer; | |||||
| } | |||||
| template { | |||||
| display: none; // Add the correct display in IE | |||||
| } | |||||
| // Always hide an element with the `hidden` HTML attribute (from PureCSS). | |||||
| // Needed for proper display in IE 10-. | |||||
| [hidden] { | |||||
| display: none !important; | |||||
| } | |||||