Skip to content

Commit 2108419

Browse files
committed
Fixes #13079: Scope .open class in button variant mixin to immediate children
1 parent 0dfd737 commit 2108419

13 files changed

+98
-74
lines changed

dist/css/bootstrap-rtl.css

Lines changed: 12 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/css/bootstrap-rtl.min.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/css/bootstrap.css

Lines changed: 12 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/css/bootstrap.css.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/css/bootstrap.min.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/js/bootstrap.js

Lines changed: 63 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,14 +1082,19 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
10821082
title: '',
10831083
delay: 0,
10841084
html: false,
1085-
container: false
1085+
container: false,
1086+
viewport: {
1087+
selector: 'body',
1088+
padding: 0
1089+
}
10861090
}
10871091

10881092
Tooltip.prototype.init = function (type, element, options) {
1089-
this.enabled = true
1090-
this.type = type
1091-
this.$element = $(element)
1092-
this.options = this.getOptions(options)
1093+
this.enabled = true
1094+
this.type = type
1095+
this.$element = $(element)
1096+
this.options = this.getOptions(options)
1097+
this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
10931098

10941099
var triggers = this.options.trigger.split(' ')
10951100

@@ -1205,18 +1210,14 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
12051210
var actualHeight = $tip[0].offsetHeight
12061211

12071212
if (autoPlace) {
1208-
var $parent = this.$element.parent()
1209-
12101213
var orgPlacement = placement
1211-
var docScroll = document.documentElement.scrollTop
1212-
var parentWidth = this.options.container == 'body' ? window.innerWidth : $parent.outerWidth()
1213-
var parentHeight = this.options.container == 'body' ? window.innerHeight : $parent.outerHeight()
1214-
var parentLeft = this.options.container == 'body' ? 0 : $parent.offset().left
1215-
1216-
placement = placement == 'bottom' && pos.top + pos.height + actualHeight - docScroll > parentHeight ? 'top' :
1217-
placement == 'top' && pos.top - docScroll - actualHeight < 0 ? 'bottom' :
1218-
placement == 'right' && pos.right + actualWidth > parentWidth ? 'left' :
1219-
placement == 'left' && pos.left - actualWidth < parentLeft ? 'right' :
1214+
var $parent = this.$element.parent()
1215+
var parentDim = this.getPosition($parent)
1216+
1217+
placement = placement == 'bottom' && pos.top + pos.height + actualHeight - parentDim.scroll > parentDim.height ? 'top' :
1218+
placement == 'top' && pos.top - parentDim.scroll - actualHeight < 0 ? 'bottom' :
1219+
placement == 'right' && pos.right + actualWidth > parentDim.width ? 'left' :
1220+
placement == 'left' && pos.left - actualWidth < parentDim.left ? 'right' :
12201221
placement
12211222

12221223
$tip
@@ -1276,29 +1277,20 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
12761277
var actualHeight = $tip[0].offsetHeight
12771278

12781279
if (placement == 'top' && actualHeight != height) {
1279-
replace = true
12801280
offset.top = offset.top + height - actualHeight
12811281
}
12821282

1283-
if (/bottom|top/.test(placement)) {
1284-
var delta = 0
1285-
1286-
if (offset.left < 0) {
1287-
delta = offset.left * -2
1288-
offset.left = 0
1283+
var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
12891284

1290-
$tip.offset(offset)
1285+
if (delta.left) offset.left += delta.left
1286+
else offset.top += delta.top
12911287

1292-
actualWidth = $tip[0].offsetWidth
1293-
actualHeight = $tip[0].offsetHeight
1294-
}
1288+
var arrowDelta = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
1289+
var arrowPosition = delta.left ? 'left' : 'top'
1290+
var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight'
12951291

1296-
this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')
1297-
} else {
1298-
this.replaceArrow(actualHeight - height, actualHeight, 'top')
1299-
}
1300-
1301-
if (replace) $tip.offset(offset)
1292+
$tip.offset(offset)
1293+
this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition)
13021294
}
13031295

13041296
Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
@@ -1351,19 +1343,51 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re
13511343
return this.getTitle()
13521344
}
13531345

1354-
Tooltip.prototype.getPosition = function () {
1355-
var el = this.$element[0]
1356-
return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {
1357-
width: el.offsetWidth,
1358-
height: el.offsetHeight
1359-
}, this.$element.offset())
1346+
Tooltip.prototype.getPosition = function ($element) {
1347+
$element = $element || this.$element
1348+
var el = $element[0]
1349+
var isBody = el.tagName == 'BODY'
1350+
return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, {
1351+
scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(),
1352+
width: isBody ? $(window).width() : $element.outerWidth(),
1353+
height: isBody ? $(window).height() : $element.outerHeight()
1354+
}, isBody ? {top: 0, left: 0} : $element.offset())
13601355
}
13611356

13621357
Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
13631358
return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
13641359
placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
13651360
placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
13661361
/* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
1362+
1363+
}
1364+
1365+
Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
1366+
var delta = { top: 0, left: 0 }
1367+
if (!this.$viewport) return delta
1368+
1369+
var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
1370+
var viewportDimensions = this.getPosition(this.$viewport)
1371+
1372+
if (/right|left/.test(placement)) {
1373+
var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll
1374+
var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
1375+
if (topEdgeOffset < viewportDimensions.top) { // top overflow
1376+
delta.top = viewportDimensions.top - topEdgeOffset
1377+
} else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
1378+
delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
1379+
}
1380+
} else {
1381+
var leftEdgeOffset = pos.left - viewportPadding
1382+
var rightEdgeOffset = pos.left + viewportPadding + actualWidth
1383+
if (leftEdgeOffset < viewportDimensions.left) { // left overflow
1384+
delta.left = viewportDimensions.left - leftEdgeOffset
1385+
} else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
1386+
delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
1387+
}
1388+
}
1389+
1390+
return delta
13671391
}
13681392

13691393
Tooltip.prototype.getTitle = function () {

dist/js/bootstrap.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/assets/js/customize.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/dist/css/bootstrap-rtl.min.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/dist/css/bootstrap.css.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/dist/css/bootstrap.min.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/dist/js/bootstrap.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

less/mixins/buttons.less

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@
1212
&:focus,
1313
&:active,
1414
&.active,
15-
.open .dropdown-toggle& {
15+
.open > .dropdown-toggle& {
1616
color: @color;
1717
background-color: darken(@background, 10%);
1818
border-color: darken(@border, 12%);
1919
}
2020
&:active,
2121
&.active,
22-
.open .dropdown-toggle& {
22+
.open > .dropdown-toggle& {
2323
background-image: none;
2424
}
2525
&.disabled,

0 commit comments

Comments
 (0)