Compare commits

...

8 Commits

Author SHA1 Message Date
XhmikosR ac6069641e bundle-modularity.js: add file extensions 2024-03-13 22:10:48 +02:00
XhmikosR cb0ab4e05e Rename variable 2024-03-11 16:40:04 +02:00
XhmikosR 5fc4efb910 ESLint: fix sourceType for docs md files 2024-03-11 16:37:25 +02:00
XhmikosR 7df3fb5970 ESLint: properly disable no-negated-condition 2024-03-11 16:37:24 +02:00
XhmikosR 76bbd3fdee unicorn/prefer-top-level-await 2024-03-11 16:34:07 +02:00
XhmikosR 9c1b83a23c unicorn/prefer-node-protocol 2024-03-11 16:34:07 +02:00
XhmikosR 958cdec31b Switch to using for...of 2024-03-11 16:34:07 +02:00
XhmikosR 8590295993 Enable unicorn/prefer-spread rule 2024-03-11 16:34:04 +02:00
30 changed files with 165 additions and 183 deletions
+5 -15
View File
@@ -67,7 +67,6 @@
}
],
"no-console": "error",
"no-negated-condition": "off",
"object-curly-spacing": [
"error",
"always"
@@ -87,6 +86,7 @@
"unicorn/filename-case": "off",
"unicorn/no-array-callback-reference": "off",
"unicorn/no-array-method-this-argument": "off",
"unicorn/no-negated-condition": "off",
"unicorn/no-null": "off",
"unicorn/no-typeof-undefined": "off",
"unicorn/no-unused-properties": "error",
@@ -96,7 +96,6 @@
"unicorn/prefer-dom-node-dataset": "off",
"unicorn/prefer-module": "off",
"unicorn/prefer-query-selector": "off",
"unicorn/prefer-spread": "off",
"unicorn/prefer-string-replace-all": "off",
"unicorn/prevent-abbreviations": "off"
},
@@ -113,8 +112,7 @@
"sourceType": "module"
},
"rules": {
"no-console": "off",
"unicorn/prefer-top-level-await": "off"
"no-console": "off"
}
},
{
@@ -165,8 +163,7 @@
},
"rules": {
"no-console": "off",
"no-new": "off",
"unicorn/no-array-for-each": "off"
"no-new": "off"
}
},
{
@@ -193,8 +190,7 @@
"ecmaVersion": 2019
},
"rules": {
"no-new": "off",
"unicorn/no-array-for-each": "off"
"no-new": "off"
}
},
{
@@ -210,13 +206,7 @@
"files": [
"**/*.md/*.js"
],
"extends": "plugin:markdown/recommended",
"parserOptions": {
"sourceType": "module"
},
"rules": {
"unicorn/prefer-node-protocol": "off"
}
"extends": "plugin:markdown/recommended"
}
]
}
+6 -13
View File
@@ -87,19 +87,12 @@ const build = async plugin => {
console.log(`Built ${plugin.className}`)
}
(async () => {
try {
const basename = path.basename(__filename)
const timeLabel = `[${basename}] finished`
const basename = path.basename(__filename)
const timeLabel = `[${basename}] finished`
console.log('Building individual plugins...')
console.time(timeLabel)
console.log('Building individual plugins...')
console.time(timeLabel)
await Promise.all(Object.values(resolvedPlugins).map(plugin => build(plugin)))
await Promise.all(Object.values(resolvedPlugins).map(plugin => build(plugin)))
console.timeEnd(timeLabel)
} catch (error) {
console.error(error)
process.exit(1)
}
})()
console.timeEnd(timeLabel)
+19 -27
View File
@@ -81,33 +81,25 @@ function showUsage(args) {
process.exit(1)
}
async function main(args) {
let [oldVersion, newVersion] = args
const args = process.argv.slice(2)
let [oldVersion, newVersion] = args
if (!oldVersion || !newVersion) {
showUsage(args)
}
// Strip any leading `v` from arguments because
// otherwise we will end up with duplicate `v`s
[oldVersion, newVersion] = [oldVersion, newVersion].map(arg => {
return arg.startsWith('v') ? arg.slice(1) : arg
})
if (oldVersion === newVersion) {
showUsage(args)
}
bumpNpmVersion(newVersion)
try {
await Promise.all(
FILES.map(file => replaceRecursively(file, oldVersion, newVersion))
)
} catch (error) {
console.error(error)
process.exit(1)
}
if (!oldVersion || !newVersion) {
showUsage(args)
}
main(process.argv.slice(2))
// Strip any leading `v` from arguments because
// otherwise we will end up with duplicate `v`s
[oldVersion, newVersion] = [oldVersion, newVersion].map(arg => {
return arg.startsWith('v') ? arg.slice(1) : arg
})
if (oldVersion === newVersion) {
showUsage(args)
}
bumpNpmVersion(newVersion)
await Promise.all(
FILES.map(file => replaceRecursively(file, oldVersion, newVersion))
)
+1 -1
View File
@@ -23,7 +23,7 @@ export default {
// can be removed later when multiple key/instances are fine to be used
if (!instanceMap.has(key) && instanceMap.size !== 0) {
// eslint-disable-next-line no-console
console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(instanceMap.keys())[0]}.`)
console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${[...instanceMap.keys()][0]}.`)
return
}
+2 -2
View File
@@ -34,7 +34,7 @@ const getSelector = element => {
const SelectorEngine = {
find(selector, element = document.documentElement) {
return [].concat(...Element.prototype.querySelectorAll.call(element, selector))
return [...Element.prototype.querySelectorAll.call(element, selector)]
},
findOne(selector, element = document.documentElement) {
@@ -42,7 +42,7 @@ const SelectorEngine = {
},
children(element, selector) {
return [].concat(...element.children).filter(child => child.matches(selector))
return [...element.children].filter(child => child.matches(selector))
},
parents(element, selector) {
+4 -2
View File
@@ -143,7 +143,8 @@ class Dropdown extends BaseComponent {
// only needed because of broken event delegation on iOS
// https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
if ('ontouchstart' in document.documentElement && !this._parent.closest(SELECTOR_NAVBAR_NAV)) {
for (const element of [].concat(...document.body.children)) {
const children = [...document.body.children]
for (const element of children) {
EventHandler.on(element, 'mouseover', noop)
}
}
@@ -193,7 +194,8 @@ class Dropdown extends BaseComponent {
// If this is a touch-enabled device we remove the extra
// empty mouseover listeners we added for iOS support
if ('ontouchstart' in document.documentElement) {
for (const element of [].concat(...document.body.children)) {
const children = [...document.body.children]
for (const element of children) {
EventHandler.off(element, 'mouseover', noop)
}
}
+4 -2
View File
@@ -222,7 +222,8 @@ class Tooltip extends BaseComponent {
// only needed because of broken event delegation on iOS
// https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
if ('ontouchstart' in document.documentElement) {
for (const element of [].concat(...document.body.children)) {
const children = [...document.body.children]
for (const element of children) {
EventHandler.on(element, 'mouseover', noop)
}
}
@@ -256,7 +257,8 @@ class Tooltip extends BaseComponent {
// If this is a touch-enabled device we remove the extra
// empty mouseover listeners we added for iOS support
if ('ontouchstart' in document.documentElement) {
for (const element of [].concat(...document.body.children)) {
const children = [...document.body.children]
for (const element of children) {
EventHandler.off(element, 'mouseover', noop)
}
}
+3 -3
View File
@@ -93,7 +93,7 @@ export function sanitizeHtml(unsafeHtml, allowList, sanitizeFunction) {
const domParser = new window.DOMParser()
const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html')
const elements = [].concat(...createdDocument.body.querySelectorAll('*'))
const elements = [...createdDocument.body.querySelectorAll('*')]
for (const element of elements) {
const elementName = element.nodeName.toLowerCase()
@@ -103,8 +103,8 @@ export function sanitizeHtml(unsafeHtml, allowList, sanitizeFunction) {
continue
}
const attributeList = [].concat(...element.attributes)
const allowedAttributes = [].concat(allowList['*'] || [], allowList[elementName] || [])
const attributeList = [...element.attributes]
const allowedAttributes = [...allowList['*'] || [], ...allowList[elementName] || []]
for (const attribute of attributeList) {
if (!allowedAttribute(attribute, allowedAttributes)) {
+3 -3
View File
@@ -1,7 +1,7 @@
/* eslint-disable import/extensions, import/no-unassigned-import */
/* eslint-disable import/no-unassigned-import */
import Tooltip from '../../dist/tooltip'
import '../../dist/carousel'
import Tooltip from '../../dist/tooltip.js'
import '../../dist/carousel.js'
window.addEventListener('load', () => {
[].concat(...document.querySelectorAll('[data-bs-toggle="tooltip"]'))
+1 -1
View File
@@ -1,6 +1,6 @@
import { Tooltip } from '../../../dist/js/bootstrap.esm.js'
window.addEventListener('load', () => {
[].concat(...document.querySelectorAll('[data-bs-toggle="tooltip"]'))
[...document.querySelectorAll('[data-bs-toggle="tooltip"]')]
.map(tooltipNode => new Tooltip(tooltipNode))
})
+1 -1
View File
@@ -153,7 +153,7 @@ describe('Collapse', () => {
const collapseEl1 = fixtureEl.querySelector('#collapse1')
const collapseEl2 = fixtureEl.querySelector('#collapse2')
const collapseList = [].concat(...fixtureEl.querySelectorAll('.collapse'))
const collapseList = [...fixtureEl.querySelectorAll('.collapse')]
.map(el => new Collapse(el, {
parent,
toggle: false
+5 -5
View File
@@ -68,7 +68,7 @@ describe('SelectorEngine', () => {
].join('')
const list = fixtureEl.querySelector('ul')
const liList = [].concat(...fixtureEl.querySelectorAll('li'))
const liList = [...fixtureEl.querySelectorAll('li')]
const result = SelectorEngine.children(list, 'li')
expect(result).toEqual(liList)
@@ -356,7 +356,7 @@ describe('SelectorEngine', () => {
const testEl = fixtureEl.querySelector('#test')
expect(SelectorEngine.getMultipleElementsFromSelector(testEl)).toEqual(Array.from(fixtureEl.querySelectorAll('.target')))
expect(SelectorEngine.getMultipleElementsFromSelector(testEl)).toEqual([...fixtureEl.querySelectorAll('.target')])
})
it('should get elements if several ids are given', () => {
@@ -368,7 +368,7 @@ describe('SelectorEngine', () => {
const testEl = fixtureEl.querySelector('#test')
expect(SelectorEngine.getMultipleElementsFromSelector(testEl)).toEqual(Array.from(fixtureEl.querySelectorAll('.target')))
expect(SelectorEngine.getMultipleElementsFromSelector(testEl)).toEqual([...fixtureEl.querySelectorAll('.target')])
})
it('should get elements if several ids with special chars are given', () => {
@@ -380,7 +380,7 @@ describe('SelectorEngine', () => {
const testEl = fixtureEl.querySelector('#test')
expect(SelectorEngine.getMultipleElementsFromSelector(testEl)).toEqual(Array.from(fixtureEl.querySelectorAll('.target')))
expect(SelectorEngine.getMultipleElementsFromSelector(testEl)).toEqual([...fixtureEl.querySelectorAll('.target')])
})
it('should get elements in array, from href if no data-bs-target set', () => {
@@ -392,7 +392,7 @@ describe('SelectorEngine', () => {
const testEl = fixtureEl.querySelector('#test')
expect(SelectorEngine.getMultipleElementsFromSelector(testEl)).toEqual(Array.from(fixtureEl.querySelectorAll('.target')))
expect(SelectorEngine.getMultipleElementsFromSelector(testEl)).toEqual([...fixtureEl.querySelectorAll('.target')])
})
it('should return empty array if elements not found', () => {
+6 -2
View File
@@ -217,9 +217,13 @@
}
}
document.querySelectorAll('[data-bs-toggle="popover"]').forEach(popoverEl => new bootstrap.Popover(popoverEl))
for (const popoverEl of document.querySelectorAll('[data-bs-toggle="popover"]')) {
new bootstrap.Popover(popoverEl)
}
document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(tooltipEl => new bootstrap.Tooltip(tooltipEl))
for (const tooltipEl of document.querySelectorAll('[data-bs-toggle="tooltip"]')) {
new bootstrap.Tooltip(tooltipEl)
}
const tall = document.getElementById('tall')
document.getElementById('tall-toggle').addEventListener('click', () => {
+3 -1
View File
@@ -35,7 +35,9 @@
<script>
/* global bootstrap: false */
document.querySelectorAll('[data-bs-toggle="popover"]').forEach(popoverEl => new bootstrap.Popover(popoverEl))
for (const popoverEl of document.querySelectorAll('[data-bs-toggle="popover"]')) {
new bootstrap.Popover(popoverEl)
}
</script>
</body>
</html>
+9 -3
View File
@@ -55,14 +55,20 @@
/* global bootstrap: false */
window.addEventListener('load', () => {
document.querySelectorAll('.toast').forEach(toastEl => new bootstrap.Toast(toastEl))
for (const toastEl of document.querySelectorAll('.toast')) {
new bootstrap.Toast(toastEl)
}
document.getElementById('btnShowToast').addEventListener('click', () => {
document.querySelectorAll('.toast').forEach(toastEl => bootstrap.Toast.getInstance(toastEl).show())
for (const toastEl of document.querySelectorAll('.toast')) {
bootstrap.Toast.getInstance(toastEl).show()
}
})
document.getElementById('btnHideToast').addEventListener('click', () => {
document.querySelectorAll('.toast').forEach(toastEl => bootstrap.Toast.getInstance(toastEl).hide())
for (const toastEl of document.querySelectorAll('.toast')) {
bootstrap.Toast.getInstance(toastEl).hide()
}
})
})
</script>
+3 -1
View File
@@ -113,7 +113,9 @@
})
targetTooltip.show()
document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(tooltipEl => new bootstrap.Tooltip(tooltipEl))
for (const tooltipEl of document.querySelectorAll('[data-bs-toggle="tooltip"]')) {
new bootstrap.Tooltip(tooltipEl)
}
</script>
<script>
+9 -10
View File
@@ -29,14 +29,13 @@
].join('')
// Wrap programmatically code blocks and add copy btn.
document.querySelectorAll('.highlight')
.forEach(element => {
// Ignore examples made by shortcode
if (!element.closest('.bd-example-snippet')) {
element.insertAdjacentHTML('beforebegin', btnHtml)
element.previousElementSibling.append(element)
}
})
for (const element of document.querySelectorAll('.highlight')) {
// Ignore examples made by shortcode
if (!element.closest('.bd-example-snippet')) {
element.insertAdjacentHTML('beforebegin', btnHtml)
element.previousElementSibling.append(element)
}
}
/**
*
@@ -44,9 +43,9 @@
* @param {string} title
*/
function snippetButtonTooltip(selector, title) {
document.querySelectorAll(selector).forEach(btn => {
for (const btn of document.querySelectorAll(selector)) {
bootstrap.Tooltip.getOrCreateInstance(btn, { title })
})
}
}
snippetButtonTooltip('.btn-clipboard', btnTitle)
+26 -32
View File
@@ -20,19 +20,17 @@
// Tooltips
// --------
// Instantiate all tooltips in a docs or StackBlitz
document.querySelectorAll('[data-bs-toggle="tooltip"]')
.forEach(tooltip => {
new bootstrap.Tooltip(tooltip)
})
for (const tooltip of document.querySelectorAll('[data-bs-toggle="tooltip"]')) {
new bootstrap.Tooltip(tooltip)
}
// --------
// Popovers
// --------
// Instantiate all popovers in docs or StackBlitz
document.querySelectorAll('[data-bs-toggle="popover"]')
.forEach(popover => {
new bootstrap.Popover(popover)
})
for (const popover of document.querySelectorAll('[data-bs-toggle="popover"]')) {
new bootstrap.Popover(popover)
}
// -------------------------------
// Toasts
@@ -50,15 +48,14 @@
}
// Instantiate all toasts in docs pages only
document.querySelectorAll('.bd-example .toast')
.forEach(toastNode => {
const toast = new bootstrap.Toast(toastNode, {
autohide: false
})
toast.show()
for (const toastEl of document.querySelectorAll('.bd-example .toast')) {
const toast = new bootstrap.Toast(toastEl, {
autohide: false
})
toast.show()
}
// Instantiate all toasts in docs pages only
// js-docs-start live-toast
const toastTrigger = document.getElementById('liveToastBtn')
@@ -103,32 +100,29 @@
// Carousels
// --------
// Instantiate all non-autoplaying carousels in docs or StackBlitz
document.querySelectorAll('.carousel:not([data-bs-ride="carousel"])')
.forEach(carousel => {
bootstrap.Carousel.getOrCreateInstance(carousel)
})
for (const carousel of document.querySelectorAll('.carousel:not([data-bs-ride="carousel"])')) {
bootstrap.Carousel.getOrCreateInstance(carousel)
}
// -------------------------------
// Checks & Radios
// -------------------------------
// Indeterminate checkbox example in docs and StackBlitz
document.querySelectorAll('.bd-example-indeterminate [type="checkbox"]')
.forEach(checkbox => {
if (checkbox.id.includes('Indeterminate')) {
checkbox.indeterminate = true
}
})
for (const checkbox of document.querySelectorAll('.bd-example-indeterminate [type="checkbox"]')) {
if (checkbox.id.includes('Indeterminate')) {
checkbox.indeterminate = true
}
}
// -------------------------------
// Links
// -------------------------------
// Disable empty links in docs examples only
document.querySelectorAll('.bd-content [href="#"]')
.forEach(link => {
link.addEventListener('click', event => {
event.preventDefault()
})
for (const link of document.querySelectorAll('.bd-content [href="#"]')) {
link.addEventListener('click', event => {
event.preventDefault()
})
}
// -------------------------------
// Modal
@@ -161,10 +155,10 @@
// 'Offcanvas components' example in docs only
const myOffcanvas = document.querySelectorAll('.bd-example-offcanvas .offcanvas')
if (myOffcanvas) {
myOffcanvas.forEach(offcanvas => {
for (const offcanvas of myOffcanvas) {
offcanvas.addEventListener('show.bs.offcanvas', event => {
event.preventDefault()
}, false)
})
}
}
})()
+2 -2
View File
@@ -215,8 +215,8 @@ This makes an alert listen for click events on descendant elements which have th
Basic usage:
```js
const alert = bootstrap.Alert.getOrCreateInstance('#myAlert')
alert.close()
const myAlert = bootstrap.Alert.getOrCreateInstance('#myAlert')
myAlert.close()
```
### Events
+2 -2
View File
@@ -223,10 +223,10 @@ const bsButton = new bootstrap.Button('#myButton')
For example, to toggle all buttons
```js
document.querySelectorAll('.btn').forEach(buttonElement => {
for (const buttonElement of document.querySelectorAll('.btn')) {
const button = bootstrap.Button.getOrCreateInstance(buttonElement)
button.toggle()
})
}
```
## CSS
@@ -413,14 +413,14 @@ Enable tabbable list item via JavaScript (each list item needs to be activated i
```js
const triggerTabList = document.querySelectorAll('#myTab a')
triggerTabList.forEach(triggerEl => {
for (const triggerEl of triggerTabList) {
const tabTrigger = new bootstrap.Tab(triggerEl)
triggerEl.addEventListener('click', event => {
event.preventDefault()
tabTrigger.show()
})
})
}
```
You can activate individual list item in several ways:
@@ -491,10 +491,10 @@ If no tab was already active, then the `hide.bs.tab` and `hidden.bs.tab` events
```js
const tabElms = document.querySelectorAll('a[data-bs-toggle="list"]')
tabElms.forEach(tabElm => {
for (const tabElm of tabElms) {
tabElm.addEventListener('shown.bs.tab', event => {
event.target // newly activated tab
event.relatedTarget // previous active tab
})
})
}
```
@@ -613,14 +613,14 @@ Enable tabbable tabs via JavaScript (each tab needs to be activated individually
```js
const triggerTabList = document.querySelectorAll('#myTab button')
triggerTabList.forEach(triggerEl => {
for (const triggerEl of triggerTabList) {
const tabTrigger = new bootstrap.Tab(triggerEl)
triggerEl.addEventListener('click', event => {
event.preventDefault()
tabTrigger.show()
})
})
}
```
You can activate individual tabs in several ways:
@@ -333,13 +333,13 @@ Scrollspy is not limited to nav components and list groups, so it will work on a
Target elements that arent visible will be ignored and their corresponding nav items won't receive an `.active` class. Scrollspy instances initialized in a non-visible wrapper will ignore all target elements. Use the `refresh` method to check for observable elements once the wrapper becomes visible.
```js
document.querySelectorAll('#nav-tab>[data-bs-toggle="tab"]').forEach(el => {
for (const el of document.querySelectorAll('#nav-tab > [data-bs-toggle="tab"]')) {
el.addEventListener('shown.bs.tab', () => {
const target = el.getAttribute('data-bs-target')
const scrollElem = document.querySelector(`${target} [data-bs-spy="scroll"]`)
bootstrap.ScrollSpy.getOrCreateInstance(scrollElem).refresh()
})
})
}
```
## Usage
@@ -406,9 +406,9 @@ Here's an example using the refresh method:
```js
const dataSpyList = document.querySelectorAll('[data-bs-spy="scroll"]')
dataSpyList.forEach(dataSpyEl => {
for (const dataSpyEl of dataSpyList) {
bootstrap.ScrollSpy.getInstance(dataSpyEl).refresh()
})
}
```
### Events
@@ -4,34 +4,30 @@
'use strict'
// Tooltip and popover demos
document.querySelectorAll('.tooltip-demo')
.forEach(tooltip => {
new bootstrap.Tooltip(tooltip, {
selector: '[data-bs-toggle="tooltip"]'
})
for (const tooltip of document.querySelectorAll('.tooltip-demo')) {
new bootstrap.Tooltip(tooltip, {
selector: '[data-bs-toggle="tooltip"]'
})
}
for (const popover of document.querySelectorAll('[data-bs-toggle="popover"]')) {
new bootstrap.Popover(popover)
}
for (const toastEl of document.querySelectorAll('.toast')) {
const toast = new bootstrap.Toast(toastEl, {
autohide: false
})
document.querySelectorAll('[data-bs-toggle="popover"]')
.forEach(popover => {
new bootstrap.Popover(popover)
})
document.querySelectorAll('.toast')
.forEach(toastNode => {
const toast = new bootstrap.Toast(toastNode, {
autohide: false
})
toast.show()
})
toast.show()
}
// Disable empty links and submit buttons
document.querySelectorAll('[href="#"], [type="submit"]')
.forEach(link => {
link.addEventListener('click', event => {
event.preventDefault()
})
for (const link of document.querySelectorAll('[href="#"], [type="submit"]')) {
link.addEventListener('click', event => {
event.preventDefault()
})
}
function setActiveItem() {
const { hash } = window.location
@@ -6,7 +6,7 @@
const forms = document.querySelectorAll('.needs-validation')
// Loop over them and prevent submission
Array.from(forms).forEach(form => {
for (const form of forms) {
form.addEventListener('submit', event => {
if (!form.checkValidity()) {
event.preventDefault()
@@ -15,5 +15,5 @@
form.classList.add('was-validated')
}, false)
})
}
})()
@@ -1,8 +1,8 @@
/* global bootstrap: false */
(() => {
'use strict'
const tooltipTriggerList = Array.from(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
tooltipTriggerList.forEach(tooltipTriggerEl => {
const tooltipTriggerList = [...document.querySelectorAll('[data-bs-toggle="tooltip"]')]
for (const tooltipTriggerEl of tooltipTriggerList) {
new bootstrap.Tooltip(tooltipTriggerEl)
})
}
})()
@@ -39,8 +39,9 @@ We provide a version of Bootstrap built as `ESM` (`bootstrap.esm.js` and `bootst
<script type="module">
import { Toast } from 'bootstrap.esm.min.js'
Array.from(document.querySelectorAll('.toast'))
.forEach(toastNode => new Toast(toastNode))
for (const toastEl of document.querySelectorAll('.toast')) {
new Toast(toastEl))
}
</script>
```
@@ -159,7 +160,7 @@ In addition to the `getInstance` and `getOrCreateInstance` methods, all plugin c
const modal = new bootstrap.Modal('#myModal')
const dropdown = new bootstrap.Dropdown('[data-bs-toggle="dropdown"]')
const offcanvas = bootstrap.Offcanvas.getInstance('#myOffcanvas')
const alert = bootstrap.Alert.getOrCreateInstance('#myAlert')
const myAlert = bootstrap.Alert.getOrCreateInstance('#myAlert')
```
### Asynchronous functions and transitions
@@ -79,7 +79,7 @@ With dependencies installed and our project folder ready for us to start coding,
```js
'use strict'
const path = require('path')
const path = require('node:path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
@@ -154,7 +154,7 @@ Importing Bootstrap into Webpack requires the loaders we installed in the first
```js
'use strict'
const path = require('path')
const path = require('node:path')
const autoprefixer = require('autoprefixer')
const HtmlWebpackPlugin = require('html-webpack-plugin')
+9 -10
View File
@@ -41,10 +41,10 @@
const btnToActive = document.querySelector(`[data-bs-theme-value="${theme}"]`)
const svgOfActiveBtn = btnToActive.querySelector('svg use').getAttribute('href')
document.querySelectorAll('[data-bs-theme-value]').forEach(element => {
for (const element of document.querySelectorAll('[data-bs-theme-value]')) {
element.classList.remove('active')
element.setAttribute('aria-pressed', 'false')
})
}
btnToActive.classList.add('active')
btnToActive.setAttribute('aria-pressed', 'true')
@@ -67,14 +67,13 @@
window.addEventListener('DOMContentLoaded', () => {
showActiveTheme(getPreferredTheme())
document.querySelectorAll('[data-bs-theme-value]')
.forEach(toggle => {
toggle.addEventListener('click', () => {
const theme = toggle.getAttribute('data-bs-theme-value')
setStoredTheme(theme)
setTheme(theme)
showActiveTheme(theme, true)
})
for (const toggle of document.querySelectorAll('[data-bs-theme-value]')) {
toggle.addEventListener('click', () => {
const theme = toggle.getAttribute('data-bs-theme-value')
setStoredTheme(theme)
setTheme(theme)
showActiveTheme(theme, true)
})
}
})
})()
@@ -6,7 +6,7 @@
const forms = document.querySelectorAll('.needs-validation')
// Loop over them and prevent submission
Array.from(forms).forEach(form => {
for (const form of forms) {
form.addEventListener('submit', event => {
if (!form.checkValidity()) {
event.preventDefault()
@@ -15,5 +15,5 @@
form.classList.add('was-validated')
}, false)
})
}
})()