Commit 089d4348 authored by Mark Otto's avatar Mark Otto
Browse files

Merge branch 'master' into derp

Conflicts:
	_config.yml
	dist/css/bootstrap-theme.css.map
	dist/css/bootstrap.css
	dist/css/bootstrap.css.map
	dist/css/bootstrap.min.css
	docs/_includes/components/glyphicons.html
	docs/_includes/css/forms.html
	docs/_includes/css/tables.html
	docs/_includes/getting-started/browser-device-support.html
	docs/_includes/header.html
	docs/_includes/js/affix.html
	docs/_includes/js/alerts.html
	docs/_includes/js/buttons.html
	docs/_includes/js/dropdowns.html
	docs/_includes/js/overview.html
	docs/_includes/js/popovers.html
	docs/_includes/js/tooltips.html
	docs/_includes/nav/javascript.html
	docs/assets/css/docs.min.css
	docs/assets/css/src/docs.css
	docs/assets/js/customize.min.js
	docs/assets/js/docs.min.js
	docs/assets/js/raw-files.min.js
	docs/browser-bugs.html
	docs/dist/css/bootstrap-theme.css.map
	docs/dist/css/bootstrap.css
	docs/dist/css/bootstrap.css.map
	docs/dist/css/bootstrap.min.css
	docs/examples/blog/index.html
	docs/examples/carousel/index.html
	docs/examples/c...
