2
0
mirror of https://github.com/tenrok/bootstrap.git synced 2026-06-20 20:00:36 +03:00

Merge branch 'v4-dev' into rip-custom

This commit is contained in:
Mark Otto
2017-06-14 20:45:31 -07:00
committed by GitHub
49 changed files with 1529 additions and 1126 deletions
+1 -1
View File
@@ -114,7 +114,7 @@ linters:
NestingDepth: NestingDepth:
enabled: true enabled: true
max_depth: 4 max_depth: 5
ignore_parent_selectors: false ignore_parent_selectors: false
PlaceholderInExtend: PlaceholderInExtend:
+1 -1
View File
@@ -18,7 +18,7 @@ module.exports = function (grunt) {
concurrency: 10, concurrency: 10,
maxRetries: 3, maxRetries: 3,
maxPollRetries: 4, maxPollRetries: 4,
urls: ['http://127.0.0.1:3000/js/tests/index.html?hidepassed'], urls: ['http://localhost:3000/js/tests/index.html?hidepassed'],
browsers: grunt.file.readYAML('build/sauce_browsers.yml') browsers: grunt.file.readYAML('build/sauce_browsers.yml')
} }
} }
+2 -2
View File
@@ -53,5 +53,5 @@ cdn:
js_hash: "sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" js_hash: "sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn"
jquery: https://code.jquery.com/jquery-3.2.1.slim.min.js jquery: https://code.jquery.com/jquery-3.2.1.slim.min.js
jquery_hash: "sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" jquery_hash: "sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
popper: https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.9.9/umd/popper.min.js popper: https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.10.1/umd/popper.min.js
popper_hash: "sha256-c477vRLKQv1jt9o7w6TTBzFyFznTaZjoMLTDFi7Hlxc=" popper_hash: "sha256-nxD3NU7Wocq19nG7DTQAx9troUwVoxjUhYrAhFSO3HM="
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+6 -2
View File
@@ -1,7 +1,7 @@
// scss-lint:disable VendorPrefix // scss-lint:disable VendorPrefix
// //
// Side navigation // Right side table of contents
// //
.bd-toc { .bd-toc {
@@ -34,7 +34,7 @@
a { a {
display: block; display: block;
padding: .25rem 1.5rem; padding: .125rem 1.5rem;
color: #99979c; color: #99979c;
&:hover { &:hover {
@@ -44,6 +44,10 @@
} }
} }
//
// Left side navigation
//
.bd-sidebar { .bd-sidebar {
background-color: #f5f2f9; background-color: #f5f2f9;
border-bottom: 1px solid rgba(0,0,0,.1); border-bottom: 1px solid rgba(0,0,0,.1);
+1 -1
View File
@@ -32,6 +32,6 @@
], ],
"dependencies": { "dependencies": {
"jquery": ">=1.9.1", "jquery": ">=1.9.1",
"popper.js": "^1.9.9" "popper.js": "^1.10.1"
} }
} }
+3 -3
View File
@@ -3390,9 +3390,9 @@
"dev": true "dev": true
}, },
"popper.js": { "popper.js": {
"version": "1.9.9", "version": "1.10.1",
"from": "popper.js@>=1.9.9 <3.0.0", "from": "popper.js@>=1.10.1 <2.0.0",
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.9.9.tgz" "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.10.1.tgz"
}, },
"postcss": { "postcss": {
"version": "5.2.17", "version": "5.2.17",
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+167 -113
View File
@@ -2156,7 +2156,7 @@ pre code {
.form-control { .form-control {
display: block; display: block;
width: 100%; width: 100%;
padding: 0.5rem 1rem; padding: 0.5rem 0.75rem;
font-size: 1rem; font-size: 1rem;
line-height: 1.25; line-height: 1.25;
color: #464a4c; color: #464a4c;
@@ -2249,7 +2249,7 @@ select.form-control:focus::-ms-value {
font-size: 1rem; font-size: 1rem;
} }
.form-control-static { .form-control-plaintext {
padding-top: 0.5rem; padding-top: 0.5rem;
padding-bottom: 0.5rem; padding-bottom: 0.5rem;
margin-bottom: 0; margin-bottom: 0;
@@ -2258,11 +2258,11 @@ select.form-control:focus::-ms-value {
border-width: 1px 0; border-width: 1px 0;
} }
.form-control-static.form-control-sm, .input-group-sm > .form-control-static.form-control, .form-control-plaintext.form-control-sm, .input-group-sm > .form-control-plaintext.form-control,
.input-group-sm > .form-control-static.input-group-addon, .input-group-sm > .form-control-plaintext.input-group-addon,
.input-group-sm > .input-group-btn > .form-control-static.btn, .form-control-static.form-control-lg, .input-group-lg > .form-control-static.form-control, .input-group-sm > .input-group-btn > .form-control-plaintext.btn, .form-control-plaintext.form-control-lg, .input-group-lg > .form-control-plaintext.form-control,
.input-group-lg > .form-control-static.input-group-addon, .input-group-lg > .form-control-plaintext.input-group-addon,
.input-group-lg > .input-group-btn > .form-control-static.btn { .input-group-lg > .input-group-btn > .form-control-plaintext.btn {
padding-right: 0; padding-right: 0;
padding-left: 0; padding-left: 0;
} }
@@ -2294,7 +2294,7 @@ select.form-control-sm:not([size]):not([multiple]), .input-group-sm > select.for
select.form-control-lg:not([size]):not([multiple]), .input-group-lg > select.form-control:not([size]):not([multiple]), select.form-control-lg:not([size]):not([multiple]), .input-group-lg > select.form-control:not([size]):not([multiple]),
.input-group-lg > select.input-group-addon:not([size]):not([multiple]), .input-group-lg > select.input-group-addon:not([size]):not([multiple]),
.input-group-lg > .input-group-btn > select.btn:not([size]):not([multiple]) { .input-group-lg > .input-group-btn > select.btn:not([size]):not([multiple]) {
height: calc(2.875rem + 2px); height: calc(2.3125rem + 2px);
} }
.form-group { .form-group {
@@ -2306,6 +2306,24 @@ select.form-control-lg:not([size]):not([multiple]), .input-group-lg > select.for
margin-top: 0.25rem; margin-top: 0.25rem;
} }
.form-row {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
margin-right: -5px;
margin-left: -5px;
}
.form-row > .col,
.form-row > [class*="col-"] {
padding-right: 5px;
padding-left: 5px;
}
.form-check { .form-check {
position: relative; position: relative;
display: block; display: block;
@@ -2343,90 +2361,124 @@ select.form-control-lg:not([size]):not([multiple]), .input-group-lg > select.for
margin-left: 0.75rem; margin-left: 0.75rem;
} }
.form-control-feedback { .invalid-feedback {
margin-top: 0.25rem; display: none;
} margin-top: .25rem;
font-size: .875rem;
.form-control-success,
.form-control-warning,
.form-control-danger {
padding-right: 3rem;
background-repeat: no-repeat;
background-position: center right 0.5625rem;
-webkit-background-size: 1.125rem 1.125rem;
background-size: 1.125rem 1.125rem;
}
.has-success .form-control-feedback,
.has-success .form-control-label,
.has-success .col-form-label,
.has-success .form-check-label,
.has-success .custom-control {
color: #5cb85c;
}
.has-success .form-control,
.has-success .custom-select,
.has-success .custom-file-control {
border-color: #5cb85c;
}
.has-success .input-group-addon {
color: #5cb85c;
background-color: #eaf6ea;
border-color: #5cb85c;
}
.has-success .form-control-success {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%235cb85c' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E");
}
.has-warning .form-control-feedback,
.has-warning .form-control-label,
.has-warning .col-form-label,
.has-warning .form-check-label,
.has-warning .custom-control {
color: #f0ad4e;
}
.has-warning .form-control,
.has-warning .custom-select,
.has-warning .custom-file-control {
border-color: #f0ad4e;
}
.has-warning .input-group-addon {
color: #f0ad4e;
background-color: white;
border-color: #f0ad4e;
}
.has-warning .form-control-warning {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23f0ad4e' d='M4.4 5.324h-.8v-2.46h.8zm0 1.42h-.8V5.89h.8zM3.76.63L.04 7.075c-.115.2.016.425.26.426h7.397c.242 0 .372-.226.258-.426C6.726 4.924 5.47 2.79 4.253.63c-.113-.174-.39-.174-.494 0z'/%3E%3C/svg%3E");
}
.has-danger .form-control-feedback,
.has-danger .form-control-label,
.has-danger .col-form-label,
.has-danger .form-check-label,
.has-danger .custom-control {
color: #d9534f; color: #d9534f;
} }
.has-danger .form-control, .invalid-tooltip {
.has-danger .custom-select, position: absolute;
.has-danger .custom-file-control { top: 100%;
z-index: 5;
display: none;
width: 250px;
padding: .5rem;
margin-top: .1rem;
font-size: .875rem;
line-height: 1;
color: #fff;
background-color: rgba(217, 83, 79, 0.8);
border-radius: .2rem;
}
.was-validated .form-control:valid, .form-control.is-valid, .was-validated
.custom-select:valid,
.custom-select.is-valid {
border-color: #5cb85c;
}
.was-validated .form-control:valid:focus, .form-control.is-valid:focus, .was-validated
.custom-select:valid:focus,
.custom-select.is-valid:focus {
-webkit-box-shadow: 0 0 0 0.2rem rgba(92, 184, 92, 0.25);
box-shadow: 0 0 0 0.2rem rgba(92, 184, 92, 0.25);
}
.was-validated .form-control:valid ~ .invalid-feedback,
.was-validated .form-control:valid ~ .invalid-tooltip, .form-control.is-valid ~ .invalid-feedback,
.form-control.is-valid ~ .invalid-tooltip, .was-validated
.custom-select:valid ~ .invalid-feedback,
.was-validated
.custom-select:valid ~ .invalid-tooltip,
.custom-select.is-valid ~ .invalid-feedback,
.custom-select.is-valid ~ .invalid-tooltip {
display: block;
}
.was-validated .form-check-input:valid + .form-check-label, .form-check-input.is-valid + .form-check-label {
color: #5cb85c;
}
.was-validated .custom-control-input:valid ~ .custom-control-indicator, .custom-control-input.is-valid ~ .custom-control-indicator {
background-color: rgba(92, 184, 92, 0.25);
}
.was-validated .custom-control-input:valid ~ .custom-control-description, .custom-control-input.is-valid ~ .custom-control-description {
color: #5cb85c;
}
.was-validated .custom-file-input:valid ~ .custom-file-control, .custom-file-input.is-valid ~ .custom-file-control {
border-color: #5cb85c;
}
.was-validated .custom-file-input:valid ~ .custom-file-control::before, .custom-file-input.is-valid ~ .custom-file-control::before {
border-color: inherit;
}
.was-validated .custom-file-input:valid:focus, .custom-file-input.is-valid:focus {
-webkit-box-shadow: 0 0 0 0.2rem rgba(92, 184, 92, 0.25);
box-shadow: 0 0 0 0.2rem rgba(92, 184, 92, 0.25);
}
.was-validated .form-control:invalid, .form-control.is-invalid, .was-validated
.custom-select:invalid,
.custom-select.is-invalid {
border-color: #d9534f; border-color: #d9534f;
} }
.has-danger .input-group-addon { .was-validated .form-control:invalid:focus, .form-control.is-invalid:focus, .was-validated
.custom-select:invalid:focus,
.custom-select.is-invalid:focus {
-webkit-box-shadow: 0 0 0 0.2rem rgba(217, 83, 79, 0.25);
box-shadow: 0 0 0 0.2rem rgba(217, 83, 79, 0.25);
}
.was-validated .form-control:invalid ~ .invalid-feedback,
.was-validated .form-control:invalid ~ .invalid-tooltip, .form-control.is-invalid ~ .invalid-feedback,
.form-control.is-invalid ~ .invalid-tooltip, .was-validated
.custom-select:invalid ~ .invalid-feedback,
.was-validated
.custom-select:invalid ~ .invalid-tooltip,
.custom-select.is-invalid ~ .invalid-feedback,
.custom-select.is-invalid ~ .invalid-tooltip {
display: block;
}
.was-validated .form-check-input:invalid + .form-check-label, .form-check-input.is-invalid + .form-check-label {
color: #d9534f; color: #d9534f;
background-color: #fdf7f7; }
.was-validated .custom-control-input:invalid ~ .custom-control-indicator, .custom-control-input.is-invalid ~ .custom-control-indicator {
background-color: rgba(217, 83, 79, 0.25);
}
.was-validated .custom-control-input:invalid ~ .custom-control-description, .custom-control-input.is-invalid ~ .custom-control-description {
color: #d9534f;
}
.was-validated .custom-file-input:invalid ~ .custom-file-control, .custom-file-input.is-invalid ~ .custom-file-control {
border-color: #d9534f; border-color: #d9534f;
} }
.has-danger .form-control-danger { .was-validated .custom-file-input:invalid ~ .custom-file-control::before, .custom-file-input.is-invalid ~ .custom-file-control::before {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23d9534f' viewBox='-2 -2 7 7'%3E%3Cpath stroke='%23d9534f' d='M0 0l3 3m0-3L0 3'/%3E%3Ccircle r='.5'/%3E%3Ccircle cx='3' r='.5'/%3E%3Ccircle cy='3' r='.5'/%3E%3Ccircle cx='3' cy='3' r='.5'/%3E%3C/svg%3E"); border-color: inherit;
}
.was-validated .custom-file-input:invalid:focus, .custom-file-input.is-invalid:focus {
-webkit-box-shadow: 0 0 0 0.2rem rgba(217, 83, 79, 0.25);
box-shadow: 0 0 0 0.2rem rgba(217, 83, 79, 0.25);
} }
.form-inline { .form-inline {
@@ -2563,7 +2615,7 @@ select.form-control-lg:not([size]):not([multiple]), .input-group-lg > select.for
-ms-user-select: none; -ms-user-select: none;
user-select: none; user-select: none;
border: 1px solid transparent; border: 1px solid transparent;
padding: 0.5rem 1rem; padding: 0.5rem 0.75rem;
font-size: 1rem; font-size: 1rem;
line-height: 1.25; line-height: 1.25;
border-radius: 0.25rem; border-radius: 0.25rem;
@@ -2578,8 +2630,8 @@ select.form-control-lg:not([size]):not([multiple]), .input-group-lg > select.for
.btn:focus, .btn.focus { .btn:focus, .btn.focus {
outline: 0; outline: 0;
-webkit-box-shadow: 0 0 0 2px rgba(2, 117, 216, 0.25); -webkit-box-shadow: 0 0 0 3px rgba(2, 117, 216, 0.25);
box-shadow: 0 0 0 2px rgba(2, 117, 216, 0.25); box-shadow: 0 0 0 3px rgba(2, 117, 216, 0.25);
} }
.btn.disabled, .btn:disabled { .btn.disabled, .btn:disabled {
@@ -2608,8 +2660,8 @@ fieldset[disabled] a.btn {
} }
.btn-primary:focus, .btn-primary.focus { .btn-primary:focus, .btn-primary.focus {
-webkit-box-shadow: 0 0 0 2px rgba(2, 117, 216, 0.5); -webkit-box-shadow: 0 0 0 3px rgba(2, 117, 216, 0.5);
box-shadow: 0 0 0 2px rgba(2, 117, 216, 0.5); box-shadow: 0 0 0 3px rgba(2, 117, 216, 0.5);
} }
.btn-primary.disabled, .btn-primary:disabled { .btn-primary.disabled, .btn-primary:disabled {
@@ -2638,8 +2690,8 @@ fieldset[disabled] a.btn {
} }
.btn-secondary:focus, .btn-secondary.focus { .btn-secondary:focus, .btn-secondary.focus {
-webkit-box-shadow: 0 0 0 2px rgba(204, 204, 204, 0.5); -webkit-box-shadow: 0 0 0 3px rgba(204, 204, 204, 0.5);
box-shadow: 0 0 0 2px rgba(204, 204, 204, 0.5); box-shadow: 0 0 0 3px rgba(204, 204, 204, 0.5);
} }
.btn-secondary.disabled, .btn-secondary:disabled { .btn-secondary.disabled, .btn-secondary:disabled {
@@ -2668,8 +2720,8 @@ fieldset[disabled] a.btn {
} }
.btn-info:focus, .btn-info.focus { .btn-info:focus, .btn-info.focus {
-webkit-box-shadow: 0 0 0 2px rgba(91, 192, 222, 0.5); -webkit-box-shadow: 0 0 0 3px rgba(91, 192, 222, 0.5);
box-shadow: 0 0 0 2px rgba(91, 192, 222, 0.5); box-shadow: 0 0 0 3px rgba(91, 192, 222, 0.5);
} }
.btn-info.disabled, .btn-info:disabled { .btn-info.disabled, .btn-info:disabled {
@@ -2698,8 +2750,8 @@ fieldset[disabled] a.btn {
} }
.btn-success:focus, .btn-success.focus { .btn-success:focus, .btn-success.focus {
-webkit-box-shadow: 0 0 0 2px rgba(92, 184, 92, 0.5); -webkit-box-shadow: 0 0 0 3px rgba(92, 184, 92, 0.5);
box-shadow: 0 0 0 2px rgba(92, 184, 92, 0.5); box-shadow: 0 0 0 3px rgba(92, 184, 92, 0.5);
} }
.btn-success.disabled, .btn-success:disabled { .btn-success.disabled, .btn-success:disabled {
@@ -2728,8 +2780,8 @@ fieldset[disabled] a.btn {
} }
.btn-warning:focus, .btn-warning.focus { .btn-warning:focus, .btn-warning.focus {
-webkit-box-shadow: 0 0 0 2px rgba(240, 173, 78, 0.5); -webkit-box-shadow: 0 0 0 3px rgba(240, 173, 78, 0.5);
box-shadow: 0 0 0 2px rgba(240, 173, 78, 0.5); box-shadow: 0 0 0 3px rgba(240, 173, 78, 0.5);
} }
.btn-warning.disabled, .btn-warning:disabled { .btn-warning.disabled, .btn-warning:disabled {
@@ -2758,8 +2810,8 @@ fieldset[disabled] a.btn {
} }
.btn-danger:focus, .btn-danger.focus { .btn-danger:focus, .btn-danger.focus {
-webkit-box-shadow: 0 0 0 2px rgba(217, 83, 79, 0.5); -webkit-box-shadow: 0 0 0 3px rgba(217, 83, 79, 0.5);
box-shadow: 0 0 0 2px rgba(217, 83, 79, 0.5); box-shadow: 0 0 0 3px rgba(217, 83, 79, 0.5);
} }
.btn-danger.disabled, .btn-danger:disabled { .btn-danger.disabled, .btn-danger:disabled {
@@ -2789,8 +2841,8 @@ fieldset[disabled] a.btn {
} }
.btn-outline-primary:focus, .btn-outline-primary.focus { .btn-outline-primary:focus, .btn-outline-primary.focus {
-webkit-box-shadow: 0 0 0 2px rgba(2, 117, 216, 0.5); -webkit-box-shadow: 0 0 0 3px rgba(2, 117, 216, 0.5);
box-shadow: 0 0 0 2px rgba(2, 117, 216, 0.5); box-shadow: 0 0 0 3px rgba(2, 117, 216, 0.5);
} }
.btn-outline-primary.disabled, .btn-outline-primary:disabled { .btn-outline-primary.disabled, .btn-outline-primary:disabled {
@@ -2819,8 +2871,8 @@ fieldset[disabled] a.btn {
} }
.btn-outline-secondary:focus, .btn-outline-secondary.focus { .btn-outline-secondary:focus, .btn-outline-secondary.focus {
-webkit-box-shadow: 0 0 0 2px rgba(204, 204, 204, 0.5); -webkit-box-shadow: 0 0 0 3px rgba(204, 204, 204, 0.5);
box-shadow: 0 0 0 2px rgba(204, 204, 204, 0.5); box-shadow: 0 0 0 3px rgba(204, 204, 204, 0.5);
} }
.btn-outline-secondary.disabled, .btn-outline-secondary:disabled { .btn-outline-secondary.disabled, .btn-outline-secondary:disabled {
@@ -2849,8 +2901,8 @@ fieldset[disabled] a.btn {
} }
.btn-outline-info:focus, .btn-outline-info.focus { .btn-outline-info:focus, .btn-outline-info.focus {
-webkit-box-shadow: 0 0 0 2px rgba(91, 192, 222, 0.5); -webkit-box-shadow: 0 0 0 3px rgba(91, 192, 222, 0.5);
box-shadow: 0 0 0 2px rgba(91, 192, 222, 0.5); box-shadow: 0 0 0 3px rgba(91, 192, 222, 0.5);
} }
.btn-outline-info.disabled, .btn-outline-info:disabled { .btn-outline-info.disabled, .btn-outline-info:disabled {
@@ -2879,8 +2931,8 @@ fieldset[disabled] a.btn {
} }
.btn-outline-success:focus, .btn-outline-success.focus { .btn-outline-success:focus, .btn-outline-success.focus {
-webkit-box-shadow: 0 0 0 2px rgba(92, 184, 92, 0.5); -webkit-box-shadow: 0 0 0 3px rgba(92, 184, 92, 0.5);
box-shadow: 0 0 0 2px rgba(92, 184, 92, 0.5); box-shadow: 0 0 0 3px rgba(92, 184, 92, 0.5);
} }
.btn-outline-success.disabled, .btn-outline-success:disabled { .btn-outline-success.disabled, .btn-outline-success:disabled {
@@ -2909,8 +2961,8 @@ fieldset[disabled] a.btn {
} }
.btn-outline-warning:focus, .btn-outline-warning.focus { .btn-outline-warning:focus, .btn-outline-warning.focus {
-webkit-box-shadow: 0 0 0 2px rgba(240, 173, 78, 0.5); -webkit-box-shadow: 0 0 0 3px rgba(240, 173, 78, 0.5);
box-shadow: 0 0 0 2px rgba(240, 173, 78, 0.5); box-shadow: 0 0 0 3px rgba(240, 173, 78, 0.5);
} }
.btn-outline-warning.disabled, .btn-outline-warning:disabled { .btn-outline-warning.disabled, .btn-outline-warning:disabled {
@@ -2939,8 +2991,8 @@ fieldset[disabled] a.btn {
} }
.btn-outline-danger:focus, .btn-outline-danger.focus { .btn-outline-danger:focus, .btn-outline-danger.focus {
-webkit-box-shadow: 0 0 0 2px rgba(217, 83, 79, 0.5); -webkit-box-shadow: 0 0 0 3px rgba(217, 83, 79, 0.5);
box-shadow: 0 0 0 2px rgba(217, 83, 79, 0.5); box-shadow: 0 0 0 3px rgba(217, 83, 79, 0.5);
} }
.btn-outline-danger.disabled, .btn-outline-danger:disabled { .btn-outline-danger.disabled, .btn-outline-danger:disabled {
@@ -3253,8 +3305,8 @@ tbody.collapse.show {
} }
.btn + .dropdown-toggle-split { .btn + .dropdown-toggle-split {
padding-right: 0.75rem; padding-right: 0.5625rem;
padding-left: 0.75rem; padding-left: 0.5625rem;
} }
.btn + .dropdown-toggle-split::after { .btn + .dropdown-toggle-split::after {
@@ -3392,7 +3444,7 @@ tbody.collapse.show {
} }
.input-group-addon { .input-group-addon {
padding: 0.5rem 1rem; padding: 0.5rem 0.75rem;
margin-bottom: 0; margin-bottom: 0;
font-size: 1rem; font-size: 1rem;
font-weight: normal; font-weight: normal;
@@ -3629,6 +3681,7 @@ tbody.collapse.show {
} }
.custom-select-sm { .custom-select-sm {
height: calc(1.8125rem + 2px);
padding-top: 0.375rem; padding-top: 0.375rem;
padding-bottom: 0.375rem; padding-bottom: 0.375rem;
font-size: 75%; font-size: 75%;
@@ -4288,6 +4341,8 @@ tbody.collapse.show {
-webkit-flex-direction: column; -webkit-flex-direction: column;
-ms-flex-direction: column; -ms-flex-direction: column;
flex-direction: column; flex-direction: column;
min-width: 0;
word-wrap: break-word;
background-color: #fff; background-color: #fff;
border: 1px solid rgba(0, 0, 0, 0.125); border: 1px solid rgba(0, 0, 0, 0.125);
border-radius: 0.25rem; border-radius: 0.25rem;
@@ -4303,7 +4358,6 @@ tbody.collapse.show {
.card-title { .card-title {
margin-bottom: 0.75rem; margin-bottom: 0.75rem;
word-break: break-all;
} }
.card-subtitle { .card-subtitle {
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+26 -6
View File
@@ -1107,6 +1107,14 @@ var Collapse = function ($) {
this._element = element; this._element = element;
this._config = this._getConfig(config); this._config = this._getConfig(config);
this._triggerArray = $.makeArray($('[data-toggle="collapse"][href="#' + element.id + '"],' + ('[data-toggle="collapse"][data-target="#' + element.id + '"]'))); this._triggerArray = $.makeArray($('[data-toggle="collapse"][href="#' + element.id + '"],' + ('[data-toggle="collapse"][data-target="#' + element.id + '"]')));
var tabToggles = $(Selector.DATA_TOGGLE);
for (var i = 0; i < tabToggles.length; i++) {
var elem = tabToggles[i];
var selector = Util.getSelectorFromElement(elem);
if (selector !== null && $(selector).filter(element).length > 0) {
this._triggerArray.push(elem);
}
}
this._parent = this._config.parent ? this._getParent() : null; this._parent = this._config.parent ? this._getParent() : null;
@@ -1225,7 +1233,16 @@ var Collapse = function ($) {
$(this._element).addClass(ClassName.COLLAPSING).removeClass(ClassName.COLLAPSE).removeClass(ClassName.SHOW); $(this._element).addClass(ClassName.COLLAPSING).removeClass(ClassName.COLLAPSE).removeClass(ClassName.SHOW);
if (this._triggerArray.length) { if (this._triggerArray.length) {
$(this._triggerArray).addClass(ClassName.COLLAPSED).attr('aria-expanded', false); for (var i = 0; i < this._triggerArray.length; i++) {
var trigger = this._triggerArray[i];
var selector = Util.getSelectorFromElement(trigger);
if (selector !== null) {
var $elem = $(selector);
if (!$elem.hasClass(ClassName.SHOW)) {
$(trigger).addClass(ClassName.COLLAPSED).attr('aria-expanded', false);
}
}
}
} }
this.setTransitioning(true); this.setTransitioning(true);
@@ -1353,11 +1370,14 @@ var Collapse = function ($) {
event.preventDefault(); event.preventDefault();
} }
var target = Collapse._getTargetFromElement(this); var $trigger = $(this);
var data = $(target).data(DATA_KEY); var selector = Util.getSelectorFromElement(this);
var config = data ? 'toggle' : $(this).data(); $(selector).each(function () {
var $target = $(this);
Collapse._jQueryInterface.call($(target), config); var data = $target.data(DATA_KEY);
var config = data ? 'toggle' : $trigger.data();
Collapse._jQueryInterface.call($target, config);
});
}); });
/** /**
+30 -1
View File
@@ -32,6 +32,35 @@ You can use a link with the `href` attribute, or a button with the `data-target`
</div> </div>
{% endexample %} {% endexample %}
## Multiple triggers / targets
A `<button>` or `<a>` can show and hide multiple elements by referencing them with a JQuery selector in its `href` or `data-target` attribute.
Multiple `<button>` or `<a>` can show and hide an element if they each reference it with their `href` or `data-target` attribute
{% example html %}
<p>
<a class="btn btn-primary" data-toggle="collapse" href="#multiCollapseExample1" aria-expanded="false" aria-controls="multiCollapseExample1">Toggle first element</a>
<button class="btn btn-primary" type="button" data-toggle="collapse" data-target="#multiCollapseExample2" aria-expanded="false" aria-controls="multiCollapseExample1">Toggle second element</button>
<button class="btn btn-primary" type="button" data-toggle="collapse" data-target=".multi-collapse" aria-expanded="false" aria-controls="multiCollapseExample1 multiCollapseExample2">Toggle both elements</button>
</p>
<div class="row">
<div class="col">
<div class="collapse multi-collapse" id="multiCollapseExample1">
<div class="card card-block">
Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident.
</div>
</div>
</div>
<div class="col">
<div class="collapse multi-collapse" id="multiCollapseExample2">
<div class="card card-block">
Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident.
</div>
</div>
</div>
</div>
{% endexample %}
## Accordion example ## Accordion example
Using the [card]({{ site.baseurl }}/docs/{{ site.docs_version }}/components/card/) component, you can extend the default collapse behavior to create an accordion. Using the [card]({{ site.baseurl }}/docs/{{ site.docs_version }}/components/card/) component, you can extend the default collapse behavior to create an accordion.
@@ -129,7 +158,7 @@ These classes can be found in `_transitions.scss`.
### Via data attributes ### Via data attributes
Just add `data-toggle="collapse"` and a `data-target` to the element to automatically assign control of a collapsible element. The `data-target` attribute accepts a CSS selector to apply the collapse to. Be sure to add the class `collapse` to the collapsible element. If you'd like it to default open, add the additional class `show`. Just add `data-toggle="collapse"` and a `data-target` to the element to automatically assign control of one or more collapsible elements. The `data-target` attribute accepts a CSS selector to apply the collapse to. Be sure to add the class `collapse` to the collapsible element. If you'd like it to default open, add the additional class `show`.
To add accordion-like group management to a collapsible area, add the data attribute `data-parent="#selector"`. Refer to the demo to see this in action. To add accordion-like group management to a collapsible area, add the data attribute `data-parent="#selector"`. Refer to the demo to see this in action.
+1 -1
View File
@@ -10,7 +10,7 @@ toc: true
Dropdowns are toggleable, contextual overlays for displaying lists of links and more. They're made interactive with the included Bootstrap dropdown JavaScript plugin. They're toggled by clicking, not by hovering; this is [an intentional design decision.](http://markdotto.com/2012/02/27/bootstrap-explained-dropdowns/) Dropdowns are toggleable, contextual overlays for displaying lists of links and more. They're made interactive with the included Bootstrap dropdown JavaScript plugin. They're toggled by clicking, not by hovering; this is [an intentional design decision.](http://markdotto.com/2012/02/27/bootstrap-explained-dropdowns/)
Dropdowns are built on a third party library, [Popper.js](https://popper.js.org), which provides dynamic positioning and viewport detection. Be sure to include [popper.min.js](https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.9.9/umd/popper.min.js) before Bootstrap's JavaScript. Dropdowns are built on a third party library, [Popper.js](https://popper.js.org), which provides dynamic positioning and viewport detection. Be sure to include [popper.min.js](https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.10.1/umd/popper.min.js) before Bootstrap's JavaScript.
## Accessibility ## Accessibility
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -11,7 +11,7 @@ toc: true
Things to know when using the popover plugin: Things to know when using the popover plugin:
- Popovers rely on the 3rd party library [Popper.js](https://popper.js.org) for positioning. You must include [popper.min.js](https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.9.9/umd/popper.min.js) before bootstrap.js in order for popovers to work! - Popovers rely on the 3rd party library [Popper.js](https://popper.js.org) for positioning. You must include [popper.min.js](https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.10.1/umd/popper.min.js) before bootstrap.js in order for popovers to work!
- Popovers require the [tooltip plugin]({{ site.baseurl }}/docs/{{ site.docs_version }}/components/tooltips/) as a dependency. - Popovers require the [tooltip plugin]({{ site.baseurl }}/docs/{{ site.docs_version }}/components/tooltips/) as a dependency.
- Popovers are opt-in for performance reasons, so **you must initialize them yourself**. - Popovers are opt-in for performance reasons, so **you must initialize them yourself**.
- Zero-length `title` and `content` values will never show a popover. - Zero-length `title` and `content` values will never show a popover.
+1 -1
View File
@@ -10,7 +10,7 @@ toc: true
Things to know when using the tooltip plugin: Things to know when using the tooltip plugin:
- Tooltips rely on the 3rd party library [Popper.js](https://popper.js.org) for positioning. You must include [popper.min.js](https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.9.9/umd/popper.min.js) before bootstrap.js in order for tooltips to work! - Tooltips rely on the 3rd party library [Popper.js](https://popper.js.org) for positioning. You must include [popper.min.js](https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.10.1/umd/popper.min.js) before bootstrap.js in order for tooltips to work!
- Tooltips are opt-in for performance reasons, so **you must initialize them yourself**. - Tooltips are opt-in for performance reasons, so **you must initialize them yourself**.
- Tooltips with zero-length titles are never displayed. - Tooltips with zero-length titles are never displayed.
- Specify `container: 'body'` to avoid rendering problems in more complex components (like our input groups, button groups, etc). - Specify `container: 'body'` to avoid rendering problems in more complex components (like our input groups, button groups, etc).
+1 -1
View File
@@ -118,7 +118,7 @@
<!-- Placed at the end of the document so the pages load faster --> <!-- Placed at the end of the document so the pages load faster -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script> <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script>window.jQuery || document.write('<script src="../../../../assets/js/vendor/jquery.min.js"><\/script>')</script> <script>window.jQuery || document.write('<script src="../../../../assets/js/vendor/jquery.min.js"><\/script>')</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.9.9/umd/popper.min.js" integrity="sha256-c477vRLKQv1jt9o7w6TTBzFyFznTaZjoMLTDFi7Hlxc=" crossorigin="anonymous"></script> <script src="../../../../assets/js/vendor/popper.min.js"></script>
<script src="../../../../assets/js/vendor/holder.min.js"></script> <script src="../../../../assets/js/vendor/holder.min.js"></script>
<script> <script>
$(function () { $(function () {
+1 -1
View File
@@ -158,7 +158,7 @@
<!-- Placed at the end of the document so the pages load faster --> <!-- Placed at the end of the document so the pages load faster -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script> <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script>window.jQuery || document.write('<script src="../../../../assets/js/vendor/jquery.min.js"><\/script>')</script> <script>window.jQuery || document.write('<script src="../../../../assets/js/vendor/jquery.min.js"><\/script>')</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.9.9/umd/popper.min.js" integrity="sha256-c477vRLKQv1jt9o7w6TTBzFyFznTaZjoMLTDFi7Hlxc=" crossorigin="anonymous"></script> <script src="../../../../assets/js/vendor/popper.min.js"></script>
<script src="../../../../dist/js/bootstrap.min.js"></script> <script src="../../../../dist/js/bootstrap.min.js"></script>
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug --> <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="../../../../assets/js/ie10-viewport-bug-workaround.js"></script> <script src="../../../../assets/js/ie10-viewport-bug-workaround.js"></script>
+1 -1
View File
@@ -176,7 +176,7 @@
<!-- Placed at the end of the document so the pages load faster --> <!-- Placed at the end of the document so the pages load faster -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script> <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script>window.jQuery || document.write('<script src="../../../../assets/js/vendor/jquery.min.js"><\/script>')</script> <script>window.jQuery || document.write('<script src="../../../../assets/js/vendor/jquery.min.js"><\/script>')</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.9.9/umd/popper.min.js" integrity="sha256-c477vRLKQv1jt9o7w6TTBzFyFznTaZjoMLTDFi7Hlxc=" crossorigin="anonymous"></script> <script src="../../../../assets/js/vendor/popper.min.js"></script>
<script src="../../../../dist/js/bootstrap.min.js"></script> <script src="../../../../dist/js/bootstrap.min.js"></script>
<!-- Just to make our placeholder images work. Don't actually copy the next line! --> <!-- Just to make our placeholder images work. Don't actually copy the next line! -->
<script src="../../../../assets/js/vendor/holder.min.js"></script> <script src="../../../../assets/js/vendor/holder.min.js"></script>
+1 -1
View File
@@ -60,7 +60,7 @@
<!-- Placed at the end of the document so the pages load faster --> <!-- Placed at the end of the document so the pages load faster -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script> <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script>window.jQuery || document.write('<script src="../../../../assets/js/vendor/jquery.min.js"><\/script>')</script> <script>window.jQuery || document.write('<script src="../../../../assets/js/vendor/jquery.min.js"><\/script>')</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.9.9/umd/popper.min.js" integrity="sha256-c477vRLKQv1jt9o7w6TTBzFyFznTaZjoMLTDFi7Hlxc=" crossorigin="anonymous"></script> <script src="../../../../assets/js/vendor/popper.min.js"></script>
<script src="../../../../dist/js/bootstrap.min.js"></script> <script src="../../../../dist/js/bootstrap.min.js"></script>
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug --> <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="../../../../assets/js/ie10-viewport-bug-workaround.js"></script> <script src="../../../../assets/js/ie10-viewport-bug-workaround.js"></script>
+1 -1
View File
@@ -254,7 +254,7 @@
<!-- Placed at the end of the document so the pages load faster --> <!-- Placed at the end of the document so the pages load faster -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script> <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script>window.jQuery || document.write('<script src="../../../../assets/js/vendor/jquery.min.js"><\/script>')</script> <script>window.jQuery || document.write('<script src="../../../../assets/js/vendor/jquery.min.js"><\/script>')</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.9.9/umd/popper.min.js" integrity="sha256-c477vRLKQv1jt9o7w6TTBzFyFznTaZjoMLTDFi7Hlxc=" crossorigin="anonymous"></script> <script src="../../../../assets/js/vendor/popper.min.js"></script>
<script src="../../../../dist/js/bootstrap.min.js"></script> <script src="../../../../dist/js/bootstrap.min.js"></script>
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug --> <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="../../../../assets/js/ie10-viewport-bug-workaround.js"></script> <script src="../../../../assets/js/ie10-viewport-bug-workaround.js"></script>
+1 -1
View File
@@ -93,7 +93,7 @@
<!-- Placed at the end of the document so the pages load faster --> <!-- Placed at the end of the document so the pages load faster -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script> <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script>window.jQuery || document.write('<script src="../../../../assets/js/vendor/jquery.min.js"><\/script>')</script> <script>window.jQuery || document.write('<script src="../../../../assets/js/vendor/jquery.min.js"><\/script>')</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.9.9/umd/popper.min.js" integrity="sha256-c477vRLKQv1jt9o7w6TTBzFyFznTaZjoMLTDFi7Hlxc=" crossorigin="anonymous"></script> <script src="../../../../assets/js/vendor/popper.min.js"></script>
<script src="../../../../dist/js/bootstrap.min.js"></script> <script src="../../../../dist/js/bootstrap.min.js"></script>
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug --> <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="../../../../assets/js/ie10-viewport-bug-workaround.js"></script> <script src="../../../../assets/js/ie10-viewport-bug-workaround.js"></script>
+1 -1
View File
@@ -96,7 +96,7 @@
<!-- Placed at the end of the document so the pages load faster --> <!-- Placed at the end of the document so the pages load faster -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script> <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script>window.jQuery || document.write('<script src="../../../../assets/js/vendor/jquery.min.js"><\/script>')</script> <script>window.jQuery || document.write('<script src="../../../../assets/js/vendor/jquery.min.js"><\/script>')</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.9.9/umd/popper.min.js" integrity="sha256-c477vRLKQv1jt9o7w6TTBzFyFznTaZjoMLTDFi7Hlxc=" crossorigin="anonymous"></script> <script src="../../../../assets/js/vendor/popper.min.js"></script>
<script src="../../../../dist/js/bootstrap.min.js"></script> <script src="../../../../dist/js/bootstrap.min.js"></script>
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug --> <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="../../../../assets/js/ie10-viewport-bug-workaround.js"></script> <script src="../../../../assets/js/ie10-viewport-bug-workaround.js"></script>
@@ -56,7 +56,7 @@
<!-- Placed at the end of the document so the pages load faster --> <!-- Placed at the end of the document so the pages load faster -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script> <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script>window.jQuery || document.write('<script src="../../../../assets/js/vendor/jquery.min.js"><\/script>')</script> <script>window.jQuery || document.write('<script src="../../../../assets/js/vendor/jquery.min.js"><\/script>')</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.9.9/umd/popper.min.js" integrity="sha256-c477vRLKQv1jt9o7w6TTBzFyFznTaZjoMLTDFi7Hlxc=" crossorigin="anonymous"></script> <script src="../../../../assets/js/vendor/popper.min.js"></script>
<script src="../../../../dist/js/bootstrap.min.js"></script> <script src="../../../../dist/js/bootstrap.min.js"></script>
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug --> <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="../../../../assets/js/ie10-viewport-bug-workaround.js"></script> <script src="../../../../assets/js/ie10-viewport-bug-workaround.js"></script>
+1 -1
View File
@@ -56,7 +56,7 @@
<!-- Placed at the end of the document so the pages load faster --> <!-- Placed at the end of the document so the pages load faster -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script> <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script>window.jQuery || document.write('<script src="../../../../assets/js/vendor/jquery.min.js"><\/script>')</script> <script>window.jQuery || document.write('<script src="../../../../assets/js/vendor/jquery.min.js"><\/script>')</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.9.9/umd/popper.min.js" integrity="sha256-c477vRLKQv1jt9o7w6TTBzFyFznTaZjoMLTDFi7Hlxc=" crossorigin="anonymous"></script> <script src="../../../../assets/js/vendor/popper.min.js"></script>
<script src="../../../../dist/js/bootstrap.min.js"></script> <script src="../../../../dist/js/bootstrap.min.js"></script>
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug --> <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="../../../../assets/js/ie10-viewport-bug-workaround.js"></script> <script src="../../../../assets/js/ie10-viewport-bug-workaround.js"></script>
+1 -1
View File
@@ -351,7 +351,7 @@
<!-- Placed at the end of the document so the pages load faster --> <!-- Placed at the end of the document so the pages load faster -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script> <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script>window.jQuery || document.write('<script src="../../../../assets/js/vendor/jquery.min.js"><\/script>')</script> <script>window.jQuery || document.write('<script src="../../../../assets/js/vendor/jquery.min.js"><\/script>')</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.9.9/umd/popper.min.js" integrity="sha256-c477vRLKQv1jt9o7w6TTBzFyFznTaZjoMLTDFi7Hlxc=" crossorigin="anonymous"></script> <script src="../../../../assets/js/vendor/popper.min.js"></script>
<script src="../../../../dist/js/bootstrap.min.js"></script> <script src="../../../../dist/js/bootstrap.min.js"></script>
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug --> <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="../../../../assets/js/ie10-viewport-bug-workaround.js"></script> <script src="../../../../assets/js/ie10-viewport-bug-workaround.js"></script>
+1 -1
View File
@@ -127,7 +127,7 @@
<!-- Placed at the end of the document so the pages load faster --> <!-- Placed at the end of the document so the pages load faster -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script> <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script>window.jQuery || document.write('<script src="../../../../assets/js/vendor/jquery.min.js"><\/script>')</script> <script>window.jQuery || document.write('<script src="../../../../assets/js/vendor/jquery.min.js"><\/script>')</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.9.9/umd/popper.min.js" integrity="sha256-c477vRLKQv1jt9o7w6TTBzFyFznTaZjoMLTDFi7Hlxc=" crossorigin="anonymous"></script> <script src="../../../../assets/js/vendor/popper.min.js"></script>
<script src="../../../../dist/js/bootstrap.min.js"></script> <script src="../../../../dist/js/bootstrap.min.js"></script>
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug --> <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="../../../../assets/js/ie10-viewport-bug-workaround.js"></script> <script src="../../../../assets/js/ie10-viewport-bug-workaround.js"></script>
@@ -66,7 +66,7 @@
<!-- Placed at the end of the document so the pages load faster --> <!-- Placed at the end of the document so the pages load faster -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script> <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script>window.jQuery || document.write('<script src="../../../../assets/js/vendor/jquery.min.js"><\/script>')</script> <script>window.jQuery || document.write('<script src="../../../../assets/js/vendor/jquery.min.js"><\/script>')</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.9.9/umd/popper.min.js" integrity="sha256-c477vRLKQv1jt9o7w6TTBzFyFznTaZjoMLTDFi7Hlxc=" crossorigin="anonymous"></script> <script src="../../../../assets/js/vendor/popper.min.js"></script>
<script src="../../../../dist/js/bootstrap.min.js"></script> <script src="../../../../dist/js/bootstrap.min.js"></script>
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug --> <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="../../../../assets/js/ie10-viewport-bug-workaround.js"></script> <script src="../../../../assets/js/ie10-viewport-bug-workaround.js"></script>
@@ -64,7 +64,7 @@
<!-- Placed at the end of the document so the pages load faster --> <!-- Placed at the end of the document so the pages load faster -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script> <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script>window.jQuery || document.write('<script src="../../../../assets/js/vendor/jquery.min.js"><\/script>')</script> <script>window.jQuery || document.write('<script src="../../../../assets/js/vendor/jquery.min.js"><\/script>')</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.9.9/umd/popper.min.js" integrity="sha256-c477vRLKQv1jt9o7w6TTBzFyFznTaZjoMLTDFi7Hlxc=" crossorigin="anonymous"></script> <script src="../../../../assets/js/vendor/popper.min.js"></script>
<script src="../../../../dist/js/bootstrap.min.js"></script> <script src="../../../../dist/js/bootstrap.min.js"></script>
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug --> <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="../../../../assets/js/ie10-viewport-bug-workaround.js"></script> <script src="../../../../assets/js/ie10-viewport-bug-workaround.js"></script>
@@ -39,7 +39,7 @@
<!-- Placed at the end of the document so the pages load faster --> <!-- Placed at the end of the document so the pages load faster -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script> <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script>window.jQuery || document.write('<script src="../../../../assets/js/vendor/jquery.min.js"><\/script>')</script> <script>window.jQuery || document.write('<script src="../../../../assets/js/vendor/jquery.min.js"><\/script>')</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.9.9/umd/popper.min.js" integrity="sha256-c477vRLKQv1jt9o7w6TTBzFyFznTaZjoMLTDFi7Hlxc=" crossorigin="anonymous"></script> <script src="../../../../assets/js/vendor/popper.min.js"></script>
<script src="../../../../dist/js/bootstrap.min.js"></script> <script src="../../../../dist/js/bootstrap.min.js"></script>
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug --> <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="../../../../assets/js/ie10-viewport-bug-workaround.js"></script> <script src="../../../../assets/js/ie10-viewport-bug-workaround.js"></script>
+3
View File
@@ -103,8 +103,11 @@ New to Bootstrap 4 is the [Reboot]({{ site.baseurl }}/docs/{{ site.docs_version
- Dropped the `.form-horizontal` class requirement. - Dropped the `.form-horizontal` class requirement.
- `.form-group` no longer applies styles from the `.row` via mixin, so `.row` is now required for horizontal grid layouts (e.g., `<div class="form-group row">`). - `.form-group` no longer applies styles from the `.row` via mixin, so `.row` is now required for horizontal grid layouts (e.g., `<div class="form-group row">`).
- Added new `.form-control-label` class to vertically center labels with `.form-control`s. - Added new `.form-control-label` class to vertically center labels with `.form-control`s.
- Added new `.form-row` for compact form layouts with the grid classes (swap your `.row` for a `.form-row` and go).
- Added custom forms support (for checkboxes, radios, selects, and file inputs). - Added custom forms support (for checkboxes, radios, selects, and file inputs).
- Added HTML5 form validation support via CSS's `:invalid` and `:valid` pseudo-classes.
- Renamed `.has-error` to `.has-danger`. - Renamed `.has-error` to `.has-danger`.
- Renamed `.form-control-static` to `.form-control-plaintext`.
### Buttons ### Buttons
+26 -6
View File
@@ -76,6 +76,14 @@ var Collapse = function ($) {
this._element = element; this._element = element;
this._config = this._getConfig(config); this._config = this._getConfig(config);
this._triggerArray = $.makeArray($('[data-toggle="collapse"][href="#' + element.id + '"],' + ('[data-toggle="collapse"][data-target="#' + element.id + '"]'))); this._triggerArray = $.makeArray($('[data-toggle="collapse"][href="#' + element.id + '"],' + ('[data-toggle="collapse"][data-target="#' + element.id + '"]')));
var tabToggles = $(Selector.DATA_TOGGLE);
for (var i = 0; i < tabToggles.length; i++) {
var elem = tabToggles[i];
var selector = Util.getSelectorFromElement(elem);
if (selector !== null && $(selector).filter(element).length > 0) {
this._triggerArray.push(elem);
}
}
this._parent = this._config.parent ? this._getParent() : null; this._parent = this._config.parent ? this._getParent() : null;
@@ -194,7 +202,16 @@ var Collapse = function ($) {
$(this._element).addClass(ClassName.COLLAPSING).removeClass(ClassName.COLLAPSE).removeClass(ClassName.SHOW); $(this._element).addClass(ClassName.COLLAPSING).removeClass(ClassName.COLLAPSE).removeClass(ClassName.SHOW);
if (this._triggerArray.length) { if (this._triggerArray.length) {
$(this._triggerArray).addClass(ClassName.COLLAPSED).attr('aria-expanded', false); for (var i = 0; i < this._triggerArray.length; i++) {
var trigger = this._triggerArray[i];
var selector = Util.getSelectorFromElement(trigger);
if (selector !== null) {
var $elem = $(selector);
if (!$elem.hasClass(ClassName.SHOW)) {
$(trigger).addClass(ClassName.COLLAPSED).attr('aria-expanded', false);
}
}
}
} }
this.setTransitioning(true); this.setTransitioning(true);
@@ -322,11 +339,14 @@ var Collapse = function ($) {
event.preventDefault(); event.preventDefault();
} }
var target = Collapse._getTargetFromElement(this); var $trigger = $(this);
var data = $(target).data(DATA_KEY); var selector = Util.getSelectorFromElement(this);
var config = data ? 'toggle' : $(this).data(); $(selector).each(function () {
var $target = $(this);
Collapse._jQueryInterface.call($(target), config); var data = $target.data(DATA_KEY);
var config = data ? 'toggle' : $trigger.data();
Collapse._jQueryInterface.call($target, config);
});
}); });
/** /**
+1 -1
View File
File diff suppressed because one or more lines are too long
+27 -8
View File
@@ -77,6 +77,14 @@ const Collapse = (($) => {
`[data-toggle="collapse"][href="#${element.id}"],` + `[data-toggle="collapse"][href="#${element.id}"],` +
`[data-toggle="collapse"][data-target="#${element.id}"]` `[data-toggle="collapse"][data-target="#${element.id}"]`
)) ))
const tabToggles = $(Selector.DATA_TOGGLE)
for (let i = 0; i < tabToggles.length; i++) {
const elem = tabToggles[i]
const selector = Util.getSelectorFromElement(elem)
if (selector !== null && $(selector).filter(element).length > 0) {
this._triggerArray.push(elem)
}
}
this._parent = this._config.parent ? this._getParent() : null this._parent = this._config.parent ? this._getParent() : null
@@ -215,9 +223,17 @@ const Collapse = (($) => {
.removeClass(ClassName.SHOW) .removeClass(ClassName.SHOW)
if (this._triggerArray.length) { if (this._triggerArray.length) {
$(this._triggerArray) for (let i = 0; i < this._triggerArray.length; i++) {
.addClass(ClassName.COLLAPSED) const trigger = this._triggerArray[i]
.attr('aria-expanded', false) const selector = Util.getSelectorFromElement(trigger)
if (selector !== null) {
const $elem = $(selector)
if (!$elem.hasClass(ClassName.SHOW)) {
$(trigger).addClass(ClassName.COLLAPSED)
.attr('aria-expanded', false)
}
}
}
} }
this.setTransitioning(true) this.setTransitioning(true)
@@ -349,11 +365,14 @@ const Collapse = (($) => {
event.preventDefault() event.preventDefault()
} }
const target = Collapse._getTargetFromElement(this) const $trigger = $(this)
const data = $(target).data(DATA_KEY) const selector = Util.getSelectorFromElement(this)
const config = data ? 'toggle' : $(this).data() $(selector).each(function () {
const $target = $(this)
Collapse._jQueryInterface.call($(target), config) const data = $target.data(DATA_KEY)
const config = data ? 'toggle' : $trigger.data()
Collapse._jQueryInterface.call($target, config)
})
}) })
+89 -4
View File
@@ -52,8 +52,28 @@ $(function () {
assert.ok(!/height/i.test($el.attr('style')), 'has height reset') assert.ok(!/height/i.test($el.attr('style')), 'has height reset')
}) })
QUnit.test('should show multiple collapsed elements', function (assert) {
assert.expect(4)
var done = assert.async()
var $target = $('<a role="button" data-toggle="collapse" class="collapsed" href=".multi"/>').appendTo('#qunit-fixture')
var $el = $('<div class="collapse multi"/>').appendTo('#qunit-fixture')
var $el2 = $('<div class="collapse multi"/>').appendTo('#qunit-fixture')
$el.one('shown.bs.collapse', function () {
assert.ok($el.hasClass('show'), 'has class "show"')
assert.ok(!/height/i.test($el.attr('style')), 'has height reset')
})
$el2.one('shown.bs.collapse', function () {
assert.ok($el2.hasClass('show'), 'has class "show"')
assert.ok(!/height/i.test($el2.attr('style')), 'has height reset')
done()
})
$target.trigger('click')
})
QUnit.test('should collapse only the first collapse', function (assert) { QUnit.test('should collapse only the first collapse', function (assert) {
assert.expect(2) assert.expect(2)
var done = assert.async()
var html = [ var html = [
'<div class="panel-group" id="accordion1">', '<div class="panel-group" id="accordion1">',
'<div class="panel">', '<div class="panel">',
@@ -69,10 +89,11 @@ $(function () {
$(html).appendTo('#qunit-fixture') $(html).appendTo('#qunit-fixture')
var $el1 = $('#collapse1') var $el1 = $('#collapse1')
var $el2 = $('#collapse2') var $el2 = $('#collapse2')
$el1.bootstrapCollapse('show') $el1.one('shown.bs.collapse', function () {
assert.ok($el1.hasClass('show'))
assert.ok($el1.hasClass('show')) assert.ok($el2.hasClass('show'))
assert.ok($el2.hasClass('show')) done()
}).bootstrapCollapse('show')
}) })
QUnit.test('should hide a collapsed element', function (assert) { QUnit.test('should hide a collapsed element', function (assert) {
@@ -588,4 +609,68 @@ $(function () {
$target.trigger($.Event('click')) $target.trigger($.Event('click'))
}) })
QUnit.test('should add "collapsed" class to triggers only when all the targeted collapse are hidden', function (assert) {
assert.expect(9)
var done = assert.async()
var $trigger1 = $('<a role="button" data-toggle="collapse" href="#test1"/>').appendTo('#qunit-fixture')
var $trigger2 = $('<a role="button" data-toggle="collapse" href="#test2"/>').appendTo('#qunit-fixture')
var $trigger3 = $('<a role="button" data-toggle="collapse" href=".multi"/>').appendTo('#qunit-fixture')
var $target1 = $('<div id="test1" class="multi"/>').appendTo('#qunit-fixture')
var $target2 = $('<div id="test2" class="multi"/>').appendTo('#qunit-fixture')
$target2.one('shown.bs.collapse', function () {
assert.ok(!$trigger1.hasClass('collapsed'), 'trigger1 does not have collapsed class')
assert.ok(!$trigger2.hasClass('collapsed'), 'trigger2 does not have collapsed class')
assert.ok(!$trigger3.hasClass('collapsed'), 'trigger3 does not have collapsed class')
$target2.one('hidden.bs.collapse', function () {
assert.ok(!$trigger1.hasClass('collapsed'), 'trigger1 does not have collapsed class')
assert.ok($trigger2.hasClass('collapsed'), 'trigger2 has collapsed class')
assert.ok(!$trigger3.hasClass('collapsed'), 'trigger3 does not have collapsed class')
$target1.one('hidden.bs.collapse', function () {
assert.ok($trigger1.hasClass('collapsed'), 'trigger1 has collapsed class')
assert.ok($trigger2.hasClass('collapsed'), 'trigger2 has collapsed class')
assert.ok($trigger3.hasClass('collapsed'), 'trigger3 has collapsed class')
done()
})
$trigger1.trigger('click')
})
$trigger2.trigger('click')
})
$trigger3.trigger('click')
})
QUnit.test('should set aria-expanded="true" to triggers targetting shown collaspe and aria-expanded="false" only when all the targeted collapses are shown', function (assert) {
assert.expect(9)
var done = assert.async()
var $trigger1 = $('<a role="button" data-toggle="collapse" href="#test1"/>').appendTo('#qunit-fixture')
var $trigger2 = $('<a role="button" data-toggle="collapse" href="#test2"/>').appendTo('#qunit-fixture')
var $trigger3 = $('<a role="button" data-toggle="collapse" href=".multi"/>').appendTo('#qunit-fixture')
var $target1 = $('<div id="test1" class="multi collapse"/>').appendTo('#qunit-fixture')
var $target2 = $('<div id="test2" class="multi collapse"/>').appendTo('#qunit-fixture')
$target2.one('shown.bs.collapse', function () {
assert.strictEqual($trigger1.attr('aria-expanded'), 'true', 'aria-expanded on trigger1 is "true"')
assert.strictEqual($trigger2.attr('aria-expanded'), 'true', 'aria-expanded on trigger2 is "true"')
assert.strictEqual($trigger3.attr('aria-expanded'), 'true', 'aria-expanded on trigger3 is "true"')
$target2.one('hidden.bs.collapse', function () {
assert.strictEqual($trigger1.attr('aria-expanded'), 'true', 'aria-expanded on trigger1 is "true"')
assert.strictEqual($trigger2.attr('aria-expanded'), 'false', 'aria-expanded on trigger2 is "false"')
assert.strictEqual($trigger3.attr('aria-expanded'), 'true', 'aria-expanded on trigger3 is "true"')
$target1.one('hidden.bs.collapse', function () {
assert.strictEqual($trigger1.attr('aria-expanded'), 'false', 'aria-expanded on trigger1 is "fasle"')
assert.strictEqual($trigger2.attr('aria-expanded'), 'false', 'aria-expanded on trigger2 is "false"')
assert.strictEqual($trigger3.attr('aria-expanded'), 'false', 'aria-expanded on trigger3 is "false"')
done()
})
$trigger1.trigger('click')
})
$trigger2.trigger('click')
})
$trigger3.trigger('click')
})
}) })
+23 -11
View File
@@ -45,7 +45,8 @@ $(function () {
}) })
QUnit.test('should not open dropdown if target is disabled via attribute', function (assert) { QUnit.test('should not open dropdown if target is disabled via attribute', function (assert) {
assert.expect(0) assert.expect(1)
var done = assert.async()
var dropdownHTML = '<div class="tabs">' var dropdownHTML = '<div class="tabs">'
+ '<div class="dropdown">' + '<div class="dropdown">'
+ '<button disabled href="#" class="btn dropdown-toggle" data-toggle="dropdown">Dropdown</button>' + '<button disabled href="#" class="btn dropdown-toggle" data-toggle="dropdown">Dropdown</button>'
@@ -57,10 +58,13 @@ $(function () {
+ '</div>' + '</div>'
+ '</div>' + '</div>'
+ '</div>' + '</div>'
var $dropdown = $(dropdownHTML).find('[data-toggle="dropdown"]').bootstrapDropdown() $(dropdownHTML).appendTo('#qunit-fixture')
setTimeout(function () { var $dropdown = $('#qunit-fixture').find('[data-toggle="dropdown"]').bootstrapDropdown()
assert.ok(!$dropdown.parent('.dropdown').hasClass('show'), '"show" class added on click') $dropdown.on('click', function () {
}, 300) assert.ok(!$dropdown.parent('.dropdown').hasClass('show'))
done()
})
$dropdown.trigger($.Event('click'))
}) })
QUnit.test('should set aria-expanded="true" on target when dropdown menu is shown', function (assert) { QUnit.test('should set aria-expanded="true" on target when dropdown menu is shown', function (assert) {
@@ -77,7 +81,10 @@ $(function () {
+ '</div>' + '</div>'
+ '</div>' + '</div>'
+ '</div>' + '</div>'
var $dropdown = $(dropdownHTML).find('[data-toggle="dropdown"]').bootstrapDropdown() var $dropdown = $(dropdownHTML)
.appendTo('#qunit-fixture')
.find('[data-toggle="dropdown"]')
.bootstrapDropdown()
$dropdown $dropdown
.parent('.dropdown') .parent('.dropdown')
.on('shown.bs.dropdown', function () { .on('shown.bs.dropdown', function () {
@@ -118,7 +125,8 @@ $(function () {
}) })
QUnit.test('should not open dropdown if target is disabled via class', function (assert) { QUnit.test('should not open dropdown if target is disabled via class', function (assert) {
assert.expect(0) assert.expect(1)
var done = assert.async()
var dropdownHTML = '<div class="tabs">' var dropdownHTML = '<div class="tabs">'
+ '<div class="dropdown">' + '<div class="dropdown">'
+ '<button href="#" class="btn dropdown-toggle disabled" data-toggle="dropdown">Dropdown</button>' + '<button href="#" class="btn dropdown-toggle disabled" data-toggle="dropdown">Dropdown</button>'
@@ -130,10 +138,14 @@ $(function () {
+ '</div>' + '</div>'
+ '</div>' + '</div>'
+ '</div>' + '</div>'
var $dropdown = $(dropdownHTML).find('[data-toggle="dropdown"]').bootstrapDropdown().trigger('click')
setTimeout(function () { $(dropdownHTML).appendTo('#qunit-fixture')
assert.ok(!$dropdown.parent('.dropdown').hasClass('show'), '"show" class added on click') var $dropdown = $('#qunit-fixture').find('[data-toggle="dropdown"]').bootstrapDropdown()
}, 300) $dropdown.on('click', function () {
assert.ok(!$dropdown.parent('.dropdown').hasClass('show'))
done()
})
$dropdown.trigger($.Event('click'))
}) })
QUnit.test('should add class show to menu if clicked', function (assert) { QUnit.test('should add class show to menu if clicked', function (assert) {
+2 -2
View File
@@ -1,12 +1,12 @@
/*! /*!
* QUnit 2.3.2 * QUnit 2.3.3
* https://qunitjs.com/ * https://qunitjs.com/
* *
* Copyright jQuery Foundation and other contributors * Copyright jQuery Foundation and other contributors
* Released under the MIT license * Released under the MIT license
* https://jquery.org/license * https://jquery.org/license
* *
* Date: 2017-04-18T02:19Z * Date: 2017-06-02T14:07Z
*/ */
/** Font Family and Sizes */ /** Font Family and Sizes */
+324 -239
View File
@@ -1,12 +1,12 @@
/*! /*!
* QUnit 2.3.2 * QUnit 2.3.3
* https://qunitjs.com/ * https://qunitjs.com/
* *
* Copyright jQuery Foundation and other contributors * Copyright jQuery Foundation and other contributors
* Released under the MIT license * Released under the MIT license
* https://jquery.org/license * https://jquery.org/license
* *
* Date: 2017-04-18T02:19Z * Date: 2017-06-02T14:07Z
*/ */
(function (global$1) { (function (global$1) {
'use strict'; 'use strict';
@@ -14,6 +14,7 @@
global$1 = 'default' in global$1 ? global$1['default'] : global$1; global$1 = 'default' in global$1 ? global$1['default'] : global$1;
var window = global$1.window; var window = global$1.window;
var self$1 = global$1.self;
var console = global$1.console; var console = global$1.console;
var setTimeout = global$1.setTimeout; var setTimeout = global$1.setTimeout;
var clearTimeout = global$1.clearTimeout; var clearTimeout = global$1.clearTimeout;
@@ -238,6 +239,27 @@
return objectType(obj) === type; return objectType(obj) === type;
} }
// Based on Java's String.hashCode, a simple but not
// rigorously collision resistant hashing function
function generateHash(module, testName) {
var str = module + "\x1C" + testName;
var hash = 0;
for (var i = 0; i < str.length; i++) {
hash = (hash << 5) - hash + str.charCodeAt(i);
hash |= 0;
}
// Convert the possibly negative integer hash code into an 8 character hex string, which isn't
// strictly necessary but increases user understanding that the id is a SHA-like hash
var hex = (0x100000000 + hash).toString(16);
if (hex.length < 8) {
hex = "0000000" + hex;
}
return hex.slice(-8);
}
// Test for equality any JavaScript type. // Test for equality any JavaScript type.
// Authors: Philippe Rathé <prathe@gmail.com>, David Chan <david@troi.org> // Authors: Philippe Rathé <prathe@gmail.com>, David Chan <david@troi.org>
var equiv = (function () { var equiv = (function () {
@@ -608,21 +630,19 @@
// Set of all modules. // Set of all modules.
modules: [], modules: [],
// Stack of nested modules
moduleStack: [],
// The first unnamed module // The first unnamed module
currentModule: { currentModule: {
name: "", name: "",
tests: [], tests: [],
childModules: [], childModules: [],
testsRun: 0 testsRun: 0,
unskippedTestsRun: 0
}, },
callbacks: {}, callbacks: {},
// The storage module to use for reordering tests // The storage module to use for reordering tests
storage: sessionStorage storage: localSessionStorage
}; };
// take a predefined QUnit.config and extend the defaults // take a predefined QUnit.config and extend the defaults
@@ -1064,6 +1084,135 @@
return extractStacktrace(error, offset); return extractStacktrace(error, offset);
} }
var priorityCount = 0;
var unitSampler = void 0;
/**
* Advances the ProcessingQueue to the next item if it is ready.
* @param {Boolean} last
*/
function advance() {
var start = now();
config.depth = (config.depth || 0) + 1;
while (config.queue.length && !config.blocking) {
var elapsedTime = now() - start;
if (!defined.setTimeout || config.updateRate <= 0 || elapsedTime < config.updateRate) {
if (priorityCount > 0) {
priorityCount--;
}
config.queue.shift()();
} else {
setTimeout(advance, 13);
break;
}
}
config.depth--;
if (!config.blocking && !config.queue.length && config.depth === 0) {
done();
}
}
function addToQueueImmediate(callback) {
if (objectType(callback) === "array") {
while (callback.length) {
addToQueueImmediate(callback.pop());
}
return;
}
config.queue.unshift(callback);
priorityCount++;
}
/**
* Adds a function to the ProcessingQueue for execution.
* @param {Function|Array} callback
* @param {Boolean} priority
* @param {String} seed
*/
function addToQueue(callback, prioritize, seed) {
if (prioritize) {
config.queue.splice(priorityCount++, 0, callback);
} else if (seed) {
if (!unitSampler) {
unitSampler = unitSamplerGenerator(seed);
}
// Insert into a random position after all prioritized items
var index = Math.floor(unitSampler() * (config.queue.length - priorityCount + 1));
config.queue.splice(priorityCount + index, 0, callback);
} else {
config.queue.push(callback);
}
}
/**
* Creates a seeded "sample" generator which is used for randomizing tests.
*/
function unitSamplerGenerator(seed) {
// 32-bit xorshift, requires only a nonzero seed
// http://excamera.com/sphinx/article-xorshift.html
var sample = parseInt(generateHash(seed), 16) || -1;
return function () {
sample ^= sample << 13;
sample ^= sample >>> 17;
sample ^= sample << 5;
// ECMAScript has no unsigned number type
if (sample < 0) {
sample += 0x100000000;
}
return sample / 0x100000000;
};
}
/**
* This function is called when the ProcessingQueue is done processing all
* items. It handles emitting the final run events.
*/
function done() {
var storage = config.storage;
ProcessingQueue.finished = true;
var runtime = now() - config.started;
var passed = config.stats.all - config.stats.bad;
emit("runEnd", globalSuite.end(true));
runLoggingCallbacks("done", {
passed: passed,
failed: config.stats.bad,
total: config.stats.all,
runtime: runtime
});
// Clear own storage items if all tests passed
if (storage && config.stats.bad === 0) {
for (var i = storage.length - 1; i >= 0; i--) {
var key = storage.key(i);
if (key.indexOf("qunit-test-") === 0) {
storage.removeItem(key);
}
}
}
}
var ProcessingQueue = {
finished: false,
add: addToQueue,
addImmediate: addToQueueImmediate,
advance: advance
};
var TestReport = function () { var TestReport = function () {
function TestReport(name, suite, options) { function TestReport(name, suite, options) {
classCallCheck(this, TestReport); classCallCheck(this, TestReport);
@@ -1077,6 +1226,8 @@
this.skipped = !!options.skip; this.skipped = !!options.skip;
this.todo = !!options.todo; this.todo = !!options.todo;
this.valid = options.valid;
this._startTime = 0; this._startTime = 0;
this._endTime = 0; this._endTime = 0;
@@ -1149,13 +1300,24 @@
value: function getAssertions() { value: function getAssertions() {
return this.assertions.slice(); return this.assertions.slice();
} }
// Remove actual and expected values from assertions. This is to prevent
// leaking memory throughout a test suite.
}, {
key: "slimAssertions",
value: function slimAssertions() {
this.assertions = this.assertions.map(function (assertion) {
delete assertion.actual;
delete assertion.expected;
return assertion;
});
}
}]); }]);
return TestReport; return TestReport;
}(); }();
var unitSampler;
var focused = false; var focused = false;
var priorityCount = 0;
function Test(settings) { function Test(settings) {
var i, l; var i, l;
@@ -1166,14 +1328,14 @@
extend(this, settings); extend(this, settings);
this.assertions = []; this.assertions = [];
this.semaphore = 0; this.semaphore = 0;
this.usedAsync = false;
this.module = config.currentModule; this.module = config.currentModule;
this.stack = sourceFromStacktrace(3); this.stack = sourceFromStacktrace(3);
this.steps = []; this.steps = [];
this.testReport = new TestReport(settings.testName, this.module.suiteReport, { this.testReport = new TestReport(settings.testName, this.module.suiteReport, {
todo: settings.todo, todo: settings.todo,
skip: settings.skip skip: settings.skip,
valid: this.valid()
}); });
// Register unique strings // Register unique strings
@@ -1187,7 +1349,8 @@
this.module.tests.push({ this.module.tests.push({
name: this.testName, name: this.testName,
testId: this.testId testId: this.testId,
skip: !!settings.skip
}); });
if (settings.skip) { if (settings.skip) {
@@ -1234,12 +1397,6 @@
config.current = this; config.current = this;
if (module.testEnvironment) {
delete module.testEnvironment.before;
delete module.testEnvironment.beforeEach;
delete module.testEnvironment.afterEach;
delete module.testEnvironment.after;
}
this.testEnvironment = extend({}, module.testEnvironment); this.testEnvironment = extend({}, module.testEnvironment);
this.started = now(); this.started = now();
@@ -1297,14 +1454,14 @@
test = this; test = this;
return function runHook() { return function runHook() {
if (hookName === "before") { if (hookName === "before") {
if (hookOwner.testsRun !== 0) { if (hookOwner.unskippedTestsRun !== 0) {
return; return;
} }
test.preserveEnvironment = true; test.preserveEnvironment = true;
} }
if (hookName === "after" && hookOwner.testsRun !== numberOfTests(hookOwner) - 1) { if (hookName === "after" && hookOwner.unskippedTestsRun !== numberOfUnskippedTests(hookOwner) - 1 && config.queue.length > 2) {
return; return;
} }
@@ -1334,8 +1491,8 @@
if (module.parentModule) { if (module.parentModule) {
processHooks(test, module.parentModule); processHooks(test, module.parentModule);
} }
if (module.testEnvironment && objectType(module.testEnvironment[handler]) === "function") { if (module.hooks && objectType(module.hooks[handler]) === "function") {
hooks.push(test.queueHook(module.testEnvironment[handler], handler, module)); hooks.push(test.queueHook(module.hooks[handler], handler, module));
} }
} }
@@ -1378,7 +1535,7 @@
} }
} }
notifyTestsRan(module); notifyTestsRan(module, skipped);
// Store result when possible // Store result when possible
if (storage) { if (storage) {
@@ -1389,7 +1546,11 @@
} }
} }
// After emitting the js-reporters event we cleanup the assertion data to
// avoid leaking it. It is not used by the legacy testDone callbacks.
emit("testEnd", this.testReport.end(true)); emit("testEnd", this.testReport.end(true));
this.testReport.slimAssertions();
runLoggingCallbacks("testDone", { runLoggingCallbacks("testDone", {
name: testName, name: testName,
module: moduleName, module: moduleName,
@@ -1409,6 +1570,20 @@
}); });
if (module.testsRun === numberOfTests(module)) { if (module.testsRun === numberOfTests(module)) {
logSuiteEnd(module);
// Check if the parent modules, iteratively, are done. If that the case,
// we emit the `suiteEnd` event and trigger `moduleDone` callback.
var parent = module.parentModule;
while (parent && parent.testsRun === numberOfTests(parent)) {
logSuiteEnd(parent);
parent = parent.parentModule;
}
}
config.current = undefined;
function logSuiteEnd(module) {
emit("suiteEnd", module.suiteReport.end(true)); emit("suiteEnd", module.suiteReport.end(true));
runLoggingCallbacks("moduleDone", { runLoggingCallbacks("moduleDone", {
name: module.name, name: module.name,
@@ -1419,8 +1594,6 @@
runtime: now() - module.stats.started runtime: now() - module.stats.started
}); });
} }
config.current = undefined;
}, },
preserveTestEnvironment: function preserveTestEnvironment() { preserveTestEnvironment: function preserveTestEnvironment() {
@@ -1431,18 +1604,16 @@
}, },
queue: function queue() { queue: function queue() {
var priority, var test = this;
previousFailCount,
test = this;
if (!this.valid()) { if (!this.valid()) {
return; return;
} }
function run() { function runTest() {
// Each of these can by async // Each of these can by async
synchronize([function () { ProcessingQueue.addImmediate([function () {
test.before(); test.before();
}, test.hooks("before"), function () { }, test.hooks("before"), function () {
test.preserveTestEnvironment(); test.preserveTestEnvironment();
@@ -1455,17 +1626,26 @@
}]); }]);
} }
previousFailCount = config.storage && +config.storage.getItem("qunit-test-" + this.module.name + "-" + this.testName); var previousFailCount = config.storage && +config.storage.getItem("qunit-test-" + this.module.name + "-" + this.testName);
// Prioritize previously failed tests, detected from storage // Prioritize previously failed tests, detected from storage
priority = config.reorder && previousFailCount; var prioritize = config.reorder && !!previousFailCount;
this.previousFailure = !!previousFailCount; this.previousFailure = !!previousFailCount;
return synchronize(run, priority, config.seed); ProcessingQueue.add(runTest, prioritize, config.seed);
// If the queue has already finished, we manually process the new test
if (ProcessingQueue.finished) {
ProcessingQueue.advance();
}
}, },
pushResult: function pushResult(resultInfo) { pushResult: function pushResult(resultInfo) {
if (this !== config.current) {
throw new Error("Assertion occured after test had finished.");
}
// Destructure of resultInfo = { result, actual, expected, message, negative } // Destructure of resultInfo = { result, actual, expected, message, negative }
var source, var source,
@@ -1503,7 +1683,7 @@
throw new Error("pushFailure() assertion outside test context, was " + sourceFromStacktrace(2)); throw new Error("pushFailure() assertion outside test context, was " + sourceFromStacktrace(2));
} }
this.assert.pushResult({ this.pushResult({
result: false, result: false,
message: message || "error", message: message || "error",
actual: actual || null, actual: actual || null,
@@ -1643,79 +1823,6 @@
return currentTest.pushFailure.apply(currentTest, arguments); return currentTest.pushFailure.apply(currentTest, arguments);
} }
// Based on Java's String.hashCode, a simple but not
// rigorously collision resistant hashing function
function generateHash(module, testName) {
var hex,
i = 0,
hash = 0,
str = module + "\x1C" + testName,
len = str.length;
for (; i < len; i++) {
hash = (hash << 5) - hash + str.charCodeAt(i);
hash |= 0;
}
// Convert the possibly negative integer hash code into an 8 character hex string, which isn't
// strictly necessary but increases user understanding that the id is a SHA-like hash
hex = (0x100000000 + hash).toString(16);
if (hex.length < 8) {
hex = "0000000" + hex;
}
return hex.slice(-8);
}
function synchronize(callback, priority, seed) {
var last = !priority,
index;
if (objectType(callback) === "array") {
while (callback.length) {
synchronize(callback.shift());
}
return;
}
if (priority) {
config.queue.splice(priorityCount++, 0, callback);
} else if (seed) {
if (!unitSampler) {
unitSampler = unitSamplerGenerator(seed);
}
// Insert into a random position after all priority items
index = Math.floor(unitSampler() * (config.queue.length - priorityCount + 1));
config.queue.splice(priorityCount + index, 0, callback);
} else {
config.queue.push(callback);
}
if (internalState.autorun && !config.blocking) {
process(last);
}
}
function unitSamplerGenerator(seed) {
// 32-bit xorshift, requires only a nonzero seed
// http://excamera.com/sphinx/article-xorshift.html
var sample = parseInt(generateHash(seed), 16) || -1;
return function () {
sample ^= sample << 13;
sample ^= sample >>> 17;
sample ^= sample << 5;
// ECMAScript has no unsigned number type
if (sample < 0) {
sample += 0x100000000;
}
return sample / 0x100000000;
};
}
function saveGlobal() { function saveGlobal() {
config.pollution = []; config.pollution = [];
@@ -1888,24 +1995,40 @@
} }
} }
function numberOfTests(module) { function collectTests(module) {
var count = module.tests.length, var tests = [].concat(module.tests);
modules = [].concat(toConsumableArray(module.childModules)); var modules = [].concat(toConsumableArray(module.childModules));
// Do a breadth-first traversal of the child modules // Do a breadth-first traversal of the child modules
while (modules.length) { while (modules.length) {
var nextModule = modules.shift(); var nextModule = modules.shift();
count += nextModule.tests.length; tests.push.apply(tests, nextModule.tests);
modules.push.apply(modules, toConsumableArray(nextModule.childModules)); modules.push.apply(modules, toConsumableArray(nextModule.childModules));
} }
return count; return tests;
} }
function notifyTestsRan(module) { function numberOfTests(module) {
return collectTests(module).length;
}
function numberOfUnskippedTests(module) {
return collectTests(module).filter(function (test) {
return !test.skip;
}).length;
}
function notifyTestsRan(module, skipped) {
module.testsRun++; module.testsRun++;
if (!skipped) {
module.unskippedTestsRun++;
}
while (module = module.parentModule) { while (module = module.parentModule) {
module.testsRun++; module.testsRun++;
if (!skipped) {
module.unskippedTestsRun++;
}
} }
} }
@@ -1978,18 +2101,22 @@
}, { }, {
key: "async", key: "async",
value: function async(count) { value: function async(count) {
var test$$1 = this.test, var test$$1 = this.test;
popped = false,
var popped = false,
acceptCallCount = count; acceptCallCount = count;
if (typeof acceptCallCount === "undefined") { if (typeof acceptCallCount === "undefined") {
acceptCallCount = 1; acceptCallCount = 1;
} }
test$$1.usedAsync = true;
var resume = internalStop(test$$1); var resume = internalStop(test$$1);
return function done() { return function done() {
if (config.current !== test$$1) {
throw Error("assert.async callback called after test finished.");
}
if (popped) { if (popped) {
test$$1.pushFailure("Too many calls to the `assert.async` callback", sourceFromStacktrace(2)); test$$1.pushFailure("Too many calls to the `assert.async` callback", sourceFromStacktrace(2));
return; return;
@@ -2027,8 +2154,8 @@
value: function pushResult(resultInfo) { value: function pushResult(resultInfo) {
// Destructure of resultInfo = { result, actual, expected, message, negative } // Destructure of resultInfo = { result, actual, expected, message, negative }
var assert = this, var assert = this;
currentTest = assert instanceof Assert && assert.test || config.current; var currentTest = assert instanceof Assert && assert.test || config.current;
// Backwards compatibility fix. // Backwards compatibility fix.
// Allows the direct use of global exported assertions and QUnit.assert.* // Allows the direct use of global exported assertions and QUnit.assert.*
@@ -2039,12 +2166,6 @@
throw new Error("assertion outside test context, in " + sourceFromStacktrace(2)); throw new Error("assertion outside test context, in " + sourceFromStacktrace(2));
} }
if (currentTest.usedAsync === true && currentTest.semaphore === 0) {
currentTest.pushFailure("Assertion after the final `assert.async` was resolved", sourceFromStacktrace(2));
// Allow this assertion to continue running anyway...
}
if (!(assert instanceof Assert)) { if (!(assert instanceof Assert)) {
assert = currentTest.assert; assert = currentTest.assert;
} }
@@ -2181,8 +2302,9 @@
key: "throws", key: "throws",
value: function throws(block, expected, message) { value: function throws(block, expected, message) {
var actual = void 0, var actual = void 0,
result = false, result = false;
currentTest = this instanceof Assert && this.test || config.current;
var currentTest = this instanceof Assert && this.test || config.current;
// 'expected' is optional unless doing string comparison // 'expected' is optional unless doing string comparison
if (objectType(expected) === "string") { if (objectType(expected) === "string") {
@@ -2306,6 +2428,11 @@
}); });
QUnit.config.autostart = false; QUnit.config.autostart = false;
} }
// For Web/Service Workers
if (self$1 && self$1.WorkerGlobalScope && self$1 instanceof self$1.WorkerGlobalScope) {
self$1.QUnit = QUnit;
}
} }
var SuiteReport = function () { var SuiteReport = function () {
@@ -2386,8 +2513,11 @@
var counts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { passed: 0, failed: 0, skipped: 0, todo: 0, total: 0 }; var counts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { passed: 0, failed: 0, skipped: 0, todo: 0, total: 0 };
counts = this.tests.reduce(function (counts, test) { counts = this.tests.reduce(function (counts, test) {
counts[test.getStatus()]++; if (test.valid) {
counts.total++; counts[test.getStatus()]++;
counts.total++;
}
return counts; return counts;
}, counts); }, counts);
@@ -2451,27 +2581,49 @@
// it since each module has a suiteReport associated with it. // it since each module has a suiteReport associated with it.
config.currentModule.suiteReport = globalSuite; config.currentModule.suiteReport = globalSuite;
var moduleStack = [];
var globalStartCalled = false; var globalStartCalled = false;
var runStarted = false; var runStarted = false;
var internalState = {
autorun: false
};
// Figure out if we're running the tests from a server or not // Figure out if we're running the tests from a server or not
QUnit.isLocal = !(defined.document && window.location.protocol !== "file:"); QUnit.isLocal = !(defined.document && window.location.protocol !== "file:");
// Expose the current QUnit version // Expose the current QUnit version
QUnit.version = "2.2.0"; QUnit.version = "2.3.3";
function createModule(name, testEnvironment) {
var parentModule = moduleStack.length ? moduleStack.slice(-1)[0] : null;
var moduleName = parentModule !== null ? [parentModule.name, name].join(" > ") : name;
var parentSuite = parentModule ? parentModule.suiteReport : globalSuite;
var module = {
name: moduleName,
parentModule: parentModule,
tests: [],
moduleId: generateHash(moduleName),
testsRun: 0,
unskippedTestsRun: 0,
childModules: [],
suiteReport: new SuiteReport(name, parentSuite)
};
var env = {};
if (parentModule) {
parentModule.childModules.push(module);
extend(env, parentModule.testEnvironment);
}
extend(env, testEnvironment);
module.testEnvironment = env;
config.modules.push(module);
return module;
}
extend(QUnit, { extend(QUnit, {
on: on, on: on,
// Call on start of module test to prepend name to all tests // Call on start of module test to prepend name to all tests
module: function module(name, testEnvironment, executeNow) { module: function module(name, testEnvironment, executeNow) {
var module, moduleFns;
var currentModule = config.currentModule;
if (arguments.length === 2) { if (arguments.length === 2) {
if (objectType(testEnvironment) === "function") { if (objectType(testEnvironment) === "function") {
executeNow = testEnvironment; executeNow = testEnvironment;
@@ -2479,57 +2631,40 @@
} }
} }
module = createModule(); var module = createModule(name, testEnvironment);
moduleFns = { // Move any hooks to a 'hooks' object
if (module.testEnvironment) {
module.hooks = {
before: module.testEnvironment.before,
beforeEach: module.testEnvironment.beforeEach,
afterEach: module.testEnvironment.afterEach,
after: module.testEnvironment.after
};
delete module.testEnvironment.before;
delete module.testEnvironment.beforeEach;
delete module.testEnvironment.afterEach;
delete module.testEnvironment.after;
}
var moduleFns = {
before: setHook(module, "before"), before: setHook(module, "before"),
beforeEach: setHook(module, "beforeEach"), beforeEach: setHook(module, "beforeEach"),
afterEach: setHook(module, "afterEach"), afterEach: setHook(module, "afterEach"),
after: setHook(module, "after") after: setHook(module, "after")
}; };
var currentModule = config.currentModule;
if (objectType(executeNow) === "function") { if (objectType(executeNow) === "function") {
config.moduleStack.push(module); moduleStack.push(module);
setCurrentModule(module); config.currentModule = module;
executeNow.call(module.testEnvironment, moduleFns); executeNow.call(module.testEnvironment, moduleFns);
config.moduleStack.pop(); moduleStack.pop();
module = module.parentModule || currentModule; module = module.parentModule || currentModule;
} }
setCurrentModule(module); config.currentModule = module;
function createModule() {
var parentModule = config.moduleStack.length ? config.moduleStack.slice(-1)[0] : null;
var moduleName = parentModule !== null ? [parentModule.name, name].join(" > ") : name;
var parentSuite = parentModule ? parentModule.suiteReport : globalSuite;
var module = {
name: moduleName,
parentModule: parentModule,
tests: [],
moduleId: generateHash(moduleName),
testsRun: 0,
childModules: [],
suiteReport: new SuiteReport(name, parentSuite)
};
var env = {};
if (parentModule) {
parentModule.childModules.push(module);
extend(env, parentModule.testEnvironment);
delete env.beforeEach;
delete env.afterEach;
}
extend(env, testEnvironment);
module.testEnvironment = env;
config.modules.push(module);
return module;
}
function setCurrentModule(module) {
config.currentModule = module;
}
}, },
test: test, test: test,
@@ -2664,73 +2799,16 @@
} }
config.blocking = false; config.blocking = false;
process(true); ProcessingQueue.advance();
}
function process(last) {
function next() {
process(last);
}
var start = now();
config.depth = (config.depth || 0) + 1;
while (config.queue.length && !config.blocking) {
if (!defined.setTimeout || config.updateRate <= 0 || now() - start < config.updateRate) {
if (config.current) {
// Reset async tracking for each phase of the Test lifecycle
config.current.usedAsync = false;
}
config.queue.shift()();
} else {
setTimeout(next, 13);
break;
}
}
config.depth--;
if (last && !config.blocking && !config.queue.length && config.depth === 0) {
done();
}
}
function done() {
var runtime,
passed,
i,
key,
storage = config.storage;
internalState.autorun = true;
runtime = now() - config.started;
passed = config.stats.all - config.stats.bad;
emit("runEnd", globalSuite.end(true));
runLoggingCallbacks("done", {
failed: config.stats.bad,
passed: passed,
total: config.stats.all,
runtime: runtime
});
// Clear own storage items if all tests passed
if (storage && config.stats.bad === 0) {
for (i = storage.length - 1; i >= 0; i--) {
key = storage.key(i);
if (key.indexOf("qunit-test-") === 0) {
storage.removeItem(key);
}
}
}
} }
function setHook(module, hookName) { function setHook(module, hookName) {
if (module.testEnvironment === undefined) { if (!module.hooks) {
module.testEnvironment = {}; module.hooks = {};
} }
return function (callback) { return function (callback) {
module.testEnvironment[hookName] = callback; module.hooks[hookName] = callback;
}; };
} }
@@ -3588,13 +3666,19 @@
message += "<tr class='test-actual'><th>Result: </th><td><pre>" + escapeText(actual) + "</pre></td></tr>"; message += "<tr class='test-actual'><th>Result: </th><td><pre>" + escapeText(actual) + "</pre></td></tr>";
// Don't show diff if actual or expected are booleans if (typeof details.actual === "number" && typeof details.expected === "number") {
if (!/^(true|false)$/.test(actual) && !/^(true|false)$/.test(expected)) { if (!isNaN(details.actual) && !isNaN(details.expected)) {
showDiff = true;
diff = details.actual - details.expected;
diff = (diff > 0 ? "+" : "") + diff;
}
} else if (typeof details.actual !== "boolean" && typeof details.expected !== "boolean") {
diff = QUnit.diff(expected, actual); diff = QUnit.diff(expected, actual);
// don't show diff if there is zero overlap
showDiff = stripHtml(diff).length !== stripHtml(expected).length + stripHtml(actual).length; showDiff = stripHtml(diff).length !== stripHtml(expected).length + stripHtml(actual).length;
} }
// Don't show diff if expected and actual are totally different
if (showDiff) { if (showDiff) {
message += "<tr class='test-diff'><th>Diff: </th><td><pre>" + diff + "</pre></td></tr>"; message += "<tr class='test-diff'><th>Diff: </th><td><pre>" + diff + "</pre></td></tr>";
} }
@@ -3691,6 +3775,7 @@
var todoLabel = document$$1.createElement("em"); var todoLabel = document$$1.createElement("em");
todoLabel.className = "qunit-todo-label"; todoLabel.className = "qunit-todo-label";
todoLabel.innerHTML = "todo"; todoLabel.innerHTML = "todo";
testItem.className += " todo";
testItem.insertBefore(todoLabel, testTitle); testItem.insertBefore(todoLabel, testTitle);
} }
+1 -1
View File
@@ -70,7 +70,7 @@
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"jquery": ">=1.9.1", "jquery": ">=1.9.1",
"popper.js": "^1.9.9" "popper.js": "^1.10.1"
}, },
"devDependencies": { "devDependencies": {
"autoprefixer": "^7.1.1", "autoprefixer": "^7.1.1",
+7 -8
View File
@@ -133,8 +133,7 @@
.custom-select { .custom-select {
display: inline-block; display: inline-block;
max-width: 100%; max-width: 100%;
$select-border-width: ($custom-select-border-width * 2); height: $input-height;
height: calc(#{$input-height} + #{$select-border-width});
padding: $custom-select-padding-y ($custom-select-padding-x + $custom-select-indicator-padding) $custom-select-padding-y $custom-select-padding-x; padding: $custom-select-padding-y ($custom-select-padding-x + $custom-select-indicator-padding) $custom-select-padding-y $custom-select-padding-x;
line-height: $custom-select-line-height; line-height: $custom-select-line-height;
color: $custom-select-color; color: $custom-select-color;
@@ -142,7 +141,11 @@
background: $custom-select-bg $custom-select-indicator no-repeat right $custom-select-padding-x center; background: $custom-select-bg $custom-select-indicator no-repeat right $custom-select-padding-x center;
background-size: $custom-select-bg-size; background-size: $custom-select-bg-size;
border: $custom-select-border-width solid $custom-select-border-color; border: $custom-select-border-width solid $custom-select-border-color;
@include border-radius($custom-select-border-radius); @if $enable-rounded {
border-radius: $custom-select-border-radius;
} @else {
border-radius: 0;
}
appearance: none; appearance: none;
&:focus { &:focus {
@@ -173,14 +176,10 @@
} }
.custom-select-sm { .custom-select-sm {
height: $custom-select-height-sm;
padding-top: $custom-select-padding-y; padding-top: $custom-select-padding-y;
padding-bottom: $custom-select-padding-y; padding-bottom: $custom-select-padding-y;
font-size: $custom-select-font-size-sm; font-size: $custom-select-font-size-sm;
// &:not([multiple]) {
// height: 26px;
// min-height: 26px;
// }
} }
+50 -46
View File
@@ -62,8 +62,7 @@
select.form-control { select.form-control {
&:not([size]):not([multiple]) { &:not([size]):not([multiple]) {
$select-border-width: ($border-width * 2); height: $input-height;
height: calc(#{$input-height} + #{$select-border-width});
} }
&:focus::-ms-value { &:focus::-ms-value {
@@ -123,12 +122,12 @@ select.form-control {
} }
// Static form control text // Readonly controls as plain text
// //
// Apply class to an element to make any string of text align with labels in a // Apply class to a readonly input to make it appear like regular plain
// horizontal form layout. // text (without any border, background color, focus indicator)
.form-control-static { .form-control-plaintext {
padding-top: $input-btn-padding-y; padding-top: $input-btn-padding-y;
padding-bottom: $input-btn-padding-y; padding-bottom: $input-btn-padding-y;
margin-bottom: 0; // match inputs if this class comes on inputs with default margins margin-bottom: 0; // match inputs if this class comes on inputs with default margins
@@ -161,8 +160,7 @@ select.form-control {
select.form-control-sm { select.form-control-sm {
&:not([size]):not([multiple]) { &:not([size]):not([multiple]) {
$select-border-width: ($border-width * 2); height: $input-height-sm;
height: calc(#{$input-height-sm} + #{$select-border-width});
} }
} }
@@ -175,8 +173,7 @@ select.form-control-sm {
select.form-control-lg { select.form-control-lg {
&:not([size]):not([multiple]) { &:not([size]):not([multiple]) {
$select-border-width: ($border-width * 2); height: $input-height-lg;
height: calc(#{$input-height-lg} + #{$select-border-width});
} }
} }
@@ -196,6 +193,24 @@ select.form-control-lg {
} }
// Form grid
//
// Special replacement for our grid system's `.row` for tighter form layouts.
.form-row {
display: flex;
flex-wrap: wrap;
margin-right: -5px;
margin-left: -5px;
> .col,
> [class*="col-"] {
padding-right: 5px;
padding-left: 5px;
}
}
// Checkboxes and radios // Checkboxes and radios
// //
// Indent the labels to position radios/checkboxes as hanging controls. // Indent the labels to position radios/checkboxes as hanging controls.
@@ -241,48 +256,37 @@ select.form-control-lg {
} }
// Form control feedback states // Form validation
// //
// Apply contextual and semantic states to individual form controls. // 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.
.form-control-feedback { .invalid-feedback {
margin-top: $form-feedback-margin-top; display: none;
margin-top: .25rem;
font-size: .875rem;
color: $form-feedback-invalid-color;
} }
.form-control-success, .invalid-tooltip {
.form-control-warning, position: absolute;
.form-control-danger { top: 100%;
padding-right: ($input-btn-padding-x * 3); z-index: 5;
background-repeat: no-repeat; display: none;
background-position: center right ($input-height / 4); width: 250px;
background-size: ($input-height / 2) ($input-height / 2); padding: .5rem;
} margin-top: .1rem;
font-size: .875rem;
// Form validation states line-height: 1;
.has-success { color: #fff;
@include form-control-validation($brand-success); background-color: rgba($form-feedback-invalid-color,.8);
border-radius: .2rem;
.form-control-success {
background-image: $form-icon-success;
}
}
.has-warning {
@include form-control-validation($brand-warning);
.form-control-warning {
background-image: $form-icon-warning;
}
}
.has-danger {
@include form-control-validation($brand-danger);
.form-control-danger {
background-image: $form-icon-danger;
}
} }
@include form-validation-state("valid", $form-feedback-valid-color);
@include form-validation-state("invalid", $form-feedback-invalid-color);
// Inline forms // Inline forms
// //
+18 -15
View File
@@ -341,7 +341,7 @@ $table-inverse-color: $body-bg !default;
// For each of Bootstrap's buttons, define text, background and border color. // For each of Bootstrap's buttons, define text, background and border color.
$input-btn-padding-y: .5rem !default; $input-btn-padding-y: .5rem !default;
$input-btn-padding-x: 1rem !default; $input-btn-padding-x: .75rem !default;
$input-btn-line-height: 1.25 !default; $input-btn-line-height: 1.25 !default;
$input-btn-padding-y-sm: .25rem !default; $input-btn-padding-y-sm: .25rem !default;
@@ -354,7 +354,7 @@ $input-btn-line-height-lg: 1.5 !default;
$btn-font-weight: $font-weight-normal !default; $btn-font-weight: $font-weight-normal !default;
$btn-box-shadow: inset 0 1px 0 rgba($white,.15), 0 1px 1px rgba($black,.075) !default; $btn-box-shadow: inset 0 1px 0 rgba($white,.15), 0 1px 1px rgba($black,.075) !default;
$btn-focus-box-shadow: 0 0 0 2px rgba($brand-primary, .25) !default; $btn-focus-box-shadow: 0 0 0 3px rgba($brand-primary, .25) !default;
$btn-active-box-shadow: inset 0 3px 5px rgba($black,.125) !default; $btn-active-box-shadow: inset 0 3px 5px rgba($black,.125) !default;
$btn-primary-color: $white !default; $btn-primary-color: $white !default;
@@ -409,14 +409,21 @@ $input-border-radius-sm: $border-radius-sm !default;
$input-focus-bg: $input-bg !default; $input-focus-bg: $input-bg !default;
$input-focus-border-color: lighten($brand-primary, 25%) !default; $input-focus-border-color: lighten($brand-primary, 25%) !default;
$input-focus-box-shadow: $input-box-shadow, rgba($input-focus-border-color, .6) !default; $input-focus-box-shadow: $input-box-shadow, $btn-focus-box-shadow !default;
$input-focus-color: $input-color !default; $input-focus-color: $input-color !default;
$input-placeholder-color: $gray-light !default; $input-placeholder-color: $gray-light !default;
$input-height: (($font-size-base * $input-btn-line-height) + ($input-btn-padding-y * 2)) !default; $input-height-border: $input-btn-border-width * 2 !default;
$input-height-lg: (($font-size-lg * $input-btn-line-height-lg) + ($input-btn-padding-y-lg * 2)) !default;
$input-height-sm: (($font-size-sm * $input-btn-line-height-sm) + ($input-btn-padding-y-sm * 2)) !default; $input-height-inner: ($font-size-base * $input-btn-line-height) + ($input-btn-padding-y * 2) !default;
$input-height: calc(#{$input-height-inner} + #{$input-height-border}) !default;
$input-height-inner-sm: ($font-size-sm * $input-btn-line-height-sm) + ($input-btn-padding-y-sm * 2) !default;
$input-height-sm: calc(#{$input-height-inner-sm} + #{$input-height-border}) !default;
$input-height-inner-lg: ($font-size-sm * $input-btn-line-height-lg) + ($input-btn-padding-y-lg * 2) !default;
$input-height-lg: calc(#{$input-height-inner-lg} + #{$input-height-border}) !default;
$input-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s !default; $input-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s !default;
@@ -470,6 +477,7 @@ $custom-radio-icon-checked: str-replace(url("data:image/svg+xml;charset=utf8,%3C
$custom-select-padding-y: .375rem !default; $custom-select-padding-y: .375rem !default;
$custom-select-padding-x: .75rem !default; $custom-select-padding-x: .75rem !default;
$custom-select-height: $input-height !default;
$custom-select-indicator-padding: 1rem !default; // Extra padding to account for the presence of the background-image based indicator $custom-select-indicator-padding: 1rem !default; // Extra padding to account for the presence of the background-image based indicator
$custom-select-line-height: $input-btn-line-height !default; $custom-select-line-height: $input-btn-line-height !default;
$custom-select-color: $input-color !default; $custom-select-color: $input-color !default;
@@ -487,6 +495,7 @@ $custom-select-focus-border-color: lighten($brand-primary, 25%) !default;
$custom-select-focus-box-shadow: inset 0 1px 2px rgba($black, .075), 0 0 5px rgba($custom-select-focus-border-color, .5) !default; $custom-select-focus-box-shadow: inset 0 1px 2px rgba($black, .075), 0 0 5px rgba($custom-select-focus-border-color, .5) !default;
$custom-select-font-size-sm: 75% !default; $custom-select-font-size-sm: 75% !default;
$custom-select-height-sm: $input-height-sm !default;
$custom-file-height: 2.5rem !default; $custom-file-height: 2.5rem !default;
$custom-file-width: 14rem !default; $custom-file-width: 14rem !default;
@@ -513,15 +522,9 @@ $custom-file-text: (
) !default; ) !default;
// Form validation icons // Form validation
$form-icon-success-color: $brand-success !default; $form-feedback-valid-color: $brand-success !default;
$form-icon-success: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#{$form-icon-success-color}' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E"), "#", "%23") !default; $form-feedback-invalid-color: $brand-danger !default;
$form-icon-warning-color: $brand-warning !default;
$form-icon-warning: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#{$form-icon-warning-color}' d='M4.4 5.324h-.8v-2.46h.8zm0 1.42h-.8V5.89h.8zM3.76.63L.04 7.075c-.115.2.016.425.26.426h7.397c.242 0 .372-.226.258-.426C6.726 4.924 5.47 2.79 4.253.63c-.113-.174-.39-.174-.494 0z'/%3E%3C/svg%3E"), "#", "%23") !default;
$form-icon-danger-color: $brand-danger !default;
$form-icon-danger: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#{$form-icon-danger-color}' viewBox='-2 -2 7 7'%3E%3Cpath stroke='#{$form-icon-danger-color}' d='M0 0l3 3m0-3L0 3'/%3E%3Ccircle r='.5'/%3E%3Ccircle cx='3' r='.5'/%3E%3Ccircle cy='3' r='.5'/%3E%3Ccircle cx='3' cy='3' r='.5'/%3E%3C/svg%3E"), "#", "%23") !default;
// Dropdowns // Dropdowns
+3 -3
View File
@@ -22,9 +22,9 @@
&.focus { &.focus {
// Avoid using mixin so we can pass custom focus shadow properly // Avoid using mixin so we can pass custom focus shadow properly
@if $enable-shadows { @if $enable-shadows {
box-shadow: $btn-box-shadow, 0 0 0 2px rgba($border, .5); box-shadow: $btn-box-shadow, 0 0 0 3px rgba($border, .5);
} @else { } @else {
box-shadow: 0 0 0 2px rgba($border, .5); box-shadow: 0 0 0 3px rgba($border, .5);
} }
} }
@@ -60,7 +60,7 @@
&:focus, &:focus,
&.focus { &.focus {
box-shadow: 0 0 0 2px rgba($color, .5); box-shadow: 0 0 0 3px rgba($color, .5);
} }
&.disabled, &.disabled,
+60 -34
View File
@@ -1,37 +1,3 @@
// Form validation states
//
// Used in _forms.scss to generate the form validation CSS for warnings, errors,
// and successes.
@mixin form-control-validation($color) {
// Color the label and help text
.form-control-feedback,
.form-control-label,
.col-form-label,
.form-check-label,
.custom-control {
color: $color;
}
// Set the border and box shadow on specific inputs to match
.form-control,
.custom-select,
.custom-file-control {
border-color: $color;
&:focus {
@include box-shadow($input-box-shadow, 0 0 6px lighten($color, 20%));
}
}
// Set validation states also for addons
.input-group-addon {
color: $color;
background-color: lighten($color, 40%);
border-color: $color;
}
}
// Form control focus state // Form control focus state
// //
// Generate a customized focus state and for any input with the specified color, // Generate a customized focus state and for any input with the specified color,
@@ -53,3 +19,63 @@
@include box-shadow($input-focus-box-shadow); @include box-shadow($input-focus-box-shadow);
} }
} }
@mixin form-validation-state($state, $color) {
.form-control,
.custom-select {
.was-validated &:#{$state},
&.is-#{$state} {
border-color: $color;
&:focus {
box-shadow: 0 0 0 .2rem rgba($color,.25);
}
~ .invalid-feedback,
~ .invalid-tooltip {
display: block;
}
}
}
// TODO: redo check markup lol crap
.form-check-input {
.was-validated &:#{$state},
&.is-#{$state} {
+ .form-check-label {
color: $color;
}
}
}
// custom radios and checks
.custom-control-input {
.was-validated &:#{$state},
&.is-#{$state} {
~ .custom-control-indicator {
background-color: rgba($color, .25);
}
~ .custom-control-description {
color: $color;
}
}
}
// custom file
.custom-file-input {
.was-validated &:#{$state},
&.is-#{$state} {
~ .custom-file-control {
border-color: $color;
&::before { border-color: inherit; }
}
&:focus {
box-shadow: 0 0 0 .2rem rgba($color,.25);
}
}
}
}