Commit ec261a83 authored by Mark Otto's avatar Mark Otto
Browse files

Merge branch 'master' of github.com:twbs/bootstrap

parents ca14b965 05b0a74d
main cleanup-floating-forms cssvar-function dependabot/npm_and_yarn/stylelint-and-stylelint-config-twbs-bootstrap-15.3.0 extend-snippets feat/data-target floating-always-visible floating-labels-icons fod-main-banner form-controls-with-icons gh-pages gh-pages-530-alpha2 github/fork/719media/patch-13 github/fork/719media/patch-14 github/fork/719media/patch-9 github/fork/ChellyAhmed/fix-typo-reboot.md github/fork/ChellyAhmed/offcanvas-scroll-back github/fork/CtrlAltLilith/main github/fork/Elysiome/offcanvas-optional-window-resizing github/fork/JanSargsyan/main github/fork/LunicLynx/support-different-line-height-for-buttons github/fork/Psixodelik/main github/fork/Ronid1/ronid1/offcanvas_static_backdrop github/fork/RyanBerliner/tooltip-accessibility github/fork/SantiagoPVazquez/Feature-default-border-bottom-to-dropdown-item github/fork/Sir-Genius/utils github/fork/Sumit-Singh-8/main github/fork/Viktor-VERA2020/offcanvas-slide github/fork/Zivangu9/input-group-for-form-control-plaintext github/fork/alpadev/alpadev/call-dispose-on-component-reinstantiation github/fork/astagi/fix/tree-shake-modules github/fork/compnerd/dark-accordion-icon github/fork/derSascha/dropdown-dont-close-on-input-click github/fork/dev-ph1l/main github/fork/donquixote/issue-33861-utl-mixin github/fork/florianlacreuse/mixin-make-row-gutter-y github/fork/gregorw/main github/fork/iteggmbh/transitionend-dispose-race github/fork/jdelStrother/patch-1 github/fork/jonnysp/form-floating github/fork/jonnysp/independent-offcanvas github/fork/jonnysp/theme-dark-on-card-and-modal-fix github/fork/josefdlange/floating-label-placeholder-opacity github/fork/julien-deramond/enhance-change-version.js github/fork/julien-deramond/main-jd-fix-offset-content github/fork/julien-deramond/main-jd-issue-with-utitlies github/fork/julien-deramond/main-xmr-pa11y-ci-jd-add-hideElements github/fork/kyletsang/fix-tooltip-padding github/fork/lacutah/CheckboxCenteringDocumentation github/fork/lekoala/patch-3 github/fork/louismaximepiton/main-kld-lmp-collapse-proposal github/fork/louismaximepiton/main-lmp-card-inner-border-radius-fix github/fork/louismaximepiton/main-lmp-carousel-multiple-images github/fork/louismaximepiton/main-lmp-css-var-init github/fork/louismaximepiton/main-lmp-disabled-floating-label-fix github/fork/louismaximepiton/main-lmp-input-range-fix github/fork/louismaximepiton/main-lmp-shift-color github/fork/louismaximepiton/main-lmp-table-active-tr-fix github/fork/maciek-szn/switch github/fork/michael-roth/feature/19964-multiple-tab-targets github/fork/mistic100/dom-utils github/fork/nkdas91/accordion github/fork/nstungcom/fix-missing-modal-open-class github/fork/oraliahdz/animation-utilities github/fork/pine3ree/patch-7 github/fork/pouwerkerk/unindent-scss-docs-shortcode github/fork/smares/smares-no-scolling-on-modal-close github/fork/tgm-git/patch-1 gs-forms gs-toasts-with-animated-progress-bar gs/add-history-helper gs/change-version-dir-on-docs gs/data-must-set-onlu-one-instance gs/docs/fix-drop-down-error gs/event-handler-2 gs/make-docs-js-build gs/make-simple-attribute-toggler gs/popover-fix-doc gs/provide-steConfig-method gs/scrollspy-smoothscroll-option-use-browser-history gs/streamline-jqueryInterface gs/support-drop-down-in-navbar gs/test-js-generic-trigger gs/try-web-components gs/tweak-collapse-js-selector gs/use-event-handler-in-cocmponent gs/use-rollup-replace-for-version jo-docs-thanks-page jo-ssr-friendly logical-props-spacing-utils main-fod-disabled-form-check-label main-fod-nested-accordion main-fod-simpler-table-structure main-fod-table-separator main-fod-utilities-contrast main-jd-abbr-title main-jd-add-chips main-jd-add-doc-for-sass-custom-colors main-jd-add-enable-host-to-handle-web-components main-jd-browserstack-fine-tune main-jd-browserstack-updates main-jd-docs-consistent-usage-of-css-sections-step-2 main-jd-fix-docs-headers-in-white main-jd-fix-highlight-docs-border-radius main-jd-fix-placeholder-color-background-params-for-img-markup main-jd-glossary-experiment main-jd-postcss-drop-empty-css-vars main-jd-proto-doc-astro main-jd-skip-navigation-component main-jd-stackblitz-for-examples main-jd-upgrade-browserlistrc main-jd-use-host main-lmp-dark-theme-customization main-lmp-handle-scroll-target main-lmp-tab-fix main-mc-opensearch main-xmr-bundlewatch-action main-xmr-eslint-plugin-compat main-xmr-hugo-docs-vendor main-xmr-hugo-rm-ver main-xmr-linkinator-prod main-xmr-min-mangle main-xmr-pa11y-ci more-darkmode-examples nested-dropdowns patrickhlauke-issue37428 patrickhlauke-use-of-color-tweaks pr/34102 pr/37590 previous-next-docs-links sticky-thead utilities-functions-mixin v3-dev v4-dev v4-dev-dropdown-hide-method v530-dev v6-postcss-custom-media v6-spinner-dots v6/gs/use-floating-ui-in-place-of-popper xmr/dev xmr/docs-png xmr/docs-svgs xmr/hugo-reorg-files xmr/js-2 xmr/markdownlint xmr/prepare-530-alpha2 xmr/xo v5.3.0-alpha1 v5.2.3 v5.2.2 v5.2.1 v5.2.0 v5.2.0-beta1 v5.1.3 v5.1.2 v5.1.1 v5.1.0 v5.0.2 v5.0.1 v5.0.0 v5.0.0-beta3 v5.0.0-beta2 v5.0.0-beta1 v5.0.0-alpha3 v5.0.0-alpha2 v5.0.0-alpha1 v4.6.2 v4.6.1 v4.6.0 v4.5.3 v4.5.2 v4.5.1 v4.5.0 v4.4.1 v4.4.0 v4.3.1 v4.3.0 v4.2.1 v4.2.0 v4.1.3 v4.1.2 v4.1.1 v4.1.0 v4.0.0 v4.0.0-beta.3 v4.0.0-beta.2 v4.0.0-beta v4.0.0-alpha.6 v4.0.0-alpha.5 v4.0.0-alpha.4 v4.0.0-alpha.3 v4.0.0-alpha.2 v4.0.0-alpha v3.4.1 v3.4.0 v3.3.7 v3.3.6 v3.3.5 v3.3.4 v3.3.2 v3.3.1 v3.3.0 v3.2.0 v3.1.1 v3.1.0
No related merge requests found
Showing with 113 additions and 89 deletions
+113 -89
...@@ -6,9 +6,9 @@ before_install: ...@@ -6,9 +6,9 @@ before_install:
install: install:
- if [ "$TWBS_TEST" = validate-html ]; then time gem install jekyll; fi - if [ "$TWBS_TEST" = validate-html ]; then time gem install jekyll; fi
- time npm install -g grunt-cli - time npm install -g grunt-cli
- time ./test-infra/node_modules_cache.py download || time npm install - time ./test-infra/node_modules_cache.py download package.json ./node_modules || time npm install
after_script: after_script:
- if [ "$TWBS_TEST" = core ]; then time ./test-infra/node_modules_cache.py upload; fi - if [ "$TWBS_TEST" = core ]; then time ./test-infra/node_modules_cache.py upload package.json ./node_modules; fi
env: env:
global: global:
- SAUCE_USERNAME: bootstrap - SAUCE_USERNAME: bootstrap
......
...@@ -193,6 +193,8 @@ module.exports = function (grunt) { ...@@ -193,6 +193,8 @@ module.exports = function (grunt) {
validation: { validation: {
options: { options: {
charset: 'utf-8',
doctype: 'HTML5',
reset: true, reset: true,
relaxerror: [ relaxerror: [
'Bad value X-UA-Compatible for attribute http-equiv on element meta.', 'Bad value X-UA-Compatible for attribute http-equiv on element meta.',
......
...@@ -1552,7 +1552,7 @@ base_url: "../" ...@@ -1552,7 +1552,7 @@ base_url: "../"
<h2 id="input-groups-basic">Basic example</h2> <h2 id="input-groups-basic">Basic example</h2>
<p>Place one add-on or button on either side of an input. You may also place one on both sides of an input. <strong class="text-danger">We do not support mutiple add-ons on a single side.</strong></p> <p>Place one add-on or button on either side of an input. You may also place one on both sides of an input. <strong class="text-danger">We do not support multiple add-ons on a single side.</strong></p>
<form class="bs-example bs-example-form" role="form"> <form class="bs-example bs-example-form" role="form">
<div class="input-group"> <div class="input-group">
<span class="input-group-addon">@</span> <span class="input-group-addon">@</span>
......
...@@ -1965,31 +1965,31 @@ For example, <code>&lt;section&gt;</code> should be wrapped as inline. ...@@ -1965,31 +1965,31 @@ For example, <code>&lt;section&gt;</code> should be wrapped as inline.
<div class="bs-example"> <div class="bs-example">
<form role="form"> <form role="form">
<div class="form-group has-success"> <div class="form-group has-success">
<label class="control-label" for="inputSuccess">Input with success</label> <label class="control-label" for="inputSuccess1">Input with success</label>
<input type="text" class="form-control" id="inputSuccess"> <input type="text" class="form-control" id="inputSuccess1">
</div> </div>
<div class="form-group has-warning"> <div class="form-group has-warning">
<label class="control-label" for="inputWarning">Input with warning</label> <label class="control-label" for="inputWarning1">Input with warning</label>
<input type="text" class="form-control" id="inputWarning"> <input type="text" class="form-control" id="inputWarning1">
</div> </div>
<div class="form-group has-error"> <div class="form-group has-error">
<label class="control-label" for="inputError">Input with error</label> <label class="control-label" for="inputError1">Input with error</label>
<input type="text" class="form-control" id="inputError"> <input type="text" class="form-control" id="inputError1">
</div> </div>
</form> </form>
</div><!-- /.bs-example --> </div><!-- /.bs-example -->
{% highlight html %} {% highlight html %}
<div class="form-group has-success"> <div class="form-group has-success">
<label class="control-label" for="inputSuccess">Input with success</label> <label class="control-label" for="inputSuccess1">Input with success</label>
<input type="text" class="form-control" id="inputSuccess"> <input type="text" class="form-control" id="inputSuccess1">
</div> </div>
<div class="form-group has-warning"> <div class="form-group has-warning">
<label class="control-label" for="inputWarning">Input with warning</label> <label class="control-label" for="inputWarning1">Input with warning</label>
<input type="text" class="form-control" id="inputWarning"> <input type="text" class="form-control" id="inputWarning1">
</div> </div>
<div class="form-group has-error"> <div class="form-group has-error">
<label class="control-label" for="inputError">Input with error</label> <label class="control-label" for="inputError1">Input with error</label>
<input type="text" class="form-control" id="inputError"> <input type="text" class="form-control" id="inputError1">
</div> </div>
{% endhighlight %} {% endhighlight %}
...@@ -1998,36 +1998,36 @@ For example, <code>&lt;section&gt;</code> should be wrapped as inline. ...@@ -1998,36 +1998,36 @@ For example, <code>&lt;section&gt;</code> should be wrapped as inline.
<div class="bs-example"> <div class="bs-example">
<form role="form"> <form role="form">
<div class="form-group has-success has-feedback"> <div class="form-group has-success has-feedback">
<label class="control-label" for="inputSuccess">Input with success</label> <label class="control-label" for="inputSuccess2">Input with success</label>
<input type="text" class="form-control" id="inputSuccess"> <input type="text" class="form-control" id="inputSuccess2">
<span class="glyphicon glyphicon-ok form-control-feedback"></span> <span class="glyphicon glyphicon-ok form-control-feedback"></span>
</div> </div>
<div class="form-group has-warning has-feedback"> <div class="form-group has-warning has-feedback">
<label class="control-label" for="inputWarning">Input with warning</label> <label class="control-label" for="inputWarning2">Input with warning</label>
<input type="text" class="form-control" id="inputWarning"> <input type="text" class="form-control" id="inputWarning2">
<span class="glyphicon glyphicon-warning-sign form-control-feedback"></span> <span class="glyphicon glyphicon-warning-sign form-control-feedback"></span>
</div> </div>
<div class="form-group has-error has-feedback"> <div class="form-group has-error has-feedback">
<label class="control-label" for="inputError">Input with error</label> <label class="control-label" for="inputError2">Input with error</label>
<input type="text" class="form-control" id="inputError"> <input type="text" class="form-control" id="inputError2">
<span class="glyphicon glyphicon-remove form-control-feedback"></span> <span class="glyphicon glyphicon-remove form-control-feedback"></span>
</div> </div>
</form> </form>
</div> </div>
{% highlight html %} {% highlight html %}
<div class="form-group has-success has-feedback"> <div class="form-group has-success has-feedback">
<label class="control-label" for="inputSuccess">Input with success</label> <label class="control-label" for="inputSuccess2">Input with success</label>
<input type="text" class="form-control" id="inputSuccess"> <input type="text" class="form-control" id="inputSuccess2">
<span class="glyphicon glyphicon-ok form-control-feedback"></span> <span class="glyphicon glyphicon-ok form-control-feedback"></span>
</div> </div>
<div class="form-group has-warning has-feedback"> <div class="form-group has-warning has-feedback">
<label class="control-label" for="inputWarning">Input with warning</label> <label class="control-label" for="inputWarning2">Input with warning</label>
<input type="text" class="form-control" id="inputWarning"> <input type="text" class="form-control" id="inputWarning2">
<span class="glyphicon glyphicon-warning-sign form-control-feedback"></span> <span class="glyphicon glyphicon-warning-sign form-control-feedback"></span>
</div> </div>
<div class="form-group has-error has-feedback"> <div class="form-group has-error has-feedback">
<label class="control-label" for="inputError">Input with error</label> <label class="control-label" for="inputError2">Input with error</label>
<input type="text" class="form-control" id="inputError"> <input type="text" class="form-control" id="inputError2">
<span class="glyphicon glyphicon-remove form-control-feedback"></span> <span class="glyphicon glyphicon-remove form-control-feedback"></span>
</div> </div>
{% endhighlight %} {% endhighlight %}
...@@ -2036,9 +2036,9 @@ For example, <code>&lt;section&gt;</code> should be wrapped as inline. ...@@ -2036,9 +2036,9 @@ For example, <code>&lt;section&gt;</code> should be wrapped as inline.
<div class="bs-example"> <div class="bs-example">
<form class="form-horizontal" role="form"> <form class="form-horizontal" role="form">
<div class="form-group has-success has-feedback"> <div class="form-group has-success has-feedback">
<label class="control-label col-sm-3" for="inputSuccess">Input with success</label> <label class="control-label col-sm-3" for="inputSuccess3">Input with success</label>
<div class="col-sm-9"> <div class="col-sm-9">
<input type="text" class="form-control" id="inputSuccess"> <input type="text" class="form-control" id="inputSuccess3">
<span class="glyphicon glyphicon-ok form-control-feedback"></span> <span class="glyphicon glyphicon-ok form-control-feedback"></span>
</div> </div>
</div> </div>
...@@ -2047,9 +2047,9 @@ For example, <code>&lt;section&gt;</code> should be wrapped as inline. ...@@ -2047,9 +2047,9 @@ For example, <code>&lt;section&gt;</code> should be wrapped as inline.
{% highlight html %} {% highlight html %}
<form class="form-horizontal" role="form"> <form class="form-horizontal" role="form">
<div class="form-group has-success has-feedback"> <div class="form-group has-success has-feedback">
<label class="control-label col-sm-3" for="inputSuccess">Input with success</label> <label class="control-label col-sm-3" for="inputSuccess3">Input with success</label>
<div class="col-sm-9"> <div class="col-sm-9">
<input type="text" class="form-control" id="inputSuccess"> <input type="text" class="form-control" id="inputSuccess3">
<span class="glyphicon glyphicon-ok form-control-feedback"></span> <span class="glyphicon glyphicon-ok form-control-feedback"></span>
</div> </div>
</div> </div>
...@@ -2059,8 +2059,8 @@ For example, <code>&lt;section&gt;</code> should be wrapped as inline. ...@@ -2059,8 +2059,8 @@ For example, <code>&lt;section&gt;</code> should be wrapped as inline.
<div class="bs-example"> <div class="bs-example">
<form class="form-inline" role="form"> <form class="form-inline" role="form">
<div class="form-group has-success has-feedback"> <div class="form-group has-success has-feedback">
<label class="control-label" for="inputSuccess">Input with success</label> <label class="control-label" for="inputSuccess4">Input with success</label>
<input type="text" class="form-control" id="inputSuccess"> <input type="text" class="form-control" id="inputSuccess4">
<span class="glyphicon glyphicon-ok form-control-feedback"></span> <span class="glyphicon glyphicon-ok form-control-feedback"></span>
</div> </div>
</form> </form>
...@@ -2068,8 +2068,8 @@ For example, <code>&lt;section&gt;</code> should be wrapped as inline. ...@@ -2068,8 +2068,8 @@ For example, <code>&lt;section&gt;</code> should be wrapped as inline.
{% highlight html %} {% highlight html %}
<form class="form-inline" role="form"> <form class="form-inline" role="form">
<div class="form-group has-success has-feedback"> <div class="form-group has-success has-feedback">
<label class="control-label" for="inputSuccess">Input with success</label> <label class="control-label" for="inputSuccess4">Input with success</label>
<input type="text" class="form-control" id="inputSuccess"> <input type="text" class="form-control" id="inputSuccess4">
<span class="glyphicon glyphicon-ok form-control-feedback"></span> <span class="glyphicon glyphicon-ok form-control-feedback"></span>
</div> </div>
</form> </form>
...@@ -3006,7 +3006,7 @@ a { ...@@ -3006,7 +3006,7 @@ a {
{% endhighlight %} {% endhighlight %}
<h3 id="less-mixins-box-shadow">Box (Drop) shadows</h3> <h3 id="less-mixins-box-shadow">Box (Drop) shadows</h3>
<p>If your target audience is using the latest and greatest browsers and devices, be sure to just use the <code>box-shadow</code> property on it's own. If you need support for older Android (pre-v4) and iOS devices (pre-iOS 5), use of the mixin to pick up the required <code>-webkit</code> prefix.</p> <p>If your target audience is using the latest and greatest browsers and devices, be sure to just use the <code>box-shadow</code> property on its own. If you need support for older Android (pre-v4) and iOS devices (pre-iOS 5), use the mixin to pick up the required <code>-webkit</code> prefix.</p>
<p>Be sure to use <code>rgba()</code> colors in your box shadows so they blend as seamlessly as possible with backgrounds.</p> <p>Be sure to use <code>rgba()</code> colors in your box shadows so they blend as seamlessly as possible with backgrounds.</p>
{% highlight css %} {% highlight css %}
.box-shadow(@shadow: 0 1px 3px rgba(0,0,0,.25)) { .box-shadow(@shadow: 0 1px 3px rgba(0,0,0,.25)) {
......
...@@ -884,8 +884,8 @@ if (navigator.userAgent.match(/IEMobile\/10\.0/)) { ...@@ -884,8 +884,8 @@ if (navigator.userAgent.match(/IEMobile\/10\.0/)) {
{% highlight html %} {% highlight html %}
<script> <script>
var nua = navigator.userAgent; var nua = navigator.userAgent;
var is_android = ((nua.indexOf('Mozilla/5.0') > -1 && nua.indexOf('Android ') > -1 && nua.indexOf('AppleWebKit') > -1) && !(nua.indexOf('Chrome') > -1)); var isAndroid = (nua.indexOf('Mozilla/5.0') > -1 && nua.indexOf('Android ') > -1 && nua.indexOf('AppleWebKit') > -1 && nua.indexOf('Chrome') === -1);
if(is_android) { if (isAndroid) {
$('select.form-control').removeClass('form-control').css('width', '100%'); $('select.form-control').removeClass('form-control').css('width', '100%');
} }
</script> </script>
......
...@@ -245,7 +245,7 @@ $('#myModal').on('show.bs.modal', function (e) { ...@@ -245,7 +245,7 @@ $('#myModal').on('show.bs.modal', function (e) {
<!-- Large modal --> <!-- Large modal -->
<button class="btn btn-primary" data-toggle="modal" data-target=".bs-modal-lg">Large modal</button> <button class="btn btn-primary" data-toggle="modal" data-target=".bs-modal-lg">Large modal</button>
<div class="modal fade bs-modal-lg" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> <div class="modal fade bs-modal-lg" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg"> <div class="modal-dialog modal-lg">
<div class="modal-content"> <div class="modal-content">
... ...
...@@ -256,7 +256,7 @@ $('#myModal').on('show.bs.modal', function (e) { ...@@ -256,7 +256,7 @@ $('#myModal').on('show.bs.modal', function (e) {
<!-- Small modal --> <!-- Small modal -->
<button class="btn btn-primary" data-toggle="modal" data-target=".bs-modal-sm">Small modal</button> <button class="btn btn-primary" data-toggle="modal" data-target=".bs-modal-sm">Small modal</button>
<div class="modal fade bs-modal-sm" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> <div class="modal fade bs-modal-sm" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">
<div class="modal-dialog modal-sm"> <div class="modal-dialog modal-sm">
<div class="modal-content"> <div class="modal-content">
... ...
...@@ -266,13 +266,13 @@ $('#myModal').on('show.bs.modal', function (e) { ...@@ -266,13 +266,13 @@ $('#myModal').on('show.bs.modal', function (e) {
{% endhighlight %} {% endhighlight %}
<!-- Modal content for the above example --> <!-- Modal content for the above example -->
<div class="modal fade bs-modal-lg" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> <div class="modal fade bs-modal-lg" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg"> <div class="modal-dialog modal-lg">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title" id="myModalLabel">Large modal</h4> <h4 class="modal-title" id="myLargeModalLabel">Large modal</h4>
</div> </div>
<div class="modal-body"> <div class="modal-body">
... ...
...@@ -280,13 +280,13 @@ $('#myModal').on('show.bs.modal', function (e) { ...@@ -280,13 +280,13 @@ $('#myModal').on('show.bs.modal', function (e) {
</div><!-- /.modal-content --> </div><!-- /.modal-content -->
</div><!-- /.modal-dialog --> </div><!-- /.modal-dialog -->
</div><!-- /.modal --> </div><!-- /.modal -->
<div class="modal fade bs-modal-sm" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> <div class="modal fade bs-modal-sm" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">
<div class="modal-dialog modal-sm"> <div class="modal-dialog modal-sm">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title" id="myModalLabel">Small modal</h4> <h4 class="modal-title" id="mySmallModalLabel">Small modal</h4>
</div> </div>
<div class="modal-body"> <div class="modal-body">
... ...
...@@ -2053,7 +2053,7 @@ $('#myCarousel').on('slide.bs.carousel', function () { ...@@ -2053,7 +2053,7 @@ $('#myCarousel').on('slide.bs.carousel', function () {
<p>The affix plugin toggles between three classes, each representing a particular state: <code>.affix</code>, <code>.affix-top</code>, and <code>.affix-bottom</code>. You must provide the styles for these classes yourself (independent of this plugin) to handle the actual positions.</p> <p>The affix plugin toggles between three classes, each representing a particular state: <code>.affix</code>, <code>.affix-top</code>, and <code>.affix-bottom</code>. You must provide the styles for these classes yourself (independent of this plugin) to handle the actual positions.</p>
<p>Here's how the affix plugin works:</p> <p>Here's how the affix plugin works:</p>
<ol> <ol>
<li>To start, the plugin adds <code>.affix-top</code> to indicate the element is in it's top-most position. At this point no CSS positioning is required.</li> <li>To start, the plugin adds <code>.affix-top</code> to indicate the element is in its top-most position. At this point no CSS positioning is required.</li>
<li>Scrolling past the element you want affixed should trigger the actual affixing. This is where <code>.affix</code> replaces <code>.affix-top</code> and sets <code>position: fixed;</code> (provided by Bootstrap's code CSS).</li> <li>Scrolling past the element you want affixed should trigger the actual affixing. This is where <code>.affix</code> replaces <code>.affix-top</code> and sets <code>position: fixed;</code> (provided by Bootstrap's code CSS).</li>
<li>If a bottom offset is defined, scrolling past that should replace <code>.affix</code> with <code>.affix-bottom</code>. Since offsets are optional, setting one requires you to set the appropriate CSS. In this case, add <code>position: absolute;</code> when necessary. The plugin uses the data attribute or JavaScript option to determine where to position the element from there.</li> <li>If a bottom offset is defined, scrolling past that should replace <code>.affix</code> with <code>.affix-bottom</code>. Since offsets are optional, setting one requires you to set the appropriate CSS. In this case, add <code>position: absolute;</code> when necessary. The plugin uses the data attribute or JavaScript option to determine where to position the element from there.</li>
</ol> </ol>
......
...@@ -265,7 +265,7 @@ input[type="checkbox"], ...@@ -265,7 +265,7 @@ input[type="checkbox"],
// Feedback icon (requires .glyphicon classes) // Feedback icon (requires .glyphicon classes)
.form-control-feedback { .form-control-feedback {
position: absolute; position: absolute;
top: (@line-height-computed + 5); // Height of the `label` and it's margin top: (@line-height-computed + 5); // Height of the `label` and its margin
right: 0; right: 0;
display: block; display: block;
width: @input-height-base; width: @input-height-base;
......
...@@ -212,7 +212,7 @@ ...@@ -212,7 +212,7 @@
// Navbar nav links // Navbar nav links
// //
// Builds on top of the `.nav` components with it's own modifier class to make // Builds on top of the `.nav` components with its own modifier class to make
// the nav the full height of the horizontal nav (above 768px). // the nav the full height of the horizontal nav (above 768px).
.navbar-nav { .navbar-nav {
......
...@@ -91,7 +91,7 @@ ...@@ -91,7 +91,7 @@
} }
} }
// Active state, and it's :hover to override normal :hover // Active state, and its :hover to override normal :hover
&.active > a { &.active > a {
&, &,
&:hover, &:hover,
......
...@@ -95,15 +95,17 @@ ...@@ -95,15 +95,17 @@
border: 0; border: 0;
margin-bottom: 0; margin-bottom: 0;
} }
> .table-striped > tbody > tr:last-child, > .table-striped,
> .table-responsive > .table-striped > tbody > tr:last-child { > .table-responsive > .table-striped {
td:first-child, > tbody > tr:last-child {
th:first-child { td:first-child,
border-bottom-left-radius: (@panel-border-radius - 1); th:first-child {
} border-bottom-left-radius: (@panel-border-radius - 1);
td:last-child, }
th:last-child { td:last-child,
border-bottom-left-radius: (@panel-border-radius - 1); th:last-child {
border-bottom-left-radius: (@panel-border-radius - 1);
}
} }
} }
} }
...@@ -120,7 +122,7 @@ ...@@ -120,7 +122,7 @@
} }
} }
// Within heading, strip any `h*` tag of it's default margins for spacing. // Within heading, strip any `h*` tag of its default margins for spacing.
.panel-title { .panel-title {
margin-top: 0; margin-top: 0;
margin-bottom: 0; margin-bottom: 0;
......
...@@ -126,7 +126,7 @@ cite { font-style: normal; } ...@@ -126,7 +126,7 @@ cite { font-style: normal; }
// For now we'll leave these alongside the text classes until v4 when we can // For now we'll leave these alongside the text classes until v4 when we can
// safely shift things around (per SemVer rules). // safely shift things around (per SemVer rules).
.bg-primary { .bg-primary {
// Given the contrast here, this is the only class to have it's color inverted // Given the contrast here, this is the only class to have its color inverted
// automatically. // automatically.
color: #fff; color: #fff;
background-color: @brand-primary; background-color: @brand-primary;
......
...@@ -3,7 +3,7 @@ from __future__ import absolute_import, unicode_literals, print_function, divisi ...@@ -3,7 +3,7 @@ from __future__ import absolute_import, unicode_literals, print_function, divisi
from sys import argv from sys import argv
from os import environ, stat, remove as _delete_file from os import environ, stat, remove as _delete_file
from os.path import isfile from os.path import isfile, dirname, basename, abspath
from hashlib import sha256 from hashlib import sha256
from subprocess import check_call as run from subprocess import check_call as run
...@@ -12,7 +12,6 @@ from boto.s3.key import Key ...@@ -12,7 +12,6 @@ from boto.s3.key import Key
from boto.exception import S3ResponseError from boto.exception import S3ResponseError
NODE_MODULES_TARBALL = 'node_modules.tar.gz'
NEED_TO_UPLOAD_MARKER = '.need-to-upload' NEED_TO_UPLOAD_MARKER = '.need-to-upload'
BYTES_PER_MB = 1024 * 1024 BYTES_PER_MB = 1024 * 1024
try: try:
...@@ -25,7 +24,9 @@ def _sha256_of_file(filename): ...@@ -25,7 +24,9 @@ def _sha256_of_file(filename):
hasher = sha256() hasher = sha256()
with open(filename, 'rb') as input_file: with open(filename, 'rb') as input_file:
hasher.update(input_file.read()) hasher.update(input_file.read())
return hasher.hexdigest() file_hash = hasher.hexdigest()
print('sha256({}) = {}'.format(filename, file_hash))
return file_hash
def _delete_file_quietly(filename): def _delete_file_quietly(filename):
...@@ -35,52 +36,71 @@ def _delete_file_quietly(filename): ...@@ -35,52 +36,71 @@ def _delete_file_quietly(filename):
pass pass
def _tarball_size(): def _tarball_size(directory):
kib = stat(NODE_MODULES_TARBALL).st_size // BYTES_PER_MB kib = stat(_tarball_filename_for(directory)).st_size // BYTES_PER_MB
return "{} MiB".format(kib) return "{} MiB".format(kib)
def _tarball_filename_for(directory):
return abspath('./{}.tar.gz'.format(basename(directory)))
def _create_tarball(directory):
print("Creating tarball of {}...".format(directory))
run(['tar', '-czf', _tarball_filename_for(directory), '-C', dirname(directory), basename(directory)])
def _extract_tarball(directory):
print("Extracting tarball of {}...".format(directory))
run(['tar', '-xzf', _tarball_filename_for(directory), '-C', dirname(directory)])
def download(directory):
_delete_file_quietly(NEED_TO_UPLOAD_MARKER)
try:
print("Downloading {} tarball from S3...".format(basename(directory)))
key.get_contents_to_filename(_tarball_filename_for(directory))
except S3ResponseError as err:
open(NEED_TO_UPLOAD_MARKER, 'a').close()
print(err)
raise SystemExit("Cached {} download failed!".format(basename(directory)))
print("Downloaded {}.".format(_tarball_size(directory)))
_extract_tarball(directory)
print("{} successfully installed from cache.".format(directory))
def upload(directory):
_create_tarball(directory)
print("Uploading {} tarball to S3... ({})".format(basename(directory), _tarball_size(directory)))
key.set_contents_from_filename(_tarball_filename_for(directory))
print("{} cache successfully updated.".format(directory))
_delete_file_quietly(NEED_TO_UPLOAD_MARKER)
if __name__ == '__main__': if __name__ == '__main__':
# Uses environment variables: # Uses environment variables:
# AWS_ACCESS_KEY_ID - AWS Access Key ID # AWS_ACCESS_KEY_ID - AWS Access Key ID
# AWS_SECRET_ACCESS_KEY - AWS Secret Access Key # AWS_SECRET_ACCESS_KEY - AWS Secret Access Key
argv.pop(0) argv.pop(0)
if len(argv) != 1: if len(argv) != 3:
raise SystemExit("USAGE: node_modules_cache.py <download | upload>") raise SystemExit("USAGE: node_modules_cache.py <download | upload> <dependencies file> <directory>")
mode = argv.pop() mode, dependencies_file, directory = argv
conn = S3Connection() conn = S3Connection()
bucket = conn.lookup(BUCKET_NAME) bucket = conn.lookup(BUCKET_NAME)
if bucket is None: if bucket is None:
raise SystemExit("Could not access bucket!") raise SystemExit("Could not access bucket!")
package_json_hash = _sha256_of_file('package.json') dependencies_file_hash = _sha256_of_file(dependencies_file)
print('sha256(package.json) = ' + package_json_hash)
key = Key(bucket, package_json_hash) key = Key(bucket, dependencies_file_hash)
key.storage_class = 'REDUCED_REDUNDANCY' key.storage_class = 'REDUCED_REDUNDANCY'
if mode == 'download': if mode == 'download':
_delete_file_quietly(NEED_TO_UPLOAD_MARKER) download(directory)
try:
print("Downloading tarball from S3...")
key.get_contents_to_filename(NODE_MODULES_TARBALL)
except S3ResponseError as err:
open(NEED_TO_UPLOAD_MARKER, 'a').close()
print(err)
raise SystemExit("Cached node_modules download failed!")
print("Downloaded {}.".format(_tarball_size()))
print("Extracting tarball...")
run(['tar', 'xzf', NODE_MODULES_TARBALL])
print("node_modules successfully installed from cache.")
elif mode == 'upload': elif mode == 'upload':
if isfile(NEED_TO_UPLOAD_MARKER): if isfile(NEED_TO_UPLOAD_MARKER): # FIXME
print("Creating tarball...") upload(directory)
run(['tar', 'czf', NODE_MODULES_TARBALL, 'node_modules'])
print("Uploading tarball to S3... ({})".format(_tarball_size()))
key.set_contents_from_filename(NODE_MODULES_TARBALL)
print("node_modules cache successfully updated.")
_delete_file_quietly(NEED_TO_UPLOAD_MARKER)
else: else:
print("No need to upload anything.") print("No need to upload anything.")
else: else:
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment