"eslint": "^8.13.0",
"eslint-config-xo": "^0.40.0",
"eslint-plugin-import": "^2.26.0",
+ "eslint-plugin-markdown": "^2.2.1",
"eslint-plugin-unicorn": "^42.0.0",
"find-unused-sass-variables": "^4.0.4",
"globby": "^11.1.0",
"integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=",
"dev": true
},
+ "node_modules/@types/mdast": {
+ "version": "3.0.10",
+ "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz",
+ "integrity": "sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "*"
+ }
+ },
"node_modules/@types/minimist": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz",
"@types/node": "*"
}
},
+ "node_modules/@types/unist": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz",
+ "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==",
+ "dev": true
+ },
"node_modules/@yarnpkg/lockfile": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz",
"node": ">=4"
}
},
+ "node_modules/character-entities": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz",
+ "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-entities-legacy": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz",
+ "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-reference-invalid": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz",
+ "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/chokidar": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"dev": true
},
+ "node_modules/eslint-plugin-markdown": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-markdown/-/eslint-plugin-markdown-2.2.1.tgz",
+ "integrity": "sha512-FgWp4iyYvTFxPwfbxofTvXxgzPsDuSKHQy2S+a8Ve6savbujey+lgrFFbXQA0HPygISpRYWYBjooPzhYSF81iA==",
+ "dev": true,
+ "dependencies": {
+ "mdast-util-from-markdown": "^0.8.5"
+ },
+ "engines": {
+ "node": "^8.10.0 || ^10.12.0 || >= 12.0.0"
+ },
+ "peerDependencies": {
+ "eslint": ">=6.0.0"
+ }
+ },
"node_modules/eslint-plugin-unicorn": {
"version": "42.0.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-42.0.0.tgz",
"integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=",
"dev": true
},
+ "node_modules/is-alphabetical": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz",
+ "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-alphanumerical": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz",
+ "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==",
+ "dev": true,
+ "dependencies": {
+ "is-alphabetical": "^1.0.0",
+ "is-decimal": "^1.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-decimal": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz",
+ "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/is-docker": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
"node": ">=0.10.0"
}
},
+ "node_modules/is-hexadecimal": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz",
+ "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/is-installed-globally": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz",
"url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/mdast-util-from-markdown": {
+ "version": "0.8.5",
+ "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.5.tgz",
+ "integrity": "sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/mdast": "^3.0.0",
+ "mdast-util-to-string": "^2.0.0",
+ "micromark": "~2.11.0",
+ "parse-entities": "^2.0.0",
+ "unist-util-stringify-position": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-to-string": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz",
+ "integrity": "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==",
+ "dev": true,
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"node": ">= 8"
}
},
+ "node_modules/micromark": {
+ "version": "2.11.4",
+ "resolved": "https://registry.npmjs.org/micromark/-/micromark-2.11.4.tgz",
+ "integrity": "sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "dependencies": {
+ "debug": "^4.0.0",
+ "parse-entities": "^2.0.0"
+ }
+ },
"node_modules/micromatch": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
"node": ">=6"
}
},
+ "node_modules/parse-entities": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz",
+ "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==",
+ "dev": true,
+ "dependencies": {
+ "character-entities": "^1.0.0",
+ "character-entities-legacy": "^1.0.0",
+ "character-reference-invalid": "^1.0.0",
+ "is-alphanumerical": "^1.0.0",
+ "is-decimal": "^1.0.0",
+ "is-hexadecimal": "^1.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/parse-json": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
"node": ">=8"
}
},
+ "node_modules/unist-util-stringify-position": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz",
+ "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.2"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/universalify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
"integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=",
"dev": true
},
+ "@types/mdast": {
+ "version": "3.0.10",
+ "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz",
+ "integrity": "sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "*"
+ }
+ },
"@types/minimist": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz",
"@types/node": "*"
}
},
+ "@types/unist": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz",
+ "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==",
+ "dev": true
+ },
"@yarnpkg/lockfile": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz",
"supports-color": "^5.3.0"
}
},
+ "character-entities": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz",
+ "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==",
+ "dev": true
+ },
+ "character-entities-legacy": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz",
+ "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==",
+ "dev": true
+ },
+ "character-reference-invalid": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz",
+ "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==",
+ "dev": true
+ },
"chokidar": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
}
}
},
+ "eslint-plugin-markdown": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-markdown/-/eslint-plugin-markdown-2.2.1.tgz",
+ "integrity": "sha512-FgWp4iyYvTFxPwfbxofTvXxgzPsDuSKHQy2S+a8Ve6savbujey+lgrFFbXQA0HPygISpRYWYBjooPzhYSF81iA==",
+ "dev": true,
+ "requires": {
+ "mdast-util-from-markdown": "^0.8.5"
+ }
+ },
"eslint-plugin-unicorn": {
"version": "42.0.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-42.0.0.tgz",
"integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=",
"dev": true
},
+ "is-alphabetical": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz",
+ "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==",
+ "dev": true
+ },
+ "is-alphanumerical": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz",
+ "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==",
+ "dev": true,
+ "requires": {
+ "is-alphabetical": "^1.0.0",
+ "is-decimal": "^1.0.0"
+ }
+ },
"is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
"has-tostringtag": "^1.0.0"
}
},
+ "is-decimal": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz",
+ "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==",
+ "dev": true
+ },
"is-docker": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
"is-extglob": "^2.1.1"
}
},
+ "is-hexadecimal": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz",
+ "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==",
+ "dev": true
+ },
"is-installed-globally": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz",
"integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==",
"dev": true
},
+ "mdast-util-from-markdown": {
+ "version": "0.8.5",
+ "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.5.tgz",
+ "integrity": "sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==",
+ "dev": true,
+ "requires": {
+ "@types/mdast": "^3.0.0",
+ "mdast-util-to-string": "^2.0.0",
+ "micromark": "~2.11.0",
+ "parse-entities": "^2.0.0",
+ "unist-util-stringify-position": "^2.0.0"
+ }
+ },
+ "mdast-util-to-string": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz",
+ "integrity": "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==",
+ "dev": true
+ },
"media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
"dev": true
},
+ "micromark": {
+ "version": "2.11.4",
+ "resolved": "https://registry.npmjs.org/micromark/-/micromark-2.11.4.tgz",
+ "integrity": "sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA==",
+ "dev": true,
+ "requires": {
+ "debug": "^4.0.0",
+ "parse-entities": "^2.0.0"
+ }
+ },
"micromatch": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
"callsites": "^3.0.0"
}
},
+ "parse-entities": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz",
+ "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==",
+ "dev": true,
+ "requires": {
+ "character-entities": "^1.0.0",
+ "character-entities-legacy": "^1.0.0",
+ "character-reference-invalid": "^1.0.0",
+ "is-alphanumerical": "^1.0.0",
+ "is-decimal": "^1.0.0",
+ "is-hexadecimal": "^1.0.0"
+ }
+ },
"parse-json": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
"crypto-random-string": "^2.0.0"
}
},
+ "unist-util-stringify-position": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz",
+ "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.2"
+ }
+ },
"universalify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
"eslint": "^8.13.0",
"eslint-config-xo": "^0.40.0",
"eslint-plugin-import": "^2.26.0",
+ "eslint-plugin-markdown": "^2.2.1",
"eslint-plugin-unicorn": "^42.0.0",
"find-unused-sass-variables": "^4.0.4",
"globby": "^11.1.0",
"browser": true,
"node": false
},
+ "plugins": [
+ "markdown"
+ ],
+ "overrides": [
+ {
+ // 2. Enable the Markdown processor for all .md files.
+ "files": ["./**/*.md"],
+ "processor": "markdown/markdown"
+ },
+ {
+ // In v2, configuration for fenced code blocks is separate from the
+ // containing Markdown file. Each code block has a virtual filename
+ // appended to the Markdown file's path.
+ "files": [
+ "./**/*.md/*.js"
+ ],
+ // Configuration for fenced code blocks goes with the override for
+ // the code block's virtual filename, for example:
+ "parserOptions": {
+ "ecmaFeatures": {
+ "impliedStrict": true
+ }
+ },
+ "rules": {
+ "no-array-for-each": "off",
+ "no-undef": "off",
+ "no-unused-vars": "off",
+ "unicorn/no-array-for-each": "off",
+ "unicorn/numeric-separators-style": "off",
+ "no-unused-expressions": "off",
+ "no-unused-labels": "off",
+ "no-labels": "off",
+ "no-redeclare": "off"
+ }
+ }
+ ],
"parserOptions": {
"sourceType": "script"
},
We use the following JavaScript to trigger our live alert demo:
```js
-var alertPlaceholder = document.getElementById('liveAlertPlaceholder')
-var alertTrigger = document.getElementById('liveAlertBtn')
+const alertPlaceholder = document.getElementById('liveAlertPlaceholder')
-function alert(message, type) {
- var wrapper = document.createElement('div')
- wrapper.innerHTML = '<div class="alert alert-' + type + ' alert-dismissible" role="alert">' + message + '<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button></div>'
+const alert = (message, type) => {
+ const wrapper = document.createElement('div')
+ wrapper.innerHTML = [
+ `<div class="alert alert-${type} alert-dismissible" role="alert">`,
+ ` <div>${message}</div>`,
+ ' <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>',
+ '</div>'
+ ].join('')
alertPlaceholder.append(wrapper)
}
+const alertTrigger = document.getElementById('liveAlertBtn')
if (alertTrigger) {
- alertTrigger.addEventListener('click', function () {
+ alertTrigger.addEventListener('click', () => {
alert('Nice, you triggered this alert message!', 'success')
})
}
Initialize elements as alerts
```js
-var alertList = document.querySelectorAll('.alert')
-var alerts = Array.prototype.slice.call(alertList).map(function (element) {
- return new bootstrap.Alert(element)
-})
+const alertList = document.querySelectorAll('.alert')
+const alerts = [...alertList].map(element => new bootstrap.Alert(element))
```
{{< callout info >}}
You can create an alert instance with the alert constructor, for example:
```js
-var myAlert = document.getElementById('myAlert')
-var bsAlert = new bootstrap.Alert(myAlert)
+const bsAlert = new bootstrap.Alert('#myAlert')
```
This makes an alert listen for click events on descendant elements which have the `data-bs-dismiss="alert"` attribute. (Not necessary when using the data-api’s auto-initialization.)
Basic usage:
```js
-var alertNode = document.querySelector('.alert')
-var alert = bootstrap.Alert.getOrCreateInstance(alertNode)
+const alert = bootstrap.Alert.getOrCreateInstance('#myAlert')
alert.close()
```
{{< /bs-table >}}
```js
-var myAlert = document.getElementById('myAlert')
-myAlert.addEventListener('closed.bs.alert', function () {
+const myAlert = document.getElementById('myAlert')
+myAlert.addEventListener('closed.bs.alert', event => {
// do something, for instance, explicitly move focus to the most appropriate element,
// so it doesn't get lost/reset to the start of the page
// document.getElementById('...').focus()
You can create a button instance with the button constructor, for example:
```js
-var button = document.getElementById('myButton')
-var bsButton = new bootstrap.Button(button)
+const bsButton = new bootstrap.Button('#myButton')
```
{{< bs-table "table" >}}
For example, to toggle all buttons
```js
-var buttons = document.querySelectorAll('.btn')
-buttons.forEach(function (button) {
- var button = new bootstrap.Button(button)
+document.querySelectorAll('.btn').forEach(buttonElement => {
+ const button = bootstrap.Button.getOrCreateInstance(buttonElement)
button.toggle()
})
```
Call carousel manually with:
```js
-var myCarousel = document.querySelector('#myCarousel')
-var carousel = new bootstrap.Carousel(myCarousel)
+const carousel = new bootstrap.Carousel('#myCarousel')
```
### Options
You can create a carousel instance with the carousel constructor, for example, to initialize with additional options and start cycling through items:
```js
-var myCarousel = document.querySelector('#myCarousel')
-var carousel = new bootstrap.Carousel(myCarousel, {
+const myCarouselElement = document.querySelector('#myCarousel')
+const carousel = new bootstrap.Carousel(myCarouselElement, {
interval: 2000,
wrap: false
})
{{< /bs-table >}}
```js
-var myCarousel = document.getElementById('myCarousel')
+const myCarousel = document.getElementById('myCarousel')
-myCarousel.addEventListener('slide.bs.carousel', function () {
+myCarousel.addEventListener('slide.bs.carousel', event => {
// do something...
})
```
Enable manually with:
```js
-var collapseElementList = Array.prototype.slice.call(document.querySelectorAll('.collapse'))
-var collapseList = collapseElementList.map(function (collapseEl) {
- return new bootstrap.Collapse(collapseEl)
-})
+const collapseElementList = document.querySelectorAll('.collapse')
+const collapseList = [...collapseElementList].map(collapseEl => new bootstrap.Collapse(collapseEl))
```
### Options
You can create a collapse instance with the constructor, for example:
```js
-var myCollapse = document.getElementById('myCollapse')
-var bsCollapse = new bootstrap.Collapse(myCollapse, {
+const bsCollapse = new bootstrap.Collapse('#myCollapse', {
toggle: false
})
```
{{< /bs-table >}}
```js
-var myCollapsible = document.getElementById('myCollapsible')
-myCollapsible.addEventListener('hidden.bs.collapse', function () {
+const myCollapsible = document.getElementById('myCollapsible')
+myCollapsible.addEventListener('hidden.bs.collapse', event => {
// do something...
})
```
Call the dropdowns via JavaScript:
```js
-var dropdownElementList = Array.prototype.slice.call(document.querySelectorAll('.dropdown-toggle'))
-var dropdownList = dropdownElementList.map(function (dropdownToggleEl) {
- return new bootstrap.Dropdown(dropdownToggleEl)
-})
+const dropdownElementList = document.querySelectorAll('.dropdown-toggle')
+const dropdownList = [...dropdownElementList].map(dropdownToggleEl => new bootstrap.Dropdown(dropdownToggleEl))
```
{{< callout info >}}
#### Using function with `popperConfig`
```js
-var dropdown = new bootstrap.Dropdown(element, {
- popperConfig: function (defaultBsPopperConfig) {
- // var newPopperConfig = {...}
+const dropdown = new bootstrap.Dropdown(element, {
+ popperConfig(defaultBsPopperConfig) {
+ // const newPopperConfig = {...}
// use defaultBsPopperConfig if needed...
// return newPopperConfig
}
{{< /bs-table >}}
```js
-var myDropdown = document.getElementById('myDropdown')
-myDropdown.addEventListener('show.bs.dropdown', function () {
+const myDropdown = document.getElementById('myDropdown')
+myDropdown.addEventListener('show.bs.dropdown', event => {
// do something...
})
```
Enable tabbable list item via JavaScript (each list item needs to be activated individually):
```js
-var triggerTabList = Array.prototype.slice.call(document.querySelectorAll('#myTab a'))
-triggerTabList.forEach(function (triggerEl) {
- var tabTrigger = new bootstrap.Tab(triggerEl)
+const triggerTabList = document.querySelectorAll('#myTab a')
+triggerTabList.forEach(triggerEl => {
+ const tabTrigger = new bootstrap.Tab(triggerEl)
- triggerEl.addEventListener('click', function (event) {
+ triggerEl.addEventListener('click', event => {
event.preventDefault()
tabTrigger.show()
})
You can activate individual list item in several ways:
```js
-var triggerEl = document.querySelector('#myTab a[href="#profile"]')
+const triggerEl = document.querySelector('#myTab a[href="#profile"]')
bootstrap.Tab.getInstance(triggerEl).show() // Select tab by name
-var triggerFirstTabEl = document.querySelector('#myTab li:first-child a')
+const triggerFirstTabEl = document.querySelector('#myTab li:first-child a')
bootstrap.Tab.getInstance(triggerFirstTabEl).show() // Select first tab
```
</div>
<script>
- var firstTabEl = document.querySelector('#myTab a:last-child')
- var firstTab = new bootstrap.Tab(firstTabEl)
+ const firstTabEl = document.querySelector('#myTab a:last-child')
+ const firstTab = new bootstrap.Tab(firstTabEl)
firstTab.show()
</script>
Selects the given list item and shows its associated pane. Any other list item that was previously selected becomes unselected and its associated pane is hidden. **Returns to the caller before the tab pane has actually been shown** (for example, before the `shown.bs.tab` event occurs).
```js
- var someListItemEl = document.querySelector('#someListItem')
- var tab = new bootstrap.Tab(someListItemEl)
+const tab = new bootstrap.Tab('#someListItem')
- tab.show()
+tab.show()
```
#### dispose
*Static* method which allows you to get the tab instance associated with a DOM element
```js
-var triggerEl = document.querySelector('#trigger')
-var tab = bootstrap.Tab.getInstance(triggerEl) // Returns a Bootstrap tab instance
+const tab = bootstrap.Tab.getInstance('#trigger') // Returns a Bootstrap tab instance
```
#### getOrCreateInstance
*Static* method which allows you to get the tab instance associated with a DOM element, or create a new one in case it wasn't initialized
```js
-var triggerEl = document.querySelector('#trigger')
-var tab = bootstrap.Tab.getOrCreateInstance(triggerEl) // Returns a Bootstrap tab instance
+const tab = bootstrap.Tab.getOrCreateInstance('#trigger') // Returns a Bootstrap tab instance
```
### Events
{{< /bs-table >}}
```js
-var tabElms = document.querySelectorAll('a[data-bs-toggle="list"]')
-tabElms.forEach(function(tabElm) {
- tabElm.addEventListener('shown.bs.tab', function (event) {
+const tabElms = document.querySelectorAll('a[data-bs-toggle="list"]')
+tabElms.forEach(tabElm => {
+ tabElm.addEventListener('shown.bs.tab', event => {
event.target // newly activated tab
event.relatedTarget // previous active tab
})
-}
+})
```
- Due to how HTML5 defines its semantics, [the `autofocus` HTML attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-autofocus) has no effect in Bootstrap modals. To achieve the same effect, use some custom JavaScript:
```js
-var myModal = document.getElementById('myModal')
-var myInput = document.getElementById('myInput')
+const myModal = document.getElementById('myModal')
+const myInput = document.getElementById('myInput')
-myModal.addEventListener('shown.bs.modal', function () {
+myModal.addEventListener('shown.bs.modal', () => {
myInput.focus()
})
```
{{< /example >}}
```js
-var exampleModal = document.getElementById('exampleModal')
-exampleModal.addEventListener('show.bs.modal', function (event) {
+const exampleModal = document.getElementById('exampleModal')
+exampleModal.addEventListener('show.bs.modal', event => {
// Button that triggered the modal
- var button = event.relatedTarget
+ const button = event.relatedTarget
// Extract info from data-bs-* attributes
- var recipient = button.getAttribute('data-bs-whatever')
+ const recipient = button.getAttribute('data-bs-whatever')
// If necessary, you could initiate an AJAX request here
// and then do the updating in a callback.
//
// Update the modal's content.
- var modalTitle = exampleModal.querySelector('.modal-title')
- var modalBodyInput = exampleModal.querySelector('.modal-body input')
+ const modalTitle = exampleModal.querySelector('.modal-title')
+ const modalBodyInput = exampleModal.querySelector('.modal-body input')
- modalTitle.textContent = 'New message to ' + recipient
+ modalTitle.textContent = `New message to ${recipient}`
modalBodyInput.value = recipient
})
```
Create a modal with a single line of JavaScript:
```js
-var myModal = new bootstrap.Modal(document.getElementById('myModal'), options)
+const myModal = new bootstrap.Modal(document.getElementById('myModal'), options)
+// or
+const myModalAlternative = new bootstrap.Modal('#myModal', options)
```
### Options
Activates your content as a modal. Accepts an optional options `object`.
```js
-var myModal = new bootstrap.Modal(document.getElementById('myModal'), {
+const myModal = new bootstrap.Modal('#myModal', {
keyboard: false
})
```
| Method | Description |
| --- | --- |
| `toggle` | Manually toggles a modal. **Returns to the caller before the modal has actually been shown or hidden** (i.e. before the `shown.bs.modal` or `hidden.bs.modal` event occurs). |
-| `show` | Manually opens a modal. **Returns to the caller before the modal has actually been shown** (i.e. before the `shown.bs.modal` event occurs). Also, you can pass a DOM element as an argument that can be received in the modal events (as the `relatedTarget` property). (i.e. `var modalToggle = document.getElementById('toggleMyModal'); myModal.show(modalToggle)` |
+| `show` | Manually opens a modal. **Returns to the caller before the modal has actually been shown** (i.e. before the `shown.bs.modal` event occurs). Also, you can pass a DOM element as an argument that can be received in the modal events (as the `relatedTarget` property). (i.e. `const modalToggle = document.getElementById('toggleMyModal'); myModal.show(modalToggle)` |
| `hide` | Manually hides a modal. **Returns to the caller before the modal has actually been hidden** (i.e. before the `hidden.bs.modal` event occurs). |
| `handleUpdate` | Manually readjust the modal's position if the height of a modal changes while it is open (i.e. in case a scrollbar appears). |
| `dispose` | Destroys an element's modal. (Removes stored data on the DOM element) |
{{< /bs-table >}}
```js
-var myModalEl = document.getElementById('myModal')
-myModalEl.addEventListener('hidden.bs.modal', function (event) {
+const myModalEl = document.getElementById('myModal')
+myModalEl.addEventListener('hidden.bs.modal', event => {
// do something...
})
```
Enable tabbable tabs via JavaScript (each tab needs to be activated individually):
```js
-var triggerTabList = Array.prototype.slice.call(document.querySelectorAll('#myTab button'))
-triggerTabList.forEach(function (triggerEl) {
- var tabTrigger = new bootstrap.Tab(triggerEl)
+const triggerTabList = document.querySelectorAll('#myTab button')
+triggerTabList.forEach(triggerEl => {
+ const tabTrigger = new bootstrap.Tab(triggerEl)
- triggerEl.addEventListener('click', function (event) {
+ triggerEl.addEventListener('click', event => {
event.preventDefault()
tabTrigger.show()
})
You can activate individual tabs in several ways:
```js
-var triggerEl = document.querySelector('#myTab button[data-bs-target="#profile"]')
+const triggerEl = document.querySelector('#myTab button[data-bs-target="#profile"]')
bootstrap.Tab.getInstance(triggerEl).show() // Select tab by name
-var triggerFirstTabEl = document.querySelector('#myTab li:first-child button')
+const triggerFirstTabEl = document.querySelector('#myTab li:first-child button')
bootstrap.Tab.getInstance(triggerFirstTabEl).show() // Select first tab
```
</div>
<script>
- var firstTabEl = document.querySelector('#myTab li:last-child button')
- var firstTab = new bootstrap.Tab(firstTabEl)
+ const firstTabEl = document.querySelector('#myTab li:last-child button')
+ const firstTab = new bootstrap.Tab(firstTabEl)
firstTab.show()
</script>
Selects the given tab and shows its associated pane. Any other tab that was previously selected becomes unselected and its associated pane is hidden. **Returns to the caller before the tab pane has actually been shown** (i.e. before the `shown.bs.tab` event occurs).
```js
- var someTabTriggerEl = document.querySelector('#someTabTrigger')
- var tab = new bootstrap.Tab(someTabTriggerEl)
+const someTabTriggerEl = document.querySelector('#someTabTrigger')
+const tab = new bootstrap.Tab(someTabTriggerEl)
- tab.show()
+tab.show()
```
#### dispose
*Static* method which allows you to get the tab instance associated with a DOM element
```js
-var triggerEl = document.querySelector('#trigger')
-var tab = bootstrap.Tab.getInstance(triggerEl) // Returns a Bootstrap tab instance
+const tab = bootstrap.Tab.getInstance('#trigger') // Returns a Bootstrap tab instance
```
#### getOrCreateInstance
*Static* method which allows you to get the tab instance associated with a DOM element, or create a new one in case it wasn't initialized
```js
-var triggerEl = document.querySelector('#trigger')
-var tab = bootstrap.Tab.getOrCreateInstance(triggerEl) // Returns a Bootstrap tab instance
+const tab = bootstrap.Tab.getOrCreateInstance('#trigger') // Returns a Bootstrap tab instance
```
### Events
{{< /bs-table >}}
```js
-var tabEl = document.querySelector('button[data-bs-toggle="tab"]')
-tabEl.addEventListener('shown.bs.tab', function (event) {
+const tabEl = document.querySelector('button[data-bs-toggle="tab"]')
+tabEl.addEventListener('shown.bs.tab', event => {
event.target // newly activated tab
event.relatedTarget // previous active tab
})
Enable manually with:
```js
-var offcanvasElementList = Array.prototype.slice.call(document.querySelectorAll('.offcanvas'))
-var offcanvasList = offcanvasElementList.map(function (offcanvasEl) {
- return new bootstrap.Offcanvas(offcanvasEl)
-})
+const offcanvasElementList = document.querySelectorAll('.offcanvas')
+const offcanvasList = [...offcanvasElementList].map(offcanvasEl => new bootstrap.Offcanvas(offcanvasEl))
```
### Options
You can create an offcanvas instance with the constructor, for example:
```js
-var myOffcanvas = document.getElementById('myOffcanvas')
-var bsOffcanvas = new bootstrap.Offcanvas(myOffcanvas)
+const bsOffcanvas = new bootstrap.Offcanvas('#myOffcanvas')
```
{{< bs-table "table" >}}
{{< /bs-table >}}
```js
-var myOffcanvas = document.getElementById('myOffcanvas')
-myOffcanvas.addEventListener('hidden.bs.offcanvas', function () {
+const myOffcanvas = document.getElementById('myOffcanvas')
+myOffcanvas.addEventListener('hidden.bs.offcanvas', event => {
// do something...
})
```
As mentioned above, you must initialize popovers before they can be used. One way to initialize all popovers on a page would be to select them by their `data-bs-toggle` attribute, like so:
```js
-var popoverTriggerList = Array.prototype.slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'))
-var popoverList = popoverTriggerList.map(function (popoverTriggerEl) {
- return new bootstrap.Popover(popoverTriggerEl)
-})
+const popoverTriggerList = document.querySelectorAll('[data-bs-toggle="popover"]')
+const popoverList = [...popoverTriggerList].map(popoverTriggerEl => new bootstrap.Popover(popoverTriggerEl))
```
### Live demo
When you have some styles on a parent element that interfere with a popover, you'll want to specify a custom `container` so that the popover's HTML appears within that element instead. This is common in responsive tables, input groups, and the like.
```js
-var popover = new bootstrap.Popover(document.querySelector('.example-popover'), {
+const popover = new bootstrap.Popover('.example-popover', {
container: 'body'
})
```
{{< /example >}}
```js
-var popover = new bootstrap.Popover(document.querySelector('.popover-dismiss'), {
+const popover = new bootstrap.Popover('.popover-dismiss', {
trigger: 'focus'
})
```
Enable popovers via JavaScript:
```js
-var exampleEl = document.getElementById('example')
-var popover = new bootstrap.Popover(exampleEl, options)
+const exampleEl = document.getElementById('example')
+const popover = new bootstrap.Popover(exampleEl, options)
```
{{< callout warning >}}
#### Using function with `popperConfig`
```js
-var popover = new bootstrap.Popover(element, {
- popperConfig: function (defaultBsPopperConfig) {
- // var newPopperConfig = {...}
+const popover = new bootstrap.Popover(element, {
+ popperConfig(defaultBsPopperConfig) {
+ // const newPopperConfig = {...}
// use defaultBsPopperConfig if needed...
// return newPopperConfig
}
```js
// getOrCreateInstance example
-var exampleTriggerEl = document.getElementById('example')
-var popover = bootstrap.Popover.getOrCreateInstance(exampleTriggerEl) // Returns a Bootstrap popover instance
+const popover = bootstrap.Popover.getOrCreateInstance('#example') // Returns a Bootstrap popover instance
// setContent example
myPopover.setContent({
{{< /bs-table >}}
```js
-var myPopoverTrigger = document.getElementById('myPopover')
-myPopoverTrigger.addEventListener('hidden.bs.popover', function () {
+const myPopoverTrigger = document.getElementById('myPopover')
+myPopoverTrigger.addEventListener('hidden.bs.popover', () => {
// do something...
})
```
### Via JavaScript
```js
-var scrollSpy = new bootstrap.ScrollSpy(document.body, {
+const scrollSpy = new bootstrap.ScrollSpy(document.body, {
target: '#navbar-example'
})
```
Here's an example using the refresh method:
```js
-var dataSpyList = Array.prototype.slice.call(document.querySelectorAll('[data-bs-spy="scroll"]'))
-dataSpyList.forEach(function (dataSpyEl) {
- bootstrap.ScrollSpy.getInstance(dataSpyEl)
- .refresh()
+const dataSpyList = document.querySelectorAll('[data-bs-spy="scroll"]')
+dataSpyList.forEach(dataSpyEl => {
+ bootstrap.ScrollSpy.getInstance(dataSpyEl).refresh()
})
```
{{< /bs-table >}}
```js
-var firstScrollSpyEl = document.querySelector('[data-bs-spy="scroll"]')
-firstScrollSpyEl.addEventListener('activate.bs.scrollspy', function () {
+const firstScrollSpyEl = document.querySelector('[data-bs-spy="scroll"]')
+firstScrollSpyEl.addEventListener('activate.bs.scrollspy', () => {
// do something...
})
```
We use the following JavaScript to trigger our live toast demo:
```js
-var toastTrigger = document.getElementById('liveToastBtn')
-var toastLiveExample = document.getElementById('liveToast')
+const toastTrigger = document.getElementById('liveToastBtn')
+const toastLiveExample = document.getElementById('liveToast')
if (toastTrigger) {
- toastTrigger.addEventListener('click', function () {
- var toast = new bootstrap.Toast(toastLiveExample)
+ toastTrigger.addEventListener('click', () => {
+ const toast = new bootstrap.Toast(toastLiveExample)
toast.show()
})
Initialize toasts via JavaScript:
```js
-var toastElList = Array.prototype.slice.call(document.querySelectorAll('.toast'))
-var toastList = toastElList.map(function (toastEl) {
- return new bootstrap.Toast(toastEl, option)
-})
+const toastElList = document.querySelectorAll('.toast')
+const toastList = [...toastElList].map(toastEl => new bootstrap.Toast(toastEl, option))
```
### Triggers
| `show` | Reveals an element's toast. **Returns to the caller before the toast has actually been shown** (i.e. before the `shown.bs.toast` event occurs). You have to manually call this method, instead your toast won't show. |
| `hide` | Hides an element's toast. **Returns to the caller before the toast has actually been hidden** (i.e. before the `hidden.bs.toast` event occurs). You have to manually call this method if you made `autohide` to `false`. |
| `dispose` | Hides an element's toast. Your toast will remain on the DOM but won't show anymore. |
-| `getInstance` | *Static* method which allows you to get the scrollspy instance associated with a DOM element. <br> For example: `var myToastEl = document.getElementById('myToastEl')` `var myToast = bootstrap.Toast.getInstance(myToastEl)` Returns a Bootstrap toast instance|
-| `getOrCreateInstance` | *Static* method which allows you to get the scrollspy instance associated with a DOM element, or create a new one, in case it wasn't initialized. <br>`var myToastEl = document.getElementById('myToastEl')` `var myToast = bootstrap.Toast.getOrCreateInstance(myToastEl)` Returns a Bootstrap toast instance |
+| `getInstance` | *Static* method which allows you to get the scrollspy instance associated with a DOM element. <br> For example: `const myToastEl = document.getElementById('myToastEl')` `const myToast = bootstrap.Toast.getInstance(myToastEl)` Returns a Bootstrap toast instance|
+| `getOrCreateInstance` | *Static* method which allows you to get the scrollspy instance associated with a DOM element, or create a new one, in case it wasn't initialized. <br>`const myToastEl = document.getElementById('myToastEl')` `const myToast = bootstrap.Toast.getOrCreateInstance(myToastEl)` Returns a Bootstrap toast instance |
{{< /bs-table >}}
### Events
{{< /bs-table >}}
```js
-var myToastEl = document.getElementById('myToast')
-myToastEl.addEventListener('hidden.bs.toast', function () {
+const myToastEl = document.getElementById('myToast')
+myToastEl.addEventListener('hidden.bs.toast', () => {
// do something...
})
```
As mentioned above, you must initialize tooltips before they can be used. One way to initialize all tooltips on a page would be to select them by their `data-bs-toggle` attribute, like so:
```js
-var tooltipTriggerList = Array.prototype.slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
-var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
- return new bootstrap.Tooltip(tooltipTriggerEl)
-})
+const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]')
+const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl))
```
### Tooltips on links
Trigger the tooltip via JavaScript:
```js
-var exampleEl = document.getElementById('example')
-var tooltip = new bootstrap.Tooltip(exampleEl, options)
+const exampleEl = document.getElementById('example')
+const tooltip = new bootstrap.Tooltip(exampleEl, options)
```
{{< callout warning >}}
Tooltip position attempts to automatically change when a **parent container** has `overflow: auto` or `overflow: scroll` like our `.table-responsive`, but still keeps the original placement's positioning. To resolve this, set the [`boundary` option](https://popper.js.org/docs/v2/modifiers/flip/#boundary) (for the flip modifier using the `popperConfig` option) to any HTMLElement to override the default value, `'clippingParents'`, such as `document.body`:
```js
-var exampleEl = document.getElementById('example')
-var tooltip = new bootstrap.Tooltip(exampleEl, {
+const tooltip = new bootstrap.Tooltip('#example', {
boundary: document.body // or document.querySelector('#boundary')
})
```
#### Using function with `popperConfig`
```js
-var tooltip = new bootstrap.Tooltip(element, {
- popperConfig: function (defaultBsPopperConfig) {
- // var newPopperConfig = {...}
+const tooltip = new bootstrap.Tooltip(element, {
+ popperConfig(defaultBsPopperConfig) {
+ // const newPopperConfig = {...}
// use defaultBsPopperConfig if needed...
// return newPopperConfig
}
{{< /bs-table >}}
```js
-// getOrCreateInstance example
-var exampleTriggerEl = document.getElementById('example')
-var tooltip = bootstrap.Tooltip.getInstance(exampleTriggerEl) // Returns a Bootstrap tooltip instance
+const tooltip = bootstrap.Tooltip.getInstance('#example') // Returns a Bootstrap tooltip instance
// setContent example
tooltip.setContent({ '.tooltip-inner': 'another title' })
{{< /bs-table >}}
```js
-var myTooltipEl = document.getElementById('myTooltip')
-var tooltip = new bootstrap.Tooltip(myTooltipEl)
+const myTooltipEl = document.getElementById('myTooltip')
+const tooltip = bootstrap.Tooltip.getOrCreateInstance(myTooltipEl)
-myTooltipEl.addEventListener('hidden.bs.tooltip', function () {
+myTooltipEl.addEventListener('hidden.bs.tooltip', () => {
// do something...
})
For instance, assuming you're using your own JavaScript bundler like Webpack or Rollup, you'd only import the JavaScript you plan on using. In the example below, we show how to just include our modal JavaScript:
+<!-- eslint-skip -->
```js
// Import just what we need
Files in `bootstrap/js/dist` use the **default export**, so if you want to use one of them you have to do the following:
+<!-- eslint-skip -->
```js
import Modal from 'bootstrap/js/dist/modal'
All infinitive events provide [`preventDefault()`](https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault) functionality. This provides the ability to stop the execution of an action before it starts. Returning false from an event handler will also automatically call `preventDefault()`.
```js
-var myModal = document.getElementById('myModal')
+const myModal = document.getElementById('myModal')
-myModal.addEventListener('show.bs.modal', function (event) {
+myModal.addEventListener('show.bs.modal', event => {
if (!data) {
return event.preventDefault() // stops modal from being shown
}
Bootstrap will detect jQuery if `jQuery` is present in the `window` object and there is no `data-bs-no-jquery` attribute set on `<body>`. If jQuery is found, Bootstrap will emit events thanks to jQuery's event system. So if you want to listen to Bootstrap's events, you'll have to use the jQuery methods (`.on`, `.one`) instead of `addEventListener`.
```js
-$('#myTab a').on('shown.bs.tab', function () {
+$('#myTab a').on('shown.bs.tab', () => {
// do something...
})
```
All constructors accept an optional options object or nothing (which initiates a plugin with its default behavior):
```js
-var myModalEl = document.getElementById('myModal')
+const myModalEl = document.getElementById('myModal')
-var modal = new bootstrap.Modal(myModalEl) // initialized with defaults
-var modal = new bootstrap.Modal(myModalEl, { keyboard: false }) // initialized with no keyboard
+const modal = new bootstrap.Modal(myModalEl) // initialized with defaults
+const modal1 = new bootstrap.Modal(myModalEl, { keyboard: false }) // initialized with no keyboard
```
If you'd like to get a particular plugin instance, each plugin exposes a `getInstance` method. In order to retrieve it directly from an element, do this: `bootstrap.Popover.getInstance(myPopoverEl)`.
You can also use a CSS selector as the first argument instead of a DOM element to initialize the plugin. Currently the element for the plugin is found by the `querySelector` method since our plugins support a single element only.
```js
-var modal = new bootstrap.Modal('#myModal')
-var dropdown = new bootstrap.Dropdown('[data-bs-toggle="dropdown"]')
+const modal = new bootstrap.Modal('#myModal')
+const dropdown = new bootstrap.Dropdown('[data-bs-toggle="dropdown"]')
```
### Asynchronous functions and transitions
In order to execute an action once the transition is complete, you can listen to the corresponding event.
```js
-var myCollapseEl = document.getElementById('myCollapse')
+const myCollapseEl = document.getElementById('myCollapse')
-myCollapseEl.addEventListener('shown.bs.collapse', function (event) {
+myCollapseEl.addEventListener('shown.bs.collapse', event => {
// Action to execute once the collapsible area is expanded
})
```
In addition a method call on a **transitioning component will be ignored**.
```js
-var myCarouselEl = document.getElementById('myCarousel')
-var carousel = bootstrap.Carousel.getInstance(myCarouselEl) // Retrieve a Carousel instance
+const myCarouselEl = document.getElementById('myCarousel')
+const carousel = bootstrap.Carousel.getInstance(myCarouselEl) // Retrieve a Carousel instance
-myCarouselEl.addEventListener('slid.bs.carousel', function (event) {
+myCarouselEl.addEventListener('slid.bs.carousel', event => {
carousel.to('2') // Will slide to the slide 2 as soon as the transition to slide 1 is finished
})
Sometimes it is necessary to use Bootstrap plugins with other UI frameworks. In these circumstances, namespace collisions can occasionally occur. If this happens, you may call `.noConflict` on the plugin you wish to revert the value of.
```js
-var bootstrapButton = $.fn.button.noConflict() // return $.fn.button to previously assigned value
+const bootstrapButton = $.fn.button.noConflict() // return $.fn.button to previously assigned value
$.fn.bootstrapBtn = bootstrapButton // give $().bootstrapBtn the Bootstrap functionality
```
The default `allowList` value is the following:
```js
-var ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i
-var DefaultAllowlist = {
+const ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i
+const DefaultAllowlist = {
// Global attributes allowed on any supplied element below.
'*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],
a: ['target', 'href', 'title', 'rel'],
If you want to add new values to this default `allowList` you can do the following:
```js
-var myDefaultAllowList = bootstrap.Tooltip.Default.allowList
+const myDefaultAllowList = bootstrap.Tooltip.Default.allowList
// To allow table elements
myDefaultAllowList.table = []
// You can push your custom regex to validate your attributes.
// Be careful about your regular expressions being too lax
-var myCustomRegex = /^data-my-app-[\w-]+/
+const myCustomRegex = /^data-my-app-[\w-]+/
myDefaultAllowList['*'].push(myCustomRegex)
```
If you want to bypass our sanitizer because you prefer to use a dedicated library, for example [DOMPurify](https://www.npmjs.com/package/dompurify), you should do the following:
```js
-var yourTooltipEl = document.getElementById('yourTooltip')
-var tooltip = new bootstrap.Tooltip(yourTooltipEl, {
- sanitizeFn: function (content) {
+const yourTooltipEl = document.getElementById('yourTooltip')
+const tooltip = new bootstrap.Tooltip(yourTooltipEl, {
+ sanitizeFn(content) {
return DOMPurify.sanitize(content)
}
})
Import [Bootstrap's JavaScript]({{< docsref "/getting-started/javascript" >}}) in your app's entry point (usually `src/index.js`). You can import all our plugins in one file or separately if you require only a subset of them.
+<!-- eslint-skip -->
```js
// Import all plugins
import * as bootstrap from 'bootstrap';
Import [Bootstrap's JavaScript]({{< docsref "/getting-started/javascript" >}}) by adding this line to your app's entry point (usually `index.js` or `app.js`):
+<!-- eslint-skip -->
```js
import 'bootstrap';
Alternatively, if you only need just a few of our plugins, you may **import plugins individually** as needed:
+<!-- eslint-skip -->
```js
import Alert from 'bootstrap/js/dist/alert';
For Bootstrap to compile, make sure you install and use the required loaders: [sass-loader](https://github.com/webpack-contrib/sass-loader), [postcss-loader](https://github.com/webpack-contrib/postcss-loader) with [Autoprefixer](https://github.com/postcss/autoprefixer#webpack). With minimal setup, your webpack config should include this rule or similar:
+<!-- eslint-skip -->
```js
// ...
{
// if you use postcss 7.x skip the key
postcssOptions: {
// postcss plugins, can be exported to postcss.config.js
- plugins: function () {
- return [
+ plugins: () => {
+ [
require('autoprefixer')
];
}
Alternatively, you may use Bootstrap's ready-to-use CSS by simply adding this line to your project's entry point:
+<!-- eslint-skip -->
```js
import 'bootstrap/dist/css/bootstrap.min.css';
```
- **All plugins can now accept a CSS selector as the first argument.** You can either pass a DOM element or any valid CSS selector to create a new instance of the plugin:
```js
- var modal = new bootstrap.Modal('#myModal')
- var dropdown = new bootstrap.Dropdown('[data-bs-toggle="dropdown"]')
+ const modal = new bootstrap.Modal('#myModal')
+ const dropdown = new bootstrap.Dropdown('[data-bs-toggle="dropdown"]')
```
- `popperConfig` can be passed as a function that accepts the Bootstrap's default Popper config as an argument, so that you can merge this default configuration in your way. **Applies to dropdowns, popovers, and tooltips.**