1
0
mirror of https://github.com/twbs/bootstrap.git synced 2025-08-10 23:54:08 +02:00

Handle disabled focused tabs with tab JavaScript plugin (#36169)

* Handle disabled tabs

* Fix after feedback

* Update js/src/tab.js

Co-authored-by: GeoSot <geo.sotis@gmail.com>

* Update js/src/tab.js

Co-authored-by: GeoSot <geo.sotis@gmail.com>

* Commit suggestions via GitHub broke the thing

* Add some unit tests

* Remove temp doc modification

* Add tests for left arrow

* Add disabled tabs in JavaScript Behavior section

* Compact 4 tests to 2 tests

* Compact 4 tests to 2 tests

* Add 'disabled' attribute for all buttons

* Change the disabled pane position only for the vertical version

* Change ids for the confusing first example in JavaScript behavior

* Use disabled attribute instead of the class for buttons in tabs

Co-authored-by: GeoSot <geo.sotis@gmail.com>
This commit is contained in:
Julien Déramond
2022-05-06 04:26:15 +02:00
committed by GitHub
parent cca801683d
commit 5d9500bdfd
4 changed files with 127 additions and 19 deletions

View File

@@ -168,8 +168,11 @@ class Tab extends BaseComponent {
event.stopPropagation()// stopPropagation/preventDefault both added to support up/down keys without scrolling the page
event.preventDefault()
const isNext = [ARROW_RIGHT_KEY, ARROW_DOWN_KEY].includes(event.key)
const nextActiveElement = getNextActiveElement(this._getChildren(), event.target, isNext, true)
Tab.getOrCreateInstance(nextActiveElement).show()
const nextActiveElement = getNextActiveElement(this._getChildren().filter(element => !isDisabled(element)), event.target, isNext, true)
if (nextActiveElement) {
Tab.getOrCreateInstance(nextActiveElement).show()
}
}
_getChildren() { // collection of inner elements

View File

@@ -548,6 +548,72 @@ describe('Tab', () => {
expect(Event.prototype.stopPropagation).toHaveBeenCalledTimes(2)
expect(Event.prototype.preventDefault).toHaveBeenCalledTimes(2)
})
it('if keydown event is right arrow and next element is disabled', () => {
fixtureEl.innerHTML = [
'<div class="nav">',
' <span id="tab1" class="nav-link" data-bs-toggle="tab"></span>',
' <span id="tab2" class="nav-link" data-bs-toggle="tab" disabled></span>',
' <span id="tab3" class="nav-link disabled" data-bs-toggle="tab"></span>',
' <span id="tab4" class="nav-link" data-bs-toggle="tab"></span>',
'</div>'
].join('')
const tabEl = fixtureEl.querySelector('#tab1')
const tabEl2 = fixtureEl.querySelector('#tab2')
const tabEl3 = fixtureEl.querySelector('#tab3')
const tabEl4 = fixtureEl.querySelector('#tab4')
const tab = new Tab(tabEl)
const tab2 = new Tab(tabEl2)
const tab3 = new Tab(tabEl3)
const tab4 = new Tab(tabEl4)
spyOn(tab, 'show').and.callThrough()
spyOn(tab2, 'show').and.callThrough()
spyOn(tab3, 'show').and.callThrough()
spyOn(tab4, 'show').and.callThrough()
const keydown = createEvent('keydown')
keydown.key = 'ArrowRight'
tabEl.dispatchEvent(keydown)
expect(tab.show).not.toHaveBeenCalled()
expect(tab2.show).not.toHaveBeenCalled()
expect(tab3.show).not.toHaveBeenCalled()
expect(tab4.show).toHaveBeenCalledTimes(1)
})
it('if keydown event is left arrow and next element is disabled', () => {
fixtureEl.innerHTML = [
'<div class="nav">',
' <span id="tab1" class="nav-link" data-bs-toggle="tab"></span>',
' <span id="tab2" class="nav-link" data-bs-toggle="tab" disabled></span>',
' <span id="tab3" class="nav-link disabled" data-bs-toggle="tab"></span>',
' <span id="tab4" class="nav-link" data-bs-toggle="tab"></span>',
'</div>'
].join('')
const tabEl = fixtureEl.querySelector('#tab1')
const tabEl2 = fixtureEl.querySelector('#tab2')
const tabEl3 = fixtureEl.querySelector('#tab3')
const tabEl4 = fixtureEl.querySelector('#tab4')
const tab = new Tab(tabEl)
const tab2 = new Tab(tabEl2)
const tab3 = new Tab(tabEl3)
const tab4 = new Tab(tabEl4)
spyOn(tab, 'show').and.callThrough()
spyOn(tab2, 'show').and.callThrough()
spyOn(tab3, 'show').and.callThrough()
spyOn(tab4, 'show').and.callThrough()
const keydown = createEvent('keydown')
keydown.key = 'ArrowLeft'
tabEl4.dispatchEvent(keydown)
expect(tab4.show).not.toHaveBeenCalled()
expect(tab3.show).not.toHaveBeenCalled()
expect(tab2.show).not.toHaveBeenCalled()
expect(tab.show).toHaveBeenCalledTimes(1)
})
})
describe('jQueryInterface', () => {