Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make carousel indicators actual buttons (backport to v4) #33166

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 11 additions & 7 deletions js/src/carousel.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,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 @@ -382,15 +383,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