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

use only data target to query elements in our plugin

This commit is contained in:
Johann-S 2020-06-27 00:28:32 +02:00
parent 2c38800ea2
commit 686b88c505
19 changed files with 212 additions and 221 deletions

View File

@ -72,7 +72,6 @@ class Collapse {
this._element = element
this._config = this._getConfig(config)
this._triggerArray = SelectorEngine.find(
`${SELECTOR_DATA_TOGGLE}[href="#${element.id}"],` +
`${SELECTOR_DATA_TOGGLE}[data-target="#${element.id}"]`
)

View File

@ -121,7 +121,7 @@ class ScrollSpy {
targets
.map(element => {
let target
const targetSelector = getSelectorFromElement(element)
const targetSelector = this._getSelectorFromElement(element)
if (targetSelector) {
target = SelectorEngine.findOne(targetSelector)
@ -163,6 +163,18 @@ class ScrollSpy {
// Private
_getSelectorFromElement(element) {
let selector = getSelectorFromElement(element)
if (!selector) {
const hrefAttr = element.getAttribute('href')
selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : null
}
return selector
}
_getConfig(config) {
config = {
...Default,

View File

@ -33,12 +33,10 @@ const getUID = prefix => {
}
const getSelector = element => {
let selector = element.getAttribute('data-target')
const selector = element.getAttribute('data-target')
if (!selector || selector === '#') {
const hrefAttr = element.getAttribute('href')
selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : null
if (!selector) {
return null
}
return selector

View File

@ -376,7 +376,7 @@ describe('Collapse', () => {
describe('data-api', () => {
it('should show multiple collapsed elements', done => {
fixtureEl.innerHTML = [
'<a role="button" data-toggle="collapse" class="collapsed" href=".multi"></a>',
'<a href="#" role="button" data-toggle="collapse" class="collapsed" data-target=".multi"></a>',
'<div id="collapse1" class="collapse multi"></div>',
'<div id="collapse2" class="collapse multi"></div>'
].join('')
@ -398,7 +398,7 @@ describe('Collapse', () => {
it('should hide multiple collapsed elements', done => {
fixtureEl.innerHTML = [
'<a role="button" data-toggle="collapse" href=".multi"></a>',
'<a href="#" role="button" data-toggle="collapse" data-target=".multi"></a>',
'<div id="collapse1" class="collapse multi show"></div>',
'<div id="collapse2" class="collapse multi show"></div>'
].join('')
@ -466,11 +466,11 @@ describe('Collapse', () => {
fixtureEl.innerHTML = [
'<div id="accordion">',
' <div class="item">',
' <a id="linkTrigger" data-toggle="collapse" href="#collapseOne" aria-expanded="false" aria-controls="collapseOne"></a>',
' <a id="linkTrigger" href="#" data-toggle="collapse" data-target="#collapseOne" aria-expanded="false" aria-controls="collapseOne"></a>',
' <div id="collapseOne" class="collapse" role="tabpanel" aria-labelledby="headingThree" data-parent="#accordion"></div>',
' </div>',
' <div class="item">',
' <a id="linkTriggerTwo" data-toggle="collapse" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo"></a>',
' <a id="linkTriggerTwo" href="#" data-toggle="collapse" data-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo"></a>',
' <div id="collapseTwo" class="collapse show" role="tabpanel" aria-labelledby="headingTwo" data-parent="#accordion"></div>',
' </div>',
'</div>'
@ -521,13 +521,13 @@ describe('Collapse', () => {
' <div class="row">',
' <div class="col-lg-6">',
' <div class="item">',
' <a id="linkTrigger" data-toggle="collapse" href="#collapseOne" aria-expanded="false" aria-controls="collapseOne"></a>',
' <a id="linkTrigger" href="#" data-toggle="collapse" data-target="#collapseOne" aria-expanded="false" aria-controls="collapseOne"></a>',
' <div id="collapseOne" class="collapse" role="tabpanel" aria-labelledby="headingThree" data-parent="#accordion"></div>',
' </div>',
' </div>',
' <div class="col-lg-6">',
' <div class="item">',
' <a id="linkTriggerTwo" data-toggle="collapse" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo"></a>',
' <a id="linkTriggerTwo" href="#" data-toggle="collapse" data-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo"></a>',
' <div id="collapseTwo" class="collapse show" role="tabpanel" aria-labelledby="headingTwo" data-parent="#accordion"></div>',
' </div>',
' </div>',
@ -647,18 +647,18 @@ describe('Collapse', () => {
fixtureEl.innerHTML = [
'<div id="accordion">',
' <div class="item">',
' <a id="linkTrigger" data-toggle="collapse" href="#collapseOne" aria-expanded="false" aria-controls="collapseOne"></a>',
' <a id="linkTrigger" href="#" data-toggle="collapse" data-target="#collapseOne" aria-expanded="false" aria-controls="collapseOne"></a>',
' <div id="collapseOne" data-parent="#accordion" class="collapse" role="tabpanel" aria-labelledby="headingThree">',
' <div id="nestedAccordion">',
' <div class="item">',
' <a id="nestedLinkTrigger" data-toggle="collapse" href="#nestedCollapseOne" aria-expanded="false" aria-controls="nestedCollapseOne"></a>',
' <a id="nestedLinkTrigger" href="#" data-toggle="collapse" data-target="#nestedCollapseOne" aria-expanded="false" aria-controls="nestedCollapseOne"></a>',
' <div id="nestedCollapseOne" data-parent="#nestedAccordion" class="collapse" role="tabpanel" aria-labelledby="headingThree"></div>',
' </div>',
' </div>',
' </div>',
' </div>',
' <div class="item">',
' <a id="linkTriggerTwo" data-toggle="collapse" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo"></a>',
' <a id="linkTriggerTwo" href="#" data-toggle="collapse" data-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo"></a>',
' <div id="collapseTwo" data-parent="#accordion" class="collapse show" role="tabpanel" aria-labelledby="headingTwo"></div>',
' </div>',
'</div>'
@ -703,9 +703,9 @@ describe('Collapse', () => {
it('should add "collapsed" class and set aria-expanded to triggers only when all the targeted collapse are hidden', done => {
fixtureEl.innerHTML = [
'<a id="trigger1" role="button" data-toggle="collapse" href="#test1"></a>',
'<a id="trigger2" role="button" data-toggle="collapse" href="#test2"></a>',
'<a id="trigger3" role="button" data-toggle="collapse" href=".multi"></a>',
'<a id="trigger1" href="#" role="button" data-toggle="collapse" data-target="#test1"></a>',
'<a id="trigger2" href="#" role="button" data-toggle="collapse" data-target="#test2"></a>',
'<a id="trigger3" href="#" role="button" data-toggle="collapse" data-target=".multi"></a>',
'<div id="test1" class="multi"></div>',
'<div id="test2" class="multi"></div>'
].join('')

View File

@ -1086,9 +1086,9 @@ describe('Dropdown', () => {
fixtureEl.innerHTML = [
'<div class="nav">',
' <div class="dropdown" id="testmenu">',
' <a class="dropdown-toggle" data-toggle="dropdown" href="#testmenu">Test menu</a>',
' <a href="#" class="dropdown-toggle" data-toggle="dropdown" data-target="#testmenu">Test menu</a>',
' <div class="dropdown-menu">',
' <a class="dropdown-item" href="#sub1">Submenu 1</a>',
' <a href="#" class="dropdown-item" data-target="#sub1">Submenu 1</a>',
' </div>',
' </div>',
'</div>',
@ -1138,9 +1138,9 @@ describe('Dropdown', () => {
it('should remove "show" class if body if tabbing outside of menu, with multiple dropdowns', done => {
fixtureEl.innerHTML = [
'<div class="dropdown">',
' <a class="dropdown-toggle" data-toggle="dropdown" href="#testmenu">Test menu</a>',
' <a href="#" class="dropdown-toggle" data-toggle="dropdown" data-target="#testmenu">Test menu</a>',
' <div class="dropdown-menu">',
' <a class="dropdown-item" href="#sub1">Submenu 1</a>',
' <a href="#" class="dropdown-item" data-target="#sub1">Submenu 1</a>',
' </div>',
'</div>',
'<div class="btn-group">',
@ -1199,7 +1199,7 @@ describe('Dropdown', () => {
'<div class="dropdown">',
' <button class="btn dropdown-toggle" data-toggle="dropdown">Dropdown</button>',
' <div class="dropdown-menu">',
' <a class="dropdown-item" href="#sub1">Submenu 1</a>',
' <a href="#" class="dropdown-item" data-target="#sub1">Submenu 1</a>',
' </div>',
'</div>'
].join('')
@ -1231,7 +1231,7 @@ describe('Dropdown', () => {
'<div class="dropdown">',
' <button class="btn dropdown-toggle" data-toggle="dropdown">Dropdown</button>',
' <div class="dropdown-menu">',
' <a class="dropdown-item" href="#sub1">Submenu 1</a>',
' <a href="#" class="dropdown-item" data-target="#sub1">Submenu 1</a>',
' <input type="text">',
' <textarea></textarea>',
' </div>',
@ -1267,7 +1267,7 @@ describe('Dropdown', () => {
'<div class="dropdown">',
' <button class="btn dropdown-toggle" data-toggle="dropdown">Dropdown</button>',
' <div class="dropdown-menu">',
' <a class="dropdown-item disabled" href="#sub1">Submenu 1</a>',
' <a href="#" class="dropdown-item disabled" data-target="#sub1">Submenu 1</a>',
' <button class="dropdown-item" type="button" disabled>Disabled button</button>',
' <a id="item1" class="dropdown-item" href="#">Another link</a>',
' </div>',
@ -1303,8 +1303,8 @@ describe('Dropdown', () => {
' <button class="btn dropdown-toggle" data-toggle="dropdown">Dropdown</button>',
' <div class="dropdown-menu">',
' <button class="dropdown-item d-none" type="button">Hidden button by class</button>',
' <a class="dropdown-item" href="#sub1" style="display: none">Hidden link</a>',
' <a class="dropdown-item" href="#sub1" style="visibility: hidden">Hidden link</a>',
' <a href="#" class="dropdown-item" data-target="#sub1" style="display: none">Hidden link</a>',
' <a href="#" class="dropdown-item" data-target="#sub1" style="visibility: hidden">Hidden link</a>',
' <a id="item1" class="dropdown-item" href="#">Another link</a>',
' </div>',
'</div>'
@ -1454,7 +1454,7 @@ describe('Dropdown', () => {
'<div class="dropdown">',
' <button class="btn dropdown-toggle" data-toggle="dropdown">Dropdown</button>',
' <div class="dropdown-menu">',
' <a class="dropdown-item" href="#sub1">Submenu 1</a>',
' <a href="#" class="dropdown-item" data-target="#sub1">Submenu 1</a>',
' <input type="text">',
' <textarea></textarea>',
' </div>',

View File

@ -64,7 +64,7 @@ describe('ScrollSpy', () => {
expect(navEl.getAttribute('id')).not.toEqual(null)
})
it('should not process element without target', () => {
it('should not process element without target and process elements with target inside href attribute', () => {
fixtureEl.innerHTML = [
'<nav id="navigation" class="navbar">',
' <ul class="navbar-nav">',
@ -86,6 +86,28 @@ describe('ScrollSpy', () => {
expect(scrollSpy._targets.length).toEqual(2)
})
it('should process element with target in data-target', () => {
fixtureEl.innerHTML = [
'<nav id="navigation" class="navbar">',
' <ul class="navbar-nav">',
' <li class="nav-item active"><a class="nav-link" id="one-link" href="#">One</a></li>',
' <li class="nav-item"><a class="nav-link" id="two-link" href="#" data-target="#two">Two</a></li>',
' <li class="nav-item"><a class="nav-link" id="three-link" href="#" data-target="#three">Three</a></li>',
' </ul>',
'</nav>',
'<div id="content" style="height: 200px; overflow-y: auto;">',
' <div id="two" style="height: 300px;"></div>',
' <div id="three" style="height: 10px;"></div>',
'</div>'
].join('')
const scrollSpy = new ScrollSpy(fixtureEl.querySelector('#content'), {
target: '#navigation'
})
expect(scrollSpy._targets.length).toEqual(2)
})
it('should only switch "active" class on current target', done => {
fixtureEl.innerHTML = [
'<div id="root" class="active" style="display: block">',

View File

@ -24,8 +24,8 @@ describe('Tab', () => {
it('should activate element by tab id', done => {
fixtureEl.innerHTML = [
'<ul class="nav">',
' <li><a href="#home" role="tab">Home</a></li>',
' <li><a id="triggerProfile" role="tab" href="#profile">Profile</a></li>',
' <li><a href="#" data-target="#home" role="tab">Home</a></li>',
' <li><a href="#" id="triggerProfile" role="tab" data-target="#profile">Profile</a></li>',
'</ul>',
'<ul>',
' <li id="home"></li>',
@ -48,8 +48,8 @@ describe('Tab', () => {
it('should activate element by tab id in ordered list', done => {
fixtureEl.innerHTML = [
'<ol class="nav nav-pills">',
' <li><a href="#home">Home</a></li>',
' <li><a id="triggerProfile" href="#profile">Profile</a></li>',
' <li><a href="#" data-target="#home">Home</a></li>',
' <li><a href="#" id="triggerProfile" data-target="#profile">Profile</a></li>',
'</ol>',
'<ol>',
' <li id="home"></li>',
@ -71,8 +71,8 @@ describe('Tab', () => {
it('should activate element by tab id in nav list', done => {
fixtureEl.innerHTML = [
'<nav class="nav">',
' <a href="#home">Home</a>',
' <a id="triggerProfile" href="#profile">Profile</a>',
' <a href="#" data-target="#home">Home</a>',
' <a href="#" id="triggerProfile" data-target="#profile">Profile</a>',
'</nav>',
'<nav><div id="home"></div><div id="profile"></div></nav>'
].join('')
@ -91,8 +91,8 @@ describe('Tab', () => {
it('should activate element by tab id in list group', done => {
fixtureEl.innerHTML = [
'<div class="list-group">',
' <a href="#home">Home</a>',
' <a id="triggerProfile" href="#profile">Profile</a>',
' <a href="#" data-target="#home">Home</a>',
' <a href="#" id="triggerProfile" data-target="#profile">Profile</a>',
'</div>',
'<nav><div id="home"></div><div id="profile"></div></nav>'
].join('')
@ -135,8 +135,8 @@ describe('Tab', () => {
it('should not fire shown when tab is already active', done => {
fixtureEl.innerHTML = [
'<ul class="nav nav-tabs" role="tablist">',
' <li class="nav-item" role="presentation"><a href="#home" class="nav-link active" role="tab">Home</a></li>',
' <li class="nav-item" role="presentation"><a href="#profile" class="nav-link" role="tab">Profile</a></li>',
' <li class="nav-item" role="presentation"><a href="#" data-target="#home" class="nav-link active" role="tab">Home</a></li>',
' <li class="nav-item" role="presentation"><a href="#" data-target="#profile" class="nav-link" role="tab">Profile</a></li>',
'</ul>',
'<div class="tab-content">',
' <div class="tab-pane active" id="home" role="tabpanel"></div>',
@ -161,8 +161,8 @@ describe('Tab', () => {
it('should not fire shown when tab is disabled', done => {
fixtureEl.innerHTML = [
'<ul class="nav nav-tabs" role="tablist">',
' <li class="nav-item" role="presentation"><a href="#home" class="nav-link active" role="tab">Home</a></li>',
' <li class="nav-item" role="presentation"><a href="#profile" class="nav-link disabled" role="tab">Profile</a></li>',
' <li class="nav-item" role="presentation"><a href="#" data-target="#home" class="nav-link active" role="tab">Home</a></li>',
' <li class="nav-item" role="presentation"><a href="#" data-target="#profile" class="nav-link disabled" role="tab">Profile</a></li>',
'</ul>',
'<div class="tab-content">',
' <div class="tab-pane active" id="home" role="tabpanel"></div>',
@ -187,8 +187,8 @@ describe('Tab', () => {
it('show and shown events should reference correct relatedTarget', done => {
fixtureEl.innerHTML = [
'<ul class="nav nav-tabs" role="tablist">',
' <li class="nav-item" role="presentation"><a href="#home" class="nav-link active" role="tab">Home</a></li>',
' <li class="nav-item" role="presentation"><a id="triggerProfile" href="#profile" class="nav-link" role="tab">Profile</a></li>',
' <li class="nav-item" role="presentation"><a href="#" data-target="#home" class="nav-link active" role="tab">Home</a></li>',
' <li class="nav-item" role="presentation"><a href="#" id="triggerProfile" data-target="#profile" class="nav-link" role="tab">Profile</a></li>',
'</ul>',
'<div class="tab-content">',
' <div class="tab-pane active" id="home" role="tabpanel"></div>',
@ -200,11 +200,11 @@ describe('Tab', () => {
const secondTab = new Tab(secondTabTrigger)
secondTabTrigger.addEventListener('show.bs.tab', ev => {
expect(ev.relatedTarget.hash).toEqual('#home')
expect(ev.relatedTarget.getAttribute('data-target')).toEqual('#home')
})
secondTabTrigger.addEventListener('shown.bs.tab', ev => {
expect(ev.relatedTarget.hash).toEqual('#home')
expect(ev.relatedTarget.getAttribute('data-target')).toEqual('#home')
expect(secondTabTrigger.getAttribute('aria-selected')).toEqual('true')
expect(fixtureEl.querySelector('a:not(.active)').getAttribute('aria-selected')).toEqual('false')
done()
@ -216,8 +216,8 @@ describe('Tab', () => {
it('should fire hide and hidden events', done => {
fixtureEl.innerHTML = [
'<ul class="nav">',
' <li><a href="#home">Home</a></li>',
' <li><a href="#profile">Profile</a></li>',
' <li><a href="#" data-target="#home">Home</a></li>',
' <li><a href="#" data-target="#profile">Profile</a></li>',
'</ul>'
].join('')
@ -232,12 +232,12 @@ describe('Tab', () => {
triggerList[0].addEventListener('hide.bs.tab', ev => {
hideCalled = true
expect(ev.relatedTarget.hash).toEqual('#profile')
expect(ev.relatedTarget.getAttribute('data-target')).toEqual('#profile')
})
triggerList[0].addEventListener('hidden.bs.tab', ev => {
expect(hideCalled).toEqual(true)
expect(ev.relatedTarget.hash).toEqual('#profile')
expect(ev.relatedTarget.getAttribute('data-target')).toEqual('#profile')
done()
})
@ -247,8 +247,8 @@ describe('Tab', () => {
it('should not fire hidden when hide is prevented', done => {
fixtureEl.innerHTML = [
'<ul class="nav">',
' <li><a href="#home">Home</a></li>',
' <li><a href="#profile">Profile</a></li>',
' <li><a href="#" data-target="#home">Home</a></li>',
' <li><a href="#" data-target="#profile">Profile</a></li>',
'</ul>'
].join('')
@ -282,17 +282,17 @@ describe('Tab', () => {
fixtureEl.innerHTML = [
'<ul class="nav nav-tabs" role="tablist">',
' <li class="nav-item" role="presentation">',
' <a class="nav-link nav-tab" href="#profile" role="tab" data-toggle="tab">',
' <a href="#" class="nav-link nav-tab" data-target="#profile" role="tab" data-toggle="tab">',
' <button class="close"><span aria-hidden="true">&times;</span></button>',
' </a>',
' </li>',
' <li class="nav-item" role="presentation">',
' <a id="secondNav" class="nav-link nav-tab" href="#buzz" role="tab" data-toggle="tab">',
' <a href="#" id="secondNav" class="nav-link nav-tab" data-target="#buzz" role="tab" data-toggle="tab">',
' <button class="close"><span aria-hidden="true">&times;</span></button>',
' </a>',
' </li>',
' <li class="nav-item" role="presentation">',
' <a class="nav-link nav-tab" href="#references" role="tab" data-toggle="tab">',
' <a href="#" class="nav-link nav-tab" data-target="#references" role="tab" data-toggle="tab">',
' <button id="btnClose" class="close"><span aria-hidden="true">&times;</span></button>',
' </a>',
' </li>',
@ -316,7 +316,7 @@ describe('Tab', () => {
btnCloseEl.addEventListener('click', () => {
const linkEl = btnCloseEl.parentNode
const liEl = linkEl.parentNode
const tabId = linkEl.getAttribute('href')
const tabId = linkEl.getAttribute('data-target')
const tabIdEl = fixtureEl.querySelector(tabId)
liEl.parentNode.removeChild(liEl)
@ -424,8 +424,8 @@ describe('Tab', () => {
it('should create dynamically a tab', done => {
fixtureEl.innerHTML = [
'<ul class="nav nav-tabs" role="tablist">',
' <li class="nav-item" role="presentation"><a href="#home" class="nav-link active" role="tab">Home</a></li>',
' <li class="nav-item" role="presentation"><a id="triggerProfile" data-toggle="tab" href="#profile" class="nav-link" role="tab">Profile</a></li>',
' <li class="nav-item" role="presentation"><a href="#" data-target="#home" class="nav-link active" role="tab">Home</a></li>',
' <li class="nav-item" role="presentation"><a href="#" id="triggerProfile" data-toggle="tab" data-target="#profile" class="nav-link" role="tab">Profile</a></li>',
'</ul>',
'<div class="tab-content">',
' <div class="tab-pane active" id="home" role="tabpanel"></div>',
@ -447,13 +447,13 @@ describe('Tab', () => {
it('selected tab should deactivate previous selected link in dropdown', () => {
fixtureEl.innerHTML = [
'<ul class="nav nav-tabs">',
' <li class="nav-item"><a class="nav-link" href="#home" data-toggle="tab">Home</a></li>',
' <li class="nav-item"><a class="nav-link" href="#profile" data-toggle="tab">Profile</a></li>',
' <li class="nav-item"><a href="#" class="nav-link" data-target="#home" data-toggle="tab">Home</a></li>',
' <li class="nav-item"><a href="#" class="nav-link" data-target="#profile" data-toggle="tab">Profile</a></li>',
' <li class="nav-item dropdown">',
' <a class="nav-link dropdown-toggle active" data-toggle="dropdown" href="#">Dropdown</a>',
' <div class="dropdown-menu">',
' <a class="dropdown-item active" href="#dropdown1" id="dropdown1-tab" data-toggle="tab">@fat</a>',
' <a class="dropdown-item" href="#dropdown2" id="dropdown2-tab" data-toggle="tab">@mdo</a>',
' <a href="#" class="dropdown-item active" data-target="#dropdown1" id="dropdown1-tab" data-toggle="tab">@fat</a>',
' <a href="#" class="dropdown-item" data-target="#dropdown2" id="dropdown2-tab" data-toggle="tab">@mdo</a>',
' </div>',
' </li>',
'</ul>'
@ -470,15 +470,15 @@ describe('Tab', () => {
it('should handle nested tabs', done => {
fixtureEl.innerHTML = [
'<nav class="nav nav-tabs" role="tablist">',
' <a id="tab1" href="#x-tab1" class="nav-link" data-toggle="tab" role="tab" aria-controls="x-tab1">Tab 1</a>',
' <a href="#x-tab2" class="nav-link active" data-toggle="tab" role="tab" aria-controls="x-tab2" aria-selected="true">Tab 2</a>',
' <a href="#x-tab3" class="nav-link" data-toggle="tab" role="tab" aria-controls="x-tab3">Tab 3</a>',
' <a href="#" id="tab1" data-target="#x-tab1" class="nav-link" data-toggle="tab" role="tab" aria-controls="x-tab1">Tab 1</a>',
' <a href="#" data-target="#x-tab2" class="nav-link active" data-toggle="tab" role="tab" aria-controls="x-tab2" aria-selected="true">Tab 2</a>',
' <a href="#" data-target="#x-tab3" class="nav-link" data-toggle="tab" role="tab" aria-controls="x-tab3">Tab 3</a>',
'</nav>',
'<div class="tab-content">',
' <div class="tab-pane" id="x-tab1" role="tabpanel">',
' <nav class="nav nav-tabs" role="tablist">',
' <a href="#nested-tab1" class="nav-link active" data-toggle="tab" role="tab" aria-controls="x-tab1" aria-selected="true">Nested Tab 1</a>',
' <a id="tabNested2" href="#nested-tab2" class="nav-link" data-toggle="tab" role="tab" aria-controls="x-profile">Nested Tab2</a>',
' <a href="#" data-target="#nested-tab1" class="nav-link active" data-toggle="tab" role="tab" aria-controls="x-tab1" aria-selected="true">Nested Tab 1</a>',
' <a href="#" id="tabNested2" data-target="#nested-tab2" class="nav-link" data-toggle="tab" role="tab" aria-controls="x-profile">Nested Tab2</a>',
' </nav>',
' <div class="tab-content">',
' <div class="tab-pane active" id="nested-tab1" role="tabpanel">Nested Tab1 Content</div>',
@ -510,8 +510,8 @@ describe('Tab', () => {
it('should not remove fade class if no active pane is present', done => {
fixtureEl.innerHTML = [
'<ul class="nav nav-tabs" role="tablist">',
' <li class="nav-item" role="presentation"><a id="tab-home" href="#home" class="nav-link" data-toggle="tab" role="tab">Home</a></li>',
' <li class="nav-item" role="presentation"><a id="tab-profile" href="#profile" class="nav-link" data-toggle="tab" role="tab">Profile</a></li>',
' <li class="nav-item" role="presentation"><a href="#" id="tab-home" data-target="#home" class="nav-link" data-toggle="tab" role="tab">Home</a></li>',
' <li class="nav-item" role="presentation"><a href="#" id="tab-profile" data-target="#profile" class="nav-link" data-toggle="tab" role="tab">Profile</a></li>',
'</ul>',
'<div class="tab-content">',
' <div class="tab-pane fade" id="home" role="tabpanel"></div>',
@ -548,10 +548,10 @@ describe('Tab', () => {
fixtureEl.innerHTML = [
'<ul class="nav nav-tabs" role="tablist">',
' <li class="nav-item" role="presentation">',
' <a class="nav-link nav-tab" href="#home" role="tab" data-toggle="tab">Home</a>',
' <a href="#" class="nav-link nav-tab" data-target="#home" role="tab" data-toggle="tab">Home</a>',
' </li>',
' <li class="nav-item" role="presentation">',
' <a id="secondNav" class="nav-link nav-tab" href="#profile" role="tab" data-toggle="tab">Profile</a>',
' <a href="#" id="secondNav" class="nav-link nav-tab" data-target="#profile" role="tab" data-toggle="tab">Profile</a>',
' </li>',
'</ul>',
'<div class="tab-content">',
@ -574,10 +574,10 @@ describe('Tab', () => {
fixtureEl.innerHTML = [
'<ul class="nav nav-tabs" role="tablist">',
' <li class="nav-item" role="presentation">',
' <a class="nav-link nav-tab" href="#home" role="tab" data-toggle="tab">Home</a>',
' <a href="#" class="nav-link nav-tab" data-target="#home" role="tab" data-toggle="tab">Home</a>',
' </li>',
' <li class="nav-item" role="presentation">',
' <a id="secondNav" class="nav-link nav-tab" href="#profile" role="tab" data-toggle="tab">Profile</a>',
' <a href="#" id="secondNav" class="nav-link nav-tab" data-target="#profile" role="tab" data-toggle="tab">Profile</a>',
' </li>',
'</ul>',
'<div class="tab-content">',

View File

@ -35,36 +35,6 @@ describe('Util', () => {
expect(Util.getSelectorFromElement(testEl)).toEqual('.target')
})
it('should get selector from href if no data-target set', () => {
fixtureEl.innerHTML = [
'<a id="test" href=".target"></a>',
'<div class="target"></div>'
].join('')
const testEl = fixtureEl.querySelector('#test')
expect(Util.getSelectorFromElement(testEl)).toEqual('.target')
})
it('should get selector from href if data-target equal to #', () => {
fixtureEl.innerHTML = [
'<a id="test" data-target="#" href=".target"></a>',
'<div class="target"></div>'
].join('')
const testEl = fixtureEl.querySelector('#test')
expect(Util.getSelectorFromElement(testEl)).toEqual('.target')
})
it('should return null if selector not found', () => {
fixtureEl.innerHTML = '<a id="test" href=".target"></a>'
const testEl = fixtureEl.querySelector('#test')
expect(Util.getSelectorFromElement(testEl)).toBeNull()
})
it('should return null if no selector', () => {
fixtureEl.innerHTML = '<div></div>'
@ -86,19 +56,8 @@ describe('Util', () => {
expect(Util.getElementFromSelector(testEl)).toEqual(fixtureEl.querySelector('.target'))
})
it('should get element from href if no data-target set', () => {
fixtureEl.innerHTML = [
'<a id="test" href=".target"></a>',
'<div class="target"></div>'
].join('')
const testEl = fixtureEl.querySelector('#test')
expect(Util.getElementFromSelector(testEl)).toEqual(fixtureEl.querySelector('.target'))
})
it('should return null if element not found', () => {
fixtureEl.innerHTML = '<a id="test" href=".target"></a>'
fixtureEl.innerHTML = '<a id="test" data-target=".target"></a>'
const testEl = fixtureEl.querySelector('#test')

View File

@ -34,11 +34,11 @@
<img src="https://i.imgur.com/Nm7xoti.jpg" alt="Third slide">
</div>
</div>
<a class="carousel-control-prev" href="#carousel-example-generic" role="button" data-slide="prev">
<a href="#" class="carousel-control-prev" data-target="#carousel-example-generic" role="button" data-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="carousel-control-next" href="#carousel-example-generic" role="button" data-slide="next">
<a href="#" class="carousel-control-next" data-target="#carousel-example-generic" role="button" data-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>

View File

@ -14,7 +14,7 @@
<div class="card" role="presentation">
<div class="card-header" role="tab" id="headingOne">
<h5 class="mb-0">
<a data-toggle="collapse" href="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
<a href="#" data-toggle="collapse" data-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
Collapsible Group Item #1
</a>
</h5>
@ -29,7 +29,7 @@
<div class="card" role="presentation">
<div class="card-header" role="tab" id="headingTwo">
<h5 class="mb-0">
<a class="collapsed" data-toggle="collapse" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
<a href="#" class="collapsed" data-toggle="collapse" data-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
Collapsible Group Item #2
</a>
</h5>
@ -43,7 +43,7 @@
<div class="card" role="presentation">
<div class="card-header" role="tab" id="headingThree">
<h5 class="mb-0">
<a class="collapsed" data-toggle="collapse" href="#collapseThree" aria-expanded="false" aria-controls="collapseThree">
<a href="#" class="collapsed" data-toggle="collapse" data-target="#collapseThree" aria-expanded="false" aria-controls="collapseThree">
Collapsible Group Item #3
</a>
</h5>
@ -57,7 +57,7 @@
<div class="card" role="presentation">
<div class="card-header" role="tab" id="headingFour">
<h5 class="mb-0">
<a class="collapsed" data-toggle="collapse" href="#collapseFour" aria-expanded="false" aria-controls="collapseFour">
<a href="#" class="collapsed" data-toggle="collapse" data-target="#collapseFour" aria-expanded="false" aria-controls="collapseFour">
Collapsible Group Item with XSS in data-parent
</a>
</h5>

View File

@ -58,7 +58,7 @@
<div class="card" role="presentation">
<div class="card-header" role="tab" id="headingOne">
<h5 class="mb-0">
<a data-toggle="collapse" href="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
<a href="#" data-toggle="collapse" data-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
Collapsible Group Item #1
</a>
</h5>
@ -73,7 +73,7 @@
<div class="card" role="presentation">
<div class="card-header" role="tab" id="headingTwo">
<h5 class="mb-0">
<a class="collapsed" data-toggle="collapse" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
<a href="#" class="collapsed" data-toggle="collapse" data-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
Collapsible Group Item #2
</a>
</h5>
@ -87,7 +87,7 @@
<div class="card" role="presentation">
<div class="card-header" role="tab" id="headingThree">
<h5 class="mb-0">
<a class="collapsed" data-toggle="collapse" href="#collapseThree" aria-expanded="false" aria-controls="collapseThree">
<a href="#" class="collapsed" data-toggle="collapse" data-target="#collapseThree" aria-expanded="false" aria-controls="collapseThree">
Collapsible Group Item #3
</a>
</h5>

View File

@ -19,16 +19,16 @@
<ul class="nav nav-tabs" role="tablist">
<li class="nav-item" role="presentation">
<a class="nav-link active" data-toggle="tab" href="#home" role="tab">Home</a>
<a href="#" class="nav-link active" data-toggle="tab" data-target="#home" role="tab">Home</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" data-toggle="tab" href="#profile" role="tab">Profile</a>
<a href="#" class="nav-link" data-toggle="tab" data-target="#profile" role="tab">Profile</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" data-toggle="tab" href="#fat" role="tab">@fat</a>
<a href="#" class="nav-link" data-toggle="tab" data-target="#fat" role="tab">@fat</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" data-toggle="tab" href="#mdo" role="tab">@mdo</a>
<a href="#" class="nav-link" data-toggle="tab" data-target="#mdo" role="tab">@mdo</a>
</li>
</ul>
@ -55,16 +55,16 @@
<ul class="nav nav-tabs" role="tablist">
<li class="nav-item" role="presentation">
<a class="nav-link active" data-toggle="tab" href="#home2" role="tab">Home</a>
<a href="#" class="nav-link active" data-toggle="tab" data-target="#home2" role="tab">Home</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" data-toggle="tab" href="#profile2" role="tab">Profile</a>
<a href="#" class="nav-link" data-toggle="tab" data-target="#profile2" role="tab">Profile</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" data-toggle="tab" href="#fat2" role="tab">@fat</a>
<a href="#" class="nav-link" data-toggle="tab" data-target="#fat2" role="tab">@fat</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" data-toggle="tab" href="#mdo2" role="tab">@mdo</a>
<a href="#" class="nav-link" data-toggle="tab" data-target="#mdo2" role="tab">@mdo</a>
</li>
</ul>
@ -91,16 +91,16 @@
<ul class="nav nav-tabs" role="tablist">
<li class="nav-item" role="presentation">
<a class="nav-link" data-toggle="tab" href="#home3" role="tab">Home</a>
<a href="#" class="nav-link" data-toggle="tab" data-target="#home3" role="tab">Home</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" data-toggle="tab" href="#profile3" role="tab">Profile</a>
<a href="#" class="nav-link" data-toggle="tab" data-target="#profile3" role="tab">Profile</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" data-toggle="tab" href="#fat3" role="tab">@fat</a>
<a class="nav-link" data-toggle="tab" data-target="#fat3" role="tab">@fat</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" data-toggle="tab" href="#mdo3" role="tab">@mdo</a>
<a href="#" class="nav-link" data-toggle="tab" data-target="#mdo3" role="tab">@mdo</a>
</li>
</ul>
@ -127,16 +127,16 @@
<ul class="nav nav-tabs" role="tablist">
<li class="nav-item" role="presentation">
<a class="nav-link" data-toggle="tab" href="#home4" role="tab">Home</a>
<a href="#" class="nav-link" data-toggle="tab" data-target="#home4" role="tab">Home</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" data-toggle="tab" href="#profile4" role="tab">Profile</a>
<a href="#" class="nav-link" data-toggle="tab" data-target="#profile4" role="tab">Profile</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" data-toggle="tab" href="#fat4" role="tab">@fat</a>
<a href="#" class="nav-link" data-toggle="tab" data-target="#fat4" role="tab">@fat</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" data-toggle="tab" href="#mdo4" role="tab">@mdo</a>
<a href="#" class="nav-link" data-toggle="tab" data-target="#mdo4" role="tab">@mdo</a>
</li>
</ul>
@ -161,13 +161,13 @@
<h4>Tabs with nav (with fade)</h4>
<nav class="nav nav-pills">
<a class="nav-link nav-item active" data-toggle="tab" href="#home5">Home</a>
<a class="nav-link nav-item" data-toggle="tab" href="#profile5">Profile</a>
<a href="#" class="nav-link nav-item active" data-toggle="tab" data-target="#home5">Home</a>
<a href="#" class="nav-link nav-item" data-toggle="tab" data-target="#profile5">Profile</a>
<div class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="dropdown5" data-toggle="dropdown" aria-expanded="false">Dropdown</a>
<ul class="dropdown-menu" aria-labelledby="dropdown5">
<li><a class="dropdown-item" data-toggle="tab" href="#fat5">@fat</a></li>
<li><a class="dropdown-item" data-toggle="tab" href="#mdo5">@mdo</a></li>
<li><a href="#" class="dropdown-item" data-toggle="tab" data-target="#fat5">@fat</a></li>
<li><a href="#" class="dropdown-item" data-toggle="tab" data-target="#mdo5">@mdo</a></li>
</ul>
</div>
<a class="nav-link nav-item disabled" href="#">Disabled</a>
@ -196,10 +196,10 @@
<div class="row">
<div class="col-4">
<div class="list-group" id="list-tab" role="tablist">
<a class="list-group-item list-group-item-action active" id="list-home-list" data-toggle="tab" href="#list-home" role="tab" aria-controls="list-home">Home</a>
<a class="list-group-item list-group-item-action" id="list-profile-list" data-toggle="tab" href="#list-profile" role="tab" aria-controls="list-profile">Profile</a>
<a class="list-group-item list-group-item-action" id="list-messages-list" data-toggle="tab" href="#list-messages" role="tab" aria-controls="list-messages">Messages</a>
<a class="list-group-item list-group-item-action" id="list-settings-list" data-toggle="tab" href="#list-settings" role="tab" aria-controls="list-settings">Settings</a>
<a href="#" class="list-group-item list-group-item-action active" id="list-home-list" data-toggle="tab" data-target="#list-home" role="tab" aria-controls="list-home">Home</a>
<a href="#" class="list-group-item list-group-item-action" id="list-profile-list" data-toggle="tab" data-target="#list-profile" role="tab" aria-controls="list-profile">Profile</a>
<a href="#" class="list-group-item list-group-item-action" id="list-messages-list" data-toggle="tab" data-target="#list-messages" role="tab" aria-controls="list-messages">Messages</a>
<a href="#" class="list-group-item list-group-item-action" id="list-settings-list" data-toggle="tab" data-target="#list-settings" role="tab" aria-controls="list-settings">Settings</a>
</div>
</div>
<div class="col-8">

View File

@ -22,7 +22,7 @@ Please be aware that nested carousels are not supported, and carousels are gener
Carousels don't automatically normalize slide dimensions. As such, you may need to use additional utilities or custom styles to appropriately size content. While carousels support previous/next controls and indicators, they're not explicitly required. Add and customize as you see fit.
**The `.active` class needs to be added to one of the slides** otherwise the carousel will not be visible. Also be sure to set a unique id on the `.carousel` for optional controls, especially if you're using multiple carousels on a single page. Control and indicator elements must have a `data-target` attribute (or `href` for links) that matches the id of the `.carousel` element.
**The `.active` class needs to be added to one of the slides** otherwise the carousel will not be visible. Also be sure to set a unique id on the `.carousel` for optional controls, especially if you're using multiple carousels on a single page. Control and indicator elements must have a `data-target` attribute that matches the id of the `.carousel` element.
### Slides only
@ -61,11 +61,11 @@ Adding in the previous and next controls:
{{< placeholder width="800" height="400" class="bd-placeholder-img-lg d-block w-100" color="#333" background="#555" text="Third slide" >}}
</div>
</div>
<a class="carousel-control-prev" href="#carouselExampleControls" role="button" data-slide="prev">
<a href="#" class="carousel-control-prev" data-target="#carouselExampleControls" role="button" data-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="carousel-control-next" href="#carouselExampleControls" role="button" data-slide="next">
<a href="#" class="carousel-control-next" data-target="#carouselExampleControls" role="button" data-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
@ -94,11 +94,11 @@ You can also add the indicators to the carousel, alongside the controls, too.
{{< placeholder width="800" height="400" class="bd-placeholder-img-lg d-block w-100" color="#333" background="#555" text="Third slide" >}}
</div>
</div>
<a class="carousel-control-prev" href="#carouselExampleIndicators" role="button" data-slide="prev">
<a href="#" class="carousel-control-prev" data-target="#carouselExampleIndicators" role="button" data-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="carousel-control-next" href="#carouselExampleIndicators" role="button" data-slide="next">
<a href="#" class="carousel-control-next" data-target="#carouselExampleIndicators" role="button" data-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
@ -139,11 +139,11 @@ Add captions to your slides easily with the `.carousel-caption` element within a
</div>
</div>
</div>
<a class="carousel-control-prev" href="#carouselExampleCaptions" role="button" data-slide="prev">
<a href="#" class="carousel-control-prev" data-target="#carouselExampleCaptions" role="button" data-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="carousel-control-next" href="#carouselExampleCaptions" role="button" data-slide="next">
<a href="#" class="carousel-control-next" data-target="#carouselExampleCaptions" role="button" data-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
@ -167,11 +167,11 @@ Add `.carousel-fade` to your carousel to animate slides with a fade transition i
{{< placeholder width="800" height="400" class="bd-placeholder-img-lg d-block w-100" color="#333" background="#555" text="Third slide" >}}
</div>
</div>
<a class="carousel-control-prev" href="#carouselExampleFade" role="button" data-slide="prev">
<a href="#" class="carousel-control-prev" data-target="#carouselExampleFade" role="button" data-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="carousel-control-next" href="#carouselExampleFade" role="button" data-slide="next">
<a href="#" class="carousel-control-next" data-target="#carouselExampleFade" role="button" data-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
@ -195,11 +195,11 @@ Add `data-interval=""` to a `.carousel-item` to change the amount of time to del
{{< placeholder width="800" height="400" class="bd-placeholder-img-lg d-block w-100" color="#333" background="#555" text="Third slide" >}}
</div>
</div>
<a class="carousel-control-prev" href="#carouselExampleInterval" role="button" data-slide="prev">
<a href="#" class="carousel-control-prev" data-target="#carouselExampleInterval" role="button" data-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="carousel-control-next" href="#carouselExampleInterval" role="button" data-slide="next">
<a href="#" class="carousel-control-next" data-target="#carouselExampleInterval" role="button" data-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>

View File

@ -22,12 +22,12 @@ Click the buttons below to show and hide another element via class changes:
- `.collapsing` is applied during transitions
- `.collapse.show` shows content
You can use a link with the `href` attribute, or a button with the `data-target` attribute. In both cases, the `data-toggle="collapse"` is required.
You can use any element with the `data-target` attribute. In both cases, the `data-toggle="collapse"` is required.
{{< example >}}
<p>
<a class="btn btn-primary" data-toggle="collapse" href="#collapseExample" role="button" aria-expanded="false" aria-controls="collapseExample">
Link with href
<a href="#" class="btn btn-primary" data-toggle="collapse" data-target="#collapseExample" role="button" aria-expanded="false" aria-controls="collapseExample">
Link with data-target
</a>
<button class="btn btn-primary" type="button" data-toggle="collapse" data-target="#collapseExample" aria-expanded="false" aria-controls="collapseExample">
Button with data-target
@ -42,12 +42,12 @@ You can use a link with the `href` attribute, or a button with the `data-target`
## Multiple targets
A `<button>` or `<a>` can show and hide multiple elements by referencing them with a selector in its `href` or `data-target` attribute.
Multiple `<button>` or `<a>` can show and hide an element if they each reference it with their `href` or `data-target` attribute
Any element can show and hide multiple elements by referencing them with a selector in its `data-target` attribute.
Multiple `<button>` or `<a>` can show and hide an element if they each reference it with their `data-target` attribute
{{< example >}}
<p>
<a class="btn btn-primary" data-toggle="collapse" href="#multiCollapseExample1" role="button" aria-expanded="false" aria-controls="multiCollapseExample1">Toggle first element</a>
<a href="#" class="btn btn-primary" data-toggle="collapse" data-target="#multiCollapseExample1" role="button" aria-expanded="false" aria-controls="multiCollapseExample1">Toggle first element</a>
<button class="btn btn-primary" type="button" data-toggle="collapse" data-target="#multiCollapseExample2" aria-expanded="false" aria-controls="multiCollapseExample2">Toggle second element</button>
<button class="btn btn-primary" type="button" data-toggle="collapse" data-target=".multi-collapse" aria-expanded="false" aria-controls="multiCollapseExample1 multiCollapseExample2">Toggle both elements</button>
</p>

View File

@ -263,10 +263,10 @@ Use the tab JavaScript plugin—include it individually or through the compiled
<div class="row">
<div class="col-4">
<div class="list-group" id="list-tab" role="tablist">
<a class="list-group-item list-group-item-action active" id="list-home-list" data-toggle="tab" href="#list-home" role="tab" aria-controls="list-home">Home</a>
<a class="list-group-item list-group-item-action" id="list-profile-list" data-toggle="tab" href="#list-profile" role="tab" aria-controls="list-profile">Profile</a>
<a class="list-group-item list-group-item-action" id="list-messages-list" data-toggle="tab" href="#list-messages" role="tab" aria-controls="list-messages">Messages</a>
<a class="list-group-item list-group-item-action" id="list-settings-list" data-toggle="tab" href="#list-settings" role="tab" aria-controls="list-settings">Settings</a>
<a href="#" class="list-group-item list-group-item-action active" id="list-home-list" data-toggle="tab" data-target="#list-home" role="tab" aria-controls="list-home">Home</a>
<a href="#" class="list-group-item list-group-item-action" id="list-profile-list" data-toggle="tab" data-target="#list-profile" role="tab" aria-controls="list-profile">Profile</a>
<a href="#" class="list-group-item list-group-item-action" id="list-messages-list" data-toggle="tab" data-target="#list-messages" role="tab" aria-controls="list-messages">Messages</a>
<a href="#" class="list-group-item list-group-item-action" id="list-settings-list" data-toggle="tab" data-target="#list-settings" role="tab" aria-controls="list-settings">Settings</a>
</div>
</div>
<div class="col-8">
@ -292,10 +292,10 @@ Use the tab JavaScript plugin—include it individually or through the compiled
<div class="row">
<div class="col-4">
<div class="list-group" id="list-tab" role="tablist">
<a class="list-group-item list-group-item-action active" id="list-home-list" data-toggle="list" href="#list-home" role="tab" aria-controls="home">Home</a>
<a class="list-group-item list-group-item-action" id="list-profile-list" data-toggle="list" href="#list-profile" role="tab" aria-controls="profile">Profile</a>
<a class="list-group-item list-group-item-action" id="list-messages-list" data-toggle="list" href="#list-messages" role="tab" aria-controls="messages">Messages</a>
<a class="list-group-item list-group-item-action" id="list-settings-list" data-toggle="list" href="#list-settings" role="tab" aria-controls="settings">Settings</a>
<a href="#" class="list-group-item list-group-item-action active" id="list-home-list" data-toggle="list" data-target="#list-home" role="tab" aria-controls="home">Home</a>
<a href="#" class="list-group-item list-group-item-action" id="list-profile-list" data-toggle="list" data-target="#list-profile" role="tab" aria-controls="profile">Profile</a>
<a href="#" class="list-group-item list-group-item-action" id="list-messages-list" data-toggle="list" data-target="#list-messages" role="tab" aria-controls="messages">Messages</a>
<a href="#" class="list-group-item list-group-item-action" id="list-settings-list" data-toggle="list" data-target="#list-settings" role="tab" aria-controls="settings">Settings</a>
</div>
</div>
<div class="col-8">
@ -317,10 +317,10 @@ You can activate a list group navigation without writing any JavaScript by simpl
{{< highlight html >}}
<!-- List group -->
<div class="list-group" id="myList" role="tablist">
<a class="list-group-item list-group-item-action active" data-toggle="list" href="#home" role="tab">Home</a>
<a class="list-group-item list-group-item-action" data-toggle="list" href="#profile" role="tab">Profile</a>
<a class="list-group-item list-group-item-action" data-toggle="list" href="#messages" role="tab">Messages</a>
<a class="list-group-item list-group-item-action" data-toggle="list" href="#settings" role="tab">Settings</a>
<a href="#" class="list-group-item list-group-item-action active" data-toggle="list" data-target="#home" role="tab">Home</a>
<a href="#" class="list-group-item list-group-item-action" data-toggle="list" data-target="#profile" role="tab">Profile</a>
<a href="#" class="list-group-item list-group-item-action" data-toggle="list" data-target="#messages" role="tab">Messages</a>
<a href="#" class="list-group-item list-group-item-action" data-toggle="list" data-target="#settings" role="tab">Settings</a>
</div>
<!-- Tab panes -->
@ -352,7 +352,7 @@ triggerTabList.forEach(function (triggerEl) {
You can activate individual list item in several ways:
{{< highlight js >}}
var triggerEl = document.querySelector('#myTab a[href="#profile"]')
var triggerEl = document.querySelector('#myTab a[data-target="#profile"]')
bootstrap.Tab.getInstance(triggerEl).show() // Select tab by name
var triggerFirstTabEl = document.querySelector('#myTab li:first-child a')
@ -376,14 +376,14 @@ To make tabs panel fade in, add `.fade` to each `.tab-pane`. The first tab pane
#### constructor
Activates a list item element and content container. Tab should have either a `data-target` or an `href` targeting a container node in the DOM.
Activates a list item element and content container. Tab should have either a `data-target` targeting a container node in the DOM.
{{< highlight html >}}
<div class="list-group" id="myList" role="tablist">
<a class="list-group-item list-group-item-action active" data-toggle="list" href="#home" role="tab">Home</a>
<a class="list-group-item list-group-item-action" data-toggle="list" href="#profile" role="tab">Profile</a>
<a class="list-group-item list-group-item-action" data-toggle="list" href="#messages" role="tab">Messages</a>
<a class="list-group-item list-group-item-action" data-toggle="list" href="#settings" role="tab">Settings</a>
<a href="#" class="list-group-item list-group-item-action active" data-toggle="list" data-target="#home" role="tab">Home</a>
<a href="#" class="list-group-item list-group-item-action" data-toggle="list" data-target="#profile" role="tab">Profile</a>
<a href="#" class="list-group-item list-group-item-action" data-toggle="list" data-target="#messages" role="tab">Messages</a>
<a href="#" class="list-group-item list-group-item-action" data-toggle="list" data-target="#settings" role="tab">Settings</a>
</div>
<div class="tab-content">

View File

@ -849,7 +849,7 @@ The modal plugin toggles your hidden content on demand, via data attributes or J
### Via data attributes
Activate a modal without writing JavaScript. Set `data-toggle="modal"` on a controller element, like a button, along with a `data-target="#foo"` or `href="#foo"` to target a specific modal to toggle.
Activate a modal without writing JavaScript. Set `data-toggle="modal"` on a controller element, like a button, along with a `data-target="#foo"` to target a specific modal to toggle.
{{< highlight html >}}
<button type="button" data-toggle="modal" data-target="#myModal">Launch modal</button>

View File

@ -314,13 +314,13 @@ Note that dynamic tabbed interfaces should <em>not</em> contain dropdown menus,
<div class="bd-example">
<ul class="nav nav-tabs mb-3" id="myTab" role="tablist">
<li class="nav-item" role="presentation">
<a class="nav-link active" id="home-tab" data-toggle="tab" href="#home" role="tab" aria-controls="home" aria-selected="true">Home</a>
<a href="#" class="nav-link active" id="home-tab" data-toggle="tab" data-target="#home" role="tab" aria-controls="home" aria-selected="true">Home</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" id="profile-tab" data-toggle="tab" href="#profile" role="tab" aria-controls="profile" aria-selected="false">Profile</a>
<a href="#" class="nav-link" id="profile-tab" data-toggle="tab" data-target="#profile" role="tab" aria-controls="profile" aria-selected="false">Profile</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" id="contact-tab" data-toggle="tab" href="#contact" role="tab" aria-controls="contact" aria-selected="false">Contact</a>
<a href="#" class="nav-link" id="contact-tab" data-toggle="tab" data-target="#contact" role="tab" aria-controls="contact" aria-selected="false">Contact</a>
</li>
</ul>
<div class="tab-content" id="myTabContent">
@ -339,13 +339,13 @@ Note that dynamic tabbed interfaces should <em>not</em> contain dropdown menus,
{{< highlight html >}}
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item" role="presentation">
<a class="nav-link active" id="home-tab" data-toggle="tab" href="#home" role="tab" aria-controls="home" aria-selected="true">Home</a>
<a href="#" class="nav-link active" id="home-tab" data-toggle="tab" data-target="#home" role="tab" aria-controls="home" aria-selected="true">Home</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" id="profile-tab" data-toggle="tab" href="#profile" role="tab" aria-controls="profile" aria-selected="false">Profile</a>
<a href="#" class="nav-link" id="profile-tab" data-toggle="tab" data-target="#profile" role="tab" aria-controls="profile" aria-selected="false">Profile</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" id="contact-tab" data-toggle="tab" href="#contact" role="tab" aria-controls="contact" aria-selected="false">Contact</a>
<a href="#" class="nav-link" id="contact-tab" data-toggle="tab" data-target="#contact" role="tab" aria-controls="contact" aria-selected="false">Contact</a>
</li>
</ul>
<div class="tab-content" id="myTabContent">
@ -360,9 +360,9 @@ To help fit your needs, this works with `<ul>`-based markup, as shown above, or
<div class="bd-example">
<nav>
<div class="nav nav-tabs mb-3" id="nav-tab" role="tablist">
<a class="nav-link active" id="nav-home-tab" data-toggle="tab" href="#nav-home" role="tab" aria-controls="nav-home" aria-selected="true">Home</a>
<a class="nav-link" id="nav-profile-tab" data-toggle="tab" href="#nav-profile" role="tab" aria-controls="nav-profile" aria-selected="false">Profile</a>
<a class="nav-link" id="nav-contact-tab" data-toggle="tab" href="#nav-contact" role="tab" aria-controls="nav-contact" aria-selected="false">Contact</a>
<a href="#" class="nav-link active" id="nav-home-tab" data-toggle="tab" data-target="#nav-home" role="tab" aria-controls="nav-home" aria-selected="true">Home</a>
<a href="#" class="nav-link" id="nav-profile-tab" data-toggle="tab" data-target="#nav-profile" role="tab" aria-controls="nav-profile" aria-selected="false">Profile</a>
<a href="#" class="nav-link" id="nav-contact-tab" data-toggle="tab" data-target="#nav-contact" role="tab" aria-controls="nav-contact" aria-selected="false">Contact</a>
</div>
</nav>
<div class="tab-content" id="nav-tabContent">
@ -381,9 +381,9 @@ To help fit your needs, this works with `<ul>`-based markup, as shown above, or
{{< highlight html >}}
<nav>
<div class="nav nav-tabs" id="nav-tab" role="tablist">
<a class="nav-link active" id="nav-home-tab" data-toggle="tab" href="#nav-home" role="tab" aria-controls="nav-home" aria-selected="true">Home</a>
<a class="nav-link" id="nav-profile-tab" data-toggle="tab" href="#nav-profile" role="tab" aria-controls="nav-profile" aria-selected="false">Profile</a>
<a class="nav-link" id="nav-contact-tab" data-toggle="tab" href="#nav-contact" role="tab" aria-controls="nav-contact" aria-selected="false">Contact</a>
<a href="#" class="nav-link active" id="nav-home-tab" data-toggle="tab" data-target="#nav-home" role="tab" aria-controls="nav-home" aria-selected="true">Home</a>
<a href="#" class="nav-link" id="nav-profile-tab" data-toggle="tab" data-target="#nav-profile" role="tab" aria-controls="nav-profile" aria-selected="false">Profile</a>
<a href="#" class="nav-link" id="nav-contact-tab" data-toggle="tab" data-target="#nav-contact" role="tab" aria-controls="nav-contact" aria-selected="false">Contact</a>
</div>
</nav>
<div class="tab-content" id="nav-tabContent">
@ -398,13 +398,13 @@ The tabs plugin also works with pills.
<div class="bd-example">
<ul class="nav nav-pills mb-3" id="pills-tab" role="tablist">
<li class="nav-item" role="presentation">
<a class="nav-link active" id="pills-home-tab" data-toggle="pill" href="#pills-home" role="tab" aria-controls="pills-home" aria-selected="true">Home</a>
<a href="#" class="nav-link active" id="pills-home-tab" data-toggle="pill" data-target="#pills-home" role="tab" aria-controls="pills-home" aria-selected="true">Home</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" id="pills-profile-tab" data-toggle="pill" href="#pills-profile" role="tab" aria-controls="pills-profile" aria-selected="false">Profile</a>
<a href="#" class="nav-link" id="pills-profile-tab" data-toggle="pill" data-target="#pills-profile" role="tab" aria-controls="pills-profile" aria-selected="false">Profile</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" id="pills-contact-tab" data-toggle="pill" href="#pills-contact" role="tab" aria-controls="pills-contact" aria-selected="false">Contact</a>
<a href="#" class="nav-link" id="pills-contact-tab" data-toggle="pill" data-target="#pills-contact" role="tab" aria-controls="pills-contact" aria-selected="false">Contact</a>
</li>
</ul>
<div class="tab-content" id="pills-tabContent">
@ -423,13 +423,13 @@ The tabs plugin also works with pills.
{{< highlight html >}}
<ul class="nav nav-pills mb-3" id="pills-tab" role="tablist">
<li class="nav-item" role="presentation">
<a class="nav-link active" id="pills-home-tab" data-toggle="pill" href="#pills-home" role="tab" aria-controls="pills-home" aria-selected="true">Home</a>
<a href="#" class="nav-link active" id="pills-home-tab" data-toggle="pill" data-target="#pills-home" role="tab" aria-controls="pills-home" aria-selected="true">Home</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" id="pills-profile-tab" data-toggle="pill" href="#pills-profile" role="tab" aria-controls="pills-profile" aria-selected="false">Profile</a>
<a href="#" class="nav-link" id="pills-profile-tab" data-toggle="pill" data-target="#pills-profile" role="tab" aria-controls="pills-profile" aria-selected="false">Profile</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" id="pills-contact-tab" data-toggle="pill" href="#pills-contact" role="tab" aria-controls="pills-contact" aria-selected="false">Contact</a>
<a href="#" class="nav-link" id="pills-contact-tab" data-toggle="pill" data-target="#pills-contact" role="tab" aria-controls="pills-contact" aria-selected="false">Contact</a>
</li>
</ul>
<div class="tab-content" id="pills-tabContent">
@ -445,10 +445,10 @@ And with vertical pills.
<div class="row">
<div class="col-3">
<div class="nav flex-column nav-pills" id="v-pills-tab" role="tablist" aria-orientation="vertical">
<a class="nav-link active" id="v-pills-home-tab" data-toggle="pill" href="#v-pills-home" role="tab" aria-controls="v-pills-home" aria-selected="true">Home</a>
<a class="nav-link" id="v-pills-profile-tab" data-toggle="pill" href="#v-pills-profile" role="tab" aria-controls="v-pills-profile" aria-selected="false">Profile</a>
<a class="nav-link" id="v-pills-messages-tab" data-toggle="pill" href="#v-pills-messages" role="tab" aria-controls="v-pills-messages" aria-selected="false">Messages</a>
<a class="nav-link" id="v-pills-settings-tab" data-toggle="pill" href="#v-pills-settings" role="tab" aria-controls="v-pills-settings" aria-selected="false">Settings</a>
<a href="#" class="nav-link active" id="v-pills-home-tab" data-toggle="pill" data-target="#v-pills-home" role="tab" aria-controls="v-pills-home" aria-selected="true">Home</a>
<a href="#" class="nav-link" id="v-pills-profile-tab" data-toggle="pill" data-target="#v-pills-profile" role="tab" aria-controls="v-pills-profile" aria-selected="false">Profile</a>
<a href="#" class="nav-link" id="v-pills-messages-tab" data-toggle="pill" data-target="#v-pills-messages" role="tab" aria-controls="v-pills-messages" aria-selected="false">Messages</a>
<a href="#" class="nav-link" id="v-pills-settings-tab" data-toggle="pill" data-target="#v-pills-settings" role="tab" aria-controls="v-pills-settings" aria-selected="false">Settings</a>
</div>
</div>
<div class="col-9">
@ -474,10 +474,10 @@ And with vertical pills.
<div class="row">
<div class="col-3">
<div class="nav flex-column nav-pills" id="v-pills-tab" role="tablist" aria-orientation="vertical">
<a class="nav-link active" id="v-pills-home-tab" data-toggle="pill" href="#v-pills-home" role="tab" aria-controls="v-pills-home" aria-selected="true">Home</a>
<a class="nav-link" id="v-pills-profile-tab" data-toggle="pill" href="#v-pills-profile" role="tab" aria-controls="v-pills-profile" aria-selected="false">Profile</a>
<a class="nav-link" id="v-pills-messages-tab" data-toggle="pill" href="#v-pills-messages" role="tab" aria-controls="v-pills-messages" aria-selected="false">Messages</a>
<a class="nav-link" id="v-pills-settings-tab" data-toggle="pill" href="#v-pills-settings" role="tab" aria-controls="v-pills-settings" aria-selected="false">Settings</a>
<a href="#" class="nav-link active" id="v-pills-home-tab" data-toggle="pill" data-target="#v-pills-home" role="tab" aria-controls="v-pills-home" aria-selected="true">Home</a>
<a href="#" class="nav-link" id="v-pills-profile-tab" data-toggle="pill" data-target="#v-pills-profile" role="tab" aria-controls="v-pills-profile" aria-selected="false">Profile</a>
<a href="#" class="nav-link" id="v-pills-messages-tab" data-toggle="pill" data-target="#v-pills-messages" role="tab" aria-controls="v-pills-messages" aria-selected="false">Messages</a>
<a href="#" class="nav-link" id="v-pills-settings-tab" data-toggle="pill" data-target="#v-pills-settings" role="tab" aria-controls="v-pills-settings" aria-selected="false">Settings</a>
</div>
</div>
<div class="col-9">
@ -499,16 +499,16 @@ You can activate a tab or pill navigation without writing any JavaScript by simp
<!-- Nav tabs -->
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item" role="presentation">
<a class="nav-link active" id="home-tab" data-toggle="tab" href="#home" role="tab" aria-controls="home" aria-selected="true">Home</a>
<a href="#" class="nav-link active" id="home-tab" data-toggle="tab" data-target="#home" role="tab" aria-controls="home" aria-selected="true">Home</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" id="profile-tab" data-toggle="tab" href="#profile" role="tab" aria-controls="profile" aria-selected="false">Profile</a>
<a href="#" class="nav-link" id="profile-tab" data-toggle="tab" data-target="#profile" role="tab" aria-controls="profile" aria-selected="false">Profile</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" id="messages-tab" data-toggle="tab" href="#messages" role="tab" aria-controls="messages" aria-selected="false">Messages</a>
<a href="#" class="nav-link" id="messages-tab" data-toggle="tab" data-target="#messages" role="tab" aria-controls="messages" aria-selected="false">Messages</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" id="settings-tab" data-toggle="tab" href="#settings" role="tab" aria-controls="settings" aria-selected="false">Settings</a>
<a href="#" class="nav-link" id="settings-tab" data-toggle="tab" data-target="#settings" role="tab" aria-controls="settings" aria-selected="false">Settings</a>
</li>
</ul>
@ -540,7 +540,7 @@ triggerTabList.forEach(function (triggerEl) {
You can activate individual tabs in several ways:
{{< highlight js >}}
var triggerEl = document.querySelector('#myTab a[href="#profile"]')
var triggerEl = document.querySelector('#myTab a[data-target="#profile"]')
bootstrap.Tab.getInstance(triggerEl).show() // Select tab by name
var triggerFirstTabEl = document.querySelector('#myTab li:first-child a')
@ -568,21 +568,21 @@ To make tabs fade in, add `.fade` to each `.tab-pane`. The first tab pane must a
#### constructor
Activates a tab element and content container. Tab should have either a `data-target` or an `href` targeting a container node in the DOM.
Activates a tab element and content container. Tab should have either a `data-target` targeting a container node in the DOM.
{{< highlight html >}}
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item" role="presentation">
<a class="nav-link active" id="home-tab" data-toggle="tab" href="#home" role="tab" aria-controls="home" aria-selected="true">Home</a>
<a href="#" class="nav-link active" id="home-tab" data-toggle="tab" data-target="#home" role="tab" aria-controls="home" aria-selected="true">Home</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" id="profile-tab" data-toggle="tab" href="#profile" role="tab" aria-controls="profile" aria-selected="false">Profile</a>
<a href="#" class="nav-link" id="profile-tab" data-toggle="tab" data-target="#profile" role="tab" aria-controls="profile" aria-selected="false">Profile</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" id="messages-tab" data-toggle="tab" href="#messages" role="tab" aria-controls="messages" aria-selected="false">Messages</a>
<a href="#" class="nav-link" id="messages-tab" data-toggle="tab" data-target="#messages" role="tab" aria-controls="messages" aria-selected="false">Messages</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" id="settings-tab" data-toggle="tab" href="#settings" role="tab" aria-controls="settings" aria-selected="false">Settings</a>
<a href="#" class="nav-link" id="settings-tab" data-toggle="tab" data-target="#settings" role="tab" aria-controls="settings" aria-selected="false">Settings</a>
</li>
</ul>

View File

@ -57,6 +57,7 @@ Changes to our source and compiled JavaScript files.
- Dropped jQuery dependency and rewrote plugins to be in regular JavaScript.
- Removed underscore from public static methods like `_getInstance()``getInstance()`.
- Drop the use of `href` attributes to target element, except for our Scrollspy.
## Color system

View File

@ -16,7 +16,7 @@
{{- $is_active_group := eq $.Page.Params.group $group_slug }}
<li class="my-1{{ if $is_active_group }} active{{ end }}">
<a class="d-inline-flex align-items-center rounded{{ if not $is_active_group }} collapsed{{ end }}" data-toggle="collapse" href="#{{ $group_slug }}-collapse" role="button" aria-expanded="{{ $is_active_group }}"{{ if $is_active_group }} aria-current="true"{{ end }}>
<a href="#" class="d-inline-flex align-items-center rounded{{ if not $is_active_group }} collapsed{{ end }}" data-toggle="collapse" data-target="#{{ $group_slug }}-collapse" role="button" aria-expanded="{{ $is_active_group }}"{{ if $is_active_group }} aria-current="true"{{ end }}>
{{ $group.title }}
</a>