Merge branch 'master' into derp

Conflicts:
	Gruntfile.js
	dist/css/bootstrap-theme.css
	dist/css/bootstrap-theme.css.map
	dist/css/bootstrap-theme.min.css
	dist/css/bootstrap.css
	dist/css/bootstrap.css.map
	dist/css/bootstrap.min.css
	docs/_includes/components/dropdowns.html
	docs/_includes/components/media.html
	docs/_includes/components/navs.html
	docs/_includes/components/progress-bars.html
	docs/_includes/components/responsive-embed.html
	docs/_includes/css/buttons.html
	docs/_includes/css/forms.html
	docs/_includes/css/less.html
	docs/_includes/css/overview.html
	docs/_includes/css/responsive-utilities.html
	docs/_includes/customizer-variables.html
	docs/_includes/getting-started/browser-device-support.html
	docs/_includes/getting-started/grunt.html
	docs/_includes/getting-started/template.html
	docs/_includes/header.html
	docs/_includes/js/alerts.html
	docs/_includes/js/buttons.html
	docs/_includes/js/carousel.html
	docs/_includes/js/collapse.html
	docs/_includes/js/dropdowns.html
	docs/_includes/js/modal.html
	docs/_includes/js/popovers.html
	docs/_includes/js/scrollspy.html
	docs/_includes/js/tabs.html
	docs/_includes/js/tooltips.html
	docs/_includes/nav/components.html
	docs/_includes/nav/getting-started.html
	docs/_layouts/default.html
	docs/about.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/components.html
	docs/components/navbar.md
	docs/css.html
	docs/dist/css/bootstrap-theme.css
	docs/dist/css/bootstrap-theme.css.map
	docs/dist/css/bootstrap-theme.min.css
	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/cover/index.html
	docs/examples/dashboard/index.html
	docs/examples/grid/index.html
	docs/examples/jumbotron-narrow/index.html
	docs/examples/jumbotron/index.html
	docs/examples/justified-nav/index.html
	docs/examples/navbar-fixed-top/index.html
	docs/examples/navbar-static-top/index.html
	docs/examples/navbar/index.html
	docs/examples/non-responsive/index.html
	docs/examples/offcanvas/index.html
	docs/examples/signin/index.html
	docs/examples/starter-template/index.html
	docs/examples/sticky-footer-navbar/index.html
	docs/examples/sticky-footer/index.html
	docs/examples/theme/index.html
	docs/examples/tooltip-viewport/index.html
	docs/getting-started.html
	docs/javascript.html
	docs/migration.html
	less/_animation.less
	less/_modal.less
	less/_navbar.less
	less/_variables.less
	less/glyphicons.less
	less/navs.less
	less/panels.less
	less/progress-bars.less
This commit is contained in:
Mark Otto 2014-10-26 22:31:59 -07:00
commit d6b0f45fb7
82 changed files with 2272 additions and 1575 deletions

View File

@ -3,12 +3,12 @@
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.py]
indent_size = 4

18
.gitignore vendored
View File

@ -6,37 +6,37 @@ _site
# Numerous always-ignore extensions
*.diff
*.err
*.orig
*.log
*.orig
*.rej
*.swo
*.swp
*.zip
*.vi
*.zip
*~
# OS or Editor folders
.DS_Store
._*
Thumbs.db
.cache
.DS_Store
.idea
.project
.settings
.tmproj
*.esproj
nbproject
*.sublime-project
*.sublime-workspace
.idea
nbproject
Thumbs.db
# Komodo
*.komodoproject
.komodotools
*.komodoproject
# grunt-html-validation
validation-status.json
validation-report.json
validation-status.json
# Folders to ignore
node_modules
bower_components
node_modules

View File

@ -36,6 +36,10 @@ Good bug reports are extremely helpful, so thanks!
Guidelines for bug reports:
0. **Validate and lint your code** — [validate your HTML](http://html5.validator.nu)
and [lint your HTML](https://github.com/twbs/bootlint) to ensure your
problem isn't caused by a simple error in your own code.
1. **Use the GitHub issue search** — check if the issue has already been
reported.
@ -72,6 +76,18 @@ Example:
> causing the bug, and potential solutions (and your opinions on their
> merits).
### Reporting upstream browser bugs
Sometimes bugs reported to us are actually caused by bugs in the browser(s) themselves, not bugs in Bootstrap per se.
When feasible, we aim to report such upstream bugs to the relevant browser vendor(s), and then list them on our [Wall of Browser Bugs](http://getbootstrap.com/browser-bugs/).
| Vendor(s) | Browser(s) | Rendering engine | Bug reporting website(s) | Notes |
| ------------- | ---------------------------- | ---------------- | ------------------------------------------------------------------------------------- | -------------------------------------------------------- |
| Mozilla | Firefox | Gecko | https://bugzilla.mozilla.org/enter_bug.cgi | "Core" is normally the right product option to choose. |
| Apple | Safari | WebKit | https://bugs.webkit.org/enter_bug.cgi?product=WebKit <br> https://bugreport.apple.com | In Apple's bug reporter, choose "Safari" as the product. |
| Google, Opera | Chrome, Chromium, Opera v15+ | Blink | https://code.google.com/p/chromium/issues/list | Click the "New issue" button. |
| Microsoft | Internet Explorer | Trident | https://connect.microsoft.com/IE/feedback/LoadSubmitFeedbackForm | |
## Feature requests

View File

@ -26,6 +26,7 @@ module.exports = function (grunt) {
return { sections: parser.parseFile() };
};
var generateRawFiles = require('./grunt/bs-raw-files-generator.js');
var generateCommonJSModule = require('./grunt/bs-commonjs-generator.js');
// Project configuration.
grunt.initConfig({
@ -37,8 +38,21 @@ module.exports = function (grunt) {
' * Copyright 2011-<%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' +
' * Licensed under <%= pkg.license.type %> (<%= pkg.license.url %>)\n' +
' */\n',
// NOTE: This jqueryCheck code is duplicated in customizer.js; if making changes here, be sure to update the other copy too.
jqueryCheck: 'if (typeof jQuery === \'undefined\') { throw new Error(\'Bootstrap\\\'s JavaScript requires jQuery\') }\n\n',
// NOTE: This jqueryCheck/jqueryVersionCheck code is duplicated in customizer.js;
// if making changes here, be sure to update the other copy too.
jqueryCheck: [
'if (typeof jQuery === \'undefined\') {',
' throw new Error(\'Bootstrap\\\'s JavaScript requires jQuery\')',
'}\n'
].join('\n'),
jqueryVersionCheck: [
'+function ($) {',
' var version = $.fn.jquery.split(\' \')[0].split(\'.\')',
' if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1)) {',
' throw new Error(\'Bootstrap\\\'s JavaScript requires jQuery version 1.9.1 or higher\')',
' }',
'}(jQuery);\n\n'
].join('\n'),
// Task configuration.
clean: {
@ -93,7 +107,7 @@ module.exports = function (grunt) {
concat: {
options: {
banner: '<%= banner %>\n<%= jqueryCheck %>',
banner: '<%= banner %>\n<%= jqueryCheck %>\n<%= jqueryVersionCheck %>',
stripBanners: false
},
bootstrap: {
@ -128,8 +142,8 @@ module.exports = function (grunt) {
'docs/assets/js/vendor/less.min.js',
'docs/assets/js/vendor/jszip.min.js',
'docs/assets/js/vendor/uglify.min.js',
'docs/assets/js/vendor/blob.js',
'docs/assets/js/vendor/filesaver.js',
'docs/assets/js/vendor/Blob.js',
'docs/assets/js/vendor/FileSaver.js',
'docs/assets/js/raw-files.min.js',
'docs/assets/js/src/customizer.js'
],
@ -378,7 +392,7 @@ module.exports = function (grunt) {
var testSubtasks = [];
// Skip core tests if running a different subset of the test suite
if (runSubset('core')) {
testSubtasks = testSubtasks.concat(['dist-css', 'dist-js', 'jshint:core', 'jshint:test', 'jshint:grunt', 'jscs:core', 'jscs:test', 'jscs:grunt', 'qunit', 'docs']);
testSubtasks = testSubtasks.concat(['dist-css', 'dist-js', 'test-js', 'docs']);
}
// Skip HTML validation if running a different subset of the test suite
if (runSubset('validate-html') &&
@ -396,9 +410,10 @@ module.exports = function (grunt) {
testSubtasks.push('saucelabs-qunit');
}
grunt.registerTask('test', testSubtasks);
grunt.registerTask('test-js', ['jshint:core', 'jshint:test', 'jshint:grunt', 'jscs:core', 'jscs:test', 'jscs:grunt', 'qunit']);
// JS distribution task.
grunt.registerTask('dist-js', ['concat', 'uglify:core']);
grunt.registerTask('dist-js', ['concat', 'uglify:core', 'commonjs']);
// CSS distribution task.
grunt.registerTask('less-compile', ['less:compileCore']);
@ -423,6 +438,12 @@ module.exports = function (grunt) {
generateRawFiles(grunt, banner);
});
grunt.registerTask('commonjs', 'Generate CommonJS entrypoint module in dist dir.', function () {
var srcFiles = grunt.config.get('concat.bootstrap.src');
var destFilepath = 'dist/js/npm.js';
generateCommonJSModule(grunt, srcFiles, destFilepath);
});
// Docs task.
grunt.registerTask('docs-css', ['autoprefixer:docs', 'autoprefixer:examples', 'csscomb:docs', 'csscomb:examples', 'cssmin:docs']);
grunt.registerTask('docs-js', ['uglify:docsJs', 'uglify:customize']);

View File

@ -29,6 +29,6 @@
"test-infra"
],
"dependencies": {
"jquery": ">= 1.9.0"
"jquery": ">= 1.9.1"
}
}

168
dist/js/bootstrap.js vendored
View File

@ -4,7 +4,16 @@
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/
if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript requires jQuery') }
if (typeof jQuery === 'undefined') {
throw new Error('Bootstrap\'s JavaScript requires jQuery')
}
+function ($) {
var version = $.fn.jquery.split(' ')[0].split('.')
if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1)) {
throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher')
}
}(jQuery);
/* ========================================================================
* Bootstrap: transition.js v3.2.0
@ -223,6 +232,8 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
else $parent.find('.active').removeClass('active')
}
if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change')
} else {
this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
}
if (changed) this.$element.toggleClass('active')
@ -292,7 +303,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
// =========================
var Carousel = function (element, options) {
this.$element = $(element).on('keydown.bs.carousel', $.proxy(this.keydown, this))
this.$element = $(element)
this.$indicators = this.$element.find('.carousel-indicators')
this.options = options
this.paused =
@ -301,7 +312,9 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
this.$active =
this.$items = null
this.options.pause == 'hover' && this.$element
this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))
this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
.on('mouseenter.bs.carousel', $.proxy(this.pause, this))
.on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
}
@ -313,7 +326,8 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
Carousel.DEFAULTS = {
interval: 5000,
pause: 'hover',
wrap: true
wrap: true,
keyboard: true
}
Carousel.prototype.keydown = function (e) {
@ -549,17 +563,21 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
Collapse.prototype.show = function () {
if (this.transitioning || this.$element.hasClass('in')) return
var activesData
var actives = this.$parent && this.$parent.find('> .panel').children('.in, .collapsing')
if (actives && actives.length) {
activesData = actives.data('bs.collapse')
if (activesData && activesData.transitioning) return
}
var startEvent = $.Event('show.bs.collapse')
this.$element.trigger(startEvent)
if (startEvent.isDefaultPrevented()) return
var actives = this.$parent && this.$parent.find('> .panel').children('.in, .collapsing')
if (actives && actives.length) {
var hasData = actives.data('bs.collapse')
if (hasData && hasData.transitioning) return
Plugin.call(actives, 'hide')
hasData || actives.data('bs.collapse', null)
activesData || actives.data('bs.collapse', null)
}
var dimension = this.dimension()
@ -741,7 +759,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
}
Dropdown.prototype.keydown = function (e) {
if (!/(38|40|27)/.test(e.keyCode)) return
if (!/(38|40|27|32)/.test(e.which)) return
var $this = $(this)
@ -753,7 +771,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
var $parent = getParent($this)
var isActive = $parent.hasClass('open')
if (!isActive || (isActive && e.keyCode == 27)) {
if ((!isActive && e.which != 27) || (isActive && e.which == 27)) {
if (e.which == 27) $parent.find(toggle).trigger('focus')
return $this.trigger('click')
}
@ -763,10 +781,10 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
if (!$items.length) return
var index = $items.index($items.filter(':focus'))
var index = $items.index(e.target)
if (e.keyCode == 38 && index > 0) index-- // up
if (e.keyCode == 40 && index < $items.length - 1) index++ // down
if (e.which == 38 && index > 0) index-- // up
if (e.which == 40 && index < $items.length - 1) index++ // down
if (!~index) index = 0
$items.eq(index).trigger('focus')
@ -953,9 +971,6 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
this.isShown = false
this.$body.removeClass('modal-open')
this.resetScrollbar()
this.escape()
$(document).off('focusin.bs.modal')
@ -996,6 +1011,8 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
var that = this
this.$element.hide()
this.backdrop(function () {
that.$body.removeClass('modal-open')
that.resetScrollbar()
that.$element.trigger('hidden.bs.modal')
})
}
@ -1013,14 +1030,13 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
var doAnimate = $.support.transition && animate
this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
.appendTo(this.$body)
this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
if (e.target !== e.currentTarget) return
this.options.backdrop == 'static'
? this.$element[0].focus.call(this.$element[0])
: this.hide.call(this)
}, this))
.prependTo(this.$element)
.on('click.dismiss.bs.modal', $.proxy(function (e) {
if (e.target !== e.currentTarget) return
this.options.backdrop == 'static'
? this.$element[0].focus.call(this.$element[0])
: this.hide.call(this)
}, this))
if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
@ -1318,13 +1334,13 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
if (autoPlace) {
var orgPlacement = placement
var $parent = this.$element.parent()
var parentDim = this.getPosition($parent)
var $container = this.options.container ? $(this.options.container) : this.$element.parent()
var containerDim = this.getPosition($container)
placement = placement == 'bottom' && pos.top + pos.height + actualHeight - parentDim.scroll > parentDim.height ? 'top' :
placement == 'top' && pos.top - parentDim.scroll - actualHeight < 0 ? 'bottom' :
placement == 'right' && pos.right + actualWidth > parentDim.width ? 'left' :
placement == 'left' && pos.left - actualWidth < parentDim.left ? 'right' :
placement = placement == 'bottom' && pos.bottom + actualHeight > containerDim.bottom ? 'top' :
placement == 'top' && pos.top - actualHeight < containerDim.top ? 'bottom' :
placement == 'right' && pos.right + actualWidth > containerDim.width ? 'left' :
placement == 'left' && pos.left - actualWidth < containerDim.left ? 'right' :
placement
$tip
@ -1337,8 +1353,11 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
this.applyPlacement(calculatedOffset, placement)
var complete = function () {
var prevHoverState = that.hoverState
that.$element.trigger('shown.bs.' + that.type)
that.hoverState = null
if (prevHoverState == 'out') that.leave(that)
}
$.support.transition && this.$tip.hasClass('fade') ?
@ -1459,7 +1478,6 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
var el = $element[0]
var isBody = el.tagName == 'BODY'
var isSvg = window.SVGElement && el instanceof window.SVGElement
var elRect = el.getBoundingClientRect()
if (elRect.width == null) {
@ -1468,10 +1486,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
}
var elOffset = isBody ? { top: 0, left: 0 } : $element.offset()
var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
var outerDims = isSvg ? {} : {
width: isBody ? $(window).width() : $element.outerWidth(),
height: isBody ? $(window).height() : $element.outerHeight()
}
var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
return $.extend({}, elRect, scroll, outerDims, elOffset)
}
@ -1576,12 +1591,18 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.tooltip')
var options = typeof option == 'object' && option
var $this = $(this)
var data = $this.data('bs.tooltip')
var options = typeof option == 'object' && option
var selector = options && options.selector
if (!data && option == 'destroy') return
if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
if (selector) {
if (!data) $this.data('bs.tooltip', (data = {}))
if (!data[selector]) data[selector] = new Tooltip(this, options)
} else {
if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
}
if (typeof option == 'string') data[option]()
})
}
@ -1690,12 +1711,18 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.popover')
var options = typeof option == 'object' && option
var $this = $(this)
var data = $this.data('bs.popover')
var options = typeof option == 'object' && option
var selector = options && options.selector
if (!data && option == 'destroy') return
if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
if (selector) {
if (!data) $this.data('bs.popover', (data = {}))
if (!data[selector]) data[selector] = new Popover(this, options)
} else {
if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
}
if (typeof option == 'string') data[option]()
})
}
@ -1783,7 +1810,6 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
return ($href
&& $href.length
&& $href.is(':visible')
&& $el.is(':visible')
&& [[$href[offsetMethod]().top + offsetBase, href]]) || null
})
.sort(function (a, b) { return a[0] - b[0] })
@ -1810,8 +1836,9 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
}
if (activeTarget && scrollTop <= offsets[0]) {
return activeTarget != (i = targets[0]) && this.activate(i)
if (activeTarget && scrollTop < offsets[0]) {
this.activeTarget = null
return this.clear()
}
for (i = offsets.length; i--;) {
@ -1825,9 +1852,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
ScrollSpy.prototype.activate = function (target) {
this.activeTarget = target
$(this.selector)
.parentsUntil(this.options.target, '.active')
.removeClass('active')
this.clear()
var selector = this.selector +
'[data-target="' + target + '"],' +
@ -1846,6 +1871,12 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
active.trigger('activate.bs.scrollspy')
}
ScrollSpy.prototype.clear = function () {
$(this.selector)
.parentsUntil(this.options.target, '.active')
.removeClass('active')
}
// SCROLLSPY PLUGIN DEFINITION
// ===========================
@ -1923,22 +1954,30 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
if ($this.parent('li').hasClass('active')) return
var previous = $ul.find('.active:last a')[0]
var e = $.Event('show.bs.tab', {
relatedTarget: previous
var $previous = $ul.find('.active:last a')
var hideEvent = $.Event('hide.bs.tab', {
relatedTarget: $this[0]
})
var showEvent = $.Event('show.bs.tab', {
relatedTarget: $previous[0]
})
$this.trigger(e)
$previous.trigger(hideEvent)
$this.trigger(showEvent)
if (e.isDefaultPrevented()) return
if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
var $target = $(selector)
this.activate($this.closest('li'), $ul)
this.activate($target, $target.parent(), function () {
$previous.trigger({
type: 'hidden.bs.tab',
relatedTarget: $this[0]
})
$this.trigger({
type: 'shown.bs.tab',
relatedTarget: previous
relatedTarget: $previous[0]
})
})
}
@ -1953,9 +1992,15 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
$active
.removeClass('active')
.find('> .dropdown-menu > .active')
.removeClass('active')
.removeClass('active')
.end()
.find('[data-toggle="tab"]')
.attr('aria-expanded', false)
element.addClass('active')
element
.addClass('active')
.find('[data-toggle="tab"]')
.attr('aria-expanded', true)
if (transition) {
element[0].offsetWidth // reflow for transition
@ -1965,7 +2010,12 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
}
if (element.parent('.dropdown-menu')) {
element.closest('li.dropdown').addClass('active')
element
.closest('li.dropdown')
.addClass('active')
.end()
.find('[data-toggle="tab"]')
.attr('aria-expanded', true)
}
callback && callback()

File diff suppressed because one or more lines are too long

13
dist/js/npm.js vendored Normal file
View File

@ -0,0 +1,13 @@
// This file is generated. You can require() it in a CommonJS environment.
require('../../js/transition.js')
require('../../js/alert.js')
require('../../js/button.js')
require('../../js/carousel.js')
require('../../js/collapse.js')
require('../../js/dropdown.js')
require('../../js/modal.js')
require('../../js/tooltip.js')
require('../../js/popover.js')
require('../../js/scrollspy.js')
require('../../js/tab.js')
require('../../js/affix.js')

View File

@ -3,6 +3,11 @@
description: Bootstrap 中文文档
url: http://v3.bootcss.com/
- name: Danish
code: da
description: Bootstrap på Dansk
url: http://getbootstrap.dk/
- name: French
code: fr
description: Bootstrap en Français

View File

@ -0,0 +1,6 @@
<div class="bs-docs-section">
<h1 id="tools" class="page-header">Tools</h1>
<h2 id="tools-bootlint">Bootlint</h2>
<p><strong><a href="https://github.com/twbs/bootlint">Bootlint</a></strong> is an official Bootstrap HTML <a href="http://en.wikipedia.org/wiki/Lint_(software)">linter</a> tool. It automatically checks for several common HTML mistakes in webpages that are using Bootstrap in a fairly "vanilla" way. Vanilla Bootstrap's components/widgets require their parts of the DOM to conform to certain structures. Bootlint checks that instances of Bootstrap components have correctly-structured HTML. Consider adding Bootlint to your Bootstrap web development toolchain so that none of the common mistakes slow down your project's development.</p>
</div>

View File

@ -0,0 +1,151 @@
<div class="bs-docs-section">
<h1 id="scrollspy" class="page-header">ScrollSpy <small>scrollspy.js</small></h1>
<h2 id="scrollspy-examples">Example in navbar</h2>
<p>The ScrollSpy plugin is for automatically updating nav targets based on scroll position. Scroll the area below the navbar and watch the active class change. The dropdown sub items will be highlighted as well.</p>
<div class="bs-example">
<nav id="navbar-example2" class="navbar navbar-default navbar-static" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<button class="navbar-toggle collapsed" type="button" data-toggle="collapse" data-target=".bs-example-js-navbar-scrollspy">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Project Name</a>
</div>
<div class="collapse navbar-collapse bs-example-js-navbar-scrollspy">
<ul class="nav navbar-nav">
<li><a href="#fat">@fat</a></li>
<li><a href="#mdo">@mdo</a></li>
<li class="dropdown">
<a href="#" id="navbarDrop1" class="dropdown-toggle" data-toggle="dropdown">Dropdown <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu" aria-labelledby="navbarDrop1">
<li><a href="#one" tabindex="-1">one</a></li>
<li><a href="#two" tabindex="-1">two</a></li>
<li class="divider"></li>
<li><a href="#three" tabindex="-1">three</a></li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
<div data-spy="scroll" data-target="#navbar-example2" data-offset="0" class="scrollspy-example">
<h4 id="fat">@fat</h4>
<p>Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.</p>
<h4 id="mdo">@mdo</h4>
<p>Veniam marfa mustache skateboard, adipisicing fugiat velit pitchfork beard. Freegan beard aliqua cupidatat mcsweeney's vero. Cupidatat four loko nisi, ea helvetica nulla carles. Tattooed cosby sweater food truck, mcsweeney's quis non freegan vinyl. Lo-fi wes anderson +1 sartorial. Carles non aesthetic exercitation quis gentrify. Brooklyn adipisicing craft beer vice keytar deserunt.</p>
<h4 id="one">one</h4>
<p>Occaecat commodo aliqua delectus. Fap craft beer deserunt skateboard ea. Lomo bicycle rights adipisicing banh mi, velit ea sunt next level locavore single-origin coffee in magna veniam. High life id vinyl, echo park consequat quis aliquip banh mi pitchfork. Vero VHS est adipisicing. Consectetur nisi DIY minim messenger bag. Cred ex in, sustainable delectus consectetur fanny pack iphone.</p>
<h4 id="two">two</h4>
<p>In incididunt echo park, officia deserunt mcsweeney's proident master cleanse thundercats sapiente veniam. Excepteur VHS elit, proident shoreditch +1 biodiesel laborum craft beer. Single-origin coffee wayfarers irure four loko, cupidatat terry richardson master cleanse. Assumenda you probably haven't heard of them art party fanny pack, tattooed nulla cardigan tempor ad. Proident wolf nesciunt sartorial keffiyeh eu banh mi sustainable. Elit wolf voluptate, lo-fi ea portland before they sold out four loko. Locavore enim nostrud mlkshk brooklyn nesciunt.</p>
<h4 id="three">three</h4>
<p>Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.</p>
<p>Keytar twee blog, culpa messenger bag marfa whatever delectus food truck. Sapiente synth id assumenda. Locavore sed helvetica cliche irony, thundercats you probably haven't heard of them consequat hoodie gluten-free lo-fi fap aliquip. Labore elit placeat before they sold out, terry richardson proident brunch nesciunt quis cosby sweater pariatur keffiyeh ut helvetica artisan. Cardigan craft beer seitan readymade velit. VHS chambray laboris tempor veniam. Anim mollit minim commodo ullamco thundercats.
</p>
</div>
</div><!-- /example -->
<h2 id="scrollspy-usage">Usage</h2>
<div class="bs-callout bs-callout-warning">
<h4>Requires Bootstrap nav</h4>
<p>Scrollspy currently requires the use of a <a href="../components/#nav">Bootstrap nav component</a> for proper highlighting of active links.</p>
</div>
<h3>Requires relative positioning</h3>
<p>No matter the implementation method, scrollspy requires the use of <code>position: relative;</code> on the element you're spying on. In most cases this is the <code>&lt;body&gt;</code>.</p>
<h3>Via data attributes</h3>
<p>To easily add scrollspy behavior to your topbar navigation, add <code>data-spy="scroll"</code> to the element you want to spy on (most typically this would be the <code>&lt;body&gt;</code>). Then add the <code>data-target</code> attribute with the ID or class of the parent element of any Bootstrap <code>.nav</code> component.</p>
{% highlight css %}
body {
position: relative;
}
{% endhighlight %}
{% highlight html %}
<body data-spy="scroll" data-target=".navbar-example">
...
<div class="navbar-example">
<ul class="nav nav-tabs" role="tablist">
...
</ul>
</div>
...
</body>
{% endhighlight %}
<h3>Via JavaScript</h3>
<p>After adding <code>position: relative;</code> in your CSS, call the scrollspy via JavaScript:</p>
{% highlight js %}
$('body').scrollspy({ target: '.navbar-example' })
{% endhighlight %}
<div class="bs-callout bs-callout-danger">
<h4>Resolvable ID targets required</h4>
<p>Navbar links must have resolvable id targets. For example, a <code>&lt;a href="#home"&gt;home&lt;/a&gt;</code> must correspond to something in the DOM like <code>&lt;div id="home"&gt;&lt;/div&gt;</code>.</p>
</div>
<div class="bs-callout bs-callout-info">
<h4>Non-<code>:visible</code> target elements ignored</h4>
<p>Target elements that are not <a href="http://api.jquery.com/visible-selector/"><code>:visible</code> according to jQuery</a> will be ignored and their corresponding nav items will never be highlighted.</p>
</div>
<h3>Methods</h3>
<h4>.scrollspy('refresh')</h4>
<p>When using scrollspy in conjunction with adding or removing of elements from the DOM, you'll need to call the refresh method like so:</p>
{% highlight js %}
$('[data-spy="scroll"]').each(function () {
var $spy = $(this).scrollspy('refresh')
})
{% endhighlight %}
<h3>Options</h3>
<p>Options can be passed via data attributes or JavaScript. For data attributes, append the option name to <code>data-</code>, as in <code>data-offset=""</code>.</p>
<div class="table-responsive">
<table class="table table-bordered table-striped">
<thead>
<tr>
<th style="width: 100px;">Name</th>
<th style="width: 100px;">type</th>
<th style="width: 50px;">default</th>
<th>description</th>
</tr>
</thead>
<tbody>
<tr>
<td>offset</td>
<td>number</td>
<td>10</td>
<td>Pixels to offset from top when calculating position of scroll.</td>
</tr>
</tbody>
</table>
</div><!-- ./bs-table-responsive -->
<h3>Events</h3>
<div class="table-responsive">
<table class="table table-bordered table-striped">
<thead>
<tr>
<th style="width: 150px;">Event Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>activate.bs.scrollspy</td>
<td>This event fires whenever a new item becomes activated by the scrollspy.</td>
</tr>
</tbody>
</table>
</div><!-- ./bs-table-responsive -->
{% highlight js %}
$('#myScrollspy').on('activate.bs.scrollspy', function () {
// do something…
})
{% endhighlight %}
</div>

View File

@ -1,6 +1,6 @@
<!-- 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</a></li>
<li><a href="#import-drop-target">Import</a></li>
<li><a href="#less">Less components</a></li>
<li><a href="#plugins">jQuery plugins</a></li>
<li><a href="#less-variables">Less variables</a>

View File

@ -1,6 +1,6 @@
// 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
a(href='#import-drop-target') Import
li
a(href='#less') Less components
li

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

BIN
docs/apple-touch-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@ -77,7 +77,7 @@
$('.bs-docs-popover').popover()
// Button state demo
$('#loading-example-btn').click(function () {
$('#loading-example-btn').on('click', function () {
var btn = $(this)
btn.button('loading')
setTimeout(function () {
@ -85,6 +85,10 @@
}, 3000)
})
// Activate animated progress bar
$('.bs-docs-activate-animated-progressbar').on('click', function () {
$(this).siblings('.progress').find('.progress-bar-striped').toggleClass('active')
})
// Config ZeroClipboard
ZeroClipboard.config({
@ -92,17 +96,10 @@
hoverClass: 'btn-clipboard-hover'
})
// Insert copy to clipboard button before .highlight or .bs-example
// Insert copy to clipboard button before .highlight
$('.highlight').each(function () {
var highlight = $(this)
var previous = highlight.prev()
var btnHtml = '<div class="zero-clipboard"><span class="btn-clipboard">Copy</span></div>'
if (previous.hasClass('bs-example')) {
previous.before(btnHtml.replace(/btn-clipboard/, 'btn-clipboard with-example'))
} else {
highlight.before(btnHtml)
}
$(this).before(btnHtml)
})
var zeroClipboard = new ZeroClipboard($('.btn-clipboard'))
var htmlBridge = $('#global-zeroclipboard-html-bridge')

View File

@ -319,7 +319,19 @@ window.onload = function () { // wait for load in a dumb way because B-0
function generateJS(preamble) {
var $checked = $('#plugin-section input:checked')
var jqueryCheck = 'if (typeof jQuery === "undefined") { throw new Error("Bootstrap\'s JavaScript requires jQuery") }\n\n'
var jqueryCheck = [
'if (typeof jQuery === \'undefined\') {',
' throw new Error(\'Bootstrap\\\'s JavaScript requires jQuery\')',
'}\n'
].join('\n')
var jqueryVersionCheck = [
'+function ($) {',
' var version = $.fn.jquery.split(\' \')[0].split(\'.\')',
' if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1)) {',
' throw new Error(\'Bootstrap\\\'s JavaScript requires jQuery version 1.9.1 or higher\')',
' }',
'}(jQuery);\n\n'
].join('\n')
if (!$checked.length) return false
@ -329,7 +341,7 @@ window.onload = function () { // wait for load in a dumb way because B-0
.join('\n')
preamble = cw + preamble
js = jqueryCheck + js
js = jqueryCheck + jqueryVersionCheck + js
return {
'bootstrap.js': preamble + js,

View File

@ -1,9 +1,9 @@
/* Blob.js
* A Blob implementation.
* 2014-07-01
*
* 2014-07-24
*
* By Eli Grey, http://eligrey.com
* By Devin Samarin, https://github.com/eboyjr
* By Devin Samarin, https://github.com/dsamarin
* License: X11/MIT
* See https://github.com/eligrey/Blob.js/blob/master/LICENSE.md
*/
@ -59,16 +59,34 @@
, URL = real_URL
, btoa = view.btoa
, atob = view.atob
, ArrayBuffer = view.ArrayBuffer
, Uint8Array = view.Uint8Array
, origin = /^[\w-]+:\/*\[?[\w\.:-]+\]?(?::[0-9]+)?/
;
FakeBlob.fake = FB_proto.fake = true;
while (file_ex_code--) {
FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1;
}
// Polyfill URL
if (!real_URL.createObjectURL) {
URL = view.URL = {};
URL = view.URL = function(uri) {
var
uri_info = document.createElementNS("http://www.w3.org/1999/xhtml", "a")
, uri_origin
;
uri_info.href = uri;
if (!("origin" in uri_info)) {
if (uri_info.protocol.toLowerCase() === "data:") {
uri_info.origin = null;
} else {
uri_origin = uri.match(origin);
uri_info.origin = uri_origin && uri_origin[1];
}
}
return uri_info;
};
}
URL.createObjectURL = function(blob) {
var

View File

@ -1,6 +1,6 @@
/* FileSaver.js
* A saveAs() FileSaver implementation.
* 2014-07-21
* 2014-08-29
*
* By Eli Grey, http://eligrey.com
* License: X11/MIT
@ -31,7 +31,7 @@ var saveAs = saveAs
return view.URL || view.webkitURL || view;
}
, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
, can_use_save_link = !view.externalHost && "download" in save_link
, can_use_save_link = "download" in save_link
, click = function(node) {
var event = doc.createEvent("MouseEvents");
event.initMouseEvent(
@ -53,13 +53,18 @@ var saveAs = saveAs
// the reasoning behind the timeout and revocation flow
, arbitrary_revoke_timeout = 10
, revoke = function(file) {
setTimeout(function() {
var revoker = function() {
if (typeof file === "string") { // file is an object URL
get_URL().revokeObjectURL(file);
} else { // file is a File
file.remove();
}
}, arbitrary_revoke_timeout);
};
if (view.chrome) {
revoker();
} else {
setTimeout(revoker, arbitrary_revoke_timeout);
}
}
, dispatch = function(filesaver, event_types, event) {
event_types = [].concat(event_types);
@ -95,7 +100,11 @@ var saveAs = saveAs
if (target_view) {
target_view.location.href = object_url;
} else {
view.open(object_url, "_blank");
var new_tab = view.open(object_url, "_blank");
if (new_tab == undefined && typeof safari !== "undefined") {
//Apple do not allow window.open, see http://bit.ly/1kZffRI
view.location.href = object_url
}
}
filesaver.readyState = filesaver.DONE;
dispatch_all();

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -18,6 +18,12 @@ We publicly list browser bugs that are impacting us here, in the hopes of expedi
</tr>
</thead>
<tbody>
<tr>
<td>Internet Explorer 11</td>
<td>Hovered element still remains in <code>:hover</code> state after scrolling away</td>
<td><a href="https://connect.microsoft.com/IE/feedback/details/926665/ie-11-hovering-over-an-element-and-then-scrolling-without-moving-the-mouse-pointer-leaves-the-element-in-hover-state">IE bug #926665</a></td>
<td><a href="https://github.com/twbs/bootstrap/issues/14211">#14211</a></td>
</tr>
<tr>
<td>Internet Explorer 11</td>
<td>When hovering over a <code>&lt;select&gt;</code> menu item, the cursor for the element underneath the menu is displayed</td>
@ -27,20 +33,14 @@ We publicly list browser bugs that are impacting us here, in the hopes of expedi
<tr>
<td>Firefox</td>
<td><code>.table-bordered</code> with an empty <code>&lt;tbody&gt;</code> is missing borders</td>
<td><a href="{{ site.bug.firefox }}1023761">Mozilla bug #1023761</a></td>
<td><a href="{{ site.bug.github }}13453">#13453</a></td>
</tr>
<tr>
<td>Firefox</td>
<td>Unusual default form control styles on Android</td>
<td><a href="{{ site.bug.firefox }}900871">Closed Mozilla bug #900871</a>, <a href="{{ site.bug.firefox }}763671">Open Mozilla bug #763671</a></td>
<td><a href="{{ site.bug.github }}8702">#8702</a></td>
<td><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1023761">Mozilla bug #1023761</a></td>
<td><a href="https://github.com/twbs/bootstrap/issues/13453">#13453</a></td>
</tr>
<tr>
<td>Firefox</td>
<td><code>max-width: 100%;</code> doesn't work inside tables</td>
<td><a href="{{ site.bug.firefox }}975632">Mozilla bug #975632</a></td>
<td><a href="{{ site.bug.github }}10690">#10690</a></td>
<td><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=975632">Mozilla bug #975632</a></td>
<td><a href="https://github.com/twbs/bootstrap/issues/10690">#10690</a></td>
</tr>
<tr>
<td>Firefox</td>
@ -48,77 +48,65 @@ We publicly list browser bugs that are impacting us here, in the hopes of expedi
<td><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1048279">Mozilla bug #1048279</a></td>
<td><a href="https://github.com/twbs/bootstrap/issues/14124">#14124</a></td>
</tr>
<tr>
<td>Firefox</td>
<td>If the disabled state of a form control is changed via JavaScript, the normal state doesn't return after refreshing the page.</td>
<td><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=654072">Mozilla bug #654072</a></td>
<td><a href="https://github.com/twbs/bootstrap/issues/793">#793</a></td>
</tr>
<tr>
<td>Firefox</td>
<td>Button elements with <code>width: 100%</code> become cropped in long tables.</td>
<td><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1060131">Mozilla bug #1060131</a></td>
<td><a href="https://github.com/twbs/bootstrap/issues/14320">#14320</a></td>
</tr>
<tr>
<td>Firefox</td>
<td>If the disabled state of a form control is changed via JavaScript, the normal state doesn't return after refreshing the page.</td>
<td><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=654072">Mozilla bug #654072</a></td>
<td><a href="https://github.com/twbs/bootstrap/issues/793">#793</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>
<td>Clicking above <code>&lt;input type="number"&gt;</code> increment button flashes the decrement button</td>
<td><a href="https://code.google.com/p/chromium/issues/detail?id=419108"></a></td>
<td>Offshoot of <a href="https://github.com/twbs/bootstrap/issues/8350">#8350</a> &amp; <a href="https://code.google.com/p/chromium/issues/detail?id=337668">Chromium issue #337668</a></td>
</tr>
<tr>
<td>Chrome</td>
<td><code>display: table;</code> within <code>display: block;</code> forces sibling content to new line</td>
<td><a href="{{ site.bug.chrome }}309483">Chromium issue #309483</a></td>
<td><a href="{{ site.bug.github }}9950">#9950</a></td>
</tr>
<tr>
<td>Chrome</td>
<td>Unwanted vertical lines when printing styled <code>&lt;select&gt;</code> on OS X</td>
<td><a href="{{ site.bug.chrome }}282918">Chromium issue #282918</a></td>
<td><a href="{{ site.bug.github }}11245">#11245</a></td>
</tr>
<tr>
<td>Chrome</td>
<td>inline-block element collapses white-space on Windows</td>
<td><a href="{{ site.bug.chrome }}329574">Chromium issue #329574</a></td>
<td><a href="{{ site.bug.github }}11885">#11885</a></td>
<td><a href="https://code.google.com/p/chromium/issues/detail?id=309483">Chromium issue #309483</a></td>
<td><a href="https://github.com/twbs/bootstrap/issues/9950">#9950</a></td>
</tr>
<tr>
<td>Chrome</td>
<td>Incorrect viewport size used for media queries when printing</td>
<td><a href="{{ site.bug.chrome }}273306">Chromium issue #273306</a></td>
<td><a href="{{ site.bug.github }}12078">#12078</a></td>
<td><a href="https://code.google.com/p/chromium/issues/detail?id=273306">Chromium issue #273306</a></td>
<td><a href="https://github.com/twbs/bootstrap/issues/12078">#12078</a></td>
</tr>
<tr>
<td>Chrome &amp; Safari</td>
<td>OS X scrollbar clipped in <code>select[multiple]</code> with padding</td>
<td><a href="{{ site.bug.chrome }}342208">Chromium issue #342208</a>, <a href="{{ site.bug.webkit }}128489">WebKit bug #128489</a></td>
<td><a href="{{ site.bug.github }}12536">#12536</a></td>
<td><a href="https://code.google.com/p/chromium/issues/detail?id=342208">Chromium issue #342208</a>, <a href="https://bugs.webkit.org/show_bug.cgi?id=128489">WebKit bug #128489</a></td>
<td><a href="https://github.com/twbs/bootstrap/issues/12536">#12536</a></td>
</tr>
<tr>
<td>Chrome</td>
<td><code>display: table-cell; width: 100%;</code> doesn't work correctly on date <code>&lt;input&gt;</code></td>
<td><a href="{{ site.bug.chrome }}346051">Chromium issue #346051</a></td>
<td><a href="{{ site.bug.github }}12548">#12548</a></td>
<td><a href="https://code.google.com/p/chromium/issues/detail?id=346051">Chromium issue #346051</a></td>
<td><a href="https://github.com/twbs/bootstrap/issues/12548">#12548</a></td>
</tr>
<tr>
<td>Chrome</td>
<td><code>&lt;input type="password"&gt;</code> sporadically causes bad widths on floated elements</td>
<td><a href="{{ site.bug.chrome }}377346">Chrome issue #377346</a></td>
<td><a href="{{ site.bug.github }}13892">#13892</a></td>
<td><a href="https://code.google.com/p/chromium/issues/detail?id=377346">Chrome issue #377346</a></td>
<td><a href="https://github.com/twbs/bootstrap/issues/13892">#13892</a></td>
</tr>
<tr>
<td>Safari</td>
<td>Insufficient CSS percentage precision</td>
<td>(No public bug tracker)</td>
<td><a href="{{ site.bug.github }}9282">#9282</a></td>
<td>Weird button behavior with some number <code>&lt;input&gt;</code>s</td>
<td><a href="https://bugs.webkit.org/show_bug.cgi?id=137269">WebKit bug #137269</a></td>
<td><a href="https://github.com/twbs/bootstrap/issues/8350">#8350</a>, <a href="https://github.com/necolas/normalize.css/issues/283">Normalize #283</a>, <a href="https://code.google.com/p/chromium/issues/detail?id=337668">Chromium issue #337668</a></td>
</tr>
<tr>
<td>Safari</td>
<td>Justified nav rendering bug</td>
<td>(No public bug tracker)</td>
<td><a href="{{ site.bug.github }}9774">#9774</a></td>
<td><a href="https://github.com/twbs/bootstrap/issues/9774">#9774</a></td>
</tr>
</tbody>
</table>

View File

@ -183,7 +183,7 @@ A checkbox or radio with the `disabled` attribute will be styled appropriately.
</div>
{% endexample %}
#### Inline checkboxes and radios
#### Inline
Use the `.checkbox-inline` or `.radio-inline` classes on a series of checkboxes or radios for controls that appear on the same line.
@ -209,7 +209,24 @@ Use the `.checkbox-inline` or `.radio-inline` classes on a series of checkboxes
</label>
{% endexample %}
#### Selects
#### Without labels
Should you have no text within the `<label>`, the input is positioned as you'd expect. **Currently only works on non-inline checkboxes and radios.**
{% example html %}
<div class="checkbox">
<label>
<input type="checkbox" id="blankCheckbox" value="option1">
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="blankRadio" id="blankRadio1" value="option1">
</label>
</div>
{% endexample %}
### Selects
Use the default option, or add `multiple` to show multiple options at once.

View File

@ -7,6 +7,8 @@ title: Navbar
Navbars are responsive meta components that serve as navigation headers for your application or site. They begin collapsed (and are toggleable) in mobile views and become horizontal as the available viewport width increases.
**Justified navbar nav links are currently not supported.**
<div class="bs-callout bs-callout-warning" id="callout-navbar-overflow">
<h4>Overflowing content</h4>
<p>Since Bootstrap doesn't know how much space the content in your navbar needs, you might run into issues with content wrapping into a second row. To resolve this, you can:</p>

View File

@ -5,7 +5,7 @@ title: Responsive embed
Allow browsers to determine video or slideshow dimensions based on the width of their containing block by creating an intrinsic ratio that will properly scale on any device.
Rules are directly applied to `<iframe>`, `<embed>`, and `<object>` elements; optionally use an explicit descendant class `.embed-responsive-item` when you want to match the styling for other attributes.
Rules are directly applied to `<iframe>`, `<embed>`, `<video>`, and `<object>` elements; optionally use an explicit descendant class `.embed-responsive-item` when you want to match the styling for other attributes.
**Pro-Tip!** You don't need to include `frameborder="0"` in your `<iframe>`s as we override that for you.
@ -20,11 +20,11 @@ Aspect ratios can be customized. There are two available in Bootstrap, 16x9 and
{% highlight html %}
<!-- 16:9 aspect ratio -->
<div class="embed-responsive embed-responsive-16by9">
<iframe class="embed-responsive-item" src=""></iframe>
<iframe class="embed-responsive-item" src="..."></iframe>
</div>
<!-- 4:3 aspect ratio -->
<div class="embed-responsive embed-responsive-4by3">
<iframe class="embed-responsive-item" src=""></iframe>
<iframe class="embed-responsive-item" src="..."></iframe>
</div>
{% endhighlight %}

View File

@ -5,6 +5,7 @@ slug: customize
lead: Customize Bootstrap's components, Less variables, and jQuery plugins to get your very own version.
---
<!-- less.js isn't IE8-compatible and throws an exception during initialization, so our Blob compatibility check and error messaging code never get called in that case.
So we use a conditional comment instead to inform folks about the lack of IE8 support.
-->
@ -260,8 +261,6 @@ lead: Customize Bootstrap's components, Less variables, and jQuery plugins to ge
</div><!-- /.row -->
</div>
<div class="bs-docs-section" id="plugin-section">
<button class="btn btn-secondary toggle" type="button">Toggle all</button>
<h1 id="plugins" class="page-header">jQuery plugins</h1>
@ -359,8 +358,6 @@ lead: Customize Bootstrap's components, Less variables, and jQuery plugins to ge
</div>
</div>
<div class="bs-docs-section" id="less-variables-section">
<button class="btn btn-secondary toggle" type="button">Reset to defaults</button>
<h1 id="less-variables" class="page-header">Less variables</h1>

View File

@ -4,7 +4,16 @@
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/
if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript requires jQuery') }
if (typeof jQuery === 'undefined') {
throw new Error('Bootstrap\'s JavaScript requires jQuery')
}
+function ($) {
var version = $.fn.jquery.split(' ')[0].split('.')
if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1)) {
throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher')
}
}(jQuery);
/* ========================================================================
* Bootstrap: transition.js v3.2.0
@ -223,6 +232,8 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
else $parent.find('.active').removeClass('active')
}
if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change')
} else {
this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
}
if (changed) this.$element.toggleClass('active')
@ -292,7 +303,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
// =========================
var Carousel = function (element, options) {
this.$element = $(element).on('keydown.bs.carousel', $.proxy(this.keydown, this))
this.$element = $(element)
this.$indicators = this.$element.find('.carousel-indicators')
this.options = options
this.paused =
@ -301,7 +312,9 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
this.$active =
this.$items = null
this.options.pause == 'hover' && this.$element
this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))
this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
.on('mouseenter.bs.carousel', $.proxy(this.pause, this))
.on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
}
@ -313,7 +326,8 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
Carousel.DEFAULTS = {
interval: 5000,
pause: 'hover',
wrap: true
wrap: true,
keyboard: true
}
Carousel.prototype.keydown = function (e) {
@ -549,17 +563,21 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
Collapse.prototype.show = function () {
if (this.transitioning || this.$element.hasClass('in')) return
var activesData
var actives = this.$parent && this.$parent.find('> .panel').children('.in, .collapsing')
if (actives && actives.length) {
activesData = actives.data('bs.collapse')
if (activesData && activesData.transitioning) return
}
var startEvent = $.Event('show.bs.collapse')
this.$element.trigger(startEvent)
if (startEvent.isDefaultPrevented()) return
var actives = this.$parent && this.$parent.find('> .panel').children('.in, .collapsing')
if (actives && actives.length) {
var hasData = actives.data('bs.collapse')
if (hasData && hasData.transitioning) return
Plugin.call(actives, 'hide')
hasData || actives.data('bs.collapse', null)
activesData || actives.data('bs.collapse', null)
}
var dimension = this.dimension()
@ -741,7 +759,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
}
Dropdown.prototype.keydown = function (e) {
if (!/(38|40|27)/.test(e.keyCode)) return
if (!/(38|40|27|32)/.test(e.which)) return
var $this = $(this)
@ -753,7 +771,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
var $parent = getParent($this)
var isActive = $parent.hasClass('open')
if (!isActive || (isActive && e.keyCode == 27)) {
if ((!isActive && e.which != 27) || (isActive && e.which == 27)) {
if (e.which == 27) $parent.find(toggle).trigger('focus')
return $this.trigger('click')
}
@ -763,10 +781,10 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
if (!$items.length) return
var index = $items.index($items.filter(':focus'))
var index = $items.index(e.target)
if (e.keyCode == 38 && index > 0) index-- // up
if (e.keyCode == 40 && index < $items.length - 1) index++ // down
if (e.which == 38 && index > 0) index-- // up
if (e.which == 40 && index < $items.length - 1) index++ // down
if (!~index) index = 0
$items.eq(index).trigger('focus')
@ -953,9 +971,6 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
this.isShown = false
this.$body.removeClass('modal-open')
this.resetScrollbar()
this.escape()
$(document).off('focusin.bs.modal')
@ -996,6 +1011,8 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
var that = this
this.$element.hide()
this.backdrop(function () {
that.$body.removeClass('modal-open')
that.resetScrollbar()
that.$element.trigger('hidden.bs.modal')
})
}
@ -1013,14 +1030,13 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
var doAnimate = $.support.transition && animate
this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
.appendTo(this.$body)
this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
if (e.target !== e.currentTarget) return
this.options.backdrop == 'static'
? this.$element[0].focus.call(this.$element[0])
: this.hide.call(this)
}, this))
.prependTo(this.$element)
.on('click.dismiss.bs.modal', $.proxy(function (e) {
if (e.target !== e.currentTarget) return
this.options.backdrop == 'static'
? this.$element[0].focus.call(this.$element[0])
: this.hide.call(this)
}, this))
if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
@ -1318,13 +1334,13 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
if (autoPlace) {
var orgPlacement = placement
var $parent = this.$element.parent()
var parentDim = this.getPosition($parent)
var $container = this.options.container ? $(this.options.container) : this.$element.parent()
var containerDim = this.getPosition($container)
placement = placement == 'bottom' && pos.top + pos.height + actualHeight - parentDim.scroll > parentDim.height ? 'top' :
placement == 'top' && pos.top - parentDim.scroll - actualHeight < 0 ? 'bottom' :
placement == 'right' && pos.right + actualWidth > parentDim.width ? 'left' :
placement == 'left' && pos.left - actualWidth < parentDim.left ? 'right' :
placement = placement == 'bottom' && pos.bottom + actualHeight > containerDim.bottom ? 'top' :
placement == 'top' && pos.top - actualHeight < containerDim.top ? 'bottom' :
placement == 'right' && pos.right + actualWidth > containerDim.width ? 'left' :
placement == 'left' && pos.left - actualWidth < containerDim.left ? 'right' :
placement
$tip
@ -1337,8 +1353,11 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
this.applyPlacement(calculatedOffset, placement)
var complete = function () {
var prevHoverState = that.hoverState
that.$element.trigger('shown.bs.' + that.type)
that.hoverState = null
if (prevHoverState == 'out') that.leave(that)
}
$.support.transition && this.$tip.hasClass('fade') ?
@ -1459,7 +1478,6 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
var el = $element[0]
var isBody = el.tagName == 'BODY'
var isSvg = window.SVGElement && el instanceof window.SVGElement
var elRect = el.getBoundingClientRect()
if (elRect.width == null) {
@ -1468,10 +1486,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
}
var elOffset = isBody ? { top: 0, left: 0 } : $element.offset()
var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
var outerDims = isSvg ? {} : {
width: isBody ? $(window).width() : $element.outerWidth(),
height: isBody ? $(window).height() : $element.outerHeight()
}
var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
return $.extend({}, elRect, scroll, outerDims, elOffset)
}
@ -1576,12 +1591,18 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.tooltip')
var options = typeof option == 'object' && option
var $this = $(this)
var data = $this.data('bs.tooltip')
var options = typeof option == 'object' && option
var selector = options && options.selector
if (!data && option == 'destroy') return
if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
if (selector) {
if (!data) $this.data('bs.tooltip', (data = {}))
if (!data[selector]) data[selector] = new Tooltip(this, options)
} else {
if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
}
if (typeof option == 'string') data[option]()
})
}
@ -1690,12 +1711,18 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.popover')
var options = typeof option == 'object' && option
var $this = $(this)
var data = $this.data('bs.popover')
var options = typeof option == 'object' && option
var selector = options && options.selector
if (!data && option == 'destroy') return
if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
if (selector) {
if (!data) $this.data('bs.popover', (data = {}))
if (!data[selector]) data[selector] = new Popover(this, options)
} else {
if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
}
if (typeof option == 'string') data[option]()
})
}
@ -1783,7 +1810,6 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
return ($href
&& $href.length
&& $href.is(':visible')
&& $el.is(':visible')
&& [[$href[offsetMethod]().top + offsetBase, href]]) || null
})
.sort(function (a, b) { return a[0] - b[0] })
@ -1810,8 +1836,9 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
}
if (activeTarget && scrollTop <= offsets[0]) {
return activeTarget != (i = targets[0]) && this.activate(i)
if (activeTarget && scrollTop < offsets[0]) {
this.activeTarget = null
return this.clear()
}
for (i = offsets.length; i--;) {
@ -1825,9 +1852,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
ScrollSpy.prototype.activate = function (target) {
this.activeTarget = target
$(this.selector)
.parentsUntil(this.options.target, '.active')
.removeClass('active')
this.clear()
var selector = this.selector +
'[data-target="' + target + '"],' +
@ -1846,6 +1871,12 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
active.trigger('activate.bs.scrollspy')
}
ScrollSpy.prototype.clear = function () {
$(this.selector)
.parentsUntil(this.options.target, '.active')
.removeClass('active')
}
// SCROLLSPY PLUGIN DEFINITION
// ===========================
@ -1923,22 +1954,30 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
if ($this.parent('li').hasClass('active')) return
var previous = $ul.find('.active:last a')[0]
var e = $.Event('show.bs.tab', {
relatedTarget: previous
var $previous = $ul.find('.active:last a')
var hideEvent = $.Event('hide.bs.tab', {
relatedTarget: $this[0]
})
var showEvent = $.Event('show.bs.tab', {
relatedTarget: $previous[0]
})
$this.trigger(e)
$previous.trigger(hideEvent)
$this.trigger(showEvent)
if (e.isDefaultPrevented()) return
if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
var $target = $(selector)
this.activate($this.closest('li'), $ul)
this.activate($target, $target.parent(), function () {
$previous.trigger({
type: 'hidden.bs.tab',
relatedTarget: $this[0]
})
$this.trigger({
type: 'shown.bs.tab',
relatedTarget: previous
relatedTarget: $previous[0]
})
})
}
@ -1953,9 +1992,15 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
$active
.removeClass('active')
.find('> .dropdown-menu > .active')
.removeClass('active')
.removeClass('active')
.end()
.find('[data-toggle="tab"]')
.attr('aria-expanded', false)
element.addClass('active')
element
.addClass('active')
.find('[data-toggle="tab"]')
.attr('aria-expanded', true)
if (transition) {
element[0].offsetWidth // reflow for transition
@ -1965,7 +2010,12 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
}
if (element.parent('.dropdown-menu')) {
element.closest('li.dropdown').addClass('active')
element
.closest('li.dropdown')
.addClass('active')
.end()
.find('[data-toggle="tab"]')
.attr('aria-expanded', true)
}
callback && callback()

File diff suppressed because one or more lines are too long

13
docs/dist/js/npm.js vendored Normal file
View File

@ -0,0 +1,13 @@
// This file is generated. You can require() it in a CommonJS environment.
require('../../js/transition.js')
require('../../js/alert.js')
require('../../js/button.js')
require('../../js/carousel.js')
require('../../js/collapse.js')
require('../../js/dropdown.js')
require('../../js/modal.js')
require('../../js/tooltip.js')
require('../../js/popover.js')
require('../../js/scrollspy.js')
require('../../js/tab.js')
require('../../js/affix.js')

View File

@ -29,8 +29,8 @@ Run `grunt` to run tests locally and compile the CSS and JavaScript into `/dist`
#### Tests - `grunt test`
Runs [JSHint](http://jshint.com) and [QUnit](http://qunitjs.com/) tests headlessly in [PhantomJS](http://phantomjs.org/) (used for CI).
#### Tests and assets - `grunt docs`
Compiles and tests CSS, JavaScript, and more for running the local documentation via `jekyll serve`.
#### Build and test docs assets - `grunt docs`
Builds and tests CSS, JavaScript, and other assets which are used when running the documentation locally via `jekyll serve`.
#### Watch - `grunt watch`
This is a convenience method for watching just Less files and automatically building them whenever you save.

View File

@ -159,7 +159,7 @@ As a heads up, we include this in all of Bootstrap's documentation and examples
### Safari percent rounding
As of Safari v7.0.1 for OS X and Safari for iOS v7.0.1, Safari's rendering engine has some trouble with the number of decimal places used in our `.col-*-1` grid classes. So if you have 12 individual grid columns, you'll notice that they come up short compared to other rows of columns. We can't do much here ([see #9282](https://github.com/twbs/bootstrap/issues/9282)) but you do have some options:
The rendering engine of versions of Safari prior to v7.1 for OS X and Safari for iOS v8.0 had some trouble with the number of decimal places used in our `.col-*-1` grid classes. So if you had 12 individual grid columns, you'd notice that they came up short compared to other rows of columns. Besides upgrading Safari/iOS, you have some options for workarounds:
- Add `.pull-right` to your last grid column to get the hard-right alignment
- Tweak your percentages manually to get the perfect rounding for Safari (more difficult than the first option)

View File

@ -3,6 +3,7 @@ layout: home
title: Bootstrap &middot; The world's most popular mobile-first and responsive front-end framework.
---
<main class="bs-docs-masthead" id="content" role="main">
<div class="container">
<span class="bs-docs-booticon outline">B</span>

View File

@ -8,7 +8,7 @@ Do more with buttons. Control button states or create groups of buttons for more
<div class="bs-callout bs-callout-danger">
<h4>Cross-browser compatibility</h4>
<p><a href="https://github.com/twbs/bootstrap/issues/793">Firefox persists form control states (disabledness and checkedness) across page loads</a>. A workaround for this is to use <code>autocomplete="off"</code>.</p>
<p><a href="https://github.com/twbs/bootstrap/issues/793">Firefox persists form control states (disabledness and checkedness) across page loads</a>. A workaround for this is to use <code>autocomplete="off"</code>. See <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=654072">Mozilla bug #654072</a>.</p>
</div>
## Stateful
@ -38,11 +38,16 @@ Add `data-loading-text="Loading..."` to use a loading state on a button.
Add `data-toggle="button"` to activate toggling on a single button.
{% example html %}
<button type="button" class="btn btn-primary" data-toggle="button" autocomplete="off">
<button type="button" class="btn btn-primary" data-toggle="button" aria-pressed="false" autocomplete="off">
Single toggle
</button>
{% endexample %}
<div class="bs-callout bs-callout-warning">
<h4>Pre-toggled buttons need <code>.active</code> and <code>aria-pressed="true"</code></h4>
<p>For pre-toggled buttons, you must add the <code>.active</code> class and the <code>aria-pressed="true"</code> attribute to the <code>button</code> yourself.</p>
</div>
## Checkbox and radio
Add `data-toggle="buttons"` to a `.btn-group` containing checkbox or radio inputs to enable toggling in their respective styles.

View File

@ -154,6 +154,12 @@ Options can be passed via data attributes or JavaScript. For data attributes, ap
<td>true</td>
<td>Whether the carousel should cycle continuously or have hard stops.</td>
</tr>
<tr>
<td>keyboard</td>
<td>boolean</td>
<td>true</td>
<td>Whether the carousel should react to keyboard events.</td>
</tr>
</tbody>
</table>
</div>

View File

@ -33,7 +33,7 @@ Using the collapse plugin, we built a simple accordion by extending the panel co
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="headingTwo">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
<a class="collapsed" data-toggle="collapse" data-parent="#accordion" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
Collapsible Group Item #2
</a>
</h4>
@ -47,7 +47,7 @@ Using the collapse plugin, we built a simple accordion by extending the panel co
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="headingThree">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapseThree" aria-expanded="false" aria-controls="collapseThree">
<a class="collapsed" data-toggle="collapse" data-parent="#accordion" href="#collapseThree" aria-expanded="false" aria-controls="collapseThree">
Collapsible Group Item #3
</a>
</h4>

View File

@ -26,11 +26,11 @@ Add dropdown menus to nearly anything with this simple plugin, including the nav
Dropdown
</button>
<ul class="dropdown-menu" role="menu" aria-labelledby="drop1">
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Another action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Something else here</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Another action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Something else here</a></li>
<li role="presentation" class="divider"></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Separated link</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Separated link</a></li>
</ul>
</li>
<li class="dropdown">
@ -38,11 +38,11 @@ Add dropdown menus to nearly anything with this simple plugin, including the nav
Dropdown 2
</button>
<ul class="dropdown-menu" role="menu" aria-labelledby="drop2">
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Another action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Something else here</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Another action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Something else here</a></li>
<li role="presentation" class="divider"></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Separated link</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Separated link</a></li>
</ul>
</li>
</ul>
@ -52,11 +52,11 @@ Add dropdown menus to nearly anything with this simple plugin, including the nav
Dropdown 3
</button>
<ul class="dropdown-menu" role="menu" aria-labelledby="drop3">
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Another action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Something else here</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Another action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Something else here</a></li>
<li role="presentation" class="divider"></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Separated link</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Separated link</a></li>
</ul>
</li>
</ul>
@ -75,11 +75,11 @@ Add dropdown menus to nearly anything with this simple plugin, including the nav
Dropdown
</button>
<ul id="menu1" class="dropdown-menu" role="menu" aria-labelledby="drop4">
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Another action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Something else here</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Another action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Something else here</a></li>
<li role="presentation" class="divider"></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Separated link</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Separated link</a></li>
</ul>
</li>
<li role="presentation" class="dropdown">
@ -87,11 +87,11 @@ Add dropdown menus to nearly anything with this simple plugin, including the nav
Dropdown 2
</button>
<ul id="menu2" class="dropdown-menu" role="menu" aria-labelledby="drop5">
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Another action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Something else here</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Another action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Something else here</a></li>
<li role="presentation" class="divider"></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Separated link</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Separated link</a></li>
</ul>
</li>
<li role="presentation" class="dropdown">
@ -99,11 +99,11 @@ Add dropdown menus to nearly anything with this simple plugin, including the nav
Dropdown 3
</button>
<ul id="menu3" class="dropdown-menu" role="menu" aria-labelledby="drop6">
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Another action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Something else here</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Another action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Something else here</a></li>
<li role="presentation" class="divider"></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Separated link</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Separated link</a></li>
</ul>
</li>
</ul>

View File

@ -5,6 +5,8 @@ title: Modal
Modals are streamlined, but flexible, dialog prompts with the minimum required functionality and smart defaults.
**Due to how HTML5 defines its semantics, the `autofocus` HTML attribute has no effect in Bootstrap modals.**
<div class="bs-callout bs-callout-warning" id="callout-stacked-modals">
<h4>Overlapping modals not supported</h4>
<p>Be sure not to open a modal while another is still visible. Showing more than one modal at a time requires custom code.</p>

View File

@ -127,7 +127,7 @@ Use the `focus` trigger to dismiss popovers on the next click that the user make
</div>
{% example html %}
<a href="#" tabindex="0" class="btn btn-lg btn-danger bs-docs-popover" data-toggle="popover" data-trigger="focus" title="Dismissible popover" data-content="And here's some amazing content. It's very engaging. Right?">Dismissible popover</a>
<a href="#" tabindex="0" class="btn btn-lg btn-danger bs-docs-popover" role="button" data-toggle="popover" data-trigger="focus" title="Dismissible popover" data-content="And here's some amazing content. It's very engaging. Right?">Dismissible popover</a>
{% endexample %}
{% highlight js %}
@ -265,19 +265,19 @@ Initializes popovers for an element collection.
#### .popover('show')
Reveals an elements popover.
Reveals an element's popover. Popovers whose both title and content are zero-length are never displayed.
{% highlight js %}$('#element').popover('show'){% endhighlight %}
#### .popover('hide')
Hides an elements popover.
Hides an element's popover.
{% highlight js %}$('#element').popover('hide'){% endhighlight %}
#### .popover('toggle')
Toggles an elements popover.
Toggles an element's popover.
{% highlight js %}$('#element').popover('toggle'){% endhighlight %}

View File

@ -55,6 +55,10 @@ The ScrollSpy plugin is for automatically updating nav targets based on scroll p
## Usage
### Requires Bootstrap nav
Scrollspy currently requires the use of a [Bootstrap nav component](/components/nav/) for proper highlighting of active links.
### Requires relative positioning
No matter the implementation method, scrollspy requires the use of `position: relative;` on the element you're spying on. In most cases this is the `<body>`.

View File

@ -9,27 +9,34 @@ Add quick, dynamic tab functionality to transition through panes of local conten
<div class="bs-example bs-example-tabs">
<ul id="myTab" class="nav nav-tabs" role="tablist">
<li role="presentation" class="active"><a href="#home" role="tab" data-toggle="tab">Home</a></li>
<li role="presentation"><a href="#profile" role="tab" data-toggle="tab">Profile</a></li>
<li role="presentation" class="active">
<a href="#home" id="home-tab" role="tab" data-toggle="tab" aria-controls="home" aria-expanded="true">Home</a>
</li>
<li role="presentation">
<a href="#profile" role="tab" id="profile-tab" data-toggle="tab" aria-controls="profile">Profile</a>
</li>
<li role="presentation" class="dropdown">
<a href="#" id="myTabDrop1" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="myTabDrop1">
<li><a href="#dropdown1" tabindex="-1" role="tab" data-toggle="tab">@fat</a></li>
<li><a href="#dropdown2" tabindex="-1" role="tab" data-toggle="tab">@mdo</a></li>
<a href="#" id="myTabDrop1" class="dropdown-toggle" data-toggle="dropdown" aria-controls="myTabDrop1-contents">
Dropdown
<span class="caret"></span>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="myTabDrop1" id="myTabDrop1-contents">
<li><a href="#dropdown1" tabindex="-1" role="tab" id="dropdown1-tab" data-toggle="tab" aria-controls="dropdown1">@fat</a></li>
<li><a href="#dropdown2" tabindex="-1" role="tab" id="dropdown2-tab" data-toggle="tab" aria-controls="dropdown2">@mdo</a></li>
</ul>
</li>
</ul>
<div id="myTabContent" class="tab-content">
<div role="tabpanel" class="tab-pane fade in active" id="home">
<div role="tabpanel" class="tab-pane fade in active" id="home" aria-labelledBy="home-tab">
<p>Raw denim you probably haven't heard of them jean shorts Austin. Nesciunt tofu stumptown aliqua, retro synth master cleanse. Mustache cliche tempor, williamsburg carles vegan helvetica. Reprehenderit butcher retro keffiyeh dreamcatcher synth. Cosby sweater eu banh mi, qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan aliquip quis cardigan american apparel, butcher voluptate nisi qui.</p>
</div>
<div role="tabpanel" class="tab-pane fade" id="profile">
<div role="tabpanel" class="tab-pane fade" id="profile" aria-labelledBy="profile-tab">
<p>Food truck fixie locavore, accusamus mcsweeney's marfa nulla single-origin coffee squid. Exercitation +1 labore velit, blog sartorial PBR leggings next level wes anderson artisan four loko farm-to-table craft beer twee. Qui photo booth letterpress, commodo enim craft beer mlkshk aliquip jean shorts ullamco ad vinyl cillum PBR. Homo nostrud organic, assumenda labore aesthetic magna delectus mollit. Keytar helvetica VHS salvia yr, vero magna velit sapiente labore stumptown. Vegan fanny pack odio cillum wes anderson 8-bit, sustainable jean shorts beard ut DIY ethical culpa terry richardson biodiesel. Art party scenester stumptown, tumblr butcher vero sint qui sapiente accusamus tattooed echo park.</p>
</div>
<div role="tabpanel" class="tab-pane fade" id="dropdown1">
<div role="tabpanel" class="tab-pane fade" id="dropdown1" aria-labelledBy="dropdown1-tab">
<p>Etsy mixtape wayfarers, ethical wes anderson tofu before they sold out mcsweeney's organic lomo retro fanny pack lo-fi farm-to-table readymade. Messenger bag gentrify pitchfork tattooed craft beer, iphone skateboard locavore carles etsy salvia banksy hoodie helvetica. DIY synth PBR banksy irony. Leggings gentrify squid 8-bit cred pitchfork. Williamsburg banh mi whatever gluten-free, carles pitchfork biodiesel fixie etsy retro mlkshk vice blog. Scenester cred you probably haven't heard of them, vinyl craft beer blog stumptown. Pitchfork sustainable tofu synth chambray yr.</p>
</div>
<div role="tabpanel" class="tab-pane fade" id="dropdown2">
<div role="tabpanel" class="tab-pane fade" id="dropdown2" aria-labelledBy="dropdown2-tab">
<p>Trust fund seitan letterpress, keytar raw denim keffiyeh etsy art party before they sold out master cleanse gluten-free squid scenester freegan cosby sweater. Fanny pack portland seitan DIY, art party locavore wolf cliche high life echo park Austin. Cred vinyl keffiyeh DIY salvia PBR, banh mi before they sold out farm-to-table VHS viral locavore cosby sweater. Lomo wolf viral, mustache readymade thundercats keffiyeh craft beer marfa ethical. Wolf salvia freegan, sartorial keffiyeh echo park vegan.</p>
</div>
</div>
@ -125,6 +132,15 @@ Activates a tab element and content container. Tab should have either a `data-ta
### Events
When showing a new tab, the events fire in the following order:
1. `hide.bs.tab` (on the current active tab)
2. `show.bs.tab` (on the to-be-shown tab)
3. `hidden.bs.tab` (on the previous active tab, the same one as for the `hide.bs.tab` event)
4. `shown.bs.tab` (on the newly-active just-shown tab, the same one as for the `show.bs.tab` event)
If no tab was already active, then the `hide.bs.tab` and `hidden.bs.tab` events will not be fired.
<div class="table-responsive">
<table class="table table-bordered table-striped">
<thead>
@ -134,21 +150,29 @@ Activates a tab element and content container. Tab should have either a `data-ta
</tr>
</thead>
<tbody>
<tr>
<td>show.bs.tab</td>
<td>This event fires on tab show, but before the new tab has been shown. Use <code>event.target</code> and <code>event.relatedTarget</code> to target the active tab and the previous active tab (if available) respectively.</td>
</tr>
<tr>
<td>shown.bs.tab</td>
<td>This event fires on tab show after a tab has been shown. Use <code>event.target</code> and <code>event.relatedTarget</code> to target the active tab and the previous active tab (if available) respectively.</td>
<tr>
<td>show.bs.tab</td>
<td>This event fires on tab show, but before the new tab has been shown. Use <code>event.target</code> and <code>event.relatedTarget</code> to target the active tab and the previous active tab (if available) respectively.</td>
</tr>
<tr>
<td>shown.bs.tab</td>
<td>This event fires on tab show after a tab has been shown. Use <code>event.target</code> and <code>event.relatedTarget</code> to target the active tab and the previous active tab (if available) respectively.</td>
</tr>
<tr>
<td>hide.bs.tab</td>
<td>This event fires when a new tab is to be shown (and thus the previous active tab is to be hidden). Use <code>event.target</code> and <code>event.relatedTarget</code> to target the current active tab and the new soon-to-be-active tab, respectively.</td>
</tr>
<tr>
<td>hidden.bs.tab</td>
<td>This event fires after a new tab is shown (and thus the previous active tab is hidden). Use <code>event.target</code> and <code>event.relatedTarget</code> to target the previous active tab and the new active tab, respectively.</td>
</tr>
</tbody>
</table>
</div>
{% highlight js %}
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
e.target // activated tab
e.relatedTarget // previous tab
e.target // newly activated tab
e.relatedTarget // previous active tab
})
{% endhighlight %}

View File

@ -235,7 +235,7 @@ Attaches a tooltip handler to an element collection.
#### .tooltip('show')
Reveals an element's tooltip.
Reveals an element's tooltip. Tooltips with zero-length titles are never displayed.
{% highlight js %}$('#element').tooltip('show'){% endhighlight %}

View File

@ -46,6 +46,49 @@ Media components can also be nested.
</div>
{% endexample %}
### Media alignment
The images or other media can be aligned top, middle, or bottom. The default is top aligned.
{% example html %}
<div class="media">
<a class="media-left" href="#">
<img data-src="holder.js/64x64" alt="Generic placeholder image">
</a>
<div class="media-body">
<h4 class="media-heading">Top aligned media</h4>
<p>Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.</p>
<p>Donec sed odio dui. Nullam quis risus eget urna mollis ornare vel eu leo. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p>
</div>
</div>
{% endexample %}
{% example html %}
<div class="media">
<a class="media-left media-middle" href="#">
<img data-src="holder.js/64x64" alt="Generic placeholder image">
</a>
<div class="media-body">
<h4 class="media-heading">Middle aligned media</h4>
<p>Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.</p>
<p>Donec sed odio dui. Nullam quis risus eget urna mollis ornare vel eu leo. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p>
</div>
</div>
{% endexample %}
{% example html %}
<div class="media">
<a class="media-left media-bottom" href="#">
<img data-src="holder.js/64x64" alt="Generic placeholder image">
</a>
<div class="media-body">
<h4 class="media-heading">Bottom aligned media</h4>
<p>Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.</p>
<p>Donec sed odio dui. Nullam quis risus eget urna mollis ornare vel eu leo. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p>
</div>
</div>
{% endexample %}
### Media list
With a bit of extra markup, you can use media inside list (useful for comment threads or articles lists).

View File

@ -183,29 +183,29 @@ Green checkmarks indicate the element **is visible** in your current viewport.
</div>
</div>
<div class="row responsive-utilities-test visible-on">
<div class="col-xs-6 col-sm-6">
<div class="col-xs-6">
<span class="hidden-xs hidden-sm">Extra small and small</span>
<span class="visible-xs-block visible-sm-block">&#10004; Visible on x-small and small</span>
</div>
<div class="col-xs-6 col-sm-6">
<div class="col-xs-6">
<span class="hidden-md hidden-lg">Medium and large</span>
<span class="visible-md-block visible-lg-block">&#10004; Visible on medium and large</span>
</div>
<div class="clearfix visible-xs-block"></div>
<div class="col-xs-6 col-sm-6">
<div class="col-xs-6">
<span class="hidden-xs hidden-md">Extra small and medium</span>
<span class="visible-xs-block visible-md-block">&#10004; Visible on x-small and medium</span>
</div>
<div class="col-xs-6 col-sm-6">
<div class="col-xs-6">
<span class="hidden-sm hidden-lg">Small and large</span>
<span class="visible-sm-block visible-lg-block">&#10004; Visible on small and large</span>
</div>
<div class="clearfix visible-xs-block"></div>
<div class="col-xs-6 col-sm-6">
<div class="col-xs-6">
<span class="hidden-xs hidden-lg">Extra small and large</span>
<span class="visible-xs-block visible-lg-block">&#10004; Visible on x-small and large</span>
</div>
<div class="col-xs-6 col-sm-6">
<div class="col-xs-6">
<span class="hidden-sm hidden-md">Small and medium</span>
<span class="visible-sm-block visible-md-block">&#10004; Visible on small and medium</span>
</div>
@ -235,29 +235,29 @@ Here, green checkmarks also indicate the element **is hidden** in your current v
</div>
</div>
<div class="row responsive-utilities-test hidden-on">
<div class="col-xs-6 col-sm-6">
<div class="col-xs-6">
<span class="hidden-xs hidden-sm">Extra small and small</span>
<span class="visible-xs-block visible-sm-block">&#10004; Hidden on x-small and small</span>
</div>
<div class="col-xs-6 col-sm-6">
<div class="col-xs-6">
<span class="hidden-md hidden-lg">Medium and large</span>
<span class="visible-md-block visible-lg-block">&#10004; Hidden on medium and large</span>
</div>
<div class="clearfix visible-xs-block"></div>
<div class="col-xs-6 col-sm-6">
<div class="col-xs-6">
<span class="hidden-xs hidden-md">Extra small and medium</span>
<span class="visible-xs-block visible-md-block">&#10004; Hidden on x-small and medium</span>
</div>
<div class="col-xs-6 col-sm-6">
<div class="col-xs-6">
<span class="hidden-sm hidden-lg">Small and large</span>
<span class="visible-sm-block visible-lg-block">&#10004; Hidden on small and large</span>
</div>
<div class="clearfix visible-xs-block"></div>
<div class="col-xs-6 col-sm-6">
<div class="col-xs-6">
<span class="hidden-xs hidden-lg">Extra small and large</span>
<span class="visible-xs-block visible-lg-block">&#10004; Hidden on x-small and large</span>
</div>
<div class="col-xs-6 col-sm-6">
<div class="col-xs-6">
<span class="hidden-sm hidden-md">Small and medium</span>
<span class="visible-sm-block visible-md-block">&#10004; Hidden on small and medium</span>
</div>

View File

@ -1,6 +1,7 @@
---
---
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>

View File

@ -0,0 +1,23 @@
'use strict';
var fs = require('fs');
var path = require('path');
var COMMONJS_BANNER = '// This file is generated. You can require() it in a CommonJS environment.\n';
module.exports = function generateCommonJSModule(grunt, srcFiles, destFilepath) {
var destDir = path.dirname(destFilepath);
function srcPathToDestRequire(srcFilepath) {
var requirePath = path.relative(destDir, srcFilepath).replace(/\\/g, '/');
return 'require(\'' + requirePath + '\')';
}
var moduleOutputJs = COMMONJS_BANNER + srcFiles.map(srcPathToDestRequire).join('\n');
try {
fs.writeFileSync(destFilepath, moduleOutputJs);
}
catch (err) {
grunt.fail.warn(err);
}
grunt.log.writeln('File ' + destFilepath.cyan + ' created.');
};

View File

@ -60,6 +60,8 @@
else $parent.find('.active').removeClass('active')
}
if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change')
} else {
this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
}
if (changed) this.$element.toggleClass('active')

View File

@ -14,7 +14,7 @@
// =========================
var Carousel = function (element, options) {
this.$element = $(element).on('keydown.bs.carousel', $.proxy(this.keydown, this))
this.$element = $(element)
this.$indicators = this.$element.find('.carousel-indicators')
this.options = options
this.paused =
@ -23,7 +23,9 @@
this.$active =
this.$items = null
this.options.pause == 'hover' && this.$element
this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))
this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
.on('mouseenter.bs.carousel', $.proxy(this.pause, this))
.on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
}
@ -35,7 +37,8 @@
Carousel.DEFAULTS = {
interval: 5000,
pause: 'hover',
wrap: true
wrap: true,
keyboard: true
}
Carousel.prototype.keydown = function (e) {

View File

@ -38,17 +38,21 @@
Collapse.prototype.show = function () {
if (this.transitioning || this.$element.hasClass('in')) return
var activesData
var actives = this.$parent && this.$parent.find('> .panel').children('.in, .collapsing')
if (actives && actives.length) {
activesData = actives.data('bs.collapse')
if (activesData && activesData.transitioning) return
}
var startEvent = $.Event('show.bs.collapse')
this.$element.trigger(startEvent)
if (startEvent.isDefaultPrevented()) return
var actives = this.$parent && this.$parent.find('> .panel').children('.in, .collapsing')
if (actives && actives.length) {
var hasData = actives.data('bs.collapse')
if (hasData && hasData.transitioning) return
Plugin.call(actives, 'hide')
hasData || actives.data('bs.collapse', null)
activesData || actives.data('bs.collapse', null)
}
var dimension = this.dimension()

View File

@ -55,7 +55,7 @@
}
Dropdown.prototype.keydown = function (e) {
if (!/(38|40|27)/.test(e.keyCode)) return
if (!/(38|40|27|32)/.test(e.which)) return
var $this = $(this)
@ -67,7 +67,7 @@
var $parent = getParent($this)
var isActive = $parent.hasClass('open')
if (!isActive || (isActive && e.keyCode == 27)) {
if ((!isActive && e.which != 27) || (isActive && e.which == 27)) {
if (e.which == 27) $parent.find(toggle).trigger('focus')
return $this.trigger('click')
}
@ -77,10 +77,10 @@
if (!$items.length) return
var index = $items.index($items.filter(':focus'))
var index = $items.index(e.target)
if (e.keyCode == 38 && index > 0) index-- // up
if (e.keyCode == 40 && index < $items.length - 1) index++ // down
if (e.which == 38 && index > 0) index-- // up
if (e.which == 40 && index < $items.length - 1) index++ // down
if (!~index) index = 0
$items.eq(index).trigger('focus')

View File

@ -107,9 +107,6 @@
this.isShown = false
this.$body.removeClass('modal-open')
this.resetScrollbar()
this.escape()
$(document).off('focusin.bs.modal')
@ -150,6 +147,8 @@
var that = this
this.$element.hide()
this.backdrop(function () {
that.$body.removeClass('modal-open')
that.resetScrollbar()
that.$element.trigger('hidden.bs.modal')
})
}
@ -167,14 +166,13 @@
var doAnimate = $.support.transition && animate
this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
.appendTo(this.$body)
this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
if (e.target !== e.currentTarget) return
this.options.backdrop == 'static'
? this.$element[0].focus.call(this.$element[0])
: this.hide.call(this)
}, this))
.prependTo(this.$element)
.on('click.dismiss.bs.modal', $.proxy(function (e) {
if (e.target !== e.currentTarget) return
this.options.backdrop == 'static'
? this.$element[0].focus.call(this.$element[0])
: this.hide.call(this)
}, this))
if (doAnimate) this.$backdrop[0].offsetWidth // force reflow

View File

@ -86,12 +86,18 @@
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.popover')
var options = typeof option == 'object' && option
var $this = $(this)
var data = $this.data('bs.popover')
var options = typeof option == 'object' && option
var selector = options && options.selector
if (!data && option == 'destroy') return
if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
if (selector) {
if (!data) $this.data('bs.popover', (data = {}))
if (!data[selector]) data[selector] = new Popover(this, options)
} else {
if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
}
if (typeof option == 'string') data[option]()
})
}

View File

@ -65,7 +65,6 @@
return ($href
&& $href.length
&& $href.is(':visible')
&& $el.is(':visible')
&& [[$href[offsetMethod]().top + offsetBase, href]]) || null
})
.sort(function (a, b) { return a[0] - b[0] })
@ -92,8 +91,9 @@
return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
}
if (activeTarget && scrollTop <= offsets[0]) {
return activeTarget != (i = targets[0]) && this.activate(i)
if (activeTarget && scrollTop < offsets[0]) {
this.activeTarget = null
return this.clear()
}
for (i = offsets.length; i--;) {
@ -107,9 +107,7 @@
ScrollSpy.prototype.activate = function (target) {
this.activeTarget = target
$(this.selector)
.parentsUntil(this.options.target, '.active')
.removeClass('active')
this.clear()
var selector = this.selector +
'[data-target="' + target + '"],' +
@ -128,6 +126,12 @@
active.trigger('activate.bs.scrollspy')
}
ScrollSpy.prototype.clear = function () {
$(this.selector)
.parentsUntil(this.options.target, '.active')
.removeClass('active')
}
// SCROLLSPY PLUGIN DEFINITION
// ===========================

View File

@ -33,22 +33,30 @@
if ($this.parent('li').hasClass('active')) return
var previous = $ul.find('.active:last a')[0]
var e = $.Event('show.bs.tab', {
relatedTarget: previous
var $previous = $ul.find('.active:last a')
var hideEvent = $.Event('hide.bs.tab', {
relatedTarget: $this[0]
})
var showEvent = $.Event('show.bs.tab', {
relatedTarget: $previous[0]
})
$this.trigger(e)
$previous.trigger(hideEvent)
$this.trigger(showEvent)
if (e.isDefaultPrevented()) return
if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
var $target = $(selector)
this.activate($this.closest('li'), $ul)
this.activate($target, $target.parent(), function () {
$previous.trigger({
type: 'hidden.bs.tab',
relatedTarget: $this[0]
})
$this.trigger({
type: 'shown.bs.tab',
relatedTarget: previous
relatedTarget: $previous[0]
})
})
}
@ -63,9 +71,15 @@
$active
.removeClass('active')
.find('> .dropdown-menu > .active')
.removeClass('active')
.removeClass('active')
.end()
.find('[data-toggle="tab"]')
.attr('aria-expanded', false)
element.addClass('active')
element
.addClass('active')
.find('[data-toggle="tab"]')
.attr('aria-expanded', true)
if (transition) {
element[0].offsetWidth // reflow for transition
@ -75,7 +89,12 @@
}
if (element.parent('.dropdown-menu')) {
element.closest('li.dropdown').addClass('active')
element
.closest('li.dropdown')
.addClass('active')
.end()
.find('[data-toggle="tab"]')
.attr('aria-expanded', true)
}
callback && callback()

View File

@ -10,6 +10,11 @@
<!-- QUnit -->
<link rel="stylesheet" href="vendor/qunit.css" media="screen">
<script src="vendor/qunit.js"></script>
<style>
#qunit-tests > li.pass {
display: none;/* Make it easier to see failing tests is Sauce screencasts */
}
</style>
<script>
// See https://github.com/axemclion/grunt-saucelabs#test-result-details-with-qunit
var log = []

View File

@ -85,7 +85,7 @@ $(function () {
})
test('should toggle active', function () {
var $btn = $('<button class="btn">mdo</button>')
var $btn = $('<button class="btn" data-toggle="button">mdo</button>')
ok(!$btn.hasClass('active'), 'btn does not have active class')
$btn.bootstrapButton('toggle')
ok($btn.hasClass('active'), 'btn has class active')
@ -102,6 +102,24 @@ $(function () {
ok($btn.hasClass('active'), 'btn has class active')
})
test('should toggle aria-pressed', function () {
var $btn = $('<button class="btn" data-toggle="button" aria-pressed="false">redux</button>')
equal($btn.attr('aria-pressed'), 'false', 'btn aria-pressed state is false')
$btn.bootstrapButton('toggle')
equal($btn.attr('aria-pressed'), 'true', 'btn aria-pressed state is true')
})
test('should toggle aria-pressed when btn children are clicked', function () {
var $btn = $('<button class="btn" data-toggle="button" aria-pressed="false">redux</button>')
var $inner = $('<i/>')
$btn
.append($inner)
.appendTo('#qunit-fixture')
equal($btn.attr('aria-pressed'), 'false', 'btn aria-pressed state is false')
$inner.click()
equal($btn.attr('aria-pressed'), 'true', 'btn aria-pressed state is true')
})
test('should toggle active when btn children are clicked within btn-group', function () {
var $btngroup = $('<div class="btn-group" data-toggle="buttons"/>')
var $btn = $('<button class="btn">fat</button>')

View File

@ -398,4 +398,105 @@ $(function () {
strictEqual($template.find('.item')[1], $template.find('.active')[0], 'second item active')
})
test('should go to previous item if left arrow key is pressed', function () {
var templateHTML = '<div id="myCarousel" class="carousel" data-interval="false">'
+ '<div class="carousel-inner">'
+ '<div id="first" class="item">'
+ '<img alt="">'
+ '</div>'
+ '<div id="second" class="item active">'
+ '<img alt="">'
+ '</div>'
+ '<div id="third" class="item">'
+ '<img alt="">'
+ '</div>'
+ '</div>'
+ '</div>'
var $template = $(templateHTML)
$template.bootstrapCarousel()
strictEqual($template.find('.item')[1], $template.find('.active')[0], 'second item active')
$template.trigger($.Event('keydown', { which: 37 }))
strictEqual($template.find('.item')[0], $template.find('.active')[0], 'first item active')
})
test('should go to next item if right arrow key is pressed', function () {
var templateHTML = '<div id="myCarousel" class="carousel" data-interval="false">'
+ '<div class="carousel-inner">'
+ '<div id="first" class="item active">'
+ '<img alt="">'
+ '</div>'
+ '<div id="second" class="item">'
+ '<img alt="">'
+ '</div>'
+ '<div id="third" class="item">'
+ '<img alt="">'
+ '</div>'
+ '</div>'
+ '</div>'
var $template = $(templateHTML)
$template.bootstrapCarousel()
strictEqual($template.find('.item')[0], $template.find('.active')[0], 'first item active')
$template.trigger($.Event('keydown', { which: 39 }))
strictEqual($template.find('.item')[1], $template.find('.active')[0], 'second item active')
})
test('should support disabling the keyboard navigation', function () {
var templateHTML = '<div id="myCarousel" class="carousel" data-interval="false" data-keyboard="false">'
+ '<div class="carousel-inner">'
+ '<div id="first" class="item active">'
+ '<img alt="">'
+ '</div>'
+ '<div id="second" class="item">'
+ '<img alt="">'
+ '</div>'
+ '<div id="third" class="item">'
+ '<img alt="">'
+ '</div>'
+ '</div>'
+ '</div>'
var $template = $(templateHTML)
$template.bootstrapCarousel()
strictEqual($template.find('.item')[0], $template.find('.active')[0], 'first item active')
$template.trigger($.Event('keydown', { which: 39 }))
strictEqual($template.find('.item')[0], $template.find('.active')[0], 'first item still active after right arrow press')
$template.trigger($.Event('keydown', { which: 37 }))
strictEqual($template.find('.item')[0], $template.find('.active')[0], 'first item still active after left arrow press')
})
test('should only add mouseenter and mouseleave listeners when not on mobile', function () {
var isMobile = 'ontouchstart' in document.documentElement
var templateHTML = '<div id="myCarousel" class="carousel" data-interval="false" data-pause="hover">'
+ '<div class="carousel-inner">'
+ '<div id="first" class="item active">'
+ '<img alt="">'
+ '</div>'
+ '<div id="second" class="item">'
+ '<img alt="">'
+ '</div>'
+ '<div id="third" class="item">'
+ '<img alt="">'
+ '</div>'
+ '</div>'
+ '</div>'
var $template = $(templateHTML).bootstrapCarousel()
$.each(['mouseover', 'mouseout'], function (i, type) {
strictEqual(type in $._data($template[0], 'events'), !isMobile, 'does' + (isMobile ? ' not' : '') + ' listen for ' + type + ' events')
})
})
})

View File

@ -263,4 +263,39 @@ $(function () {
$target3.click()
})
test('should not fire show event if show is prevented because other element is still transitioning', function () {
stop()
var accordionHTML = '<div id="accordion">'
+ '<div class="panel"/>'
+ '<div class="panel"/>'
+ '</div>'
var showFired = false
var $groups = $(accordionHTML).appendTo('#qunit-fixture').find('.panel')
var $target1 = $('<a data-toggle="collapse" href="#body1" data-parent="#accordion"/>').appendTo($groups.eq(0))
$('<div id="body1" class="collapse"/>')
.appendTo($groups.eq(0))
.on('show.bs.collapse', function () {
showFired = true
})
var $target2 = $('<a data-toggle="collapse" href="#body2" data-parent="#accordion"/>').appendTo($groups.eq(1))
var $body2 = $('<div id="body2" class="collapse"/>').appendTo($groups.eq(1))
$target2.click()
$body2
.toggleClass('in collapsing')
.data('bs.collapse').transitioning = 1
$target1.click()
setTimeout(function () {
ok(!showFired, 'show event didn\'t fire')
start()
}, 1)
})
})

View File

@ -141,7 +141,7 @@ $(function () {
notEqual($('#modal-test').length, 0, 'modal insterted into dom')
$('.contents').click()
ok($('#modal-test').is(':visible'), 'modal visible')
$('#modal-test').click()
$('#modal-test .modal-backdrop').click()
})
.on('hidden.bs.modal', function () {
ok(!$('#modal-test').is(':visible'), 'modal hidden')
@ -196,7 +196,7 @@ $(function () {
$('<div id="modal-test"><div class="contents"/></div>')
.on('shown.bs.modal', function () {
triggered = 0
$('#modal-test').click()
$('#modal-test .modal-backdrop').click()
})
.on('hide.bs.modal', function () {
triggered += 1

View File

@ -30,7 +30,7 @@ $(function () {
})
test('should render popover element', function () {
var $popover = $('<a href="#" title="mdo" data-content="http://twitter.com/mdo">@mdo</a>')
var $popover = $('<a href="#" title="mdo" data-content="https://twitter.com/mdo">@mdo</a>')
.appendTo('#qunit-fixture')
.bootstrapPopover('show')
@ -40,7 +40,7 @@ $(function () {
})
test('should store popover instance in popover data object', function () {
var $popover = $('<a href="#" title="mdo" data-content="http://twitter.com/mdo">@mdo</a>').bootstrapPopover()
var $popover = $('<a href="#" title="mdo" data-content="https://twitter.com/mdo">@mdo</a>').bootstrapPopover()
ok($popover.data('bs.popover'), 'popover instance exists')
})
@ -173,4 +173,48 @@ $(function () {
ok(!$._data($popover[0], 'events').mouseover && !$._data($popover[0], 'events').mouseout, 'popover does not have any events')
})
test('should render popover element using delegated selector', function () {
var $div = $('<div><a href="#" title="mdo" data-content="http://twitter.com/mdo">@mdo</a></div>')
.appendTo('#qunit-fixture')
.bootstrapPopover({
selector: 'a',
trigger: 'click'
})
$div.find('a').click()
notEqual($('.popover').length, 0, 'popover was inserted')
$div.find('a').click()
equal($('.popover').length, 0, 'popover was removed')
})
test('should render popover elements using different delegated selectors on the same node', function () {
var popoverHTML = '<div>'
+ '<a href="#" class="first" title="mdo" data-content="http://twitter.com/mdo">@mdo</a>'
+ '<a href="#" class="second" title="mdo" data-content="http://twitter.com/mdo">@mdo</a>'
+ '</div>'
var $div = $(popoverHTML)
.appendTo('#qunit-fixture')
.bootstrapPopover({
selector: 'a.first',
trigger: 'click'
})
.bootstrapPopover({
selector: 'a.second',
trigger: 'click'
})
$div.find('a.first').click()
notEqual($('.popover').length, 0, 'first popover was inserted')
$div.find('a.first').click()
equal($('.popover').length, 0, 'first popover removed')
$div.find('a.second').click()
notEqual($('.popover').length, 0, 'second popover was inserted')
$div.find('a.second').click()
equal($('.popover').length, 0, 'second popover removed')
})
})

View File

@ -29,22 +29,6 @@ $(function () {
strictEqual($scrollspy[0], $el[0], 'collection contains element')
})
// Does not work properly ATM, #13500 will fix this
test('should switch "active" class on scroll', function () {
var topbarHTML = '<div class="topbar">'
+ '<div class="topbar-inner">'
+ '<div class="container">'
+ '<h3><a href="#">Bootstrap</a></h3>'
+ '<li><a href="#masthead">Overview</a></li>'
+ '</ul>'
+ '</div>'
+ '</div>'
+ '</div>'
var $topbar = $(topbarHTML).bootstrapScrollspy()
ok($topbar.find('.active', true))
})
test('should only switch "active" class on current target', function () {
stop()
@ -77,9 +61,9 @@ $(function () {
var $section = $(sectionHTML).appendTo('#qunit-fixture')
var $scrollspy = $section
.show()
.find('#scrollspy-example')
.bootstrapScrollspy({ target: '#ss-target' })
.show()
.find('#scrollspy-example')
.bootstrapScrollspy({ target: '#ss-target' })
$scrollspy.on('scroll.bs.scrollspy', function () {
ok($section.hasClass('active'), '"active" class still on root node')
@ -89,7 +73,7 @@ $(function () {
$scrollspy.scrollTop(350)
})
test('middle navigation option correctly selected when large offset is used', function () {
test('should correctly select middle navigation option when large offset is used', function () {
stop()
var sectionHTML = '<div id="header" style="height: 500px;"></div>'
@ -107,8 +91,8 @@ $(function () {
+ '</div>'
var $section = $(sectionHTML).appendTo('#qunit-fixture')
var $scrollspy = $section
.show()
.filter('#content')
.show()
.filter('#content')
$scrollspy.bootstrapScrollspy({ target: '#navigation', offset: $scrollspy.position().top })
@ -158,4 +142,45 @@ $(function () {
.then(function () { return testElementIsActiveAfterScroll('#li-2', '#div-2') })
})
test('should clear selection if above the first section', function () {
stop()
var sectionHTML = '<div id="header" style="height: 500px;"></div>'
+ '<nav id="navigation" class="navbar">'
+ '<ul class="nav navbar-nav">'
+ '<li class="active"><a id="one-link" href="#one">One</a></li>'
+ '<li><a id="two-link" href="#two">Two</a></li>'
+ '<li><a id="three-link" href="#three">Three</a></li>'
+ '</ul>'
+ '</nav>'
$(sectionHTML).appendTo('#qunit-fixture')
var scrollspyHTML = '<div id="content" style="height: 200px; overflow-y: auto;">'
+ '<div id="spacer" style="height: 100px;"/>'
+ '<div id="one" style="height: 100px;"/>'
+ '<div id="two" style="height: 100px;"/>'
+ '<div id="three" style="height: 100px;"/>'
+ '<div id="spacer" style="height: 100px;"/>'
+ '</div>'
var $scrollspy = $(scrollspyHTML).appendTo('#qunit-fixture')
$scrollspy
.bootstrapScrollspy({
target: '#navigation',
offset: $scrollspy.position().top
})
.one('scroll.bs.scrollspy', function () {
strictEqual($('.active').length, 1, '"active" class on only one element present')
strictEqual($('.active').has('#two-link').length, 1, '"active" class on second section')
$scrollspy
.one('scroll.bs.scrollspy', function () {
strictEqual($('.active').length, 0, 'selection cleared')
start()
})
.scrollTop(0)
})
.scrollTop(201)
})
})

View File

@ -101,4 +101,105 @@ $(function () {
.bootstrapTab('show')
})
test('should fire hide and hidden events', function () {
stop()
var tabsHTML = '<ul class="tabs">'
+ '<li><a href="#home">Home</a></li>'
+ '<li><a href="#profile">Profile</a></li>'
+ '</ul>'
$(tabsHTML)
.find('li:first a')
.on('hide.bs.tab', function () {
ok(true, 'hide event fired')
})
.bootstrapTab('show')
.end()
.find('li:last a')
.bootstrapTab('show')
$(tabsHTML)
.find('li:first a')
.on('hidden.bs.tab', function () {
ok(true, 'hidden event fired')
start()
})
.bootstrapTab('show')
.end()
.find('li:last a')
.bootstrapTab('show')
})
test('should not fire hidden when hide is prevented', function () {
stop()
var tabsHTML = '<ul class="tabs">'
+ '<li><a href="#home">Home</a></li>'
+ '<li><a href="#profile">Profile</a></li>'
+ '</ul>'
$(tabsHTML)
.find('li:first a')
.on('hide.bs.tab', function (e) {
e.preventDefault()
ok(true, 'hide event fired')
start()
})
.on('hidden.bs.tab', function () {
ok(false, 'hidden event fired')
})
.bootstrapTab('show')
.end()
.find('li:last a')
.bootstrapTab('show')
})
test('hide and hidden events contain correct relatedTarget', function () {
stop()
var tabsHTML = '<ul class="tabs">'
+ '<li><a href="#home">Home</a></li>'
+ '<li><a href="#profile">Profile</a></li>'
+ '</ul>'
$(tabsHTML)
.find('li:first a')
.on('hide.bs.tab', function (e) {
equal(e.relatedTarget.hash, '#profile', 'references correct element as relatedTarget')
})
.on('hidden.bs.tab', function (e) {
equal(e.relatedTarget.hash, '#profile', 'references correct element as relatedTarget')
start()
})
.bootstrapTab('show')
.end()
.find('li:last a')
.bootstrapTab('show')
})
test('selected tab should have aria-expanded', function () {
var tabsHTML = '<ul class="nav nav-tabs">'
+ '<li class="active"><a href="#home" toggle="tab" aria-expanded="true">Home</a></li>'
+ '<li><a href="#profile" toggle="tab" aria-expanded="false">Profile</a></li>'
+ '</ul>'
var $tabs = $(tabsHTML).appendTo('#qunit-fixture')
$tabs.find('li:first a').bootstrapTab('show')
equal($tabs.find('.active a').attr('aria-expanded'), 'true', 'shown tab has aria-expanded = true')
equal($tabs.find('li:not(.active) a').attr('aria-expanded'), 'false', 'hidden tab has aria-expanded = false')
$tabs.find('li:last a').click()
equal($tabs.find('.active a').attr('aria-expanded'), 'true', 'after click, shown tab has aria-expanded = true')
equal($tabs.find('li:not(.active) a').attr('aria-expanded'), 'false', 'after click, hidden tab has aria-expanded = false')
$tabs.find('li:first a').bootstrapTab('show')
equal($tabs.find('.active a').attr('aria-expanded'), 'true', 'shown tab has aria-expanded = true')
equal($tabs.find('li:not(.active) a').attr('aria-expanded'), 'false', 'hidden tab has aria-expanded = false')
$tabs.find('li:first a').click()
equal($tabs.find('.active a').attr('aria-expanded'), 'true', 'after second show event, shown tab still has aria-expanded = true')
equal($tabs.find('li:not(.active) a').attr('aria-expanded'), 'false', 'after second show event, hidden tab has aria-expanded = false')
})
})

View File

@ -235,6 +235,37 @@ $(function () {
equal($('.tooltip').length, 0, 'tooltip was removed from dom')
})
test('should show tooltips with different delegate selectors on the same node on click', function () {
var tooltipHTML = '<div>'
+ '<a href="#" class="first" rel="tooltip" title="First delegated tooltip"/>'
+ '<a href="#" class="second" rel="tooltip" title="Second delegated tooltip"/>'
+ '</div>'
var $div = $(tooltipHTML)
.append()
.appendTo('#qunit-fixture')
.bootstrapTooltip({
selector: 'a.first[rel="tooltip"]',
trigger: 'click'
})
.bootstrapTooltip({
selector: 'a.second[rel="tooltip"]',
trigger: 'click'
})
$div.find('a.first').click()
ok($('.tooltip').is('.fade.in'), 'first tooltip is faded in')
$div.find('a.first').click()
equal($('.tooltip').length, 0, 'first tooltip was removed from dom')
$div.find('a.second').click()
ok($('.tooltip').is('.fade.in'), 'second tooltip is faded in')
$div.find('a.second').click()
equal($('.tooltip').length, 0, 'second tooltip was removed from dom')
})
test('should show tooltip when toggle is called', function () {
$('<a href="#" rel="tooltip" title="tooltip on toggle"/>')
.appendTo('#qunit-fixture')
@ -382,6 +413,164 @@ $(function () {
$style.remove()
})
test('should position tip on top if viewport has enough space and placement is "auto top"', function () {
var styles = '<style>'
+ 'body { padding-top: 100px; }'
+ '#section { height: 300px; border: 1px solid red; padding-top: 50px }'
+ 'div[rel="tooltip"] { width: 150px; border: 1px solid blue; }'
+ '</style>'
var $styles = $(styles).appendTo('head')
var $container = $('<div id="section"/>').appendTo('#qunit-fixture')
var $target = $('<div rel="tooltip" title="tip"/>')
.appendTo($container)
.bootstrapTooltip({
placement: 'auto top',
viewport: '#section'
})
$target.bootstrapTooltip('show')
ok($('.tooltip').is('.top'), 'top positioned tooltip is dynamically positioned to top')
$target.bootstrapTooltip('hide')
equal($('.tooltip').length, 0, 'tooltip removed from dom')
$styles.remove()
})
test('should position tip on bottom if the tip\'s dimension exceeds the viewport area and placement is "auto top"', function () {
var styles = '<style>'
+ 'body { padding-top: 100px; }'
+ '#section { height: 300px; border: 1px solid red; }'
+ 'div[rel="tooltip"] { width: 150px; border: 1px solid blue; }'
+ '</style>'
var $styles = $(styles).appendTo('head')
var $container = $('<div id="section"/>').appendTo('#qunit-fixture')
var $target = $('<div rel="tooltip" title="tip"/>')
.appendTo($container)
.bootstrapTooltip({
placement: 'auto top',
viewport: '#section'
})
$target.bootstrapTooltip('show')
ok($('.tooltip').is('.bottom'), 'top positioned tooltip is dynamically positioned to bottom')
$target.bootstrapTooltip('hide')
equal($('.tooltip').length, 0, 'tooltip removed from dom')
$styles.remove()
})
test('should display the tip on top whenever scrollable viewport has enough room if the given placement is "auto top"', function () {
var styles = '<style>'
+ '#scrollable-div { height: 200px; overflow: auto; }'
+ '.tooltip-item { margin: 200px 0 400px; width: 150px; }'
+ '</style>'
var $styles = $(styles).appendTo('head')
var $container = $('<div id="scrollable-div"/>').appendTo('#qunit-fixture')
var $target = $('<div rel="tooltip" title="tip" class="tooltip-item">Tooltip Item</div>')
.appendTo($container)
.bootstrapTooltip({
placement: 'top auto',
viewport: '#scrollable-div'
})
$('#scrollable-div').scrollTop(100)
$target.bootstrapTooltip('show')
ok($('.tooltip').is('.fade.top.in'), 'has correct classes applied')
$target.bootstrapTooltip('hide')
equal($('.tooltip').length, 0, 'tooltip removed from dom')
$styles.remove()
})
test('should display the tip on bottom whenever scrollable viewport doesn\'t have enough room if the given placement is "auto top"', function () {
var styles = '<style>'
+ '#scrollable-div { height: 200px; overflow: auto; }'
+ '.tooltip-item { padding: 200px 0 400px; width: 150px; }'
+ '</style>'
var $styles = $(styles).appendTo('head')
var $container = $('<div id="scrollable-div"/>').appendTo('#qunit-fixture')
var $target = $('<div rel="tooltip" title="tip" class="tooltip-item">Tooltip Item</div>')
.appendTo($container)
.bootstrapTooltip({
placement: 'top auto',
viewport: '#scrollable-div'
})
$('#scrollable-div').scrollTop(200)
$target.bootstrapTooltip('show')
ok($('.tooltip').is('.fade.bottom.in'), 'has correct classes applied')
$target.bootstrapTooltip('hide')
equal($('.tooltip').length, 0, 'tooltip removed from dom')
$styles.remove()
})
test('should display the tip on bottom whenever scrollable viewport has enough room if the given placement is "auto bottom"', function () {
var styles = '<style>'
+ '#scrollable-div { height: 200px; overflow: auto; }'
+ '.spacer { height: 400px; }'
+ '.spacer:first-child { height: 200px; }'
+ '.tooltip-item { width: 150px; }'
+ '</style>'
var $styles = $(styles).appendTo('head')
var $container = $('<div id="scrollable-div"/>').appendTo('#qunit-fixture')
var $target = $('<div rel="tooltip" title="tip" class="tooltip-item">Tooltip Item</div>')
.appendTo($container)
.before('<div class="spacer"/>')
.after('<div class="spacer"/>')
.bootstrapTooltip({
placement: 'bottom auto',
viewport: '#scrollable-div'
})
$('#scrollable-div').scrollTop(200)
$target.bootstrapTooltip('show')
ok($('.tooltip').is('.fade.bottom.in'), 'has correct classes applied')
$target.bootstrapTooltip('hide')
equal($('.tooltip').length, 0, 'tooltip removed from dom')
$styles.remove()
})
test('should display the tip on top whenever scrollable viewport doesn\'t have enough room if the given placement is "auto bottom"', function () {
var styles = '<style>'
+ '#scrollable-div { height: 200px; overflow: auto; }'
+ '.tooltip-item { margin-top: 400px; width: 150px; }'
+ '</style>'
var $styles = $(styles).appendTo('head')
var $container = $('<div id="scrollable-div"/>').appendTo('#qunit-fixture')
var $target = $('<div rel="tooltip" title="tip" class="tooltip-item">Tooltip Item</div>')
.appendTo($container)
.bootstrapTooltip({
placement: 'bottom auto',
viewport: '#scrollable-div'
})
$('#scrollable-div').scrollTop(400)
$target.bootstrapTooltip('show')
ok($('.tooltip').is('.fade.top.in'), 'has correct classes applied')
$target.bootstrapTooltip('hide')
equal($('.tooltip').length, 0, 'tooltip removed from dom')
$styles.remove()
})
test('should adjust the tip\'s top position when up against the top of the viewport', function () {
var styles = '<style>'
+ '.tooltip .tooltip-inner { width: 200px; height: 200px; max-width: none; }'
@ -609,7 +798,7 @@ $(function () {
}, 0)
})
test('should show tooltip if leave event hasn\'t occured before delay expires', function () {
test('should show tooltip if leave event hasn\'t occurred before delay expires', function () {
stop()
var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>')
@ -777,6 +966,47 @@ $(function () {
$circle.bootstrapTooltip('show')
})
test('should correctly determine auto placement based on container rather than parent', function () {
stop()
var styles = '<style>'
+ '.tooltip, .tooltip *, .tooltip *:before, .tooltip *:after { box-sizing: border-box; }'
+ '.tooltip { position: absolute; display: block; font-size: 12px; line-height: 1.4; }'
+ '.tooltip .tooltip-inner { max-width: 200px; padding: 3px 8px; font-family: Helvetica; text-align: center; }'
+ '#trigger-parent {'
+ ' position: fixed;'
+ ' top: 100px;'
+ ' right: 17px;'
+ '}'
+ '</style>'
var $styles = $(styles).appendTo('head')
$('#qunit-fixture').append('<span id="trigger-parent"><a id="tt-trigger" title="If a_larger_text is written here, it won\'t fit using older broken version of BS">HOVER OVER ME</a></span>')
var $trigger = $('#tt-trigger')
$trigger
.on('shown.bs.tooltip', function () {
var $tip = $('.tooltip-inner')
var tipXrightEdge = $tip.offset().left + $tip.width()
var triggerXleftEdge = $trigger.offset().left
ok(tipXrightEdge < triggerXleftEdge, 'tooltip with auto left placement, when near the right edge of the viewport, gets left placement')
$trigger.bootstrapTooltip('hide')
})
.on('hidden.bs.tooltip', function () {
$styles.remove()
$(this).remove()
equal($('.tooltip').length, 0, 'tooltip removed from dom')
start()
})
.bootstrapTooltip({
container: 'body',
placement: 'auto left',
trigger: 'manual'
})
$trigger.bootstrapTooltip('show')
})
test('should not reload the tooltip on subsequent mouseenter events', function () {
var titleHtml = function () {
var uid = $.fn.bootstrapTooltip.Constructor.prototype.getUID('tooltip')
@ -859,6 +1089,7 @@ $(function () {
.on('hidden.bs.tooltip', function () {
$styles.remove()
$(this).remove()
equal($('.tooltip').length, 0, 'tooltip removed from dom')
start()
})
.bootstrapTooltip({
@ -869,4 +1100,42 @@ $(function () {
.bootstrapTooltip('show')
})
test('should correctly position tooltips on transformed elements', function () {
var styleProps = document.documentElement.style
if (!('transform' in styleProps) && !('webkitTransform' in styleProps) && !('msTransform' in styleProps)) {
expect(0)
return
}
stop()
var styles = '<style>'
+ '#qunit-fixture { top: 0; left: 0; }'
+ '.tooltip, .tooltip *, .tooltip *:before, .tooltip *:after { box-sizing: border-box; }'
+ '.tooltip { position: absolute; }'
+ '.tooltip .tooltip-inner { width: 24px; height: 24px; font-family: Helvetica; }'
+ '#target { position: absolute; top: 100px; left: 50px; width: 100px; height: 200px; -webkit-transform: rotate(270deg); -ms-transform: rotate(270deg); transform: rotate(270deg); }'
+ '</style>'
var $styles = $(styles).appendTo('head')
var $element = $('<div id="target" title="1"/>').appendTo('#qunit-fixture')
$element
.on('shown.bs.tooltip', function () {
var offset = $('.tooltip').offset()
$styles.remove()
ok(Math.abs(offset.left - 88) <= 1, 'tooltip has correct horizontal location')
ok(Math.abs(offset.top - 126) <= 1, 'tooltip has correct vertical location')
$element.bootstrapTooltip('hide')
start()
})
.bootstrapTooltip({
container: 'body',
placement: 'top',
trigger: 'manual'
})
$element.bootstrapTooltip('show')
})
})

View File

@ -28,21 +28,21 @@
<li class="dropdown">
<a id="drop1" href="#" role="button" class="dropdown-toggle" data-toggle="dropdown">Dropdown <b class="caret"></b></a>
<ul class="dropdown-menu" role="menu" aria-labelledby="drop1">
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Another action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Something else here</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Another action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Something else here</a></li>
<li role="presentation" class="divider"></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Separated link</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Separated link</a></li>
</ul>
</li>
<li class="dropdown">
<a href="#" id="drop2" role="button" class="dropdown-toggle" data-toggle="dropdown">Dropdown 2 <b class="caret"></b></a>
<ul class="dropdown-menu" role="menu" aria-labelledby="drop2">
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Another action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Something else here</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Another action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Something else here</a></li>
<li role="presentation" class="divider"></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Separated link</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Separated link</a></li>
</ul>
</li>
</ul>
@ -50,11 +50,11 @@
<li id="fat-menu" class="dropdown">
<a href="#" id="drop3" role="button" class="dropdown-toggle" data-toggle="dropdown">Dropdown 3 <b class="caret"></b></a>
<ul class="dropdown-menu" role="menu" aria-labelledby="drop3">
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Another action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Something else here</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Another action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Something else here</a></li>
<li role="presentation" class="divider"></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Separated link</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Separated link</a></li>
</ul>
</li>
</ul>
@ -67,21 +67,21 @@
<li class="dropdown">
<a id="drop4" role="button" data-toggle="dropdown" href="#">Dropdown <b class="caret"></b></a>
<ul id="menu1" class="dropdown-menu" role="menu" aria-labelledby="drop4">
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Another action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Something else here</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Another action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Something else here</a></li>
<li role="presentation" class="divider"></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Separated link</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Separated link</a></li>
</ul>
</li>
<li class="dropdown">
<a id="drop5" role="button" data-toggle="dropdown" href="#">Dropdown 2 <b class="caret"></b></a>
<ul id="menu2" class="dropdown-menu" role="menu" aria-labelledby="drop5">
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Another action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Something else here</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Another action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Something else here</a></li>
<li role="presentation" class="divider"></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Separated link</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Separated link</a></li>
</ul>
</li>
</ul>
@ -92,6 +92,7 @@
<script src="../vendor/jquery.min.js"></script>
<script src="../../transition.js"></script>
<script src="../../dropdown.js"></script>
<script src="../../collapse.js"></script>
</body>
</html>

View File

@ -188,13 +188,13 @@
if (autoPlace) {
var orgPlacement = placement
var $parent = this.$element.parent()
var parentDim = this.getPosition($parent)
var $container = this.options.container ? $(this.options.container) : this.$element.parent()
var containerDim = this.getPosition($container)
placement = placement == 'bottom' && pos.top + pos.height + actualHeight - parentDim.scroll > parentDim.height ? 'top' :
placement == 'top' && pos.top - parentDim.scroll - actualHeight < 0 ? 'bottom' :
placement == 'right' && pos.right + actualWidth > parentDim.width ? 'left' :
placement == 'left' && pos.left - actualWidth < parentDim.left ? 'right' :
placement = placement == 'bottom' && pos.bottom + actualHeight > containerDim.bottom ? 'top' :
placement == 'top' && pos.top - actualHeight < containerDim.top ? 'bottom' :
placement == 'right' && pos.right + actualWidth > containerDim.width ? 'left' :
placement == 'left' && pos.left - actualWidth < containerDim.left ? 'right' :
placement
$tip
@ -207,8 +207,11 @@
this.applyPlacement(calculatedOffset, placement)
var complete = function () {
var prevHoverState = that.hoverState
that.$element.trigger('shown.bs.' + that.type)
that.hoverState = null
if (prevHoverState == 'out') that.leave(that)
}
$.support.transition && this.$tip.hasClass('fade') ?
@ -329,7 +332,6 @@
var el = $element[0]
var isBody = el.tagName == 'BODY'
var isSvg = window.SVGElement && el instanceof window.SVGElement
var elRect = el.getBoundingClientRect()
if (elRect.width == null) {
@ -338,10 +340,7 @@
}
var elOffset = isBody ? { top: 0, left: 0 } : $element.offset()
var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
var outerDims = isSvg ? {} : {
width: isBody ? $(window).width() : $element.outerWidth(),
height: isBody ? $(window).height() : $element.outerHeight()
}
var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
return $.extend({}, elRect, scroll, outerDims, elOffset)
}
@ -446,12 +445,18 @@
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.tooltip')
var options = typeof option == 'object' && option
var $this = $(this)
var data = $this.data('bs.tooltip')
var options = typeof option == 'object' && option
var selector = options && options.selector
if (!data && option == 'destroy') return
if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
if (selector) {
if (!data) $this.data('bs.tooltip', (data = {}))
if (!data[selector]) data[selector] = new Tooltip(this, options)
} else {
if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
}
if (typeof option == 'string') data[option]()
})
}

View File

@ -12,8 +12,9 @@
.collapse {
display: none;
visibility: hidden;
&.in { display: block; }
&.in { display: block; visibility: visible; }
tr&.in { display: table-row; }
tbody&.in { display: table-row-group; }
}
@ -23,4 +24,7 @@
height: 0;
overflow: hidden;
transition: height .35s ease;
transition-property: height, visibility;
transition-duration: .35s;
transition-timing-function: ease;
}

View File

@ -1,54 +1,45 @@
// Media objects
// Source: http://stubbornella.org/content/?p=497
// --------------------------------------------------
// Common styles
// -------------------------
// Clear the floats
.media,
.media-body {
overflow: hidden;
zoom: 1;
}
// Proper spacing between instances of .media
.media,
.media .media {
.media {
// Proper spacing between instances of .media
margin-top: 15px;
}
.media:first-child {
margin-top: 0;
&:first-child {
margin-top: 0;
}
}
// For images and videos, set to block
.media-object {
display: block;
.media-right,
.media > .pull-right {
padding-left: 10px;
}
.media-left,
.media > .pull-left {
padding-right: 10px;
}
.media-left,
.media-right,
.media-body {
display: table-cell;
vertical-align: top;
}
.media-middle {
vertical-align: middle;
}
.media-bottom {
vertical-align: bottom;
}
// Reset margins on headings for tighter default spacing
.media-heading {
margin: 0 0 5px;
margin-top: 0;
margin-bottom: 5px;
}
// Media image alignment
// -------------------------
.media {
> .pull-left {
margin-right: 10px;
}
> .pull-right {
margin-left: 10px;
}
}
// Media list variation
// -------------------------
//
// Undo default ul/ol styles
.media-list {
padding-left: 0;

View File

@ -30,10 +30,10 @@
// When fading in the modal, animate it to slide down
&.fade .modal-dialog {
transform: translate3d(0, -25%, 0);
transform: translate(0, -25%);
transform: transition .3s ease-out;
}
&.in .modal-dialog { transform: translate3d(0, 0, 0) }
&.in .modal-dialog { .translate(0, 0) }
}
.modal-open .modal {
overflow-x: hidden;
@ -51,8 +51,9 @@
.modal-content {
position: relative;
background-color: @modal-content-bg;
border: 1px solid @modal-content-fallback-border-color; //old browsers fallback (ie8 etc)
border: 1px solid @modal-content-border-color;
.border-radius(@border-radius-lg);
border-radius: @border-radius-large;
.box-shadow(0 3px 9px rgba(0,0,0,.5));
background-clip: padding-box;
// Remove focus outline from opened modal
@ -66,11 +67,10 @@
right: 0;
bottom: 0;
left: 0;
z-index: @zindex-modal-background;
background-color: @modal-backdrop-bg;
// Fade for backdrop
&.fade { opacity: 0; }
&.in { opacity: @modal-backdrop-opacity; }
&.fade { .opacity(0); }
&.in { .opacity(@modal-backdrop-opacity); }
}
// Modal header
@ -130,8 +130,8 @@
}
// Scale up the modal
.media-sm({
// Automatically set modal width for larger viewports
@media (min-width: @screen-sm-min) {
// Automatically set modal's width for larger viewports
.modal-dialog {
width: @modal-md;
margin: 30px auto;
@ -142,8 +142,8 @@
// Modal sizes
.modal-sm { width: @modal-sm; }
});
}
.media-sm({
@media (min-width: @screen-md-min) {
.modal-lg { width: @modal-lg; }
});
}

View File

@ -147,9 +147,11 @@
.tab-content {
> .tab-pane {
display: none;
visibility: hidden;
}
> .active {
display: block;
visibility: visible;
}
}

View File

@ -68,6 +68,7 @@
&.collapse {
display: block !important;
visibility: visible !important;
height: auto !important;
padding-bottom: 0; // Override default setting
overflow: visible !important;
@ -142,7 +143,6 @@
right: 0;
left: 0;
z-index: @zindex-navbar-fixed;
transform: translate3d(0, 0, 0);
// Undo the rounded corners
@media (min-width: @grid-float-breakpoint) {

View File

@ -1,4 +1,4 @@
/*! normalize.css v3.0.1 | MIT License | git.io/normalize */
/*! normalize.css v3.0.2 | MIT License | git.io/normalize */
//
// 1. Set default font family to sans-serif.
@ -25,7 +25,8 @@ body {
//
// Correct `block` display not defined for any HTML5 element in IE 8/9.
// Correct `block` display not defined for `details` or `summary` in IE 10/11 and Firefox.
// Correct `block` display not defined for `details` or `summary` in IE 10/11
// and Firefox.
// Correct `block` display not defined for `main` in IE 11.
//
@ -38,6 +39,7 @@ footer,
header,
hgroup,
main,
menu,
nav,
section,
summary {
@ -85,7 +87,7 @@ template {
//
a {
background: transparent;
background-color: transparent;
}
//

View File

@ -1,99 +1,107 @@
//
// Basic print styles
// --------------------------------------------------
// Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css
/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */
// ==========================================================================
// Print styles.
// Inlined to avoid the additional HTTP request: h5bp.com/r
// ==========================================================================
@media print {
* {
background: transparent !important;
color: #000 !important; // Black prints faster: h5bp.com/s
box-shadow: none !important;
text-shadow: none !important;
}
a,
a:visited {
text-decoration: underline;
}
a[href]:after {
content: " (" attr(href) ")";
}
abbr[title]:after {
content: " (" attr(title) ")";
}
// Don't show links that are fragment identifiers,
// or use the `javascript:` pseudo protocol
a[href^="#"]:after,
a[href^="javascript:"]:after {
content: "";
}
pre,
blockquote {
border: 1px solid #999;
page-break-inside: avoid;
}
thead {
display: table-header-group; // h5bp.com/t
}
tr,
img {
page-break-inside: avoid;
}
img {
max-width: 100% !important;
}
p,
h2,
h3 {
orphans: 3;
widows: 3;
}
h2,
h3 {
page-break-after: avoid;
}
// Chrome (OSX) fix for https://github.com/twbs/bootstrap/issues/11245
// Once fixed, we can just straight up remove this.
select {
background: #fff !important;
}
// Bootstrap components
.navbar {
display: none;
}
.btn,
.dropup > .btn {
> .caret {
border-top-color: #000 !important;
*,
*:before,
*:after {
background: transparent !important;
color: #000 !important; // Black prints faster: h5bp.com/s
box-shadow: none !important;
text-shadow: none !important;
}
}
.label {
border: 1px solid #000;
}
.table {
border-collapse: collapse !important;
a,
a:visited {
text-decoration: underline;
}
td,
th {
background-color: #fff !important;
a[href]:after {
content: " (" attr(href) ")";
}
}
.table-bordered {
th,
td {
border: 1px solid #ddd !important;
abbr[title]:after {
content: " (" attr(title) ")";
}
}
// Don't show links that are fragment identifiers,
// or use the `javascript:` pseudo protocol
a[href^="#"]:after,
a[href^="javascript:"]:after {
content: "";
}
pre,
blockquote {
border: 1px solid #999;
page-break-inside: avoid;
}
thead {
display: table-header-group; // h5bp.com/t
}
tr,
img {
page-break-inside: avoid;
}
img {
max-width: 100% !important;
}
p,
h2,
h3 {
orphans: 3;
widows: 3;
}
h2,
h3 {
page-break-after: avoid;
}
// Bootstrap specific changes start
//
// Chrome (OSX) fix for https://github.com/twbs/bootstrap/issues/11245
// Once fixed, we can just straight up remove this.
select {
background: #fff !important;
}
// Bootstrap components
.navbar {
display: none;
}
.btn,
.dropup > .btn {
> .caret {
border-top-color: #000 !important;
}
}
.label {
border: 1px solid #000;
}
.table {
border-collapse: collapse !important;
td,
th {
background-color: #fff !important;
}
}
.table-bordered {
th,
td {
border: 1px solid #ddd !important;
}
}
// Bootstrap specific changes end
}

View File

@ -51,42 +51,38 @@
border-top-left-radius: @border-radius-base;
border-bottom-left-radius: @border-radius-base;
}
.progress[value="0"]::-webkit-progress-value {
color: @gray-light;
min-width: 2rem;
background-color: transparent;
background-image: none;
}
.progress[value="100"]::-webkit-progress-value {
border-top-right-radius: @border-radius-base;
border-bottom-right-radius: @border-radius-base;
}
// Firefox styles must be entirely separate or it busts Webkit styles.
/* Commented out for now because linter.
@-moz-document url-prefix() {
.progress[value] {
background-color: #eee;
.border-radius(@border-radius-base);
.box-shadow(inset 0 .1rem .1rem rgba(0,0,0,.1));
}
.progress[value]::-moz-progress-bar {
background-color: #0074d9;
border-top-left-radius: @border-radius-base;
border-bottom-left-radius: @border-radius-base;
}
.progress[value="0"]::-moz-progress-bar {
color: @gray-light;
min-width: 2rem;
background-color: transparent;
background-image: none;
}
.progress[value="100"]::-moz-progress-bar {
border-top-right-radius: @border-radius-base;
border-bottom-right-radius: @border-radius-base;
}
}
*/
//
// Commented out for now because linter.
//
// @-moz-document url-prefix() {
// .progress[value] {
// background-color: #eee;
// .border-radius(@border-radius-base);
// .box-shadow(inset 0 .1rem .1rem rgba(0,0,0,.1));
// }
// .progress[value]::-moz-progress-bar {
// background-color: #0074d9;
// border-top-left-radius: @border-radius-base;
// border-bottom-left-radius: @border-radius-base;
// }
// .progress[value="0"]::-moz-progress-bar {
// color: @gray-light;
// min-width: 2rem;
// background-color: transparent;
// background-image: none;
// }
// .progress[value="100"]::-moz-progress-bar {
// border-top-right-radius: @border-radius-base;
// border-bottom-right-radius: @border-radius-base;
// }
// }
// IE9 hacks to accompany custom markup. We don't need to scope this via media queries, but I feel better doing it anyway.
@media screen and (~"min-width:0\0") {
.progress {

View File

@ -12,7 +12,8 @@
.embed-responsive-item,
iframe,
embed,
object {
object,
video {
position: absolute;
top: 0;
left: 0;

View File

@ -50,7 +50,7 @@ a {
&:hover,
&:focus {
color: @link-hover-color;
text-decoration: underline;
text-decoration: @link-hover-decoration;
}
&:focus {

View File

@ -170,6 +170,7 @@ table {
.table-responsive {
overflow-x: auto;
min-height: 0.01%; // Workaround for IE9 bug (see https://github.com/twbs/bootstrap/issues/14837)
@media screen and (max-width: @screen-xs-max) {
width: 100%;

View File

@ -225,12 +225,6 @@ blockquote {
}
}
// Quotes
blockquote:before,
blockquote:after {
content: "";
}
// Addresses
address {
margin-bottom: @line-height-computed;

View File

@ -34,6 +34,8 @@
@link-color: @brand-primary;
//** Link hover color set via `darken()` function.
@link-hover-color: darken(@link-color, 15%);
//** Link hover decoration.
@link-hover-decoration: underline;
//== Global settings
@ -260,8 +262,7 @@
@zindex-popover: 1060;
@zindex-tooltip: 1070;
@zindex-navbar-fixed: 1030;
@zindex-modal-background: 1040;
@zindex-modal: 1050;
@zindex-modal: 1040;
//== Media queries breakpoints
@ -606,6 +607,8 @@
@progress-bg: #f5f5f5;
//** Progress bar text color
@progress-bar-color: #fff;
//** Variable for setting rounded corners on progress bar.
@progress-border-radius: @border-radius-base;
//** Default progress bar color
@progress-bar-bg: @brand-primary;

View File

@ -27,6 +27,10 @@
&.active {
.box-shadow(inset 0 3px 5px rgba(0,0,0,.125));
}
.badge {
text-shadow: none;
}
}
// Mixin for generating new styles
@ -116,7 +120,7 @@
.navbar-nav > .open > a,
.navbar-nav > .active > a {
#gradient > .vertical(@start-color: darken(@navbar-default-bg, 5%); @end-color: darken(@navbar-default-bg, 2%));
#gradient > .vertical(@start-color: darken(@navbar-default-link-active-bg, 5%); @end-color: darken(@navbar-default-link-active-bg, 2%));
.box-shadow(inset 0 3px 9px rgba(0,0,0,.075));
}
}
@ -132,7 +136,7 @@
.navbar-nav > .open > a,
.navbar-nav > .active > a {
#gradient > .vertical(@start-color: @navbar-inverse-bg; @end-color: lighten(@navbar-inverse-bg, 2.5%));
#gradient > .vertical(@start-color: @navbar-inverse-link-active-bg; @end-color: lighten(@navbar-inverse-link-active-bg, 2.5%));
.box-shadow(inset 0 3px 9px rgba(0,0,0,.25));
}

View File

@ -18,6 +18,7 @@
},
"style": "dist/css/bootstrap.css",
"less": "less/bootstrap.less",
"main": "./dist/js/npm",
"repository": {
"type": "git",
"url": "https://github.com/twbs/bootstrap.git"
@ -31,32 +32,32 @@
},
"devDependencies": {
"btoa": "~1.1.2",
"glob": "~4.0.5",
"glob": "~4.0.6",
"grunt": "~0.4.5",
"grunt-autoprefixer": "~1.0.1",
"grunt-banner": "~0.2.3",
"grunt-contrib-clean": "~0.6.0",
"grunt-contrib-concat": "~0.5.0",
"grunt-contrib-connect": "~0.8.0",
"grunt-contrib-copy": "~0.5.0",
"grunt-contrib-copy": "~0.7.0",
"grunt-contrib-csslint": "~0.3.1",
"grunt-contrib-cssmin": "~0.10.0",
"grunt-contrib-jade": "~0.12.0",
"grunt-contrib-jade": "~0.13.0",
"grunt-contrib-jshint": "~0.10.0",
"grunt-contrib-less": "~0.11.4",
"grunt-contrib-less": "~0.12.0",
"grunt-contrib-qunit": "~0.5.2",
"grunt-contrib-uglify": "~0.5.1",
"grunt-contrib-uglify": "~0.6.0",
"grunt-contrib-watch": "~0.6.1",
"grunt-csscomb": "~3.0.0",
"grunt-exec": "~0.4.6",
"grunt-html-validation": "~0.1.18",
"grunt-jekyll": "~0.4.2",
"grunt-jscs": "~0.7.1",
"grunt-jscs": "~0.8.1",
"grunt-saucelabs": "~8.3.2",
"grunt-sed": "~0.1.1",
"load-grunt-tasks": "~0.6.0",
"load-grunt-tasks": "~1.0.0",
"markdown": "~0.5.0",
"npm-shrinkwrap": "~3.1.8",
"npm-shrinkwrap": "~4.0.0",
"time-grunt": "~1.0.0"
},
"engines": {

View File

@ -27,7 +27,25 @@ For RubyGems, the `gemdir` of the current RVM-selected Ruby is cached based on t
Travis does offer built-in caching on their paid plans, but this do-it-ourselves S3 solution is significantly cheaper since we only need caching and not Travis' other paid features.
## Setup
## Configuration
`s3_cache.py` is configured via `S3Cachefile.json`, which has the following format:
```json
{
"cache-name-here": {
"key": "path/to/file/to/SHA-256/hash/and/use/that/as/the/cache.key",
"cache": "path/to/directory/to/be/cached",
"generate": "shell-command --to run --to regenerate --the-cache $from scratch"
},
...
}
```
`s3_cache.py` will SHA-256 hash the contents of the `key` file and try to fetch a tarball from S3 using the hash as the filename.
If it's unable to fetch the tarball (either because it doesn't exist or there was a network error), it will run the `generate` command. If it was able to fetch the tarball, it will extract it to the `cache` directory.
If it had to `generate` the cache, it will later create a tarball of the `cache` directory and try to upload the tarball to S3 using the SHA-256 hash of the `key` file as the tarball's filename.
## AWS Setup
### Overview
1. Create an Amazon Web Services (AWS) account.

File diff suppressed because it is too large Load Diff