Commit 0df96d8c authored by Mark Otto's avatar Mark Otto

Merge branch 'master' into docs_dir

parents 70b8b330 a1b54580
...@@ -9,7 +9,10 @@ module.exports = function (grunt) { ...@@ -9,7 +9,10 @@ module.exports = function (grunt) {
RegExp.quote = function (string) { RegExp.quote = function (string) {
return string.replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&') return string.replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&')
} }
var fs = require('fs')
var btoa = require('btoa') var btoa = require('btoa')
// Project configuration. // Project configuration.
grunt.initConfig({ grunt.initConfig({
...@@ -284,7 +287,7 @@ module.exports = function (grunt) { ...@@ -284,7 +287,7 @@ module.exports = function (grunt) {
build: process.env.TRAVIS_JOB_ID, build: process.env.TRAVIS_JOB_ID,
concurrency: 3, concurrency: 3,
urls: ['http://127.0.0.1:3000/js/tests/index.html'], urls: ['http://127.0.0.1:3000/js/tests/index.html'],
browsers: grunt.file.readYAML('sauce_browsers.yml') browsers: grunt.file.readYAML('test-infra/sauce_browsers.yml')
} }
} }
} }
...@@ -337,8 +340,6 @@ module.exports = function (grunt) { ...@@ -337,8 +340,6 @@ module.exports = function (grunt) {
grunt.registerTask('change-version-number', ['sed']); grunt.registerTask('change-version-number', ['sed']);
grunt.registerTask('build-glyphicons-data', function () { grunt.registerTask('build-glyphicons-data', function () {
var fs = require('fs')
// Pass encoding, utf8, so `readFileSync` will return a string instead of a // Pass encoding, utf8, so `readFileSync` will return a string instead of a
// buffer // buffer
var glyphiconsFile = fs.readFileSync('less/glyphicons.less', 'utf8') var glyphiconsFile = fs.readFileSync('less/glyphicons.less', 'utf8')
...@@ -364,8 +365,6 @@ module.exports = function (grunt) { ...@@ -364,8 +365,6 @@ module.exports = function (grunt) {
// task for building customizer // task for building customizer
grunt.registerTask('build-customizer', 'Add scripts/less files to customizer.', function () { grunt.registerTask('build-customizer', 'Add scripts/less files to customizer.', function () {
var fs = require('fs')
function getFiles(type) { function getFiles(type) {
var files = {} var files = {}
fs.readdirSync(type) fs.readdirSync(type)
......
...@@ -351,7 +351,7 @@ if (typeof jQuery === "undefined") { throw new Error("Bootstrap requires jQuery" ...@@ -351,7 +351,7 @@ if (typeof jQuery === "undefined") { throw new Error("Bootstrap requires jQuery"
$next = this.$element.find('.item')[fallback]() $next = this.$element.find('.item')[fallback]()
} }
if ($next.hasClass('active')) return if ($next.hasClass('active')) return this.sliding = false
var e = $.Event('slide.bs.carousel', { relatedTarget: $next[0], direction: direction }) var e = $.Event('slide.bs.carousel', { relatedTarget: $next[0], direction: direction })
this.$element.trigger(e) this.$element.trigger(e)
...@@ -659,13 +659,14 @@ if (typeof jQuery === "undefined") { throw new Error("Bootstrap requires jQuery" ...@@ -659,13 +659,14 @@ if (typeof jQuery === "undefined") { throw new Error("Bootstrap requires jQuery"
$('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus) $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
} }
$parent.trigger(e = $.Event('show.bs.dropdown')) var relatedTarget = { relatedTarget: this }
$parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
if (e.isDefaultPrevented()) return if (e.isDefaultPrevented()) return
$parent $parent
.toggleClass('open') .toggleClass('open')
.trigger('shown.bs.dropdown') .trigger('shown.bs.dropdown', relatedTarget)
$this.focus() $this.focus()
} }
...@@ -691,7 +692,8 @@ if (typeof jQuery === "undefined") { throw new Error("Bootstrap requires jQuery" ...@@ -691,7 +692,8 @@ if (typeof jQuery === "undefined") { throw new Error("Bootstrap requires jQuery"
return $this.click() return $this.click()
} }
var $items = $('[role=menu] li:not(.divider):visible a', $parent) var desc = ' li:not(.divider):visible a'
var $items = $parent.find('[role=menu]' + desc + ', [role=listbox]' + desc)
if (!$items.length) return if (!$items.length) return
...@@ -704,14 +706,15 @@ if (typeof jQuery === "undefined") { throw new Error("Bootstrap requires jQuery" ...@@ -704,14 +706,15 @@ if (typeof jQuery === "undefined") { throw new Error("Bootstrap requires jQuery"
$items.eq(index).focus() $items.eq(index).focus()
} }
function clearMenus() { function clearMenus(e) {
$(backdrop).remove() $(backdrop).remove()
$(toggle).each(function (e) { $(toggle).each(function () {
var $parent = getParent($(this)) var $parent = getParent($(this))
var relatedTarget = { relatedTarget: this }
if (!$parent.hasClass('open')) return if (!$parent.hasClass('open')) return
$parent.trigger(e = $.Event('hide.bs.dropdown')) $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
if (e.isDefaultPrevented()) return if (e.isDefaultPrevented()) return
$parent.removeClass('open').trigger('hidden.bs.dropdown') $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
}) })
} }
...@@ -763,7 +766,7 @@ if (typeof jQuery === "undefined") { throw new Error("Bootstrap requires jQuery" ...@@ -763,7 +766,7 @@ if (typeof jQuery === "undefined") { throw new Error("Bootstrap requires jQuery"
.on('click.bs.dropdown.data-api', clearMenus) .on('click.bs.dropdown.data-api', clearMenus)
.on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
.on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle) .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
.on('keydown.bs.dropdown.data-api', toggle + ', [role=menu]', Dropdown.prototype.keydown) .on('keydown.bs.dropdown.data-api', toggle + ', [role=menu], [role=listbox]', Dropdown.prototype.keydown)
}(jQuery); }(jQuery);
...@@ -787,9 +790,13 @@ if (typeof jQuery === "undefined") { throw new Error("Bootstrap requires jQuery" ...@@ -787,9 +790,13 @@ if (typeof jQuery === "undefined") { throw new Error("Bootstrap requires jQuery"
this.$backdrop = this.$backdrop =
this.isShown = null this.isShown = null
if (this.options.remote) this.$element.find('.modal-content').load(this.options.remote, $.proxy(function () { if (this.options.remote) {
this.$element.trigger('loaded.bs.modal') this.$element
}, this)) .find('.modal-content')
.load(this.options.remote, $.proxy(function () {
this.$element.trigger('loaded.bs.modal')
}, this))
}
} }
Modal.DEFAULTS = { Modal.DEFAULTS = {
...@@ -823,7 +830,9 @@ if (typeof jQuery === "undefined") { throw new Error("Bootstrap requires jQuery" ...@@ -823,7 +830,9 @@ if (typeof jQuery === "undefined") { throw new Error("Bootstrap requires jQuery"
that.$element.appendTo(document.body) // don't move modals dom position that.$element.appendTo(document.body) // don't move modals dom position
} }
that.$element.show() that.$element
.show()
.scrollTop(0)
if (transition) { if (transition) {
that.$element[0].offsetWidth // force reflow that.$element[0].offsetWidth // force reflow
...@@ -1566,6 +1575,7 @@ if (typeof jQuery === "undefined") { throw new Error("Bootstrap requires jQuery" ...@@ -1566,6 +1575,7 @@ if (typeof jQuery === "undefined") { throw new Error("Bootstrap requires jQuery"
return ($href return ($href
&& $href.length && $href.length
&& $href.is(':visible')
&& [[ $href[offsetMethod]().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]]) || null && [[ $href[offsetMethod]().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]]) || null
}) })
.sort(function (a, b) { return a[0] - b[0] }) .sort(function (a, b) { return a[0] - b[0] })
...@@ -1588,6 +1598,10 @@ if (typeof jQuery === "undefined") { throw new Error("Bootstrap requires jQuery" ...@@ -1588,6 +1598,10 @@ if (typeof jQuery === "undefined") { throw new Error("Bootstrap requires jQuery"
return activeTarget != (i = targets.last()[0]) && this.activate(i) return activeTarget != (i = targets.last()[0]) && this.activate(i)
} }
if (activeTarget && scrollTop <= offsets[0]) {
return activeTarget != (i = targets[0]) && this.activate(i)
}
for (i = offsets.length; i--;) { for (i = offsets.length; i--;) {
activeTarget != targets[i] activeTarget != targets[i]
&& scrollTop >= offsets[i] && scrollTop >= offsets[i]
......
This diff is collapsed.
This diff is collapsed.
...@@ -401,7 +401,7 @@ lead: Customize Bootstrap's components, LESS variables, and jQuery plugins to ge ...@@ -401,7 +401,7 @@ lead: Customize Bootstrap's components, LESS variables, and jQuery plugins to ge
<input type="text" class="form-control" placeholder="Menlo, Monaco, Consolas, 'Courier New', monospace" data-var="@font-family-monospace"> <input type="text" class="form-control" placeholder="Menlo, Monaco, Consolas, 'Courier New', monospace" data-var="@font-family-monospace">
<p class="help-block">Default monospace fonts for <code>&lt;code&gt;</code> and <code>&lt;pre&gt;</code>.</p> <p class="help-block">Default monospace fonts for <code>&lt;code&gt;</code> and <code>&lt;pre&gt;</code>.</p>
<h4>Base type styes</h4> <h4>Base type styles</h4>
<label>@font-family-base</label> <label>@font-family-base</label>
<input type="text" class="form-control" placeholder="@font-family-sans-serif" data-var="@font-family-base"> <input type="text" class="form-control" placeholder="@font-family-sans-serif" data-var="@font-family-base">
<label>@font-size-base</label> <label>@font-size-base</label>
......
...@@ -872,6 +872,8 @@ if (navigator.userAgent.match(/IEMobile\/10\.0/)) { ...@@ -872,6 +872,8 @@ if (navigator.userAgent.match(/IEMobile\/10\.0/)) {
<p>Support for <code>overflow: hidden</code> on the <code>&lt;body&gt;</code> element is quite limited in iOS and Android. To that end, when you scroll past the top or bottom of a modal in either of those devices' browsers, the <code>&lt;body&gt;</code> content will begin to scroll.</p> <p>Support for <code>overflow: hidden</code> on the <code>&lt;body&gt;</code> element is quite limited in iOS and Android. To that end, when you scroll past the top or bottom of a modal in either of those devices' browsers, the <code>&lt;body&gt;</code> content will begin to scroll.</p>
<h4>Virtual keyboards</h4> <h4>Virtual keyboards</h4>
<p>Also, note that if you're using inputs in your modal or navbar, iOS has a rendering bug that doesn't update the position of fixed elements when the virtual keyboard is triggered. A few workarounds for this include transforming your elements to <code>position: absolute</code> or invoking a timer on focus to try to correct the positioning manually. This is not handled by Bootstrap, so it is up to you to decide which solution is best for your application.</p> <p>Also, note that if you're using inputs in your modal or navbar, iOS has a rendering bug that doesn't update the position of fixed elements when the virtual keyboard is triggered. A few workarounds for this include transforming your elements to <code>position: absolute</code> or invoking a timer on focus to try to correct the positioning manually. This is not handled by Bootstrap, so it is up to you to decide which solution is best for your application.</p>
<h4>Navbar Dropdowns</h4>
<p>The <code>.dropdown-backdrop</code> element isn't used on iOS in the nav because of the complexity of z-indexing. Thus, to close dropdowns in navbars, you must directly click the dropdown element (or any other element which will fire a click event in iOS).</p>
<h3 id="support-browser-zoom">Browser zooming</h3> <h3 id="support-browser-zoom">Browser zooming</h3>
<p>Page zooming inevitably presents rendering artifacts in some components, both in Bootstrap and the rest of the web. Depending on the issue, we may be able to fix it (search first and then open an issue if need be). However, we tend to ignore these as they often have no direct solution other than hacky workarounds.</p> <p>Page zooming inevitably presents rendering artifacts in some components, both in Bootstrap and the rest of the web. Depending on the issue, we may be able to fix it (search first and then open an issue if need be). However, we tend to ignore these as they often have no direct solution other than hacky workarounds.</p>
......
...@@ -569,19 +569,19 @@ $('.dropdown-toggle').dropdown() ...@@ -569,19 +569,19 @@ $('.dropdown-toggle').dropdown()
<tbody> <tbody>
<tr> <tr>
<td>show.bs.dropdown</td> <td>show.bs.dropdown</td>
<td>This event fires immediately when the show instance method is called.</td> <td>This event fires immediately when the show instance method is called. The toggling anchor element is available as the <code>relatedTarget</code> property of the event.</td>
</tr> </tr>
<tr> <tr>
<td>shown.bs.dropdown</td> <td>shown.bs.dropdown</td>
<td>This event is fired when the dropdown has been made visible to the user (will wait for CSS transitions, to complete).</td> <td>This event is fired when the dropdown has been made visible to the user (will wait for CSS transitions, to complete). The toggling anchor element is available as the <code>relatedTarget</code> property of the event.</td>
</tr> </tr>
<tr> <tr>
<td>hide.bs.dropdown</td> <td>hide.bs.dropdown</td>
<td>This event is fired immediately when the hide instance method has been called.</td> <td>This event is fired immediately when the hide instance method has been called. The toggling anchor element is available as the <code>relatedTarget</code> property of the event.</td>
</tr> </tr>
<tr> <tr>
<td>hidden.bs.dropdown</td> <td>hidden.bs.dropdown</td>
<td>This event is fired when the dropdown has finished being hidden from the user (will wait for CSS transitions, to complete).</td> <td>This event is fired when the dropdown has finished being hidden from the user (will wait for CSS transitions, to complete). The toggling anchor element is available as the <code>relatedTarget</code> property of the event.</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
......
...@@ -100,7 +100,7 @@ ...@@ -100,7 +100,7 @@
$next = this.$element.find('.item')[fallback]() $next = this.$element.find('.item')[fallback]()
} }
if ($next.hasClass('active')) return if ($next.hasClass('active')) return this.sliding = false
var e = $.Event('slide.bs.carousel', { relatedTarget: $next[0], direction: direction }) var e = $.Event('slide.bs.carousel', { relatedTarget: $next[0], direction: direction })
this.$element.trigger(e) this.$element.trigger(e)
......
...@@ -34,13 +34,14 @@ ...@@ -34,13 +34,14 @@
$('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus) $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
} }
$parent.trigger(e = $.Event('show.bs.dropdown')) var relatedTarget = { relatedTarget: this }
$parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
if (e.isDefaultPrevented()) return if (e.isDefaultPrevented()) return
$parent $parent
.toggleClass('open') .toggleClass('open')
.trigger('shown.bs.dropdown') .trigger('shown.bs.dropdown', relatedTarget)
$this.focus() $this.focus()
} }
...@@ -66,7 +67,8 @@ ...@@ -66,7 +67,8 @@
return $this.click() return $this.click()
} }
var $items = $('[role=menu] li:not(.divider):visible a', $parent) var desc = ' li:not(.divider):visible a'
var $items = $parent.find('[role=menu]' + desc + ', [role=listbox]' + desc)
if (!$items.length) return if (!$items.length) return
...@@ -79,14 +81,15 @@ ...@@ -79,14 +81,15 @@
$items.eq(index).focus() $items.eq(index).focus()
} }
function clearMenus() { function clearMenus(e) {
$(backdrop).remove() $(backdrop).remove()
$(toggle).each(function (e) { $(toggle).each(function () {
var $parent = getParent($(this)) var $parent = getParent($(this))
var relatedTarget = { relatedTarget: this }
if (!$parent.hasClass('open')) return if (!$parent.hasClass('open')) return
$parent.trigger(e = $.Event('hide.bs.dropdown')) $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
if (e.isDefaultPrevented()) return if (e.isDefaultPrevented()) return
$parent.removeClass('open').trigger('hidden.bs.dropdown') $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
}) })
} }
...@@ -138,6 +141,6 @@ ...@@ -138,6 +141,6 @@
.on('click.bs.dropdown.data-api', clearMenus) .on('click.bs.dropdown.data-api', clearMenus)
.on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
.on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle) .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
.on('keydown.bs.dropdown.data-api', toggle + ', [role=menu]', Dropdown.prototype.keydown) .on('keydown.bs.dropdown.data-api', toggle + ', [role=menu], [role=listbox]', Dropdown.prototype.keydown)
}(jQuery); }(jQuery);
...@@ -18,9 +18,13 @@ ...@@ -18,9 +18,13 @@
this.$backdrop = this.$backdrop =
this.isShown = null this.isShown = null
if (this.options.remote) this.$element.find('.modal-content').load(this.options.remote, $.proxy(function () { if (this.options.remote) {
this.$element.trigger('loaded.bs.modal') this.$element
}, this)) .find('.modal-content')
.load(this.options.remote, $.proxy(function () {
this.$element.trigger('loaded.bs.modal')
}, this))
}
} }
Modal.DEFAULTS = { Modal.DEFAULTS = {
...@@ -54,7 +58,9 @@ ...@@ -54,7 +58,9 @@
that.$element.appendTo(document.body) // don't move modals dom position that.$element.appendTo(document.body) // don't move modals dom position
} }
that.$element.show() that.$element
.show()
.scrollTop(0)
if (transition) { if (transition) {
that.$element[0].offsetWidth // force reflow that.$element[0].offsetWidth // force reflow
......
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
return ($href return ($href
&& $href.length && $href.length
&& $href.is(':visible')
&& [[ $href[offsetMethod]().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]]) || null && [[ $href[offsetMethod]().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]]) || null
}) })
.sort(function (a, b) { return a[0] - b[0] }) .sort(function (a, b) { return a[0] - b[0] })
...@@ -73,6 +74,10 @@ ...@@ -73,6 +74,10 @@
return activeTarget != (i = targets.last()[0]) && this.activate(i) return activeTarget != (i = targets.last()[0]) && this.activate(i)
} }
if (activeTarget && scrollTop <= offsets[0]) {
return activeTarget != (i = targets[0]) && this.activate(i)
}
for (i = offsets.length; i--;) { for (i = offsets.length; i--;) {
activeTarget != targets[i] activeTarget != targets[i]
&& scrollTop >= offsets[i] && scrollTop >= offsets[i]
......
...@@ -16,8 +16,7 @@ ...@@ -16,8 +16,7 @@
# { # FIXME: currently fails 1 tooltip test # { # FIXME: currently fails 1 tooltip test
# browserName: "firefox", # browserName: "firefox",
# version: "25", # platform: "OS X 10.9"
# platform: "OS X 10.6"
# }, # },
# Mac Opera not currently supported by Sauce Labs # Mac Opera not currently supported by Sauce Labs
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment