Skip to content

Commit

Permalink
Manual backport of #32661
Browse files Browse the repository at this point in the history
Make carousel indicators actual buttons
  • Loading branch information
patrickhlauke authored and XhmikosR committed Oct 8, 2021
1 parent 8133c3e commit 759bc24
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 65 deletions.
18 changes: 11 additions & 7 deletions js/src/carousel.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ const SELECTOR_ITEM = '.carousel-item'
const SELECTOR_ITEM_IMG = '.carousel-item img'
const SELECTOR_NEXT_PREV = '.carousel-item-next, .carousel-item-prev'
const SELECTOR_INDICATORS = '.carousel-indicators'
const SELECTOR_INDICATOR = '[data-target]'
const SELECTOR_DATA_SLIDE = '[data-slide], [data-slide-to]'
const SELECTOR_DATA_RIDE = '[data-ride="carousel"]'

Expand Down Expand Up @@ -388,15 +389,18 @@ class Carousel {

_setActiveIndicatorElement(element) {
if (this._indicatorsElement) {
const indicators = [].slice.call(this._indicatorsElement.querySelectorAll(SELECTOR_ACTIVE))
$(indicators).removeClass(CLASS_NAME_ACTIVE)
const activeIndicator = this._indicatorsElement.querySelector(SELECTOR_ACTIVE)
$(activeIndicator).removeClass(CLASS_NAME_ACTIVE)
$(activeIndicator).removeAttr('aria-current')

const nextIndicator = this._indicatorsElement.children[
this._getItemIndex(element)
]
const indicators = this._indicatorsElement.querySelectorAll(SELECTOR_INDICATOR)

if (nextIndicator) {
$(nextIndicator).addClass(CLASS_NAME_ACTIVE)
for (let i = 0; i < indicators.length; i++) {
if (parseInt(indicators[i].getAttribute('data-slide-to'), 10) === this._getItemIndex(element)) {
$(indicators[i]).addClass(CLASS_NAME_ACTIVE)
$(indicators[i]).attr('aria-current', 'true')
break
}
}
}
}
Expand Down
10 changes: 5 additions & 5 deletions js/tests/integration/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ <h1>Hello, world!</h1>
Tooltip on top
</button>
<div id="carouselExampleCaptions" class="carousel slide mt-2" data-ride="carousel">
<ol class="carousel-indicators">
<li data-target="#carouselExampleCaptions" data-slide-to="0"></li>
<li data-target="#carouselExampleCaptions" data-slide-to="1" class="active"></li>
<li data-target="#carouselExampleCaptions" data-slide-to="2"></li>
</ol>
<div class="carousel-indicators">
<button type="button" data-target="#carouselExampleIndicators" data-slide-to="0" aria-label="Slide 1"></button>
<button type="button" data-target="#carouselExampleIndicators" data-slide-to="1" class="active" aria-current="true" aria-label="Slide 2"></button>
<button type="button" data-target="#carouselExampleIndicators" data-slide-to="2" aria-label="Slide 3"></button>
</div>
<div class="carousel-inner">
<div class="carousel-item">
<img class="d-block w-100" alt="First slide [800x400]" src="data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%22800%22%20height%3D%22400%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20800%20400%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_167a6f826cb%20text%20%7B%20fill%3A%23555%3Bfont-weight%3Anormal%3Bfont-family%3AHelvetica%2C%20monospace%3Bfont-size%3A40pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_167a6f826cb%22%3E%3Crect%20width%3D%22800%22%20height%3D%22400%22%20fill%3D%22%23777%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%22285.921875%22%20y%3D%22217.7%22%3EFirst%20slide%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E">
Expand Down
56 changes: 28 additions & 28 deletions js/tests/unit/carousel.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,11 @@ $(function () {
QUnit.test('should reset when slide is prevented', function (assert) {
assert.expect(6)
var carouselHTML = '<div id="carousel-example-generic" class="carousel slide">' +
'<ol class="carousel-indicators">' +
'<li data-target="#carousel-example-generic" data-slide-to="0" class="active"/>' +
'<li data-target="#carousel-example-generic" data-slide-to="1"/>' +
'<li data-target="#carousel-example-generic" data-slide-to="2"/>' +
'</ol>' +
'<div class="carousel-indicators">' +
'<button data-target="#carousel-example-generic" data-slide-to="0" class="active" aria-current="true"></button>' +
'<button data-target="#carousel-example-generic" data-slide-to="1"></button>' +
'<button data-target="#carousel-example-generic" data-slide-to="2"></button>' +
'</div>' +
'<div class="carousel-inner">' +
'<div class="carousel-item active">' +
'<div class="carousel-caption"></div>' +
Expand All @@ -154,16 +154,16 @@ $(function () {
e.preventDefault()
setTimeout(function () {
assert.true($carousel.find('.carousel-item:nth-child(1)').is('.active'), 'first item still active')
assert.true($carousel.find('.carousel-indicators li:nth-child(1)').is('.active'), 'first indicator still active')
assert.true($carousel.find('.carousel-indicators button:nth-child(1)').is('.active'), 'first indicator still active')
$carousel.bootstrapCarousel('next')
}, 0)
})
.one('slid.bs.carousel', function () {
setTimeout(function () {
assert.false($carousel.find('.carousel-item:nth-child(1)').is('.active'), 'first item still active')
assert.false($carousel.find('.carousel-indicators li:nth-child(1)').is('.active'), 'first indicator still active')
assert.false($carousel.find('.carousel-indicators button:nth-child(1)').is('.active'), 'first indicator still active')
assert.true($carousel.find('.carousel-item:nth-child(2)').is('.active'), 'second item active')
assert.true($carousel.find('.carousel-indicators li:nth-child(2)').is('.active'), 'second indicator active')
assert.true($carousel.find('.carousel-indicators button:nth-child(2)').is('.active'), 'second indicator active')
done()
}, 0)
})
Expand Down Expand Up @@ -769,11 +769,11 @@ $(function () {
QUnit.test('should wrap around from end to start when wrap option is true', function (assert) {
assert.expect(3)
var carouselHTML = '<div id="carousel-example-generic" class="carousel slide" data-wrap="true">' +
'<ol class="carousel-indicators">' +
'<li data-target="#carousel-example-generic" data-slide-to="0" class="active"/>' +
'<li data-target="#carousel-example-generic" data-slide-to="1"/>' +
'<li data-target="#carousel-example-generic" data-slide-to="2"/>' +
'</ol>' +
'<div class="carousel-indicators">' +
'<button data-target="#carousel-example-generic" data-slide-to="0" class="active" aria-current="true"></button>' +
'<button data-target="#carousel-example-generic" data-slide-to="1"></button>' +
'<button data-target="#carousel-example-generic" data-slide-to="2"></button>' +
'</div>' +
'<div class="carousel-inner">' +
'<div class="carousel-item active" id="one">' +
'<div class="carousel-caption"></div>' +
Expand Down Expand Up @@ -816,11 +816,11 @@ $(function () {
QUnit.test('should wrap around from start to end when wrap option is true', function (assert) {
assert.expect(1)
var carouselHTML = '<div id="carousel-example-generic" class="carousel slide" data-wrap="true">' +
'<ol class="carousel-indicators">' +
'<li data-target="#carousel-example-generic" data-slide-to="0" class="active"/>' +
'<li data-target="#carousel-example-generic" data-slide-to="1"/>' +
'<li data-target="#carousel-example-generic" data-slide-to="2"/>' +
'</ol>' +
'<div class="carousel-indicators">' +
'<button data-target="#carousel-example-generic" data-slide-to="0" class="active" aria-current="true"></button>' +
'<button data-target="#carousel-example-generic" data-slide-to="1"></button>' +
'<button data-target="#carousel-example-generic" data-slide-to="2"></button>' +
'</div>' +
'<div class="carousel-inner">' +
'<div class="carousel-item active" id="one">' +
'<div class="carousel-caption"></div>' +
Expand Down Expand Up @@ -850,11 +850,11 @@ $(function () {
QUnit.test('should stay at the end when the next method is called and wrap is false', function (assert) {
assert.expect(3)
var carouselHTML = '<div id="carousel-example-generic" class="carousel slide" data-wrap="false">' +
'<ol class="carousel-indicators">' +
'<li data-target="#carousel-example-generic" data-slide-to="0" class="active"/>' +
'<li data-target="#carousel-example-generic" data-slide-to="1"/>' +
'<li data-target="#carousel-example-generic" data-slide-to="2"/>' +
'</ol>' +
'<div class="carousel-indicators">' +
'<button data-target="#carousel-example-generic" data-slide-to="0" class="active" aria-current="true"></button>' +
'<button data-target="#carousel-example-generic" data-slide-to="1"></button>' +
'<button data-target="#carousel-example-generic" data-slide-to="2"></button>' +
'</div>' +
'<div class="carousel-inner">' +
'<div class="carousel-item active" id="one">' +
'<div class="carousel-caption"></div>' +
Expand Down Expand Up @@ -898,11 +898,11 @@ $(function () {
QUnit.test('should stay at the start when the prev method is called and wrap is false', function (assert) {
assert.expect(1)
var carouselHTML = '<div id="carousel-example-generic" class="carousel slide" data-wrap="false">' +
'<ol class="carousel-indicators">' +
'<li data-target="#carousel-example-generic" data-slide-to="0" class="active"/>' +
'<li data-target="#carousel-example-generic" data-slide-to="1"/>' +
'<li data-target="#carousel-example-generic" data-slide-to="2"/>' +
'</ol>' +
'<div class="carousel-indicators">' +
'<button data-target="#carousel-example-generic" data-slide-to="0" class="active" aria-current="true"></button>' +
'<button data-target="#carousel-example-generic" data-slide-to="1"></button>' +
'<button data-target="#carousel-example-generic" data-slide-to="2"></button>' +
'</div>' +
'<div class="carousel-inner">' +
'<div class="carousel-item active" id="one">' +
'<div class="carousel-caption"></div>' +
Expand Down
10 changes: 5 additions & 5 deletions js/tests/visual/carousel.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ <h1>Carousel <small>Bootstrap Visual Test</small></h1>
<p>The transition duration should be around 2s. Also, the carousel shouldn't slide when its window/tab is hidden. Check the console log.</p>

<div id="carousel-example-generic" class="carousel slide" data-ride="carousel">
<ol class="carousel-indicators">
<li data-target="#carousel-example-generic" data-slide-to="0" class="active"></li>
<li data-target="#carousel-example-generic" data-slide-to="1"></li>
<li data-target="#carousel-example-generic" data-slide-to="2"></li>
</ol>
<div class="carousel-indicators">
<button data-target="#carousel-example-generic" data-slide-to="0" class="active" aria-current="true"></button>
<button data-target="#carousel-example-generic" data-slide-to="1"></button>
<button data-target="#carousel-example-generic" data-slide-to="2"></button>
</div>
<div class="carousel-inner">
<div class="carousel-item active">
<img src="https://i.imgur.com/iEZgY7Y.jpg" alt="First slide">
Expand Down
13 changes: 8 additions & 5 deletions scss/_carousel.scss
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,10 @@
}


// Optional indicator pips
// Optional indicator pips/controls
//
// Add an ordered list with the following class and add a list item for each
// slide your carousel holds.
// Add an container (such as a list) with the following class and add an item (ideally a focusable control,
// like a button) with data-target for each slide your carousel holds.

.carousel-indicators {
position: absolute;
Expand All @@ -153,23 +153,26 @@
z-index: 15;
display: flex;
justify-content: center;
padding-left: 0; // override <ol> default
padding: 0;
// Use the .carousel-control's width as margin so we don't overlay those
margin-right: $carousel-control-width;
margin-bottom: 1rem;
margin-left: $carousel-control-width;
list-style: none;

li {
[data-target] {
box-sizing: content-box;
flex: 0 1 auto;
width: $carousel-indicator-width;
height: $carousel-indicator-height;
padding: 0;
margin-right: $carousel-indicator-spacer;
margin-left: $carousel-indicator-spacer;
text-indent: -999px;
cursor: pointer;
background-color: $carousel-indicator-active-bg;
background-clip: padding-box;
border: 0;
// Use transparent borders to increase the hit area by 10px on top and bottom.
border-top: $carousel-indicator-hit-area-height solid transparent;
border-bottom: $carousel-indicator-hit-area-height solid transparent;
Expand Down
20 changes: 10 additions & 10 deletions site/content/docs/4.6/components/carousel.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,11 @@ You can also add the indicators to the carousel, alongside the controls, too.

{{< example >}}
<div id="carouselExampleIndicators" class="carousel slide" data-ride="carousel">
<ol class="carousel-indicators">
<li data-target="#carouselExampleIndicators" data-slide-to="0" class="active"></li>
<li data-target="#carouselExampleIndicators" data-slide-to="1"></li>
<li data-target="#carouselExampleIndicators" data-slide-to="2"></li>
</ol>
<div class="carousel-indicators">
<button type="button" data-target="#carouselExampleIndicators" data-slide-to="0" class="active" aria-current="true" aria-label="Slide 1"></button>
<button type="button" data-target="#carouselExampleIndicators" data-slide-to="1" aria-label="Slide 2"></button>
<button type="button" data-target="#carouselExampleIndicators" data-slide-to="2" aria-label="Slide 3"></button>
</div>
<div class="carousel-inner">
<div class="carousel-item active">
{{< placeholder width="800" height="400" class="bd-placeholder-img-lg d-block w-100" color="#555" background="#777" text="First slide" >}}
Expand Down Expand Up @@ -113,11 +113,11 @@ Add captions to your slides easily with the `.carousel-caption` element within a

{{< example >}}
<div id="carouselExampleCaptions" class="carousel slide" data-ride="carousel">
<ol class="carousel-indicators">
<li data-target="#carouselExampleCaptions" data-slide-to="0" class="active"></li>
<li data-target="#carouselExampleCaptions" data-slide-to="1"></li>
<li data-target="#carouselExampleCaptions" data-slide-to="2"></li>
</ol>
<div class="carousel-indicators">
<button type="button" data-target="#carouselExampleCaptions" data-slide-to="0" class="active" aria-current="true" aria-label="Slide 1"></button>
<button type="button" data-target="#carouselExampleCaptions" data-slide-to="1" aria-label="Slide 2"></button>
<button type="button" data-target="#carouselExampleCaptions" data-slide-to="2" aria-label="Slide 3"></button>
</div>
<div class="carousel-inner">
<div class="carousel-item active">
{{< placeholder width="800" height="400" class="bd-placeholder-img-lg d-block w-100" color="#555" background="#777" text="First slide" >}}
Expand Down
10 changes: 5 additions & 5 deletions site/content/docs/4.6/examples/carousel/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@
<main role="main">

<div id="myCarousel" class="carousel slide" data-ride="carousel">
<ol class="carousel-indicators">
<li data-target="#myCarousel" data-slide-to="0" class="active"></li>
<li data-target="#myCarousel" data-slide-to="1"></li>
<li data-target="#myCarousel" data-slide-to="2"></li>
</ol>
<div class="carousel-indicators">
<button type="button" data-target="#myCarousel" data-slide-to="0" class="active" aria-current="true" aria-label="Slide 1"></button>
<button type="button" data-target="#myCarousel" data-slide-to="1" aria-label="Slide 2"></button>
<button type="button" data-target="#myCarousel" data-slide-to="2" aria-label="Slide 3"></button>
</div>
<div class="carousel-inner">
<div class="carousel-item active">
{{< placeholder width="100%" height="100%" background="#777" color="#777" text=" " title=" " >}}
Expand Down

0 comments on commit 759bc24

Please sign in to comment.