parents f200c396 033f1654
main cleanup-floating-forms cssvar-function dependabot/npm_and_yarn/stylelint-and-stylelint-config-twbs-bootstrap-15.3.0 extend-snippets feat/data-target floating-always-visible floating-labels-icons fod-main-banner form-controls-with-icons github/fork/719media/patch-13 github/fork/719media/patch-14 github/fork/719media/patch-9 github/fork/ChellyAhmed/fix-typo-reboot.md github/fork/ChellyAhmed/offcanvas-scroll-back github/fork/CtrlAltLilith/main github/fork/Elysiome/offcanvas-optional-window-resizing github/fork/JanSargsyan/main github/fork/LunicLynx/support-different-line-height-for-buttons github/fork/Psixodelik/main github/fork/Ronid1/ronid1/offcanvas_static_backdrop github/fork/RyanBerliner/tooltip-accessibility github/fork/SantiagoPVazquez/Feature-default-border-bottom-to-dropdown-item github/fork/Sir-Genius/utils github/fork/Sumit-Singh-8/main github/fork/Viktor-VERA2020/offcanvas-slide github/fork/Zivangu9/input-group-for-form-control-plaintext github/fork/alpadev/alpadev/call-dispose-on-component-reinstantiation github/fork/astagi/fix/tree-shake-modules github/fork/compnerd/dark-accordion-icon github/fork/derSascha/dropdown-dont-close-on-input-click github/fork/dev-ph1l/main github/fork/donquixote/issue-33861-utl-mixin github/fork/florianlacreuse/mixin-make-row-gutter-y github/fork/gregorw/main github/fork/iteggmbh/transitionend-dispose-race github/fork/jdelStrother/patch-1 github/fork/jonnysp/form-floating github/fork/jonnysp/independent-offcanvas github/fork/jonnysp/theme-dark-on-card-and-modal-fix github/fork/josefdlange/floating-label-placeholder-opacity github/fork/julien-deramond/enhance-change-version.js github/fork/julien-deramond/main-jd-fix-offset-content github/fork/julien-deramond/main-jd-issue-with-utitlies github/fork/julien-deramond/main-xmr-pa11y-ci-jd-add-hideElements github/fork/kyletsang/fix-tooltip-padding github/fork/lacutah/CheckboxCenteringDocumentation github/fork/lekoala/patch-3 github/fork/louismaximepiton/main-kld-lmp-collapse-proposal github/fork/louismaximepiton/main-lmp-card-inner-border-radius-fix github/fork/louismaximepiton/main-lmp-carousel-multiple-images github/fork/louismaximepiton/main-lmp-css-var-init github/fork/louismaximepiton/main-lmp-disabled-floating-label-fix github/fork/louismaximepiton/main-lmp-input-range-fix github/fork/louismaximepiton/main-lmp-shift-color github/fork/louismaximepiton/main-lmp-table-active-tr-fix github/fork/maciek-szn/switch github/fork/michael-roth/feature/19964-multiple-tab-targets github/fork/mistic100/dom-utils github/fork/nkdas91/accordion github/fork/nstungcom/fix-missing-modal-open-class github/fork/oraliahdz/animation-utilities github/fork/pine3ree/patch-7 github/fork/pouwerkerk/unindent-scss-docs-shortcode github/fork/smares/smares-no-scolling-on-modal-close github/fork/tgm-git/patch-1 gs-forms gs-toasts-with-animated-progress-bar gs/add-history-helper gs/change-version-dir-on-docs gs/data-must-set-onlu-one-instance gs/docs/fix-drop-down-error gs/event-handler-2 gs/make-docs-js-build gs/make-simple-attribute-toggler gs/popover-fix-doc gs/provide-steConfig-method gs/scrollspy-smoothscroll-option-use-browser-history gs/streamline-jqueryInterface gs/support-drop-down-in-navbar gs/test-js-generic-trigger gs/try-web-components gs/tweak-collapse-js-selector gs/use-event-handler-in-cocmponent gs/use-rollup-replace-for-version jo-docs-thanks-page jo-ssr-friendly logical-props-spacing-utils main-fod-disabled-form-check-label main-fod-nested-accordion main-fod-simpler-table-structure main-fod-table-separator main-fod-utilities-contrast main-jd-abbr-title main-jd-add-chips main-jd-add-doc-for-sass-custom-colors main-jd-add-enable-host-to-handle-web-components main-jd-browserstack-fine-tune main-jd-browserstack-updates main-jd-docs-consistent-usage-of-css-sections-step-2 main-jd-fix-docs-headers-in-white main-jd-fix-highlight-docs-border-radius main-jd-fix-placeholder-color-background-params-for-img-markup main-jd-glossary-experiment main-jd-postcss-drop-empty-css-vars main-jd-proto-doc-astro main-jd-skip-navigation-component main-jd-stackblitz-for-examples main-jd-upgrade-browserlistrc main-jd-use-host main-lmp-dark-theme-customization main-lmp-handle-scroll-target main-lmp-tab-fix main-mc-opensearch main-xmr-bundlewatch-action main-xmr-eslint-plugin-compat main-xmr-hugo-docs-vendor main-xmr-hugo-rm-ver main-xmr-linkinator-prod main-xmr-min-mangle main-xmr-pa11y-ci more-darkmode-examples nested-dropdowns patrickhlauke-issue37428 patrickhlauke-use-of-color-tweaks pr/34102 pr/37590 previous-next-docs-links sticky-thead utilities-functions-mixin v4-dev v4-dev-dropdown-hide-method v530-dev v6-postcss-custom-media v6-spinner-dots v6/gs/use-floating-ui-in-place-of-popper xmr/dev xmr/docs-png xmr/docs-svgs xmr/hugo-reorg-files xmr/js-2 xmr/markdownlint xmr/prepare-530-alpha2 xmr/xo v5.3.0-alpha1 v5.2.3 v5.2.2 v5.2.1 v5.2.0 v5.2.0-beta1 v5.1.3 v5.1.2 v5.1.1 v5.1.0 v5.0.2 v5.0.1 v5.0.0 v5.0.0-beta3 v5.0.0-beta2 v5.0.0-beta1 v5.0.0-alpha3 v5.0.0-alpha2 v5.0.0-alpha1 v4.6.2 v4.6.1 v4.6.0 v4.5.3 v4.5.2 v4.5.1 v4.5.0 v4.4.1 v4.4.0 v4.3.1 v4.3.0 v4.2.1 v4.2.0 v4.1.3 v4.1.2 v4.1.1 v4.1.0 v4.0.0 v4.0.0-beta.3 v4.0.0-beta.2 v4.0.0-beta v4.0.0-alpha.6 v4.0.0-alpha.5 v4.0.0-alpha.4 v4.0.0-alpha.3 v4.0.0-alpha.2 v4.0.0-alpha
48 merge requests!28721Hot test,!27561Adds font-weight-medium to font weight classes,!26437merge,!26197V4 dev xmr,!20778V4 dev,!20539Allow multiple modals,!18047#17986,!18988Blockquote border width,!20854Fixes 15534,!19272V4 dev xmr grunt html,!17218Issue 17066,!19581V4 fix popover,!18283Tether docs fix,!17229Include documentation for .navbar-static-top,!20493V4 dev display,!20636Fix docs for heading sizes,!19824blockquote-center,!22547Finished a new translation for bootstrap,!19534Docs 17264,!19533Npm deps,!22143Fix selectable disabled toggle radio buttons,!19084V4 rhythm,!18085Ie9 click comment,!22598test,!18829Add prefix to carousel classes,!18581Check getting started files for broken links - Issue 18568,!18067replace grunt-autoprefixer with gruntpostcss + autoprefixer,!20099V4.0.0 alpha.3,!20438V4 grid classes,!17307Vertical alignment on Bootstrap columns with equal height,!18477add utility color-contrast function,!18864Feature/navbar toggler support color schemes,!19602V4 palettes arun,!18311V4 dev xmr,!19448New pull request for testing,!19358XXL grid size,!19825.blockquote-center,!17508Fix usage of “its” and “it’s” (v4 docs),!25326Adjust examples,!23995Add back cursor: pointer for .btn-link,!23178Spinner,!19754Issue template,!19753Card img overlay padding,!19747Blockquote border width,!19580ExitStars,!18684Docs: change "Button" to "Go somewhere",!18661Docs: accessibility fix-up of collapsible content navbar, change site-wide main navbar,!17021v4
Showing with 248 additions and 123 deletions
+248 -123
......@@ -18,8 +18,8 @@ after_script:
- if [ "$TWBS_TEST" = validate-html ] && [ $TWBS_DO_VALIDATOR -ne 0 ]; then ./test-infra/s3_cache.py upload rubygems; fi
env:
global:
- JEKYLL_VERSION: 2.1.0
- ROUGE_VERSION: 1.4.0
- JEKYLL_VERSION: 2.1.1
- ROUGE_VERSION: 1.6.1
- SAUCE_USERNAME: bootstrap
- secure: "pJkBwnuae9dKU5tEcCqccfS1QQw7/meEcfz63fM7ba7QJNjoA6BaXj08L5Z3Vb5vBmVPwBawxo5Hp0jC0r/Z/O0hGnAmz/Cz09L+cy7dSAZ9x4hvZePSja/UAusaB5ogMoO8l2b773MzgQeSmrLbExr9BWLeqEfjC2hFgdgHLaQ="
- secure: "gqjqISbxBJK6byFbsmr1AyP1qoWH+rap06A2gI7v72+Tn2PU2nYkIMUkCvhZw6K889jv+LhQ/ybcBxDOXHpNCExCnSgB4dcnmYp+9oeNZb37jSP0rQ+Ib4OTLjzc3/FawE/fUq5kukZTC7porzc/k0qJNLAZRx3YLALmK1GIdUY="
......
......@@ -320,7 +320,8 @@ module.exports = function (grunt) {
reset: true,
relaxerror: [
'Bad value X-UA-Compatible for attribute http-equiv on element meta.',
'Element img is missing required attribute src.'
'Element img is missing required attribute src.',
'Attribute autocomplete not allowed on element input at this point.'
]
},
files: {
......@@ -338,7 +339,7 @@ module.exports = function (grunt) {
tasks: ['jshint:test', 'qunit']
},
less: {
files: 'less/*.less',
files: 'less/**/*.less',
tasks: 'less'
},
docs: {
......
......@@ -31,9 +31,9 @@ blog: http://blog.getbootstrap.com
expo: http://expo.getbootstrap.com
cdn:
css: //maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css
css_theme: //maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css
js: //maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js
css: https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css
css_theme: https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css
js: https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js
jquery: //code.jquery.com/jquery-2.1.1.min.js
bug:
......
......@@ -714,6 +714,7 @@ kbd {
kbd kbd {
padding: 0;
font-size: 100%;
font-weight: bold;
-webkit-box-shadow: none;
box-shadow: none;
}
......@@ -1597,11 +1598,13 @@ table th[class*="col-"] {
.table-hover > tbody > tr.danger:hover > th {
background-color: #ebcccc;
}
.table-responsive {
overflow-x: auto;
}
@media screen and (max-width: 47.9em) {
.table-responsive {
width: 100%;
margin-bottom: 18px;
overflow-x: auto;
overflow-y: hidden;
-webkit-overflow-scrolling: touch;
-ms-overflow-style: -ms-autohiding-scrollbar;
......@@ -1786,12 +1789,14 @@ input[type="time"].input-sm,
input[type="datetime-local"].input-sm,
input[type="month"].input-sm {
line-height: 1.975rem;
line-height: 1.5 \0;
}
input[type="date"].input-lg,
input[type="time"].input-lg,
input[type="datetime-local"].input-lg,
input[type="month"].input-lg {
line-height: 3.2625rem;
line-height: 1.33 \0;
}
.form-group {
margin-bottom: 15px;
......@@ -2046,6 +2051,9 @@ select[multiple].form-group-lg .form-control {
width: auto;
vertical-align: middle;
}
.form-inline .form-control-static {
display: inline-block;
}
.form-inline .input-group {
display: inline-table;
vertical-align: middle;
......@@ -3390,6 +3398,9 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
width: auto;
vertical-align: middle;
}
.navbar-form .form-control-static {
display: inline-block;
}
.navbar-form .input-group {
display: inline-table;
vertical-align: middle;
......
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
This diff is collapsed.
......@@ -88,6 +88,8 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
Alert.VERSION = '3.2.0'
Alert.TRANSITION_DURATION = 150
Alert.prototype.close = function (e) {
var $this = $(this)
var selector = $this.attr('data-target')
......@@ -119,7 +121,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
$.support.transition && $parent.hasClass('fade') ?
$parent
.one('bsTransitionEnd', removeElement)
.emulateTransitionEnd(150) :
.emulateTransitionEnd(Alert.TRANSITION_DURATION) :
removeElement()
}
......@@ -258,15 +260,6 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
}
// FOCUS SHIM (FOR BUTTON GROUPS)
// ==============================
function getBtnTarget(target) {
var $target = $(target)
return $target.hasClass('btn') ? $target : $target.parent('.btn')
}
// BUTTON DATA-API
// ===============
......@@ -277,11 +270,8 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
Plugin.call($btn, 'toggle')
e.preventDefault()
})
.on('focus.bs.button.data-api', '[data-toggle^="button"]', function (e) {
getBtnTarget(e.target).addClass('focus')
})
.on('blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
getBtnTarget(e.target).removeClass('focus')
.on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
$(e.target).closest('.btn').toggleClass('focus', e.type == 'focus')
})
}(jQuery);
......@@ -318,6 +308,8 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
Carousel.VERSION = '3.2.0'
Carousel.TRANSITION_DURATION = 600
Carousel.DEFAULTS = {
interval: 5000,
pause: 'hover',
......@@ -351,6 +343,13 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
return this.$items.index(item || this.$active)
}
Carousel.prototype.getItemForDirection = function (direction, active) {
var delta = direction == 'prev' ? -1 : 1
var activeIndex = this.getItemIndex(active)
var itemIndex = (activeIndex + delta) % this.$items.length
return this.$items.eq(itemIndex)
}
Carousel.prototype.to = function (pos) {
var that = this
var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
......@@ -360,7 +359,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
if (activeIndex == pos) return this.pause().cycle()
return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))
return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
}
Carousel.prototype.pause = function (e) {
......@@ -388,7 +387,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
Carousel.prototype.slide = function (type, next) {
var $active = this.$element.find('.item.active')
var $next = next || $active[type]()
var $next = next || this.getItemForDirection(type, $active)
var isCycling = this.interval
var direction = type == 'next' ? 'left' : 'right'
var fallback = type == 'next' ? 'first' : 'last'
......@@ -434,7 +433,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
that.$element.trigger(slidEvent)
}, 0)
})
.emulateTransitionEnd($active.css('transition-duration').slice(0, -1) * 1000)
.emulateTransitionEnd(Carousel.TRANSITION_DURATION)
} else {
$active.removeClass('active')
$next.addClass('active')
......@@ -536,6 +535,8 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
Collapse.VERSION = '3.2.0'
Collapse.TRANSITION_DURATION = 350
Collapse.DEFAULTS = {
toggle: true
}
......@@ -584,7 +585,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
this.$element
.one('bsTransitionEnd', $.proxy(complete, this))
.emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize])
.emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
}
Collapse.prototype.hide = function () {
......@@ -617,7 +618,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
this.$element
[dimension](0)
.one('bsTransitionEnd', $.proxy(complete, this))
.emulateTransitionEnd(350)
.emulateTransitionEnd(Collapse.TRANSITION_DURATION)
}
Collapse.prototype.toggle = function () {
......@@ -724,7 +725,9 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
if (e.isDefaultPrevented()) return
$this.trigger('focus')
$this
.trigger('focus')
.attr('aria-expanded', 'true')
$parent
.toggleClass('open')
......@@ -770,11 +773,17 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
if (e && e.which === 3) return
$(backdrop).remove()
$(toggle).each(function () {
var $parent = getParent($(this))
var $this = $(this)
var $parent = getParent($this)
var relatedTarget = { relatedTarget: this }
if (!$parent.hasClass('open')) return
$parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
if (e.isDefaultPrevented()) return
$this.attr('aria-expanded', 'false')
$parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
})
}
......@@ -866,6 +875,9 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
Modal.VERSION = '3.2.0'
Modal.TRANSITION_DURATION = 300
Modal.BACKDROP_TRANSITION_DURATION = 150
Modal.DEFAULTS = {
backdrop: true,
keyboard: true,
......@@ -922,7 +934,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
.one('bsTransitionEnd', function () {
that.$element.trigger('focus').trigger(e)
})
.emulateTransitionEnd(300) :
.emulateTransitionEnd(Modal.TRANSITION_DURATION) :
that.$element.trigger('focus').trigger(e)
})
}
......@@ -953,7 +965,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
$.support.transition && this.$element.hasClass('fade') ?
this.$element
.one('bsTransitionEnd', $.proxy(this.hideModal, this))
.emulateTransitionEnd(300) :
.emulateTransitionEnd(Modal.TRANSITION_DURATION) :
this.hideModal()
}
......@@ -1016,7 +1028,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
doAnimate ?
this.$backdrop
.one('bsTransitionEnd', callback)
.emulateTransitionEnd(150) :
.emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
callback()
} else if (!this.isShown && this.$backdrop) {
......@@ -1029,7 +1041,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
$.support.transition && this.$element.hasClass('fade') ?
this.$backdrop
.one('bsTransitionEnd', callbackRemove)
.emulateTransitionEnd(150) :
.emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
callbackRemove()
} else if (callback) {
......@@ -1142,6 +1154,8 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
Tooltip.VERSION = '3.2.0'
Tooltip.TRANSITION_DURATION = 150
Tooltip.DEFAULTS = {
animation: true,
placement: 'top',
......@@ -1322,7 +1336,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
$.support.transition && this.$tip.hasClass('fade') ?
$tip
.one('bsTransitionEnd', complete)
.emulateTransitionEnd(150) :
.emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
complete()
}
}
......@@ -1410,7 +1424,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
$.support.transition && this.$tip.hasClass('fade') ?
$tip
.one('bsTransitionEnd', complete)
.emulateTransitionEnd(150) :
.emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
complete()
this.hoverState = null
......@@ -1884,6 +1898,8 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
Tab.VERSION = '3.2.0'
Tab.TRANSITION_DURATION = 150
Tab.prototype.show = function () {
var $this = this.element
var $ul = $this.closest('ul:not(.dropdown-menu)')
......@@ -1947,7 +1963,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
$active.length && transition ?
$active
.one('bsTransitionEnd', next)
.emulateTransitionEnd(150) :
.emulateTransitionEnd(Tab.TRANSITION_DURATION) :
next()
$active.removeClass('in')
......@@ -2031,6 +2047,28 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
target: window
}
Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
var scrollTop = this.$target.scrollTop()
var position = this.$element.offset()
var targetHeight = this.$target.height()
if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
if (this.affixed == 'bottom') {
if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
}
var initializing = this.affixed == null
var colliderTop = initializing ? scrollTop : position.top
var colliderHeight = initializing ? targetHeight : height
if (offsetTop != null && colliderTop <= offsetTop) return 'top'
if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
return false
}
Affix.prototype.getPinnedOffset = function () {
if (this.pinnedOffset) return this.pinnedOffset
this.$element.removeClass(Affix.RESET).addClass('affix')
......@@ -2046,42 +2084,40 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
Affix.prototype.checkPosition = function () {
if (!this.$element.is(':visible')) return
var scrollHeight = $(document).height()
var scrollTop = this.$target.scrollTop()
var position = this.$element.offset()
var height = this.$element.height()
var offset = this.options.offset
var offsetTop = offset.top
var offsetBottom = offset.bottom
var scrollHeight = $('body').height()
if (typeof offset != 'object') offsetBottom = offsetTop = offset
if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element)
if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
var affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ? false :
offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' :
offsetTop != null && (scrollTop <= offsetTop) ? 'top' : false
var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
if (this.affixed === affix) return
if (this.unpin != null) this.$element.css('top', '')
if (this.affixed != affix) {
if (this.unpin != null) this.$element.css('top', '')
var affixType = 'affix' + (affix ? '-' + affix : '')
var e = $.Event(affixType + '.bs.affix')
var affixType = 'affix' + (affix ? '-' + affix : '')
var e = $.Event(affixType + '.bs.affix')
this.$element.trigger(e)
this.$element.trigger(e)
if (e.isDefaultPrevented()) return
if (e.isDefaultPrevented()) return
this.affixed = affix
this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
this.affixed = affix
this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
this.$element
.removeClass(Affix.RESET)
.addClass(affixType)
.trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
this.$element
.removeClass(Affix.RESET)
.addClass(affixType)
.trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
}
if (affix == 'bottom') {
this.$element.offset({
top: scrollHeight - this.$element.height() - offsetBottom
top: scrollHeight - height - offsetBottom
})
}
}
......
This diff is collapsed.
......@@ -46,6 +46,8 @@
{% if page.slug == "customize" %}
<script src="{{ site.baseurl }}assets/js/customize.min.js"></script>
{% endif %}
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="../assets/js/ie10-viewport-bug-workaround.js"></script>
{% comment %}
Inject Twitter widgets asynchronously. Snippet snipped from Twitter's
......
// NOTE: DO NOT EDIT THE FOLLOWING SECTION DIRECTLY! It is autogenerated via the `build-customizer-html` Grunt task using the customizer-nav.jade template.
li
a(href='#import') Import
li
a(href='#less') Less components
li
......
This diff is collapsed.
This diff is collapsed.
......@@ -21,4 +21,4 @@ var Holder=Holder||{};!function(a,b){function c(a,b,c){b=parseInt(b,10),a=parseI
* Licensed under the Creative Commons Attribution 3.0 Unported License. For
* details, see http://creativecommons.org/licenses/by/3.0/.
*/
!function(a){"use strict";a(function(){a(".tooltip-demo").tooltip({selector:'[data-toggle="tooltip"]',container:"body"}),a(".popover-demo").popover({selector:'[data-toggle="popover"]',container:"body"}),a(".tooltip-test").tooltip(),a(".popover-test").popover(),a(".bs-docs-popover").popover(),a(".bs-docs-popover-dismiss").popover({trigger:"focus"}),a("#loading-example-btn").click(function(){var b=a(this);b.button("loading"),setTimeout(function(){b.button("reset")},3e3)}),ZeroClipboard.config({moviePath:"/assets/flash/ZeroClipboard.swf",hoverClass:"btn-clipboard-hover"}),a(".highlight").each(function(){var b=a(this),c=b.prev(),d='<div class="zero-clipboard"><span class="btn-clipboard">Copy</span></div>';c.hasClass("bs-example")?c.before(d.replace(/btn-clipboard/,"btn-clipboard with-example")):b.before(d)});var b=new ZeroClipboard(a(".btn-clipboard")),c=a("#global-zeroclipboard-html-bridge");b.on("load",function(){c.data("placement","top").attr("title","Copy to clipboard").tooltip()}),b.on("dataRequested",function(b){var c=a(this).parent().nextAll(".highlight").first();b.setText(c.text())}),b.on("complete",function(){c.attr("title","Copied!").tooltip("fixTitle").tooltip("show").attr("title","Copy to clipboard").tooltip("fixTitle")}),b.on("noflash wrongflash",function(){c.attr("title","Flash required").tooltip("fixTitle").tooltip("show")})})}(jQuery);
\ No newline at end of file
!function(a){"use strict";a(function(){a(".tooltip-demo").tooltip({selector:'[data-toggle="tooltip"]',container:"body"}),a(".popover-demo").popover({selector:'[data-toggle="popover"]',container:"body"}),a(".tooltip-test").tooltip(),a(".popover-test").popover(),a(".bs-docs-popover").popover(),a("#loading-example-btn").click(function(){var b=a(this);b.button("loading"),setTimeout(function(){b.button("reset")},3e3)}),ZeroClipboard.config({moviePath:"/assets/flash/ZeroClipboard.swf",hoverClass:"btn-clipboard-hover"}),a(".highlight").each(function(){var b=a(this),c=b.prev(),d='<div class="zero-clipboard"><span class="btn-clipboard">Copy</span></div>';c.hasClass("bs-example")?c.before(d.replace(/btn-clipboard/,"btn-clipboard with-example")):b.before(d)});var b=new ZeroClipboard(a(".btn-clipboard")),c=a("#global-zeroclipboard-html-bridge");b.on("load",function(){c.data("placement","top").attr("title","Copy to clipboard").tooltip()}),b.on("dataRequested",function(b){var c=a(this).parent().nextAll(".highlight").first();b.setText(c.text())}),b.on("complete",function(){c.attr("title","Copied!").tooltip("fixTitle").tooltip("show").attr("title","Copy to clipboard").tooltip("fixTitle")}),b.on("noflash wrongflash",function(){c.attr("title","Flash required").tooltip("fixTitle").tooltip("show")})})}(jQuery);
\ No newline at end of file
......@@ -73,9 +73,8 @@
$('.tooltip-test').tooltip()
$('.popover-test').popover()
// Default & dismissible popover demos
// Popover demos
$('.bs-docs-popover').popover()
$('.bs-docs-popover-dismiss').popover({ trigger: 'focus' })
// Button state demo
$('#loading-example-btn').click(function () {
......
......@@ -16,6 +16,9 @@ window.onload = function () { // wait for load in a dumb way because B-0
' * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n' +
' */\n\n'
var supportsFile = (window.File && window.FileReader && window.FileList && window.Blob)
var importDropTarget = $('#import-drop-target')
function showError(msg, err) {
$('<div id="bsCustomizerAlert" class="bs-customizer-alert">' +
'<div class="container">' +
......@@ -46,6 +49,11 @@ window.onload = function () { // wait for load in a dumb way because B-0
}
}
function showAlert(type, msg, insertAfter) {
$('<div class="alert alert-' + type + '">' + msg + '<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button></div>')
.insertAfter(insertAfter)
}
function getQueryParam(key) {
key = key.replace(/[*+?^$.\[\]{}()|\\\/]/g, '\\$&') // escape RegEx meta chars
var match = location.search.match(new RegExp('[?&]' + key + '=([^&]+)(&|$)'))
......@@ -106,6 +114,24 @@ window.onload = function () { // wait for load in a dumb way because B-0
return data
}
function updateCustomizerFromJson(data) {
if (data.js) {
$('#plugin-section input').each(function () {
$(this).prop('checked', ~$.inArray(this.value, data.js))
})
}
if (data.css) {
$('#less-section input').each(function () {
$(this).prop('checked', ~$.inArray(this.value, data.css))
})
}
if (data.vars) {
for (var i in data.vars) {
$('input[data-var="' + i + '"]').val(data.vars[i])
}
}
}
function parseUrl() {
var id = getQueryParam('id')
......@@ -118,21 +144,7 @@ window.onload = function () { // wait for load in a dumb way because B-0
})
.success(function (result) {
var data = JSON.parse(result.files['config.json'].content)
if (data.js) {
$('#plugin-section input').each(function () {
$(this).prop('checked', ~$.inArray(this.value, data.js))
})
}
if (data.css) {
$('#less-section input').each(function () {
$(this).prop('checked', ~$.inArray(this.value, data.css))
})
}
if (data.vars) {
for (var i in data.vars) {
$('input[data-var="' + i + '"]').val(data.vars[i])
}
}
updateCustomizerFromJson(data)
})
.error(function (err) {
showError('Error fetching bootstrap config file', err)
......@@ -324,6 +336,61 @@ window.onload = function () { // wait for load in a dumb way because B-0
}
}
function removeImportAlerts() {
importDropTarget.nextAll('.alert').remove()
}
function handleConfigFileSelect(e) {
e.stopPropagation()
e.preventDefault()
var file = (e.originalEvent.hasOwnProperty('dataTransfer')) ? e.originalEvent.dataTransfer.files[0] : e.originalEvent.target.files[0]
if (!file.type.match('application/json')) {
return showAlert('danger', '<strong>Ruh roh.</strong> We can only read <code>.json</code> files. Please try again.', importDropTarget)
}
var reader = new FileReader()
reader.onload = (function () {
return function (e) {
var text = e.target.result
try {
var json = JSON.parse(text)
if (typeof json != 'object') {
throw new Error('JSON data from config file is not an object.')
}
updateCustomizerFromJson(json)
showAlert('success', '<strong>Woohoo!</strong> Your configuration was successfully uploaded. Tweak your settings, then hit Download.', importDropTarget)
} catch (err) {
return showAlert('danger', '<strong>Shucks.</strong> We can only read valid <code>.json</code> files. Please try again.', importDropTarget)
}
}
})(file)
reader.readAsText(file)
}
function handleConfigDragOver(e) {
e.stopPropagation()
e.preventDefault()
e.originalEvent.dataTransfer.dropEffect = 'copy'
removeImportAlerts()
}
if (supportsFile) {
importDropTarget
.on('dragover', handleConfigDragOver)
.on('drop', handleConfigFileSelect)
}
$('#import-file-select').on('select', handleConfigFileSelect)
$('#import-manual-trigger').on('click', removeImportAlerts)
var inputsComponent = $('#less-section input')
var inputsPlugin = $('#plugin-section input')
var inputsVariables = $('#less-variables-section input')
......@@ -410,7 +477,8 @@ window.onload = function () { // wait for load in a dumb way because B-0
{ type: 'image/svg+xml;charset=utf-8' }
)
var objectUrl = url.createObjectURL(svg);
if (/^blob:/.exec(objectUrl) === null) {
if (/^blob:/.exec(objectUrl) === null || !supportsFile) {
// `URL.createObjectURL` created a URL that started with something other
// than "blob:", which means it has been polyfilled and is not supported by
// this browser.
......
/* Blob.js
* A Blob implementation.
* 2014-05-31
* 2014-07-01
*
* By Eli Grey, http://eligrey.com
* By Devin Samarin, https://github.com/eboyjr
......@@ -166,7 +166,7 @@
return FakeBlobBuilder;
}(view));
view.Blob = function Blob(blobParts, options) {
view.Blob = function(blobParts, options) {
var type = options ? (options.type || "") : "";
var builder = new BlobBuilder();
if (blobParts) {
......
/* FileSaver.js
* A saveAs() FileSaver implementation.
* 2014-05-27
* A saveAs() FileSaver implementation.
* 2014-07-21
*
* By Eli Grey, http://eligrey.com
* License: X11/MIT
* See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
* By Eli Grey, http://eligrey.com
* License: X11/MIT
* See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
*/
/*global self */
......@@ -49,18 +49,17 @@ var saveAs = saveAs
}
, force_saveable_type = "application/octet-stream"
, fs_min_size = 0
, deletion_queue = []
, process_deletion_queue = function() {
var i = deletion_queue.length;
while (i--) {
var file = deletion_queue[i];
// See https://code.google.com/p/chromium/issues/detail?id=375297#c7 for
// the reasoning behind the timeout and revocation flow
, arbitrary_revoke_timeout = 10
, revoke = function(file) {
setTimeout(function() {
if (typeof file === "string") { // file is an object URL
get_URL().revokeObjectURL(file);
} else { // file is a File
file.remove();
}
}
deletion_queue.length = 0; // clear queue
}, arbitrary_revoke_timeout);
}
, dispatch = function(filesaver, event_types, event) {
event_types = [].concat(event_types);
......@@ -84,11 +83,6 @@ var saveAs = saveAs
, blob_changed = false
, object_url
, target_view
, get_object_url = function() {
var object_url = get_URL().createObjectURL(blob);
deletion_queue.push(object_url);
return object_url;
}
, dispatch_all = function() {
dispatch(filesaver, "writestart progress write writeend".split(" "));
}
......@@ -96,15 +90,16 @@ var saveAs = saveAs
, fs_error = function() {
// don't create more object URLs than needed
if (blob_changed || !object_url) {
object_url = get_object_url(blob);
object_url = get_URL().createObjectURL(blob);
}
if (target_view) {
target_view.location.href = object_url;
} else {
window.open(object_url, "_blank");
view.open(object_url, "_blank");
}
filesaver.readyState = filesaver.DONE;
dispatch_all();
revoke(object_url);
}
, abortable = function(func) {
return function() {
......@@ -121,17 +116,20 @@ var saveAs = saveAs
name = "download";
}
if (can_use_save_link) {
object_url = get_object_url(blob);
object_url = get_URL().createObjectURL(blob);
save_link.href = object_url;
save_link.download = name;
click(save_link);
filesaver.readyState = filesaver.DONE;
dispatch_all();
revoke(object_url);
return;
}
// Object and web filesystem URLs have a problem saving in Google Chrome when
// viewed in a tab, so I force save with application/octet-stream
// http://code.google.com/p/chromium/issues/detail?id=91158
// Update: Google errantly closed 91158, I submitted it again:
// https://code.google.com/p/chromium/issues/detail?id=389642
if (view.chrome && type && type !== force_saveable_type) {
slice = blob.slice || blob.webkitSlice;
blob = slice.call(blob, 0, blob.size, force_saveable_type);
......@@ -158,9 +156,9 @@ var saveAs = saveAs
file.createWriter(abortable(function(writer) {
writer.onwriteend = function(event) {
target_view.location.href = file.toURL();
deletion_queue.push(file);
filesaver.readyState = filesaver.DONE;
dispatch(filesaver, "writeend", event);
revoke(file);
};
writer.onerror = function() {
var error = writer.error;
......@@ -217,11 +215,6 @@ var saveAs = saveAs
FS_proto.onwriteend =
null;
view.addEventListener("unload", process_deletion_queue, false);
saveAs.unload = function() {
process_deletion_queue();
view.removeEventListener("unload", process_deletion_queue, false);
};
return saveAs;
}(
typeof self !== "undefined" && self
......
......@@ -36,24 +36,12 @@ We publicly list browser bugs that are impacting us here, in the hopes of expedi
<td><a href="{{ site.bug.firefox }}975632">Mozilla bug #975632</a></td>
<td><a href="{{ site.bug.github }}10690">#10690</a></td>
</tr>
<tr>
<td>Firefox <strong>&lt;31</strong></td>
<td><code>position: relative;</code> doesn't work inside tables</td>
<td><a href="{{ site.bug.firefox }}63895">Mozilla bug #63895</a></td>
<td><a href="{{ site.bug.github }}12467">#12467</a></td>
</tr>
<tr>
<td>Chrome</td>
<td>Weird button behavior with some number <code>&lt;input&gt;</code>s</td>
<td><a href="{{ site.bug.chrome }}337668">Chromium issue #337668</a></td>
<td><a href="{{ site.bug.github }}8350">#8350</a>, <a href="https://github.com/necolas/normalize.css/issues/283">Normalize #283</a></td>
</tr>
<tr>
<td>Chrome</td>
<td>Navbar rendering problem on Windows after several clicks</td>
<td><a href="{{ site.bug.chrome }}272750">Chromium issue #272750</a>, <a href="{{ site.bug.webkit }}119793">WebKit bug #119793</a></td>
<td><a href="{{ site.bug.github }}9226">#9226</a></td>
</tr>
<tr>
<td>Chrome</td>
<td><code>display: table;</code> within <code>display: block;</code> forces sibling content to new line</td>
......
......@@ -233,7 +233,7 @@ Use the default option, or add `multiple` to show multiple options at once.
## Static controls
When you need to place plain text next to a form label within a horizontal form, use the `.form-control-static` class on a `<p>`.
When you need to place plain text next to a form label within a form, use the `.form-control-static` class on a `<p>`.
{% example html %}
<form class="form-horizontal" role="form">
......@@ -252,6 +252,20 @@ When you need to place plain text next to a form label within a horizontal form,
</form>
{% endexample %}
{% example html %}
<form class="form-inline" role="form">
<div class="form-group">
<label class="sr-only">Email</label>
<p class="form-control-static">email@example.com</p>
</div>
<div class="form-group">
<label for="inputPassword2" class="sr-only">Password</label>
<input type="password" class="form-control" id="inputPassword2" placeholder="Password">
</div>
<button type="submit" class="btn btn-default">Confirm identity</button>
</form>
{% endexample %}
## Focus state
We remove the default `outline` styles on some form controls and apply a `box-shadow` in its place for `:focus`.
......
......@@ -12,6 +12,7 @@ lead: Customize Bootstrap's components, Less variables, and jQuery plugins to ge
<!--[if lt IE 9]>
<style>
.bs-customizer,
.bs-customizer-import,
.bs-docs-sidebar {
display: none;
}
......@@ -23,6 +24,17 @@ lead: Customize Bootstrap's components, Less variables, and jQuery plugins to ge
<![endif]-->
<!-- Customizer form -->
<div class="bs-docs-section bs-customizer-import">
<div id="import-drop-target" class="bs-dropzone">
<h2></h2>
<p class="lead">Have an existing configuration? Upload your <code>config.json</code> to import it.</p>
<p>Drag and drop here, or <label id="import-manual-trigger" class="btn-link">manually upload<input type="file" id="import-file-select" class="hidden"></label>.</p>
<hr>
<p><strong>Don't have one?</strong> That's okay—just start customizing the fields below.</p>
</div>
</div><!-- /import -->
<form class="bs-customizer" role="form">
<div class="bs-docs-section" id="less-section">
<button class="btn btn-secondary toggle" type="button">Toggle all</button>
......@@ -358,8 +370,6 @@ lead: Customize Bootstrap's components, Less variables, and jQuery plugins to ge
{% include customizer-variables.html %}
</div>
<div class="bs-docs-section">
<h1 id="download" class="page-header">Download</h1>
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment