diff --git a/docs/.htmllintrc b/docs/.htmllintrc index e15284536e..d88560faa9 100644 --- a/docs/.htmllintrc +++ b/docs/.htmllintrc @@ -9,6 +9,7 @@ "html-valid-content-model": false, "id-class-ignore-regex": "(onclick|content|[a-z]+([A-Z][a-z])+)", "id-class-style": "dash", + "img-req-src": false, "img-req-alt": false, "indent-style": "spaces", "indent-width": 2, diff --git a/docs/components/carousel.md b/docs/components/carousel.md index ab84bf460d..af00dc526c 100644 --- a/docs/components/carousel.md +++ b/docs/components/carousel.md @@ -186,45 +186,45 @@ Options can be passed via data attributes or JavaScript. For data attributes, ap - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDefaultDescription
NameTypeDefaultDescription
intervalnumber5000The amount of time to delay between automatically cycling an item. If false, carousel will not automatically cycle.
keyboardbooleantrueWhether the carousel should react to keyboard events.
pausestring | boolean"hover"

If set to "hover", pauses the cycling of the carousel on mouseenter and resumes the cycling of the carousel on mouseleave. If set to false, hovering over the carousel won't pause it.

-

On touch-enabled devices, when set to "hover", cycling will pause on touchend (once the user finished interacting with the carousel) for two intervals, before automatically resuming. Note that this is in addition to the above mouse behavior.

ridestringfalseAutoplays the carousel after the user manually cycles the first item. If "carousel", autoplays the carousel on load.
wrapbooleantrueWhether the carousel should cycle continuously or have hard stops.
intervalnumber5000The amount of time to delay between automatically cycling an item. If false, carousel will not automatically cycle.
keyboardbooleantrueWhether the carousel should react to keyboard events.
pausestring | boolean"hover"

If set to "hover", pauses the cycling of the carousel on mouseenter and resumes the cycling of the carousel on mouseleave. If set to false, hovering over the carousel won't pause it.

+

On touch-enabled devices, when set to "hover", cycling will pause on touchend (once the user finished interacting with the carousel) for two intervals, before automatically resuming. Note that this is in addition to the above mouse behavior.

