Skip to content

Commit 537b372

Browse files
committed
Manual backport of #32661
1 parent 8ec32ee commit 537b372

File tree

7 files changed

+73
-65
lines changed

7 files changed

+73
-65
lines changed

js/src/carousel.js

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ const SELECTOR_ITEM = '.carousel-item'
7777
const SELECTOR_ITEM_IMG = '.carousel-item img'
7878
const SELECTOR_NEXT_PREV = '.carousel-item-next, .carousel-item-prev'
7979
const SELECTOR_INDICATORS = '.carousel-indicators'
80+
const SELECTOR_INDICATOR = '[data-target]'
8081
const SELECTOR_DATA_SLIDE = '[data-slide], [data-slide-to]'
8182
const SELECTOR_DATA_RIDE = '[data-ride="carousel"]'
8283

@@ -390,15 +391,20 @@ class Carousel {
390391

391392
_setActiveIndicatorElement(element) {
392393
if (this._indicatorsElement) {
393-
const indicators = [].slice.call(this._indicatorsElement.querySelectorAll(SELECTOR_ACTIVE))
394-
$(indicators).removeClass(CLASS_NAME_ACTIVE)
394+
const activeIndicator = this._indicatorsElement.querySelector(SELECTOR_ACTIVE)
395+
$(activeIndicator).removeClass(CLASS_NAME_ACTIVE)
396+
$(activeIndicator).removeAttr('aria-current')
395397

396-
const nextIndicator = this._indicatorsElement.children[
397-
this._getItemIndex(element)
398-
]
398+
const indicators = this._indicatorsElement.querySelectorAll(SELECTOR_INDICATOR)
399399

400-
if (nextIndicator) {
401-
$(nextIndicator).addClass(CLASS_NAME_ACTIVE)
400+
Number.parseInt = Number.parseInt || parseInt // IE11 mini-polyfill
401+
402+
for (let i = 0; i < indicators.length; i++) {
403+
if (Number.parseInt(indicators[i].getAttribute('data-slide-to'), 10) === this._getItemIndex(element)) {
404+
$(indicators[i]).addClass(CLASS_NAME_ACTIVE)
405+
$(indicators[i]).attr('aria-current', 'true')
406+
break
407+
}
402408
}
403409
}
404410
}

js/tests/integration/index.html

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ <h1>Hello, world!</h1>
2222
Tooltip on top
2323
</button>
2424
<div id="carouselExampleCaptions" class="carousel slide mt-2" data-ride="carousel">
25-
<ol class="carousel-indicators">
26-
<li data-target="#carouselExampleCaptions" data-slide-to="0"></li>
27-
<li data-target="#carouselExampleCaptions" data-slide-to="1" class="active"></li>
28-
<li data-target="#carouselExampleCaptions" data-slide-to="2"></li>
29-
</ol>
25+
<div class="carousel-indicators">
26+
<button type="button" data-target="#carouselExampleIndicators" data-slide-to="0" aria-label="Slide 1"></button>
27+
<button type="button" data-target="#carouselExampleIndicators" data-slide-to="1" class="active" aria-current="true" aria-label="Slide 2"></button>
28+
<button type="button" data-target="#carouselExampleIndicators" data-slide-to="2" aria-label="Slide 3"></button>
29+
</div>
3030
<div class="carousel-inner">
3131
<div class="carousel-item">
3232
<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">

js/tests/unit/carousel.js

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,11 @@ $(function () {
127127
QUnit.test('should reset when slide is prevented', function (assert) {
128128
assert.expect(6)
129129
var carouselHTML = '<div id="carousel-example-generic" class="carousel slide">' +
130-
'<ol class="carousel-indicators">' +
131-
'<li data-target="#carousel-example-generic" data-slide-to="0" class="active"/>' +
132-
'<li data-target="#carousel-example-generic" data-slide-to="1"/>' +
133-
'<li data-target="#carousel-example-generic" data-slide-to="2"/>' +
134-
'</ol>' +
130+
'<div class="carousel-indicators">' +
131+
'<button data-target="#carousel-example-generic" data-slide-to="0" class="active" aria-current="true"></button>' +
132+
'<button data-target="#carousel-example-generic" data-slide-to="1"></button>' +
133+
'<button data-target="#carousel-example-generic" data-slide-to="2"></button>' +
134+
'</div>' +
135135
'<div class="carousel-inner">' +
136136
'<div class="carousel-item active">' +
137137
'<div class="carousel-caption"></div>' +
@@ -154,16 +154,16 @@ $(function () {
154154
e.preventDefault()
155155
setTimeout(function () {
156156
assert.ok($carousel.find('.carousel-item:nth-child(1)').is('.active'), 'first item still active')
157-
assert.ok($carousel.find('.carousel-indicators li:nth-child(1)').is('.active'), 'first indicator still active')
157+
assert.ok($carousel.find('.carousel-indicators button:nth-child(1)').is('.active'), 'first indicator still active')
158158
$carousel.bootstrapCarousel('next')
159159
}, 0)
160160
})
161161
.one('slid.bs.carousel', function () {
162162
setTimeout(function () {
163163
assert.ok(!$carousel.find('.carousel-item:nth-child(1)').is('.active'), 'first item still active')
164-
assert.ok(!$carousel.find('.carousel-indicators li:nth-child(1)').is('.active'), 'first indicator still active')
164+
assert.ok(!$carousel.find('.carousel-indicators button:nth-child(1)').is('.active'), 'first indicator still active')
165165
assert.ok($carousel.find('.carousel-item:nth-child(2)').is('.active'), 'second item active')
166-
assert.ok($carousel.find('.carousel-indicators li:nth-child(2)').is('.active'), 'second indicator active')
166+
assert.ok($carousel.find('.carousel-indicators button:nth-child(2)').is('.active'), 'second indicator active')
167167
done()
168168
}, 0)
169169
})
@@ -769,11 +769,11 @@ $(function () {
769769
QUnit.test('should wrap around from end to start when wrap option is true', function (assert) {
770770
assert.expect(3)
771771
var carouselHTML = '<div id="carousel-example-generic" class="carousel slide" data-wrap="true">' +
772-
'<ol class="carousel-indicators">' +
773-
'<li data-target="#carousel-example-generic" data-slide-to="0" class="active"/>' +
774-
'<li data-target="#carousel-example-generic" data-slide-to="1"/>' +
775-
'<li data-target="#carousel-example-generic" data-slide-to="2"/>' +
776-
'</ol>' +
772+
'<div class="carousel-indicators">' +
773+
'<button data-target="#carousel-example-generic" data-slide-to="0" class="active" aria-current="true"></button>' +
774+
'<button data-target="#carousel-example-generic" data-slide-to="1"></button>' +
775+
'<button data-target="#carousel-example-generic" data-slide-to="2"></button>' +
776+
'</div>' +
777777
'<div class="carousel-inner">' +
778778
'<div class="carousel-item active" id="one">' +
779779
'<div class="carousel-caption"></div>' +
@@ -816,11 +816,11 @@ $(function () {
816816
QUnit.test('should wrap around from start to end when wrap option is true', function (assert) {
817817
assert.expect(1)
818818
var carouselHTML = '<div id="carousel-example-generic" class="carousel slide" data-wrap="true">' +
819-
'<ol class="carousel-indicators">' +
820-
'<li data-target="#carousel-example-generic" data-slide-to="0" class="active"/>' +
821-
'<li data-target="#carousel-example-generic" data-slide-to="1"/>' +
822-
'<li data-target="#carousel-example-generic" data-slide-to="2"/>' +
823-
'</ol>' +
819+
'<div class="carousel-indicators">' +
820+
'<button data-target="#carousel-example-generic" data-slide-to="0" class="active" aria-current="true"></button>' +
821+
'<button data-target="#carousel-example-generic" data-slide-to="1"></button>' +
822+
'<button data-target="#carousel-example-generic" data-slide-to="2"></button>' +
823+
'</div>' +
824824
'<div class="carousel-inner">' +
825825
'<div class="carousel-item active" id="one">' +
826826
'<div class="carousel-caption"></div>' +
@@ -850,11 +850,11 @@ $(function () {
850850
QUnit.test('should stay at the end when the next method is called and wrap is false', function (assert) {
851851
assert.expect(3)
852852
var carouselHTML = '<div id="carousel-example-generic" class="carousel slide" data-wrap="false">' +
853-
'<ol class="carousel-indicators">' +
854-
'<li data-target="#carousel-example-generic" data-slide-to="0" class="active"/>' +
855-
'<li data-target="#carousel-example-generic" data-slide-to="1"/>' +
856-
'<li data-target="#carousel-example-generic" data-slide-to="2"/>' +
857-
'</ol>' +
853+
'<div class="carousel-indicators">' +
854+
'<button data-target="#carousel-example-generic" data-slide-to="0" class="active" aria-current="true"></button>' +
855+
'<button data-target="#carousel-example-generic" data-slide-to="1"></button>' +
856+
'<button data-target="#carousel-example-generic" data-slide-to="2"></button>' +
857+
'</div>' +
858858
'<div class="carousel-inner">' +
859859
'<div class="carousel-item active" id="one">' +
860860
'<div class="carousel-caption"></div>' +
@@ -898,11 +898,11 @@ $(function () {
898898
QUnit.test('should stay at the start when the prev method is called and wrap is false', function (assert) {
899899
assert.expect(1)
900900
var carouselHTML = '<div id="carousel-example-generic" class="carousel slide" data-wrap="false">' +
901-
'<ol class="carousel-indicators">' +
902-
'<li data-target="#carousel-example-generic" data-slide-to="0" class="active"/>' +
903-
'<li data-target="#carousel-example-generic" data-slide-to="1"/>' +
904-
'<li data-target="#carousel-example-generic" data-slide-to="2"/>' +
905-
'</ol>' +
901+
'<div class="carousel-indicators">' +
902+
'<button data-target="#carousel-example-generic" data-slide-to="0" class="active" aria-current="true"></button>' +
903+
'<button data-target="#carousel-example-generic" data-slide-to="1"></button>' +
904+
'<button data-target="#carousel-example-generic" data-slide-to="2"></button>' +
905+
'</div>' +
906906
'<div class="carousel-inner">' +
907907
'<div class="carousel-item active" id="one">' +
908908
'<div class="carousel-caption"></div>' +

js/tests/visual/carousel.html

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ <h1>Carousel <small>Bootstrap Visual Test</small></h1>
1818
<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>
1919

2020
<div id="carousel-example-generic" class="carousel slide" data-ride="carousel">
21-
<ol class="carousel-indicators">
22-
<li data-target="#carousel-example-generic" data-slide-to="0" class="active"></li>
23-
<li data-target="#carousel-example-generic" data-slide-to="1"></li>
24-
<li data-target="#carousel-example-generic" data-slide-to="2"></li>
25-
</ol>
21+
<div class="carousel-indicators">
22+
<button data-target="#carousel-example-generic" data-slide-to="0" class="active" aria-current="true"></button>
23+
<button data-target="#carousel-example-generic" data-slide-to="1"></button>
24+
<button data-target="#carousel-example-generic" data-slide-to="2"></button>
25+
</div>
2626
<div class="carousel-inner">
2727
<div class="carousel-item active">
2828
<img src="https://i.imgur.com/iEZgY7Y.jpg" alt="First slide">

scss/_carousel.scss

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,10 @@
137137
}
138138

139139

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

145145
.carousel-indicators {
146146
position: absolute;
@@ -150,23 +150,25 @@
150150
z-index: 15;
151151
display: flex;
152152
justify-content: center;
153-
padding-left: 0; // override <ol> default
153+
padding: 0;
154154
// Use the .carousel-control's width as margin so we don't overlay those
155155
margin-right: $carousel-control-width;
156156
margin-left: $carousel-control-width;
157157
list-style: none;
158158

159-
li {
159+
[data-bs-target] {
160160
box-sizing: content-box;
161161
flex: 0 1 auto;
162162
width: $carousel-indicator-width;
163163
height: $carousel-indicator-height;
164+
padding: 0;
164165
margin-right: $carousel-indicator-spacer;
165166
margin-left: $carousel-indicator-spacer;
166167
text-indent: -999px;
167168
cursor: pointer;
168169
background-color: $carousel-indicator-active-bg;
169170
background-clip: padding-box;
171+
border: 0;
170172
// Use transparent borders to increase the hit area by 10px on top and bottom.
171173
border-top: $carousel-indicator-hit-area-height solid transparent;
172174
border-bottom: $carousel-indicator-hit-area-height solid transparent;

site/content/docs/4.6/components/carousel.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,11 @@ You can also add the indicators to the carousel, alongside the controls, too.
8080

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

114114
{{< example >}}
115115
<div id="carouselExampleCaptions" class="carousel slide" data-ride="carousel">
116-
<ol class="carousel-indicators">
117-
<li data-target="#carouselExampleCaptions" data-slide-to="0" class="active"></li>
118-
<li data-target="#carouselExampleCaptions" data-slide-to="1"></li>
119-
<li data-target="#carouselExampleCaptions" data-slide-to="2"></li>
120-
</ol>
116+
<div class="carousel-indicators">
117+
<button type="button" data-target="#carouselExampleCaptions" data-slide-to="0" class="active" aria-current="true" aria-label="Slide 1"></button>
118+
<button type="button" data-target="#carouselExampleCaptions" data-slide-to="1" aria-label="Slide 2"></button>
119+
<button type="button" data-target="#carouselExampleCaptions" data-slide-to="2" aria-label="Slide 3"></button>
120+
</div>
121121
<div class="carousel-inner">
122122
<div class="carousel-item active">
123123
{{< placeholder width="800" height="400" class="bd-placeholder-img-lg d-block w-100" color="#555" background="#777" text="First slide" >}}

site/content/docs/4.6/examples/carousel/index.html

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@
3434
<main role="main">
3535

3636
<div id="myCarousel" class="carousel slide" data-ride="carousel">
37-
<ol class="carousel-indicators">
38-
<li data-target="#myCarousel" data-slide-to="0" class="active"></li>
39-
<li data-target="#myCarousel" data-slide-to="1"></li>
40-
<li data-target="#myCarousel" data-slide-to="2"></li>
41-
</ol>
37+
<div class="carousel-indicators">
38+
<button type="button" data-target="#myCarousel" data-slide-to="0" class="active" aria-current="true" aria-label="Slide 1"></button>
39+
<button type="button" data-target="#myCarousel" data-slide-to="1" aria-label="Slide 2"></button>
40+
<button type="button" data-target="#myCarousel" data-slide-to="2" aria-label="Slide 3"></button>
41+
</div>
4242
<div class="carousel-inner">
4343
<div class="carousel-item active">
4444
{{< placeholder width="100%" height="100%" background="#777" color="#777" text=" " title=" " >}}

0 commit comments

Comments
 (0)