diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2023-08-06 07:58:36 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2023-08-06 07:58:36 +0000 |
commit | 548342184e2173d6f39aba2462196ff8b397db8f (patch) | |
tree | 995bd2844c5f4e453bdd21d27ff0417af1c910c5 /js | |
parent | Adding upstream version 5.3.0+dfsg. (diff) | |
download | bootstrap-html-548342184e2173d6f39aba2462196ff8b397db8f.tar.xz bootstrap-html-548342184e2173d6f39aba2462196ff8b397db8f.zip |
Adding upstream version 5.3.1+dfsg.upstream/5.3.1+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js')
-rw-r--r-- | js/src/base-component.js | 2 | ||||
-rw-r--r-- | js/src/tab.js | 16 | ||||
-rw-r--r-- | js/tests/unit/tab.spec.js | 112 | ||||
-rw-r--r-- | js/tests/visual/tab.html | 4 |
4 files changed, 128 insertions, 6 deletions
diff --git a/js/src/base-component.js b/js/src/base-component.js index d13c7ab..19a09ad 100644 --- a/js/src/base-component.js +++ b/js/src/base-component.js @@ -14,7 +14,7 @@ import { executeAfterTransition, getElement } from './util/index.js' * Constants */ -const VERSION = '5.3.0' +const VERSION = '5.3.1' /** * Class definition diff --git a/js/src/tab.js b/js/src/tab.js index d9993d5..5598e15 100644 --- a/js/src/tab.js +++ b/js/src/tab.js @@ -30,6 +30,8 @@ const ARROW_LEFT_KEY = 'ArrowLeft' const ARROW_RIGHT_KEY = 'ArrowRight' const ARROW_UP_KEY = 'ArrowUp' const ARROW_DOWN_KEY = 'ArrowDown' +const HOME_KEY = 'Home' +const END_KEY = 'End' const CLASS_NAME_ACTIVE = 'active' const CLASS_NAME_FADE = 'fade' @@ -151,14 +153,22 @@ class Tab extends BaseComponent { } _keydown(event) { - if (!([ARROW_LEFT_KEY, ARROW_RIGHT_KEY, ARROW_UP_KEY, ARROW_DOWN_KEY].includes(event.key))) { + if (!([ARROW_LEFT_KEY, ARROW_RIGHT_KEY, ARROW_UP_KEY, ARROW_DOWN_KEY, HOME_KEY, END_KEY].includes(event.key))) { return } 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().filter(element => !isDisabled(element)), event.target, isNext, true) + + const children = this._getChildren().filter(element => !isDisabled(element)) + let nextActiveElement + + if ([HOME_KEY, END_KEY].includes(event.key)) { + nextActiveElement = children[event.key === HOME_KEY ? 0 : children.length - 1] + } else { + const isNext = [ARROW_RIGHT_KEY, ARROW_DOWN_KEY].includes(event.key) + nextActiveElement = getNextActiveElement(children, event.target, isNext, true) + } if (nextActiveElement) { nextActiveElement.focus({ preventScroll: true }) diff --git a/js/tests/unit/tab.spec.js b/js/tests/unit/tab.spec.js index 84690fc..007addd 100644 --- a/js/tests/unit/tab.spec.js +++ b/js/tests/unit/tab.spec.js @@ -630,6 +630,58 @@ describe('Tab', () => { expect(spyPrevent).toHaveBeenCalledTimes(2) }) + it('if keydown event is Home, handle it', () => { + 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"></span>', + ' <span id="tab3" class="nav-link" data-bs-toggle="tab"></span>', + '</div>' + ].join('') + + const tabEl1 = fixtureEl.querySelector('#tab1') + const tabEl3 = fixtureEl.querySelector('#tab3') + + const tab3 = new Tab(tabEl3) + tab3.show() + + const spyShown = jasmine.createSpy() + tabEl1.addEventListener('shown.bs.tab', spyShown) + + const keydown = createEvent('keydown') + keydown.key = 'Home' + + tabEl3.dispatchEvent(keydown) + + expect(spyShown).toHaveBeenCalled() + }) + + it('if keydown event is End, handle it', () => { + 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"></span>', + ' <span id="tab3" class="nav-link" data-bs-toggle="tab"></span>', + '</div>' + ].join('') + + const tabEl1 = fixtureEl.querySelector('#tab1') + const tabEl3 = fixtureEl.querySelector('#tab3') + + const tab1 = new Tab(tabEl1) + tab1.show() + + const spyShown = jasmine.createSpy() + tabEl3.addEventListener('shown.bs.tab', spyShown) + + const keydown = createEvent('keydown') + keydown.key = 'End' + + tabEl1.dispatchEvent(keydown) + + expect(spyShown).toHaveBeenCalled() + }) + it('if keydown event is right arrow and next element is disabled', () => { fixtureEl.innerHTML = [ '<div class="nav">', @@ -711,6 +763,66 @@ describe('Tab', () => { expect(spyFocus2).not.toHaveBeenCalled() expect(spyFocus1).toHaveBeenCalledTimes(1) }) + + it('if keydown event is Home and first element is disabled', () => { + fixtureEl.innerHTML = [ + '<div class="nav">', + ' <span id="tab1" class="nav-link disabled" data-bs-toggle="tab" disabled></span>', + ' <span id="tab2" class="nav-link" data-bs-toggle="tab"></span>', + ' <span id="tab3" class="nav-link" data-bs-toggle="tab"></span>', + '</div>' + ].join('') + + const tabEl1 = fixtureEl.querySelector('#tab1') + const tabEl2 = fixtureEl.querySelector('#tab2') + const tabEl3 = fixtureEl.querySelector('#tab3') + const tab3 = new Tab(tabEl3) + + tab3.show() + + const spyShown1 = jasmine.createSpy() + const spyShown2 = jasmine.createSpy() + tabEl1.addEventListener('shown.bs.tab', spyShown1) + tabEl2.addEventListener('shown.bs.tab', spyShown2) + + const keydown = createEvent('keydown') + keydown.key = 'Home' + + tabEl3.dispatchEvent(keydown) + + expect(spyShown1).not.toHaveBeenCalled() + expect(spyShown2).toHaveBeenCalled() + }) + + it('if keydown event is End and last 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"></span>', + ' <span id="tab3" class="nav-link" data-bs-toggle="tab" disabled></span>', + '</div>' + ].join('') + + const tabEl1 = fixtureEl.querySelector('#tab1') + const tabEl2 = fixtureEl.querySelector('#tab2') + const tabEl3 = fixtureEl.querySelector('#tab3') + const tab1 = new Tab(tabEl1) + + tab1.show() + + const spyShown2 = jasmine.createSpy() + const spyShown3 = jasmine.createSpy() + tabEl2.addEventListener('shown.bs.tab', spyShown2) + tabEl3.addEventListener('shown.bs.tab', spyShown3) + + const keydown = createEvent('keydown') + keydown.key = 'End' + + tabEl1.dispatchEvent(keydown) + + expect(spyShown3).not.toHaveBeenCalled() + expect(spyShown2).toHaveBeenCalled() + }) }) describe('jQueryInterface', () => { diff --git a/js/tests/visual/tab.html b/js/tests/visual/tab.html index 4cbc86c..a424175 100644 --- a/js/tests/visual/tab.html +++ b/js/tests/visual/tab.html @@ -161,12 +161,12 @@ <h4>Tabs with nav and using links (with fade)</h4> <nav> - <div class="nav nav-pills" id="nav-tab" role="tablist"> + <div class="nav nav-pills" id="nav-tab" role="tablist"> <a class="nav-link nav-item active" role="tab" data-bs-toggle="tab" href="#home5">Home</a> <a class="nav-link nav-item" role="tab" data-bs-toggle="tab" href="#profile5">Profile</a> <a class="nav-link nav-item" role="tab" data-bs-toggle="tab" href="#fat5">@fat</a> <a class="nav-link nav-item" role="tab" data-bs-toggle="tab" href="#mdo5">@mdo</a> - <a class="nav-link nav-item disabled" role="tab" href="#">Disabled</a> + <a class="nav-link nav-item disabled" role="tab" href="#" aria-disabled="true">Disabled</a> </div> </nav> |