ridestringfalseAutoplays the carousel after the user manually cycles the first item. If "carousel", autoplays the carousel on load.
wrapbooleantrueWhether the carousel should cycle continuously or have hard stops.
@@ -276,20 +276,20 @@ All carousel events are fired at the carousel itself (i.e. at the `
- - Event Type - Description - + + Event Type + Description + - - slide.bs.carousel - This event fires immediately when the slide instance method is invoked. - - - slid.bs.carousel - This event is fired when the carousel has completed its slide transition. - + + slide.bs.carousel + This event fires immediately when the slide instance method is invoked. + + + slid.bs.carousel + This event is fired when the carousel has completed its slide transition. + diff --git a/docs/components/collapse.md b/docs/components/collapse.md index a86678ad18..65b8171bdc 100644 --- a/docs/components/collapse.md +++ b/docs/components/collapse.md @@ -153,26 +153,26 @@ Options can be passed via data attributes or JavaScript. For data attributes, ap - - - - - - + + + + + + - - - - - - - - - - - - + + + + + + + + + + + +
NameTypeDefaultDescription
NameTypeDefaultDescription
parentselectorfalseIf a selector is provided, then all collapsible elements under the specified parent will be closed when this collapsible item is shown. (similar to traditional accordion behavior - this is dependent on the card class). The attribute has to be set on the target collapsible area.
togglebooleantrueToggles the collapsible element on invocation
parentselectorfalseIf a selector is provided, then all collapsible elements under the specified parent will be closed when this collapsible item is shown. (similar to traditional accordion behavior - this is dependent on the card class). The attribute has to be set on the target collapsible area.
togglebooleantrueToggles the collapsible element on invocation
@@ -209,30 +209,28 @@ Bootstrap's collapse class exposes a few events for hooking into collapse functi - - - - + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + +
Event TypeDescription
Event TypeDescription
show.bs.collapseThis event fires immediately when the show instance method is called.
shown.bs.collapseThis event is fired when a collapse element has been made visible to the user (will wait for CSS transitions to complete).
hide.bs.collapse - This event is fired immediately when the hide method has been called. -
hidden.bs.collapseThis event is fired when a collapse element has been hidden from the user (will wait for CSS transitions to complete).
show.bs.collapseThis event fires immediately when the show instance method is called.
shown.bs.collapseThis event is fired when a collapse element has been made visible to the user (will wait for CSS transitions to complete).
hide.bs.collapseThis event is fired immediately when the hide method has been called.
hidden.bs.collapseThis event is fired when a collapse element has been hidden from the user (will wait for CSS transitions to complete).
diff --git a/docs/components/forms.md b/docs/components/forms.md index 53654fac25..fd87dec7a5 100644 --- a/docs/components/forms.md +++ b/docs/components/forms.md @@ -376,7 +376,7 @@ Be sure to add `.col-form-label` to your `
- +
Checkbox

Heading

Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa.

diff --git a/docs/getting-started/build-tools.md b/docs/getting-started/build-tools.md index 8c5b635b3e..3482bb6179 100644 --- a/docs/getting-started/build-tools.md +++ b/docs/getting-started/build-tools.md @@ -5,7 +5,7 @@ description: Details on how to use Bootstrap's included build tools to compile s group: getting-started --- -Bootstrap uses [NPM scripts](https://docs.npmjs.com/misc/scripts) for its build system. Our [package.json](https://github.com/twbs/bootstrap/blob/master/package.json) includes convenient methods for working with the framework, including compiling code, running tests, and more. +Bootstrap uses [NPM scripts](https://docs.npmjs.com/misc/scripts) for its build system. Our [package.json](https://github.com/twbs/bootstrap/blob/v4-dev/package.json) includes convenient methods for working with the framework, including compiling code, running tests, and more. ## Contents diff --git a/docs/getting-started/introduction.md b/docs/getting-started/introduction.md index d70a42627c..0ca845a8a5 100644 --- a/docs/getting-started/introduction.md +++ b/docs/getting-started/introduction.md @@ -96,9 +96,7 @@ On the rare occasion you need to override it, use something like the following: {% highlight scss %} .selector-for-some-widget { - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; + box-sizing: content-box; } {% endhighlight %} diff --git a/js/src/button.js b/js/src/button.js index 6295d0db05..722fd489de 100644 --- a/js/src/button.js +++ b/js/src/button.js @@ -90,6 +90,12 @@ const Button = (($) => { } if (triggerChangeEvent) { + if (input.hasAttribute('disabled') || + rootElement.hasAttribute('disabled') || + input.classList.contains('disabled') || + rootElement.classList.contains('disabled')) { + return + } input.checked = !$(this._element).hasClass(ClassName.ACTIVE) $(input).trigger('change') } diff --git a/js/src/collapse.js b/js/src/collapse.js index dec272297b..bf1c738f56 100644 --- a/js/src/collapse.js +++ b/js/src/collapse.js @@ -56,9 +56,8 @@ const Collapse = (($) => { } const Selector = { - ACTIVES : '.card > .show, .card > .collapsing', - DATA_TOGGLE : '[data-toggle="collapse"]', - DATA_CHILDREN : 'data-children' + ACTIVES : '.show, .collapsing', + DATA_TOGGLE : '[data-toggle="collapse"]' } @@ -78,20 +77,13 @@ const Collapse = (($) => { `[data-toggle="collapse"][href="#${element.id}"],` + `[data-toggle="collapse"][data-target="#${element.id}"]` )) + this._parent = this._config.parent ? this._getParent() : null if (!this._config.parent) { this._addAriaAndCollapsedClass(this._element, this._triggerArray) } - this._selectorActives = Selector.ACTIVES - if (this._parent) { - const childrenSelector = this._parent.hasAttribute(Selector.DATA_CHILDREN) ? this._parent.getAttribute(Selector.DATA_CHILDREN) : null - if (childrenSelector !== null) { - this._selectorActives = `${childrenSelector} > .show, ${childrenSelector} > .collapsing` - } - } - if (this._config.toggle) { this.toggle() } @@ -129,7 +121,7 @@ const Collapse = (($) => { let activesData if (this._parent) { - actives = $.makeArray($(this._parent).find(this._selectorActives)) + actives = $.makeArray($(this._parent).children().children(Selector.ACTIVES)) if (!actives.length) { actives = null } diff --git a/js/src/tab.js b/js/src/tab.js index 6f8187d170..c7bc520df6 100644 --- a/js/src/tab.js +++ b/js/src/tab.js @@ -140,7 +140,7 @@ const Tab = (($) => { } dispose() { - $.removeClass(this._element, DATA_KEY) + $.removeData(this._element, DATA_KEY) this._element = null } diff --git a/js/tests/unit/button.js b/js/tests/unit/button.js index abc04e10a9..489d400a6c 100644 --- a/js/tests/unit/button.js +++ b/js/tests/unit/button.js @@ -156,4 +156,21 @@ $(function () { assert.ok($btn2.is(':not([aria-pressed])'), 'label for nested radio input has not been given an aria-pressed attribute') }) + QUnit.test('should handle disabled attribute on non-button elements', function (assert) { + assert.expect(2) + var groupHTML = '
' + + '' + + '
' + var $group = $(groupHTML).appendTo('#qunit-fixture') + + var $btn = $group.children().eq(0) + var $input = $btn.children().eq(0) + + $btn.trigger('click') + assert.ok($btn.is(':not(.active)'), 'button did not become active') + assert.ok(!$input.is(':checked'), 'checkbox did not get checked') + }) + }) diff --git a/js/tests/unit/collapse.js b/js/tests/unit/collapse.js index 35fcf2108e..2b9d0e58fc 100644 --- a/js/tests/unit/collapse.js +++ b/js/tests/unit/collapse.js @@ -491,27 +491,85 @@ $(function () { }) QUnit.test('should allow accordion to use children other than card', function (assert) { - assert.expect(2) + assert.expect(4) var done = assert.async() - var accordionHTML = '
' + var accordionHTML = '
' + '
' + '' + '
' + '
' + '
' - + '' + + '' + '
' + '
' + '
' $(accordionHTML).appendTo('#qunit-fixture') - var $target = $('#linkTrigger') - $('#collapseOne').on('shown.bs.collapse', function () { - assert.ok($(this).hasClass('show')) - assert.ok(!$('#collapseTwo').hasClass('show')) - done() + var $trigger = $('#linkTrigger') + var $triggerTwo = $('#linkTriggerTwo') + var $collapseOne = $('#collapseOne') + var $collapseTwo = $('#collapseTwo') + $collapseOne.on('shown.bs.collapse', function () { + assert.ok($collapseOne.hasClass('show'), '#collapseOne is shown') + assert.ok(!$collapseTwo.hasClass('show'), '#collapseTwo is not shown') + $collapseTwo.on('shown.bs.collapse', function () { + assert.ok(!$collapseOne.hasClass('show'), '#collapseOne is not shown') + assert.ok($collapseTwo.hasClass('show'), '#collapseTwo is shown') + done() + }) + $triggerTwo.trigger($.Event('click')) }) - $target.trigger($.Event('click')) + $trigger.trigger($.Event('click')) + }) + + QUnit.test('should collapse accordion children but not nested accordion children', function (assert) { + assert.expect(9) + var done = assert.async() + $('
' + + '
' + + '' + + '
' + + '
' + + '
' + + '' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '' + + '
' + + '
' + + '
').appendTo('#qunit-fixture') + var $trigger = $('#linkTrigger') + var $triggerTwo = $('#linkTriggerTwo') + var $nestedTrigger = $('#nestedLinkTrigger') + var $collapseOne = $('#collapseOne') + var $collapseTwo = $('#collapseTwo') + var $nestedCollapseOne = $('#nestedCollapseOne') + + + $collapseOne.one('shown.bs.collapse', function () { + assert.ok($collapseOne.hasClass('show'), '#collapseOne is shown') + assert.ok(!$collapseTwo.hasClass('show'), '#collapseTwo is not shown') + assert.ok(!$('#nestedCollapseOne').hasClass('show'), '#nestedCollapseOne is not shown') + $nestedCollapseOne.one('shown.bs.collapse', function () { + assert.ok($collapseOne.hasClass('show'), '#collapseOne is shown') + assert.ok(!$collapseTwo.hasClass('show'), '#collapseTwo is not shown') + assert.ok($nestedCollapseOne.hasClass('show'), '#nestedCollapseOne is shown') + $collapseTwo.one('shown.bs.collapse', function () { + assert.ok(!$collapseOne.hasClass('show'), '#collapseOne is not shown') + assert.ok($collapseTwo.hasClass('show'), '#collapseTwo is shown') + assert.ok($nestedCollapseOne.hasClass('show'), '#nestedCollapseOne is shown') + done() + }) + $triggerTwo.trigger($.Event('click')) + }) + $nestedTrigger.trigger($.Event('click')) + }) + $trigger.trigger($.Event('click')) }) QUnit.test('should not prevent event for input', function (assert) { diff --git a/package.json b/package.json index ab1185bd77..7e9ee3c750 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "css-compile": "node-sass --output-style expanded --source-map true --precision 6 scss/bootstrap.scss dist/css/bootstrap.css && node-sass --output-style expanded --source-map true --precision 6 scss/bootstrap-grid.scss dist/css/bootstrap-grid.css && node-sass --output-style expanded --source-map true --precision 6 scss/bootstrap-reboot.scss dist/css/bootstrap-reboot.css", "css-compile-docs": "node-sass --output-style expanded --source-map true --precision 6 docs/assets/scss/docs.scss docs/assets/css/docs.min.css", "css-prefix": "postcss --config build/ --replace dist/css/*.css", - "css-prefix-docs": "postcss --config build/ --no-map --replace docs/assets/css/docs.min.css docs/examples/**/*.css", + "css-prefix-docs": "postcss --config build/ --no-map --replace docs/assets/css/docs.min.css", "css-minify": "cleancss --level 1 --source-map --output dist/css/bootstrap.min.css dist/css/bootstrap.css && cleancss --level 1 --source-map --output dist/css/bootstrap-grid.min.css dist/css/bootstrap-grid.css && cleancss --level 1 --source-map --output dist/css/bootstrap-reboot.min.css dist/css/bootstrap-reboot.css", "css-minify-docs": "cleancss --level 1 --source-map --output docs/assets/css/docs.min.css docs/assets/css/docs.min.css", "js": "npm-run-all js-compile js-minify", @@ -38,7 +38,9 @@ "js-minify": "uglifyjs --compress warnings=false --mangle --comments '/^!/' --output dist/js/bootstrap.min.js dist/js/bootstrap.js", "js-minify-docs": "uglifyjs --compress warnings=false --mangle --comments '/^!/' --output docs/assets/js/docs.min.js docs/assets/js/vendor/anchor.min.js docs/assets/js/vendor/clipboard.min.js docs/assets/js/vendor/holder.min.js docs/assets/js/src/application.js", "js-test": "phantomjs ./node_modules/qunit-phantomjs-runner/runner.js js/tests/index.html 60", - "js-test-cloud": "ruby -run -ehttpd . -p3000 > /dev/null & grunt saucelabs-qunit", + "js-test-dep": "npm install grunt && npm install grunt-saucelabs", + "js-launch-cloud": "ruby -run -ehttpd . -p3000 > /dev/null & grunt saucelabs-qunit", + "js-test-cloud": "npm-run-all js-test-dep js-launch-cloud", "docs": "npm-run-all docs-compile docs-lint", "docs-lint": "htmlhint --config docs/.htmlhintrc _gh_pages/ js/tests/visual/ && htmllint --rc docs/.htmllintrc _gh_pages/*.html _gh_pages/**/*.html js/tests/visual/*.html", "docs-clean": "shx rm -r docs/dist/* && shx cp -r dist/* docs/dist/", @@ -51,7 +53,10 @@ "release-version": "node build/change-version.js", "release-zip": "cd dist/ && zip -r9 bootstrap-$npm_package_version-dist.zip * && shx mv bootstrap-$npm_package_version-dist.zip ..", "dist": "npm-run-all --parallel css js", - "test": "npm-run-all dist docs" + "test": "npm-run-all dist js-test docs", + "watch-css": "nodemon --ignore js/ --ignore dist/ -e scss -x \"npm run css && npm run css-docs\"", + "watch-js": "nodemon --ignore scss/ --ignore js/dist/ --ignore dist/ -e js -x \"npm run js-compile\"", + "watch": "npm-run-all --parallel watch-css watch-js" }, "style": "dist/css/bootstrap.css", "sass": "scss/bootstrap.scss", @@ -76,11 +81,10 @@ "babel-preset-es2015": "^7.0.0-alpha.7", "clean-css-cli": "^4.0.12", "eslint": "^3.19.0", - "grunt": "^1.0.1", - "grunt-saucelabs": "^9.0.0", "htmlhint": "^0.9.13", "htmllint-cli": "^0.0.6", "node-sass": "^4.5.2", + "nodemon": "^1.11.0", "npm-run-all": "^4.0.2", "phantomjs-prebuilt": "^2.1.14", "postcss-cli": "^3.1.1",