Compare commits

..

4 Commits

Author SHA1 Message Date
Julien Déramond 8446581c3d Add new Sass mixins to the documentation 2025-09-04 22:34:24 +02:00
Julien Déramond 8915efae15 Fix docs compilation to avoid duplicate IDs 2025-09-04 22:30:39 +02:00
louismaxime.piton 72ee1af96a Proposal 2025-09-04 22:25:14 +02:00
Mark Otto f0700c7c3c Add option for always visible floating labels 2025-09-04 22:22:03 +02:00
430 changed files with 18579 additions and 20455 deletions
+8 -8
View File
@@ -2,35 +2,35 @@
"files": [
{
"path": "./dist/css/bootstrap-grid.css",
"maxSize": "10.0 kB"
"maxSize": "6.5 kB"
},
{
"path": "./dist/css/bootstrap-grid.min.css",
"maxSize": "9.0 kB"
"maxSize": "6.0 kB"
},
{
"path": "./dist/css/bootstrap-reboot.css",
"maxSize": "5.5 kB"
"maxSize": "3.5 kB"
},
{
"path": "./dist/css/bootstrap-reboot.min.css",
"maxSize": "4.5 kB"
"maxSize": "3.25 kB"
},
{
"path": "./dist/css/bootstrap-utilities.css",
"maxSize": "15.25 kB"
"maxSize": "11.75 kB"
},
{
"path": "./dist/css/bootstrap-utilities.min.css",
"maxSize": "13.5 kB"
"maxSize": "10.75 kB"
},
{
"path": "./dist/css/bootstrap.css",
"maxSize": "37.5 kB"
"maxSize": "32.5 kB"
},
{
"path": "./dist/css/bootstrap.min.css",
"maxSize": "33.75 kB"
"maxSize": "30.25 kB"
},
{
"path": "./dist/js/bootstrap.bundle.js",
-3
View File
@@ -21,7 +21,6 @@
"callout",
"callouts",
"camelCase",
"checkgroup",
"clearfix",
"Codesniffer",
"combinator",
@@ -30,7 +29,6 @@
"Crossfade",
"crossfading",
"cssgrid",
"csstricks",
"Csvg",
"Datalists",
"Deque",
@@ -48,7 +46,6 @@
"favicons",
"fieldsets",
"flexbox",
"frontmatter",
"fullscreen",
"getbootstrap",
"Grayscale",
+1 -1
View File
@@ -27,7 +27,7 @@ jobs:
persist-credentials: false
- name: Set up Node.js
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: "${{ env.NODE }}"
cache: npm
+1 -1
View File
@@ -25,7 +25,7 @@ jobs:
persist-credentials: false
- name: Set up Node.js
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: "${{ env.NODE }}"
cache: npm
@@ -27,6 +27,6 @@ jobs:
persist-credentials: false
- name: Compress Images
uses: calibreapp/image-actions@f32575787d333b0579f0b7d506ff03be63a669d1 # v1.4.1
uses: calibreapp/image-actions@f72c7c4a237181dd3b26e5935fd33b22ae4a7e26 # v1.4.0
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+3 -3
View File
@@ -29,16 +29,16 @@ jobs:
persist-credentials: false
- name: Initialize CodeQL
uses: github/codeql-action/init@0499de31b99561a6d14a36a5f662c2a54f91beee # v4.31.2
uses: github/codeql-action/init@2d92b76c45b91eb80fc44c74ce3fce0ee94e8f9d # v3.30.0
with:
config-file: ./.github/codeql/codeql-config.yml
languages: "javascript"
queries: +security-and-quality
- name: Autobuild
uses: github/codeql-action/autobuild@0499de31b99561a6d14a36a5f662c2a54f91beee # v4.31.2
uses: github/codeql-action/autobuild@2d92b76c45b91eb80fc44c74ce3fce0ee94e8f9d # v3.30.0
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@0499de31b99561a6d14a36a5f662c2a54f91beee # v4.31.2
uses: github/codeql-action/analyze@2d92b76c45b91eb80fc44c74ce3fce0ee94e8f9d # v3.30.0
with:
category: "/language:javascript"
+1 -1
View File
@@ -28,7 +28,7 @@ jobs:
persist-credentials: false
- name: Run cspell
uses: streetsidesoftware/cspell-action@3294df585d3d639e30f3bc019cb11940b9866e95 # v8.0.0
uses: streetsidesoftware/cspell-action@dcd03dc3e8a59ec2e360d0c62db517baa0b4bb6d # v7.2.0
with:
config: ".cspell.json"
files: "**/*.{md,mdx}"
+1 -1
View File
@@ -25,7 +25,7 @@ jobs:
persist-credentials: false
- name: Set up Node.js
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: "${{ env.NODE }}"
cache: npm
+5 -3
View File
@@ -25,11 +25,13 @@ jobs:
persist-credentials: false
- name: Set up Node.js
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: "${{ env.NODE }}"
cache: npm
- run: java -version
- name: Install npm dependencies
run: npm ci
@@ -37,10 +39,10 @@ jobs:
run: npm run docs-build
- name: Validate HTML
run: npm run docs-html-validate
run: npm run docs-vnu
- name: Run linkinator
uses: JustinBeckwith/linkinator-action@af984b9f30f63e796ae2ea5be5e07cb587f1bbd9 # v2.3
uses: JustinBeckwith/linkinator-action@3d5ba091319fa7b0ac14703761eebb7d100e6f6d # v1.11.0
with:
paths: _site
recurse: true
+1 -1
View File
@@ -17,7 +17,7 @@ jobs:
if: github.repository == 'twbs/bootstrap'
steps:
- name: awaiting reply
uses: actions-cool/issues-helper@9861779a695cf1898bd984c727f685f351cfc372 # v3.7.2
uses: actions-cool/issues-helper@45d75b6cf72bf4f254be6230cb887ad002702491 # v3.6.3
with:
actions: "close-issues"
labels: "awaiting-reply"
+1 -1
View File
@@ -18,7 +18,7 @@ jobs:
steps:
- name: awaiting reply
if: github.event.label.name == 'needs-example'
uses: actions-cool/issues-helper@9861779a695cf1898bd984c727f685f351cfc372 # v3.7.2
uses: actions-cool/issues-helper@45d75b6cf72bf4f254be6230cb887ad002702491 # v3.6.3
with:
actions: "create-comment"
token: ${{ secrets.GITHUB_TOKEN }}
+1 -1
View File
@@ -30,7 +30,7 @@ jobs:
persist-credentials: false
- name: Set up Node.js
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: ${{ env.NODE }}
cache: npm
+1 -1
View File
@@ -25,7 +25,7 @@ jobs:
persist-credentials: false
- name: Set up Node.js
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: "${{ env.NODE }}"
cache: npm
+49
View File
@@ -0,0 +1,49 @@
name: CSS (node-sass)
on:
push:
branches:
- main
pull_request:
workflow_dispatch:
env:
FORCE_COLOR: 2
NODE: 22
permissions:
contents: read
jobs:
css:
runs-on: ubuntu-latest
steps:
- name: Clone repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- name: Set up Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: "${{ env.NODE }}"
- name: Build CSS with node-sass
run: |
npx --package node-sass@latest node-sass --version
npx --package node-sass@latest node-sass --output-style expanded --source-map true --source-map-contents true --precision 6 scss/ -o dist-sass/css/
ls -Al dist-sass/css
- name: Check built CSS files for Sass variables
shell: bash
run: |
SASS_VARS_FOUND=$(find "dist-sass/css/" -type f -name "*.css" -print0 | xargs -0 --no-run-if-empty grep -F "\$" || true)
if [[ -z "$SASS_VARS_FOUND" ]]; then
echo "All good, no Sass variables found!"
exit 0
else
echo "Found $(echo "$SASS_VARS_FOUND" | wc -l | bc) Sass variables:"
echo "$SASS_VARS_FOUND"
exit 1
fi
+3 -3
View File
@@ -39,7 +39,7 @@ jobs:
persist-credentials: false
- name: "Run analysis"
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2
with:
results_file: results.sarif
results_format: sarif
@@ -64,7 +64,7 @@ jobs:
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: SARIF file
path: results.sarif
@@ -73,6 +73,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard (optional).
# Commenting out will disable upload of results to your repo's Code Scanning dashboard
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@0499de31b99561a6d14a36a5f662c2a54f91beee # v4.31.2
uses: github/codeql-action/upload-sarif@2d92b76c45b91eb80fc44c74ce3fce0ee94e8f9d # v3.30.0
with:
sarif_file: results.sarif
-1
View File
@@ -18,7 +18,6 @@
.cache
.DS_Store
.idea
.nvmrc
.project
.settings
.tmproj
-18
View File
@@ -1,18 +0,0 @@
{
"default": true,
"MD004": { "style": "dash" },
"MD011": false,
"MD013": false,
"MD024": false,
"MD025": false,
"MD026": false,
"MD031": false,
"MD033": false,
"MD034": false,
"MD037": false,
"MD038": false,
"MD041": false,
"MD046": false,
"line-length": false,
"no-inline-html": false
}
+1
View File
@@ -13,6 +13,7 @@
"outline": "none"
},
"function-disallowed-list": [
"calc",
"lighten",
"darken"
],
+18 -2
View File
@@ -87,18 +87,34 @@ Within the download youll find the following directories and files, logically
│ ├── bootstrap-grid.css.map
│ ├── bootstrap-grid.min.css
│ ├── bootstrap-grid.min.css.map
│ ├── bootstrap-grid.rtl.css
│ ├── bootstrap-grid.rtl.css.map
│ ├── bootstrap-grid.rtl.min.css
│ ├── bootstrap-grid.rtl.min.css.map
│ ├── bootstrap-reboot.css
│ ├── bootstrap-reboot.css.map
│ ├── bootstrap-reboot.min.css
│ ├── bootstrap-reboot.min.css.map
│ ├── bootstrap-reboot.rtl.css
│ ├── bootstrap-reboot.rtl.css.map
│ ├── bootstrap-reboot.rtl.min.css
│ ├── bootstrap-reboot.rtl.min.css.map
│ ├── bootstrap-utilities.css
│ ├── bootstrap-utilities.css.map
│ ├── bootstrap-utilities.min.css
│ ├── bootstrap-utilities.min.css.map
│ ├── bootstrap-utilities.rtl.css
│ ├── bootstrap-utilities.rtl.css.map
│ ├── bootstrap-utilities.rtl.min.css
│ ├── bootstrap-utilities.rtl.min.css.map
│ ├── bootstrap.css
│ ├── bootstrap.css.map
│ ├── bootstrap.min.css
── bootstrap.min.css.map
── bootstrap.min.css.map
│ ├── bootstrap.rtl.css
│ ├── bootstrap.rtl.css.map
│ ├── bootstrap.rtl.min.css
│ └── bootstrap.rtl.min.css.map
└── js/
├── bootstrap.bundle.js
├── bootstrap.bundle.js.map
@@ -115,7 +131,7 @@ Within the download youll find the following directories and files, logically
```
</details>
We provide compiled CSS and JS (`bootstrap.*`), as well as compiled and minified CSS and JS (`bootstrap.min.*`). [Source maps](https://web.dev/articles/source-maps) (`bootstrap.*.map`) are available for use with certain browsers' developer tools. Bundled JS files (`bootstrap.bundle.js` and minified `bootstrap.bundle.min.js`) include [Popper](https://popper.js.org/docs/v2/). All CSS files work for both LTR and RTL layouts thanks to logical properties—simply set `dir="rtl"` on your HTML element.
We provide compiled CSS and JS (`bootstrap.*`), as well as compiled and minified CSS and JS (`bootstrap.min.*`). [Source maps](https://web.dev/articles/source-maps) (`bootstrap.*.map`) are available for use with certain browsers developer tools. Bundled JS files (`bootstrap.bundle.js` and minified `bootstrap.bundle.min.js`) include [Popper](https://popper.js.org/docs/v2/).
## Bugs and feature requests
+4
View File
@@ -29,6 +29,10 @@ const files = [
file: 'dist/css/bootstrap.min.css',
configPropertyName: 'css_hash'
},
{
file: 'dist/css/bootstrap.rtl.min.css',
configPropertyName: 'css_rtl_hash'
},
{
file: 'dist/js/bootstrap.min.js',
configPropertyName: 'js_hash'
-87
View File
@@ -1,87 +0,0 @@
#!/usr/bin/env node
/**
* Generate utilities metadata JSON from Sass
* This script compiles a special Sass file that outputs utility information as CSS comments,
* then extracts and saves it as JSON for documentation use.
*/
import { readFileSync, writeFileSync, unlinkSync } from 'node:fs'
import { execSync } from 'node:child_process'
import { fileURLToPath } from 'node:url'
import path from 'node:path'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const rootDir = path.join(__dirname, '..')
// Compile the metadata generator SCSS file
console.log('Compiling utilities metadata...')
try {
execSync(
'sass --style expanded --no-source-map build/generate-utilities-metadata.scss:dist/css/utilities-metadata.tmp.css',
{ cwd: rootDir, stdio: 'inherit' }
)
} catch {
console.error('Failed to compile metadata SCSS')
process.exit(1)
}
// Read the compiled CSS
const cssPath = path.join(rootDir, 'dist/css/utilities-metadata.tmp.css')
const cssContent = readFileSync(cssPath, 'utf8')
// Extract JSON from the CSS comment
const startMarker = 'BOOTSTRAP-UTILITIES-METADATA-START'
const endMarker = 'BOOTSTRAP-UTILITIES-METADATA-END'
const startIndex = cssContent.indexOf(startMarker)
const endIndex = cssContent.indexOf(endMarker)
if (startIndex === -1 || endIndex === -1) {
console.error('Could not find metadata markers in compiled CSS')
process.exit(1)
}
// Extract JSON content between markers
const jsonContent = cssContent
.slice(startIndex + startMarker.length, endIndex)
.trim()
// Validate JSON
try {
const parsed = JSON.parse(jsonContent)
console.log(`✓ Extracted metadata for ${Object.keys(parsed.utilities).length} utilities`)
// Write to JSON file
const outputPath = path.join(rootDir, 'dist/css/bootstrap-utilities.metadata.json')
writeFileSync(outputPath, JSON.stringify(parsed, null, 2))
console.log(`✓ Wrote metadata to ${outputPath}`)
// Clean up temporary CSS files
try {
unlinkSync(cssPath)
} catch {
// File may not exist
}
// Also clean up any other temporary variants that may have been created
const tempFiles = [
'dist/css/utilities-metadata.tmp.min.css',
'dist/css/utilities-metadata.tmp.min.css.map'
]
for (const file of tempFiles) {
try {
unlinkSync(path.join(rootDir, file))
} catch {
// File may not exist, ignore
}
}
console.log('✓ Cleaned up temporary files')
} catch (error) {
console.error('Failed to parse extracted JSON:', error.message)
console.error('Extracted content:', jsonContent.slice(0, 500))
process.exit(1)
}
-112
View File
@@ -1,112 +0,0 @@
// Generate utilities metadata JSON for documentation
// This file is compiled to extract utility information without generating CSS
@use "sass:map";
@use "sass:list";
@use "sass:string";
@use "sass:meta";
@use "../scss/config" as *;
@use "../scss/colors" as *;
@use "../scss/variables" as *;
@use "../scss/functions" as *;
@use "../scss/theme" as *;
@use "../scss/utilities" as *;
// Access the utilities map
$utilities-map: $utilities !default;
// Start JSON output
$json: '{"utilities":{' !default;
$utility-count: 0 !default;
$total-utilities: list.length(map.keys($utilities-map)) !default;
@each $key, $utility in $utilities-map {
$utility-count: $utility-count + 1;
// Skip if utility is null or false (disabled)
@if $utility {
// Extract class prefix
$class: if(map.has-key($utility, "class"), map.get($utility, "class"), $key);
// Extract property
$property: if(map.has-key($utility, "property"), map.get($utility, "property"), null);
// Extract values
$values: if(map.has-key($utility, "values"), map.get($utility, "values"), null);
// Generate class list
$classes: "";
@if $values {
@if meta.type-of($values) == "map" {
$value-keys: map.keys($values);
$first: true;
@each $value-key in $value-keys {
@if not $first {
$classes: $classes + ", ";
}
$class-name: if($value-key == "null" or $value-key == null, $class, "#{$class}-#{$value-key}");
$classes: $classes + '"' + $class-name + '"';
$first: false;
}
} @else if meta.type-of($values) == "list" {
$first: true;
@each $value in $values {
@if not $first {
$classes: $classes + ", ";
}
$class-name: "#{$class}-#{$value}";
$classes: $classes + '"' + $class-name + '"';
$first: false;
}
}
}
// Build JSON entry
$json: $json + '"' + $key + '":{"class":"' + $class + '"';
@if $property {
@if meta.type-of($property) == "string" {
$json: $json + ',"property":"' + $property + '"';
} @else if meta.type-of($property) == "list" {
$property-str: "";
$first: true;
@each $prop in $property {
@if not $first {
$property-str: $property-str + " ";
}
$property-str: $property-str + $prop;
$first: false;
}
$json: $json + ',"property":"' + $property-str + '"';
}
// Skip map properties as they're complex and don't translate to JSON well
}
@if $classes != "" {
$json: $json + ',"classes":[' + $classes + "]";
} @else {
$json: $json + ',"classes":[]';
}
$json: $json + "}";
@if $utility-count < $total-utilities {
$json: $json + ",";
}
}
}
// stylelint-disable-next-line scss/dollar-variable-default
$json: $json + "}}";
// Output as CSS comment so it appears in compiled file
/*! BOOTSTRAP-UTILITIES-METADATA-START
#{$json}
BOOTSTRAP-UTILITIES-METADATA-END */
// Prevent any actual CSS output
.bootstrap-utilities-metadata-generator {
content: "This file should not generate CSS, only metadata comments";
}
-104
View File
@@ -1,104 +0,0 @@
#!/usr/bin/env node
/*!
* Script to run html-validate for HTML validation.
*
* This replaces the Java-based vnu-jar validator with a faster, Node.js-only solution.
* Benefits:
* - No Java dependency required
* - Faster execution (no JVM startup time)
* - Easy to configure with rule-based system
* - Better integration with Node.js build tools
*
* Copyright 2017-2025 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
import { HtmlValidate } from 'html-validate'
import { globby } from 'globby'
const htmlValidate = new HtmlValidate({
rules: {
// Allow autocomplete on buttons (Bootstrap specific)
'attribute-allowed-values': 'off',
// Allow aria-disabled on links (Bootstrap specific)
'aria-label-misuse': 'off',
// Allow modern CSS syntax
'valid-id': 'off',
// Allow void elements with trailing slashes (Astro)
'void-style': 'off',
// Allow custom attributes
'no-unknown-elements': 'off',
'attribute-boolean-style': 'off',
'no-inline-style': 'off',
// KEEP duplicate ID checking enabled (this is important for HTML validity)
'no-dup-id': 'error'
},
elements: [
'html5',
{
// Allow custom attributes for Astro/framework compatibility
'*': {
attributes: {
'is:raw': { boolean: true },
switch: { boolean: true },
autocomplete: { enum: ['on', 'off', 'new-password', 'current-password'] }
}
}
}
]
})
async function validateHTML() {
try {
console.log('Running html-validate validation...')
// Find all HTML files
const files = await globby([
'_site/**/*.html',
'js/tests/**/*.html'
], {
ignore: ['**/node_modules/**']
})
console.log(`Validating ${files.length} HTML files...`)
let hasErrors = false
// Validate all files in parallel to avoid await-in-loop
const validationPromises = files.map(file =>
htmlValidate.validateFile(file).then(report => ({ file, report }))
)
const validationResults = await Promise.all(validationPromises)
// Process results and check for errors
for (const { file, report } of validationResults) {
if (!report.valid) {
hasErrors = true
console.error(`\nErrors in ${file}:`)
// Extract error messages with reduced nesting
const errorMessages = report.results.flatMap(result =>
result.messages.filter(message => message.severity === 2)
)
for (const message of errorMessages) {
console.error(` Line ${message.line}:${message.column} - ${message.message} (${message.ruleId})`)
}
}
}
if (hasErrors) {
console.error('\nHTML validation failed!')
process.exit(1)
} else {
console.log('✓ All HTML files are valid!')
}
} catch (error) {
console.error('HTML validation error:', error)
process.exit(1)
}
}
validateHTML()
+2 -1
View File
@@ -10,7 +10,8 @@ export default context => {
plugins: {
autoprefixer: {
cascade: false
}
},
rtlcss: context.env === 'RTL'
}
}
}
+66
View File
@@ -0,0 +1,66 @@
#!/usr/bin/env node
/*!
* Script to run vnu-jar if Java is available.
* Copyright 2017-2025 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
import { execFile, spawn } from 'node:child_process'
import vnu from 'vnu-jar'
execFile('java', ['-version'], (error, stdout, stderr) => {
if (error) {
console.error('Skipping vnu-jar test; Java is probably missing.')
console.error(error)
return
}
console.log('Running vnu-jar validation...')
const is32bitJava = !/64-Bit/.test(stderr)
// vnu-jar accepts multiple ignores joined with a `|`.
// Also note that the ignores are string regular expressions.
const ignores = [
// "autocomplete" is included in <button> and checkboxes and radio <input>s due to
// Firefox's non-standard autocomplete behavior - see https://bugzilla.mozilla.org/show_bug.cgi?id=654072
'Attribute “autocomplete” is only allowed when the input type is.*',
'Attribute “autocomplete” not allowed on element “button” at this point.',
// Per https://www.w3.org/TR/html-aria/#docconformance having "aria-disabled" on a link is
// NOT RECOMMENDED, but it's still valid - we explain in the docs that it's not ideal,
// and offer more robust alternatives, but also need to show a less-than-ideal example
'An “aria-disabled” attribute whose value is “true” should not be specified on an “a” element that has an “href” attribute.',
// A `code` element with the `is:raw` attribute coming from remark-prismjs (Astro upstream possible bug)
'Attribute “is:raw” is not serializable as XML 1.0.',
'Attribute “is:raw” not allowed on element “code” at this point.',
// Astro's expecting trailing slashes on HTML tags such as <br />
'Trailing slash on void elements has no effect and interacts badly with unquoted attribute values.',
// Allow `switch` attribute.
'Attribute “switch” not allowed on element “input” at this point.'
].join('|')
const args = [
'-jar',
`"${vnu}"`,
'--asciiquotes',
'--skip-non-html',
'--Werror',
`--filterpattern "${ignores}"`,
'_site/',
'js/tests/'
]
// For the 32-bit Java we need to pass `-Xss512k`
if (is32bitJava) {
args.splice(0, 0, '-Xss512k')
}
console.log(`command used: java ${args.join(' ')}`)
return spawn('java', args, {
shell: true,
stdio: 'inherit'
})
.on('exit', process.exit)
})
+2
View File
@@ -36,6 +36,8 @@ cdn:
# See https://www.srihash.org for info on how to generate the hashes
css: "https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css"
css_hash: "sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB"
css_rtl: "https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.rtl.min.css"
css_rtl_hash: "sha384-CfCrinSRH2IR6a4e6fy2q6ioOX7O6Mtm1L9vRvFZ1trBncWmMePhzvafv7oIcWiW"
js: "https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.min.js"
js_hash: "sha384-G/EV+4j2dNv+tEPo3++6LCgdCROaejBqfUeNjuKAiuXbjrxilcCdDz6ZAVfHWe1Y"
js_bundle: "https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"
File diff suppressed because it is too large Load Diff
+511 -206
View File
@@ -57,6 +57,252 @@
}
};
/**
* --------------------------------------------------------------------------
* Bootstrap util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
const MAX_UID = 1000000;
const MILLISECONDS_MULTIPLIER = 1000;
const TRANSITION_END = 'transitionend';
/**
* Properly escape IDs selectors to handle weird IDs
* @param {string} selector
* @returns {string}
*/
const parseSelector = selector => {
if (selector && window.CSS && window.CSS.escape) {
// document.querySelector needs escaping to handle IDs (html5+) containing for instance /
selector = selector.replace(/#([^\s"#']+)/g, (match, id) => `#${CSS.escape(id)}`);
}
return selector;
};
// Shout-out Angus Croll (https://goo.gl/pxwQGp)
const toType = object => {
if (object === null || object === undefined) {
return `${object}`;
}
return Object.prototype.toString.call(object).match(/\s([a-z]+)/i)[1].toLowerCase();
};
/**
* Public Util API
*/
const getUID = prefix => {
do {
prefix += Math.floor(Math.random() * MAX_UID);
} while (document.getElementById(prefix));
return prefix;
};
const getTransitionDurationFromElement = element => {
if (!element) {
return 0;
}
// Get transition-duration of the element
let {
transitionDuration,
transitionDelay
} = window.getComputedStyle(element);
const floatTransitionDuration = Number.parseFloat(transitionDuration);
const floatTransitionDelay = Number.parseFloat(transitionDelay);
// Return 0 if element or transition duration is not found
if (!floatTransitionDuration && !floatTransitionDelay) {
return 0;
}
// If multiple durations are defined, take the first
transitionDuration = transitionDuration.split(',')[0];
transitionDelay = transitionDelay.split(',')[0];
return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER;
};
const triggerTransitionEnd = element => {
element.dispatchEvent(new Event(TRANSITION_END));
};
const isElement$1 = object => {
if (!object || typeof object !== 'object') {
return false;
}
if (typeof object.jquery !== 'undefined') {
object = object[0];
}
return typeof object.nodeType !== 'undefined';
};
const getElement = object => {
// it's a jQuery object or a node element
if (isElement$1(object)) {
return object.jquery ? object[0] : object;
}
if (typeof object === 'string' && object.length > 0) {
return document.querySelector(parseSelector(object));
}
return null;
};
const isVisible = element => {
if (!isElement$1(element) || element.getClientRects().length === 0) {
return false;
}
const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible';
// Handle `details` element as its content may falsie appear visible when it is closed
const closedDetails = element.closest('details:not([open])');
if (!closedDetails) {
return elementIsVisible;
}
if (closedDetails !== element) {
const summary = element.closest('summary');
if (summary && summary.parentNode !== closedDetails) {
return false;
}
if (summary === null) {
return false;
}
}
return elementIsVisible;
};
const isDisabled = element => {
if (!element || element.nodeType !== Node.ELEMENT_NODE) {
return true;
}
if (element.classList.contains('disabled')) {
return true;
}
if (typeof element.disabled !== 'undefined') {
return element.disabled;
}
return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false';
};
const findShadowRoot = element => {
if (!document.documentElement.attachShadow) {
return null;
}
// Can find the shadow root otherwise it'll return the document
if (typeof element.getRootNode === 'function') {
const root = element.getRootNode();
return root instanceof ShadowRoot ? root : null;
}
if (element instanceof ShadowRoot) {
return element;
}
// when we don't find a shadow root
if (!element.parentNode) {
return null;
}
return findShadowRoot(element.parentNode);
};
const noop = () => {};
/**
* Trick to restart an element's animation
*
* @param {HTMLElement} element
* @return void
*
* @see https://www.harrytheo.com/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
*/
const reflow = element => {
element.offsetHeight; // eslint-disable-line no-unused-expressions
};
const getjQuery = () => {
if (window.jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {
return window.jQuery;
}
return null;
};
const DOMContentLoadedCallbacks = [];
const onDOMContentLoaded = callback => {
if (document.readyState === 'loading') {
// add listener on the first call when the document is in loading state
if (!DOMContentLoadedCallbacks.length) {
document.addEventListener('DOMContentLoaded', () => {
for (const callback of DOMContentLoadedCallbacks) {
callback();
}
});
}
DOMContentLoadedCallbacks.push(callback);
} else {
callback();
}
};
const isRTL = () => document.documentElement.dir === 'rtl';
const defineJQueryPlugin = plugin => {
onDOMContentLoaded(() => {
const $ = getjQuery();
/* istanbul ignore if */
if ($) {
const name = plugin.NAME;
const JQUERY_NO_CONFLICT = $.fn[name];
$.fn[name] = plugin.jQueryInterface;
$.fn[name].Constructor = plugin;
$.fn[name].noConflict = () => {
$.fn[name] = JQUERY_NO_CONFLICT;
return plugin.jQueryInterface;
};
}
});
};
const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => {
return typeof possibleCallback === 'function' ? possibleCallback.call(...args) : defaultValue;
};
const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {
if (!waitForTransition) {
execute(callback);
return;
}
const durationPadding = 5;
const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding;
let called = false;
const handler = ({
target
}) => {
if (target !== transitionElement) {
return;
}
called = true;
transitionElement.removeEventListener(TRANSITION_END, handler);
execute(callback);
};
transitionElement.addEventListener(TRANSITION_END, handler);
setTimeout(() => {
if (!called) {
triggerTransitionEnd(transitionElement);
}
}, emulatedDuration);
};
/**
* Return the previous/next element of a list.
*
* @param {array} list The list of elements
* @param activeElement The active element
* @param shouldGetNext Choose to get next or previous element
* @param isCycleAllowed
* @return {Element|elem} The proper element
*/
const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {
const listLength = list.length;
let index = list.indexOf(activeElement);
// if the element does not exist in the list return an element
// depending on the direction and if cycle is allowed
if (index === -1) {
return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0];
}
index += shouldGetNext ? 1 : -1;
if (isCycleAllowed) {
index = (index + listLength) % listLength;
}
return list[Math.max(0, Math.min(index, listLength - 1))];
};
/**
* --------------------------------------------------------------------------
* Bootstrap dom/event-handler.js
@@ -64,6 +310,7 @@
* --------------------------------------------------------------------------
*/
/**
* Constants
*/
@@ -232,11 +479,33 @@
if (typeof event !== 'string' || !element) {
return null;
}
const $ = getjQuery();
const typeEvent = getTypeEvent(event);
const inNamespace = event !== typeEvent;
let jQueryEvent = null;
let bubbles = true;
let nativeDispatch = true;
let defaultPrevented = false;
if (inNamespace && $) {
jQueryEvent = $.Event(event, args);
$(element).trigger(jQueryEvent);
bubbles = !jQueryEvent.isPropagationStopped();
nativeDispatch = !jQueryEvent.isImmediatePropagationStopped();
defaultPrevented = jQueryEvent.isDefaultPrevented();
}
const evt = hydrateObj(new Event(event, {
bubbles: true,
bubbles,
cancelable: true
}), args);
element.dispatchEvent(evt);
if (defaultPrevented) {
evt.preventDefault();
}
if (nativeDispatch) {
element.dispatchEvent(evt);
}
if (evt.defaultPrevented && jQueryEvent) {
jQueryEvent.preventDefault();
}
return evt;
}
};
@@ -313,210 +582,6 @@
}
};
/**
* --------------------------------------------------------------------------
* Bootstrap util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
const MAX_UID = 1000000;
const MILLISECONDS_MULTIPLIER = 1000;
const TRANSITION_END = 'transitionend';
/**
* Properly escape IDs selectors to handle weird IDs
* @param {string} selector
* @returns {string}
*/
const parseSelector = selector => {
if (selector && window.CSS && window.CSS.escape) {
// document.querySelector needs escaping to handle IDs (html5+) containing for instance /
selector = selector.replace(/#([^\s"#']+)/g, (match, id) => `#${CSS.escape(id)}`);
}
return selector;
};
// Shout-out Angus Croll (https://goo.gl/pxwQGp)
const toType = object => {
if (object === null || object === undefined) {
return `${object}`;
}
return Object.prototype.toString.call(object).match(/\s([a-z]+)/i)[1].toLowerCase();
};
/**
* Public Util API
*/
const getUID = prefix => {
do {
prefix += Math.floor(Math.random() * MAX_UID);
} while (document.getElementById(prefix));
return prefix;
};
const getTransitionDurationFromElement = element => {
if (!element) {
return 0;
}
// Get transition-duration of the element
let {
transitionDuration,
transitionDelay
} = window.getComputedStyle(element);
const floatTransitionDuration = Number.parseFloat(transitionDuration);
const floatTransitionDelay = Number.parseFloat(transitionDelay);
// Return 0 if element or transition duration is not found
if (!floatTransitionDuration && !floatTransitionDelay) {
return 0;
}
// If multiple durations are defined, take the first
transitionDuration = transitionDuration.split(',')[0];
transitionDelay = transitionDelay.split(',')[0];
return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER;
};
const triggerTransitionEnd = element => {
element.dispatchEvent(new Event(TRANSITION_END));
};
const isElement$1 = object => {
if (!object || typeof object !== 'object') {
return false;
}
return typeof object.nodeType !== 'undefined';
};
const getElement = object => {
if (isElement$1(object)) {
return object;
}
if (typeof object === 'string' && object.length > 0) {
return document.querySelector(parseSelector(object));
}
return null;
};
const isVisible = element => {
if (!isElement$1(element) || element.getClientRects().length === 0) {
return false;
}
const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible';
// Handle `details` element as its content may falsie appear visible when it is closed
const closedDetails = element.closest('details:not([open])');
if (!closedDetails) {
return elementIsVisible;
}
if (closedDetails !== element) {
const summary = element.closest('summary');
if (summary && summary.parentNode !== closedDetails) {
return false;
}
if (summary === null) {
return false;
}
}
return elementIsVisible;
};
const isDisabled = element => {
if (!element || element.nodeType !== Node.ELEMENT_NODE) {
return true;
}
if (element.classList.contains('disabled')) {
return true;
}
if (typeof element.disabled !== 'undefined') {
return element.disabled;
}
return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false';
};
const findShadowRoot = element => {
if (!document.documentElement.attachShadow) {
return null;
}
// Can find the shadow root otherwise it'll return the document
if (typeof element.getRootNode === 'function') {
const root = element.getRootNode();
return root instanceof ShadowRoot ? root : null;
}
if (element instanceof ShadowRoot) {
return element;
}
// when we don't find a shadow root
if (!element.parentNode) {
return null;
}
return findShadowRoot(element.parentNode);
};
const noop = () => {};
/**
* Trick to restart an element's animation
*
* @param {HTMLElement} element
* @return void
*
* @see https://www.harrytheo.com/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
*/
const reflow = element => {
element.offsetHeight; // eslint-disable-line no-unused-expressions
};
const isRTL = () => document.documentElement.dir === 'rtl';
const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => {
return typeof possibleCallback === 'function' ? possibleCallback.call(...args) : defaultValue;
};
const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {
if (!waitForTransition) {
execute(callback);
return;
}
const durationPadding = 5;
const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding;
let called = false;
const handler = ({
target
}) => {
if (target !== transitionElement) {
return;
}
called = true;
transitionElement.removeEventListener(TRANSITION_END, handler);
execute(callback);
};
transitionElement.addEventListener(TRANSITION_END, handler);
setTimeout(() => {
if (!called) {
triggerTransitionEnd(transitionElement);
}
}, emulatedDuration);
};
/**
* Return the previous/next element of a list.
*
* @param {array} list The list of elements
* @param activeElement The active element
* @param shouldGetNext Choose to get next or previous element
* @param isCycleAllowed
* @return {Element|elem} The proper element
*/
const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {
const listLength = list.length;
let index = list.indexOf(activeElement);
// if the element does not exist in the list return an element
// depending on the direction and if cycle is allowed
if (index === -1) {
return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0];
}
index += shouldGetNext ? 1 : -1;
if (isCycleAllowed) {
index = (index + listLength) % listLength;
}
return list[Math.max(0, Math.min(index, listLength - 1))];
};
/**
* --------------------------------------------------------------------------
* Bootstrap util/config.js
@@ -802,6 +867,20 @@
EventHandler.trigger(this._element, EVENT_CLOSED);
this.dispose();
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Alert.getOrCreateInstance(this);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config](this);
});
}
}
/**
@@ -810,6 +889,12 @@
enableDismissTrigger(Alert, 'close');
/**
* jQuery
*/
defineJQueryPlugin(Alert);
/**
* --------------------------------------------------------------------------
* Bootstrap button.js
@@ -845,6 +930,16 @@
// Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method
this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE$3));
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Button.getOrCreateInstance(this);
if (config === 'toggle') {
data[config]();
}
});
}
}
/**
@@ -858,6 +953,12 @@
data.toggle();
});
/**
* jQuery
*/
defineJQueryPlugin(Button);
/**
* --------------------------------------------------------------------------
* Bootstrap util/swipe.js
@@ -1294,6 +1395,23 @@
}
return order === ORDER_PREV ? DIRECTION_RIGHT : DIRECTION_LEFT;
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Carousel.getOrCreateInstance(this, config);
if (typeof config === 'number') {
data.to(config);
return;
}
if (typeof config === 'string') {
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
}
});
}
}
/**
@@ -1328,6 +1446,12 @@
}
});
/**
* jQuery
*/
defineJQueryPlugin(Carousel);
/**
* --------------------------------------------------------------------------
* Bootstrap collapse.js
@@ -1521,6 +1645,23 @@
element.setAttribute('aria-expanded', isOpen);
}
}
// Static
static jQueryInterface(config) {
const _config = {};
if (typeof config === 'string' && /show|hide/.test(config)) {
_config.toggle = false;
}
return this.each(function () {
const data = Collapse.getOrCreateInstance(this, _config);
if (typeof config === 'string') {
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
}
});
}
}
/**
@@ -1539,6 +1680,12 @@
}
});
/**
* jQuery
*/
defineJQueryPlugin(Collapse);
var top = 'top';
var bottom = 'bottom';
var right = 'right';
@@ -3649,6 +3796,20 @@
// allow cycling to get the last item in case key equals ARROW_UP_KEY
getNextActiveElement(items, target, key === ARROW_DOWN_KEY$1, !items.includes(target)).focus();
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Dropdown.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
static clearMenus(event) {
if (event.button === RIGHT_MOUSE_BUTTON || event.type === 'keyup' && event.key !== TAB_KEY$1) {
return;
@@ -3724,6 +3885,12 @@
Dropdown.getOrCreateInstance(this).toggle();
});
/**
* jQuery
*/
defineJQueryPlugin(Dropdown);
/**
* --------------------------------------------------------------------------
* Bootstrap util/backdrop.js
@@ -4296,6 +4463,20 @@
this._element.style.paddingLeft = '';
this._element.style.paddingRight = '';
}
// Static
static jQueryInterface(config, relatedTarget) {
return this.each(function () {
const data = Modal.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config](relatedTarget);
});
}
}
/**
@@ -4329,6 +4510,12 @@
});
enableDismissTrigger(Modal);
/**
* jQuery
*/
defineJQueryPlugin(Modal);
/**
* --------------------------------------------------------------------------
* Bootstrap offcanvas.js
@@ -4497,6 +4684,20 @@
EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED);
});
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Offcanvas.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config](this);
});
}
}
/**
@@ -4540,6 +4741,12 @@
});
enableDismissTrigger(Offcanvas);
/**
* jQuery
*/
defineJQueryPlugin(Offcanvas);
/**
* --------------------------------------------------------------------------
* Bootstrap util/sanitizer.js
@@ -5261,8 +5468,28 @@
this.tip = null;
}
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Tooltip.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
* jQuery
*/
defineJQueryPlugin(Tooltip);
/**
* --------------------------------------------------------------------------
* Bootstrap popover.js
@@ -5322,8 +5549,28 @@
_getContent() {
return this._resolvePossibleFunction(this._config.content);
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Popover.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
* jQuery
*/
defineJQueryPlugin(Popover);
/**
* --------------------------------------------------------------------------
* Bootstrap scrollspy.js
@@ -5552,6 +5799,20 @@
node.classList.remove(CLASS_NAME_ACTIVE$1);
}
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = ScrollSpy.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
@@ -5564,6 +5825,12 @@
}
});
/**
* jQuery
*/
defineJQueryPlugin(ScrollSpy);
/**
* --------------------------------------------------------------------------
* Bootstrap tab.js
@@ -5790,6 +6057,20 @@
_getOuterElement(elem) {
return elem.closest(SELECTOR_OUTER) || elem;
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Tab.getOrCreateInstance(this);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
@@ -5814,6 +6095,11 @@
Tab.getOrCreateInstance(element);
}
});
/**
* jQuery
*/
defineJQueryPlugin(Tab);
/**
* --------------------------------------------------------------------------
@@ -5971,6 +6257,19 @@
clearTimeout(this._timeout);
this._timeout = null;
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Toast.getOrCreateInstance(this, config);
if (typeof config === 'string') {
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config](this);
}
});
}
}
/**
@@ -5979,6 +6278,12 @@
enableDismissTrigger(Toast);
/**
* jQuery
*/
defineJQueryPlugin(Toast);
/**
* --------------------------------------------------------------------------
* Bootstrap index.umd.js
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+511 -206
View File
@@ -53,6 +53,252 @@ const Data = {
}
};
/**
* --------------------------------------------------------------------------
* Bootstrap util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
const MAX_UID = 1000000;
const MILLISECONDS_MULTIPLIER = 1000;
const TRANSITION_END = 'transitionend';
/**
* Properly escape IDs selectors to handle weird IDs
* @param {string} selector
* @returns {string}
*/
const parseSelector = selector => {
if (selector && window.CSS && window.CSS.escape) {
// document.querySelector needs escaping to handle IDs (html5+) containing for instance /
selector = selector.replace(/#([^\s"#']+)/g, (match, id) => `#${CSS.escape(id)}`);
}
return selector;
};
// Shout-out Angus Croll (https://goo.gl/pxwQGp)
const toType = object => {
if (object === null || object === undefined) {
return `${object}`;
}
return Object.prototype.toString.call(object).match(/\s([a-z]+)/i)[1].toLowerCase();
};
/**
* Public Util API
*/
const getUID = prefix => {
do {
prefix += Math.floor(Math.random() * MAX_UID);
} while (document.getElementById(prefix));
return prefix;
};
const getTransitionDurationFromElement = element => {
if (!element) {
return 0;
}
// Get transition-duration of the element
let {
transitionDuration,
transitionDelay
} = window.getComputedStyle(element);
const floatTransitionDuration = Number.parseFloat(transitionDuration);
const floatTransitionDelay = Number.parseFloat(transitionDelay);
// Return 0 if element or transition duration is not found
if (!floatTransitionDuration && !floatTransitionDelay) {
return 0;
}
// If multiple durations are defined, take the first
transitionDuration = transitionDuration.split(',')[0];
transitionDelay = transitionDelay.split(',')[0];
return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER;
};
const triggerTransitionEnd = element => {
element.dispatchEvent(new Event(TRANSITION_END));
};
const isElement = object => {
if (!object || typeof object !== 'object') {
return false;
}
if (typeof object.jquery !== 'undefined') {
object = object[0];
}
return typeof object.nodeType !== 'undefined';
};
const getElement = object => {
// it's a jQuery object or a node element
if (isElement(object)) {
return object.jquery ? object[0] : object;
}
if (typeof object === 'string' && object.length > 0) {
return document.querySelector(parseSelector(object));
}
return null;
};
const isVisible = element => {
if (!isElement(element) || element.getClientRects().length === 0) {
return false;
}
const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible';
// Handle `details` element as its content may falsie appear visible when it is closed
const closedDetails = element.closest('details:not([open])');
if (!closedDetails) {
return elementIsVisible;
}
if (closedDetails !== element) {
const summary = element.closest('summary');
if (summary && summary.parentNode !== closedDetails) {
return false;
}
if (summary === null) {
return false;
}
}
return elementIsVisible;
};
const isDisabled = element => {
if (!element || element.nodeType !== Node.ELEMENT_NODE) {
return true;
}
if (element.classList.contains('disabled')) {
return true;
}
if (typeof element.disabled !== 'undefined') {
return element.disabled;
}
return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false';
};
const findShadowRoot = element => {
if (!document.documentElement.attachShadow) {
return null;
}
// Can find the shadow root otherwise it'll return the document
if (typeof element.getRootNode === 'function') {
const root = element.getRootNode();
return root instanceof ShadowRoot ? root : null;
}
if (element instanceof ShadowRoot) {
return element;
}
// when we don't find a shadow root
if (!element.parentNode) {
return null;
}
return findShadowRoot(element.parentNode);
};
const noop = () => {};
/**
* Trick to restart an element's animation
*
* @param {HTMLElement} element
* @return void
*
* @see https://www.harrytheo.com/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
*/
const reflow = element => {
element.offsetHeight; // eslint-disable-line no-unused-expressions
};
const getjQuery = () => {
if (window.jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {
return window.jQuery;
}
return null;
};
const DOMContentLoadedCallbacks = [];
const onDOMContentLoaded = callback => {
if (document.readyState === 'loading') {
// add listener on the first call when the document is in loading state
if (!DOMContentLoadedCallbacks.length) {
document.addEventListener('DOMContentLoaded', () => {
for (const callback of DOMContentLoadedCallbacks) {
callback();
}
});
}
DOMContentLoadedCallbacks.push(callback);
} else {
callback();
}
};
const isRTL = () => document.documentElement.dir === 'rtl';
const defineJQueryPlugin = plugin => {
onDOMContentLoaded(() => {
const $ = getjQuery();
/* istanbul ignore if */
if ($) {
const name = plugin.NAME;
const JQUERY_NO_CONFLICT = $.fn[name];
$.fn[name] = plugin.jQueryInterface;
$.fn[name].Constructor = plugin;
$.fn[name].noConflict = () => {
$.fn[name] = JQUERY_NO_CONFLICT;
return plugin.jQueryInterface;
};
}
});
};
const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => {
return typeof possibleCallback === 'function' ? possibleCallback.call(...args) : defaultValue;
};
const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {
if (!waitForTransition) {
execute(callback);
return;
}
const durationPadding = 5;
const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding;
let called = false;
const handler = ({
target
}) => {
if (target !== transitionElement) {
return;
}
called = true;
transitionElement.removeEventListener(TRANSITION_END, handler);
execute(callback);
};
transitionElement.addEventListener(TRANSITION_END, handler);
setTimeout(() => {
if (!called) {
triggerTransitionEnd(transitionElement);
}
}, emulatedDuration);
};
/**
* Return the previous/next element of a list.
*
* @param {array} list The list of elements
* @param activeElement The active element
* @param shouldGetNext Choose to get next or previous element
* @param isCycleAllowed
* @return {Element|elem} The proper element
*/
const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {
const listLength = list.length;
let index = list.indexOf(activeElement);
// if the element does not exist in the list return an element
// depending on the direction and if cycle is allowed
if (index === -1) {
return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0];
}
index += shouldGetNext ? 1 : -1;
if (isCycleAllowed) {
index = (index + listLength) % listLength;
}
return list[Math.max(0, Math.min(index, listLength - 1))];
};
/**
* --------------------------------------------------------------------------
* Bootstrap dom/event-handler.js
@@ -60,6 +306,7 @@ const Data = {
* --------------------------------------------------------------------------
*/
/**
* Constants
*/
@@ -228,11 +475,33 @@ const EventHandler = {
if (typeof event !== 'string' || !element) {
return null;
}
const $ = getjQuery();
const typeEvent = getTypeEvent(event);
const inNamespace = event !== typeEvent;
let jQueryEvent = null;
let bubbles = true;
let nativeDispatch = true;
let defaultPrevented = false;
if (inNamespace && $) {
jQueryEvent = $.Event(event, args);
$(element).trigger(jQueryEvent);
bubbles = !jQueryEvent.isPropagationStopped();
nativeDispatch = !jQueryEvent.isImmediatePropagationStopped();
defaultPrevented = jQueryEvent.isDefaultPrevented();
}
const evt = hydrateObj(new Event(event, {
bubbles: true,
bubbles,
cancelable: true
}), args);
element.dispatchEvent(evt);
if (defaultPrevented) {
evt.preventDefault();
}
if (nativeDispatch) {
element.dispatchEvent(evt);
}
if (evt.defaultPrevented && jQueryEvent) {
jQueryEvent.preventDefault();
}
return evt;
}
};
@@ -309,210 +578,6 @@ const Manipulator = {
}
};
/**
* --------------------------------------------------------------------------
* Bootstrap util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
const MAX_UID = 1000000;
const MILLISECONDS_MULTIPLIER = 1000;
const TRANSITION_END = 'transitionend';
/**
* Properly escape IDs selectors to handle weird IDs
* @param {string} selector
* @returns {string}
*/
const parseSelector = selector => {
if (selector && window.CSS && window.CSS.escape) {
// document.querySelector needs escaping to handle IDs (html5+) containing for instance /
selector = selector.replace(/#([^\s"#']+)/g, (match, id) => `#${CSS.escape(id)}`);
}
return selector;
};
// Shout-out Angus Croll (https://goo.gl/pxwQGp)
const toType = object => {
if (object === null || object === undefined) {
return `${object}`;
}
return Object.prototype.toString.call(object).match(/\s([a-z]+)/i)[1].toLowerCase();
};
/**
* Public Util API
*/
const getUID = prefix => {
do {
prefix += Math.floor(Math.random() * MAX_UID);
} while (document.getElementById(prefix));
return prefix;
};
const getTransitionDurationFromElement = element => {
if (!element) {
return 0;
}
// Get transition-duration of the element
let {
transitionDuration,
transitionDelay
} = window.getComputedStyle(element);
const floatTransitionDuration = Number.parseFloat(transitionDuration);
const floatTransitionDelay = Number.parseFloat(transitionDelay);
// Return 0 if element or transition duration is not found
if (!floatTransitionDuration && !floatTransitionDelay) {
return 0;
}
// If multiple durations are defined, take the first
transitionDuration = transitionDuration.split(',')[0];
transitionDelay = transitionDelay.split(',')[0];
return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER;
};
const triggerTransitionEnd = element => {
element.dispatchEvent(new Event(TRANSITION_END));
};
const isElement = object => {
if (!object || typeof object !== 'object') {
return false;
}
return typeof object.nodeType !== 'undefined';
};
const getElement = object => {
if (isElement(object)) {
return object;
}
if (typeof object === 'string' && object.length > 0) {
return document.querySelector(parseSelector(object));
}
return null;
};
const isVisible = element => {
if (!isElement(element) || element.getClientRects().length === 0) {
return false;
}
const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible';
// Handle `details` element as its content may falsie appear visible when it is closed
const closedDetails = element.closest('details:not([open])');
if (!closedDetails) {
return elementIsVisible;
}
if (closedDetails !== element) {
const summary = element.closest('summary');
if (summary && summary.parentNode !== closedDetails) {
return false;
}
if (summary === null) {
return false;
}
}
return elementIsVisible;
};
const isDisabled = element => {
if (!element || element.nodeType !== Node.ELEMENT_NODE) {
return true;
}
if (element.classList.contains('disabled')) {
return true;
}
if (typeof element.disabled !== 'undefined') {
return element.disabled;
}
return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false';
};
const findShadowRoot = element => {
if (!document.documentElement.attachShadow) {
return null;
}
// Can find the shadow root otherwise it'll return the document
if (typeof element.getRootNode === 'function') {
const root = element.getRootNode();
return root instanceof ShadowRoot ? root : null;
}
if (element instanceof ShadowRoot) {
return element;
}
// when we don't find a shadow root
if (!element.parentNode) {
return null;
}
return findShadowRoot(element.parentNode);
};
const noop = () => {};
/**
* Trick to restart an element's animation
*
* @param {HTMLElement} element
* @return void
*
* @see https://www.harrytheo.com/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
*/
const reflow = element => {
element.offsetHeight; // eslint-disable-line no-unused-expressions
};
const isRTL = () => document.documentElement.dir === 'rtl';
const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => {
return typeof possibleCallback === 'function' ? possibleCallback.call(...args) : defaultValue;
};
const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {
if (!waitForTransition) {
execute(callback);
return;
}
const durationPadding = 5;
const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding;
let called = false;
const handler = ({
target
}) => {
if (target !== transitionElement) {
return;
}
called = true;
transitionElement.removeEventListener(TRANSITION_END, handler);
execute(callback);
};
transitionElement.addEventListener(TRANSITION_END, handler);
setTimeout(() => {
if (!called) {
triggerTransitionEnd(transitionElement);
}
}, emulatedDuration);
};
/**
* Return the previous/next element of a list.
*
* @param {array} list The list of elements
* @param activeElement The active element
* @param shouldGetNext Choose to get next or previous element
* @param isCycleAllowed
* @return {Element|elem} The proper element
*/
const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {
const listLength = list.length;
let index = list.indexOf(activeElement);
// if the element does not exist in the list return an element
// depending on the direction and if cycle is allowed
if (index === -1) {
return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0];
}
index += shouldGetNext ? 1 : -1;
if (isCycleAllowed) {
index = (index + listLength) % listLength;
}
return list[Math.max(0, Math.min(index, listLength - 1))];
};
/**
* --------------------------------------------------------------------------
* Bootstrap util/config.js
@@ -798,6 +863,20 @@ class Alert extends BaseComponent {
EventHandler.trigger(this._element, EVENT_CLOSED);
this.dispose();
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Alert.getOrCreateInstance(this);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config](this);
});
}
}
/**
@@ -806,6 +885,12 @@ class Alert extends BaseComponent {
enableDismissTrigger(Alert, 'close');
/**
* jQuery
*/
defineJQueryPlugin(Alert);
/**
* --------------------------------------------------------------------------
* Bootstrap button.js
@@ -841,6 +926,16 @@ class Button extends BaseComponent {
// Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method
this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE$3));
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Button.getOrCreateInstance(this);
if (config === 'toggle') {
data[config]();
}
});
}
}
/**
@@ -854,6 +949,12 @@ EventHandler.on(document, EVENT_CLICK_DATA_API$6, SELECTOR_DATA_TOGGLE$5, event
data.toggle();
});
/**
* jQuery
*/
defineJQueryPlugin(Button);
/**
* --------------------------------------------------------------------------
* Bootstrap util/swipe.js
@@ -1290,6 +1391,23 @@ class Carousel extends BaseComponent {
}
return order === ORDER_PREV ? DIRECTION_RIGHT : DIRECTION_LEFT;
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Carousel.getOrCreateInstance(this, config);
if (typeof config === 'number') {
data.to(config);
return;
}
if (typeof config === 'string') {
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
}
});
}
}
/**
@@ -1324,6 +1442,12 @@ EventHandler.on(window, EVENT_LOAD_DATA_API$3, () => {
}
});
/**
* jQuery
*/
defineJQueryPlugin(Carousel);
/**
* --------------------------------------------------------------------------
* Bootstrap collapse.js
@@ -1517,6 +1641,23 @@ class Collapse extends BaseComponent {
element.setAttribute('aria-expanded', isOpen);
}
}
// Static
static jQueryInterface(config) {
const _config = {};
if (typeof config === 'string' && /show|hide/.test(config)) {
_config.toggle = false;
}
return this.each(function () {
const data = Collapse.getOrCreateInstance(this, _config);
if (typeof config === 'string') {
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
}
});
}
}
/**
@@ -1535,6 +1676,12 @@ EventHandler.on(document, EVENT_CLICK_DATA_API$4, SELECTOR_DATA_TOGGLE$4, functi
}
});
/**
* jQuery
*/
defineJQueryPlugin(Collapse);
/**
* --------------------------------------------------------------------------
* Bootstrap dropdown.js
@@ -1808,6 +1955,20 @@ class Dropdown extends BaseComponent {
// allow cycling to get the last item in case key equals ARROW_UP_KEY
getNextActiveElement(items, target, key === ARROW_DOWN_KEY$1, !items.includes(target)).focus();
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Dropdown.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
static clearMenus(event) {
if (event.button === RIGHT_MOUSE_BUTTON || event.type === 'keyup' && event.key !== TAB_KEY$1) {
return;
@@ -1883,6 +2044,12 @@ EventHandler.on(document, EVENT_CLICK_DATA_API$3, SELECTOR_DATA_TOGGLE$3, functi
Dropdown.getOrCreateInstance(this).toggle();
});
/**
* jQuery
*/
defineJQueryPlugin(Dropdown);
/**
* --------------------------------------------------------------------------
* Bootstrap util/backdrop.js
@@ -2455,6 +2622,20 @@ class Modal extends BaseComponent {
this._element.style.paddingLeft = '';
this._element.style.paddingRight = '';
}
// Static
static jQueryInterface(config, relatedTarget) {
return this.each(function () {
const data = Modal.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config](relatedTarget);
});
}
}
/**
@@ -2488,6 +2669,12 @@ EventHandler.on(document, EVENT_CLICK_DATA_API$2, SELECTOR_DATA_TOGGLE$2, functi
});
enableDismissTrigger(Modal);
/**
* jQuery
*/
defineJQueryPlugin(Modal);
/**
* --------------------------------------------------------------------------
* Bootstrap offcanvas.js
@@ -2656,6 +2843,20 @@ class Offcanvas extends BaseComponent {
EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED);
});
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Offcanvas.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config](this);
});
}
}
/**
@@ -2699,6 +2900,12 @@ EventHandler.on(window, EVENT_RESIZE, () => {
});
enableDismissTrigger(Offcanvas);
/**
* jQuery
*/
defineJQueryPlugin(Offcanvas);
/**
* --------------------------------------------------------------------------
* Bootstrap util/sanitizer.js
@@ -3420,8 +3627,28 @@ class Tooltip extends BaseComponent {
this.tip = null;
}
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Tooltip.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
* jQuery
*/
defineJQueryPlugin(Tooltip);
/**
* --------------------------------------------------------------------------
* Bootstrap popover.js
@@ -3481,8 +3708,28 @@ class Popover extends Tooltip {
_getContent() {
return this._resolvePossibleFunction(this._config.content);
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Popover.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
* jQuery
*/
defineJQueryPlugin(Popover);
/**
* --------------------------------------------------------------------------
* Bootstrap scrollspy.js
@@ -3711,6 +3958,20 @@ class ScrollSpy extends BaseComponent {
node.classList.remove(CLASS_NAME_ACTIVE$1);
}
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = ScrollSpy.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
@@ -3723,6 +3984,12 @@ EventHandler.on(window, EVENT_LOAD_DATA_API$1, () => {
}
});
/**
* jQuery
*/
defineJQueryPlugin(ScrollSpy);
/**
* --------------------------------------------------------------------------
* Bootstrap tab.js
@@ -3949,6 +4216,20 @@ class Tab extends BaseComponent {
_getOuterElement(elem) {
return elem.closest(SELECTOR_OUTER) || elem;
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Tab.getOrCreateInstance(this);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
@@ -3973,6 +4254,11 @@ EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
Tab.getOrCreateInstance(element);
}
});
/**
* jQuery
*/
defineJQueryPlugin(Tab);
/**
* --------------------------------------------------------------------------
@@ -4130,6 +4416,19 @@ class Toast extends BaseComponent {
clearTimeout(this._timeout);
this._timeout = null;
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Toast.getOrCreateInstance(this, config);
if (typeof config === 'string') {
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config](this);
}
});
}
}
/**
@@ -4138,5 +4437,11 @@ class Toast extends BaseComponent {
enableDismissTrigger(Toast);
/**
* jQuery
*/
defineJQueryPlugin(Toast);
export { Alert, Button, Carousel, Collapse, Dropdown, Modal, Offcanvas, Popover, ScrollSpy, Tab, Toast, Tooltip };
//# sourceMappingURL=bootstrap.esm.js.map
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+511 -206
View File
@@ -76,6 +76,252 @@
}
};
/**
* --------------------------------------------------------------------------
* Bootstrap util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
const MAX_UID = 1000000;
const MILLISECONDS_MULTIPLIER = 1000;
const TRANSITION_END = 'transitionend';
/**
* Properly escape IDs selectors to handle weird IDs
* @param {string} selector
* @returns {string}
*/
const parseSelector = selector => {
if (selector && window.CSS && window.CSS.escape) {
// document.querySelector needs escaping to handle IDs (html5+) containing for instance /
selector = selector.replace(/#([^\s"#']+)/g, (match, id) => `#${CSS.escape(id)}`);
}
return selector;
};
// Shout-out Angus Croll (https://goo.gl/pxwQGp)
const toType = object => {
if (object === null || object === undefined) {
return `${object}`;
}
return Object.prototype.toString.call(object).match(/\s([a-z]+)/i)[1].toLowerCase();
};
/**
* Public Util API
*/
const getUID = prefix => {
do {
prefix += Math.floor(Math.random() * MAX_UID);
} while (document.getElementById(prefix));
return prefix;
};
const getTransitionDurationFromElement = element => {
if (!element) {
return 0;
}
// Get transition-duration of the element
let {
transitionDuration,
transitionDelay
} = window.getComputedStyle(element);
const floatTransitionDuration = Number.parseFloat(transitionDuration);
const floatTransitionDelay = Number.parseFloat(transitionDelay);
// Return 0 if element or transition duration is not found
if (!floatTransitionDuration && !floatTransitionDelay) {
return 0;
}
// If multiple durations are defined, take the first
transitionDuration = transitionDuration.split(',')[0];
transitionDelay = transitionDelay.split(',')[0];
return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER;
};
const triggerTransitionEnd = element => {
element.dispatchEvent(new Event(TRANSITION_END));
};
const isElement = object => {
if (!object || typeof object !== 'object') {
return false;
}
if (typeof object.jquery !== 'undefined') {
object = object[0];
}
return typeof object.nodeType !== 'undefined';
};
const getElement = object => {
// it's a jQuery object or a node element
if (isElement(object)) {
return object.jquery ? object[0] : object;
}
if (typeof object === 'string' && object.length > 0) {
return document.querySelector(parseSelector(object));
}
return null;
};
const isVisible = element => {
if (!isElement(element) || element.getClientRects().length === 0) {
return false;
}
const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible';
// Handle `details` element as its content may falsie appear visible when it is closed
const closedDetails = element.closest('details:not([open])');
if (!closedDetails) {
return elementIsVisible;
}
if (closedDetails !== element) {
const summary = element.closest('summary');
if (summary && summary.parentNode !== closedDetails) {
return false;
}
if (summary === null) {
return false;
}
}
return elementIsVisible;
};
const isDisabled = element => {
if (!element || element.nodeType !== Node.ELEMENT_NODE) {
return true;
}
if (element.classList.contains('disabled')) {
return true;
}
if (typeof element.disabled !== 'undefined') {
return element.disabled;
}
return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false';
};
const findShadowRoot = element => {
if (!document.documentElement.attachShadow) {
return null;
}
// Can find the shadow root otherwise it'll return the document
if (typeof element.getRootNode === 'function') {
const root = element.getRootNode();
return root instanceof ShadowRoot ? root : null;
}
if (element instanceof ShadowRoot) {
return element;
}
// when we don't find a shadow root
if (!element.parentNode) {
return null;
}
return findShadowRoot(element.parentNode);
};
const noop = () => {};
/**
* Trick to restart an element's animation
*
* @param {HTMLElement} element
* @return void
*
* @see https://www.harrytheo.com/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
*/
const reflow = element => {
element.offsetHeight; // eslint-disable-line no-unused-expressions
};
const getjQuery = () => {
if (window.jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {
return window.jQuery;
}
return null;
};
const DOMContentLoadedCallbacks = [];
const onDOMContentLoaded = callback => {
if (document.readyState === 'loading') {
// add listener on the first call when the document is in loading state
if (!DOMContentLoadedCallbacks.length) {
document.addEventListener('DOMContentLoaded', () => {
for (const callback of DOMContentLoadedCallbacks) {
callback();
}
});
}
DOMContentLoadedCallbacks.push(callback);
} else {
callback();
}
};
const isRTL = () => document.documentElement.dir === 'rtl';
const defineJQueryPlugin = plugin => {
onDOMContentLoaded(() => {
const $ = getjQuery();
/* istanbul ignore if */
if ($) {
const name = plugin.NAME;
const JQUERY_NO_CONFLICT = $.fn[name];
$.fn[name] = plugin.jQueryInterface;
$.fn[name].Constructor = plugin;
$.fn[name].noConflict = () => {
$.fn[name] = JQUERY_NO_CONFLICT;
return plugin.jQueryInterface;
};
}
});
};
const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => {
return typeof possibleCallback === 'function' ? possibleCallback.call(...args) : defaultValue;
};
const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {
if (!waitForTransition) {
execute(callback);
return;
}
const durationPadding = 5;
const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding;
let called = false;
const handler = ({
target
}) => {
if (target !== transitionElement) {
return;
}
called = true;
transitionElement.removeEventListener(TRANSITION_END, handler);
execute(callback);
};
transitionElement.addEventListener(TRANSITION_END, handler);
setTimeout(() => {
if (!called) {
triggerTransitionEnd(transitionElement);
}
}, emulatedDuration);
};
/**
* Return the previous/next element of a list.
*
* @param {array} list The list of elements
* @param activeElement The active element
* @param shouldGetNext Choose to get next or previous element
* @param isCycleAllowed
* @return {Element|elem} The proper element
*/
const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {
const listLength = list.length;
let index = list.indexOf(activeElement);
// if the element does not exist in the list return an element
// depending on the direction and if cycle is allowed
if (index === -1) {
return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0];
}
index += shouldGetNext ? 1 : -1;
if (isCycleAllowed) {
index = (index + listLength) % listLength;
}
return list[Math.max(0, Math.min(index, listLength - 1))];
};
/**
* --------------------------------------------------------------------------
* Bootstrap dom/event-handler.js
@@ -83,6 +329,7 @@
* --------------------------------------------------------------------------
*/
/**
* Constants
*/
@@ -251,11 +498,33 @@
if (typeof event !== 'string' || !element) {
return null;
}
const $ = getjQuery();
const typeEvent = getTypeEvent(event);
const inNamespace = event !== typeEvent;
let jQueryEvent = null;
let bubbles = true;
let nativeDispatch = true;
let defaultPrevented = false;
if (inNamespace && $) {
jQueryEvent = $.Event(event, args);
$(element).trigger(jQueryEvent);
bubbles = !jQueryEvent.isPropagationStopped();
nativeDispatch = !jQueryEvent.isImmediatePropagationStopped();
defaultPrevented = jQueryEvent.isDefaultPrevented();
}
const evt = hydrateObj(new Event(event, {
bubbles: true,
bubbles,
cancelable: true
}), args);
element.dispatchEvent(evt);
if (defaultPrevented) {
evt.preventDefault();
}
if (nativeDispatch) {
element.dispatchEvent(evt);
}
if (evt.defaultPrevented && jQueryEvent) {
jQueryEvent.preventDefault();
}
return evt;
}
};
@@ -332,210 +601,6 @@
}
};
/**
* --------------------------------------------------------------------------
* Bootstrap util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
const MAX_UID = 1000000;
const MILLISECONDS_MULTIPLIER = 1000;
const TRANSITION_END = 'transitionend';
/**
* Properly escape IDs selectors to handle weird IDs
* @param {string} selector
* @returns {string}
*/
const parseSelector = selector => {
if (selector && window.CSS && window.CSS.escape) {
// document.querySelector needs escaping to handle IDs (html5+) containing for instance /
selector = selector.replace(/#([^\s"#']+)/g, (match, id) => `#${CSS.escape(id)}`);
}
return selector;
};
// Shout-out Angus Croll (https://goo.gl/pxwQGp)
const toType = object => {
if (object === null || object === undefined) {
return `${object}`;
}
return Object.prototype.toString.call(object).match(/\s([a-z]+)/i)[1].toLowerCase();
};
/**
* Public Util API
*/
const getUID = prefix => {
do {
prefix += Math.floor(Math.random() * MAX_UID);
} while (document.getElementById(prefix));
return prefix;
};
const getTransitionDurationFromElement = element => {
if (!element) {
return 0;
}
// Get transition-duration of the element
let {
transitionDuration,
transitionDelay
} = window.getComputedStyle(element);
const floatTransitionDuration = Number.parseFloat(transitionDuration);
const floatTransitionDelay = Number.parseFloat(transitionDelay);
// Return 0 if element or transition duration is not found
if (!floatTransitionDuration && !floatTransitionDelay) {
return 0;
}
// If multiple durations are defined, take the first
transitionDuration = transitionDuration.split(',')[0];
transitionDelay = transitionDelay.split(',')[0];
return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER;
};
const triggerTransitionEnd = element => {
element.dispatchEvent(new Event(TRANSITION_END));
};
const isElement = object => {
if (!object || typeof object !== 'object') {
return false;
}
return typeof object.nodeType !== 'undefined';
};
const getElement = object => {
if (isElement(object)) {
return object;
}
if (typeof object === 'string' && object.length > 0) {
return document.querySelector(parseSelector(object));
}
return null;
};
const isVisible = element => {
if (!isElement(element) || element.getClientRects().length === 0) {
return false;
}
const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible';
// Handle `details` element as its content may falsie appear visible when it is closed
const closedDetails = element.closest('details:not([open])');
if (!closedDetails) {
return elementIsVisible;
}
if (closedDetails !== element) {
const summary = element.closest('summary');
if (summary && summary.parentNode !== closedDetails) {
return false;
}
if (summary === null) {
return false;
}
}
return elementIsVisible;
};
const isDisabled = element => {
if (!element || element.nodeType !== Node.ELEMENT_NODE) {
return true;
}
if (element.classList.contains('disabled')) {
return true;
}
if (typeof element.disabled !== 'undefined') {
return element.disabled;
}
return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false';
};
const findShadowRoot = element => {
if (!document.documentElement.attachShadow) {
return null;
}
// Can find the shadow root otherwise it'll return the document
if (typeof element.getRootNode === 'function') {
const root = element.getRootNode();
return root instanceof ShadowRoot ? root : null;
}
if (element instanceof ShadowRoot) {
return element;
}
// when we don't find a shadow root
if (!element.parentNode) {
return null;
}
return findShadowRoot(element.parentNode);
};
const noop = () => {};
/**
* Trick to restart an element's animation
*
* @param {HTMLElement} element
* @return void
*
* @see https://www.harrytheo.com/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
*/
const reflow = element => {
element.offsetHeight; // eslint-disable-line no-unused-expressions
};
const isRTL = () => document.documentElement.dir === 'rtl';
const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => {
return typeof possibleCallback === 'function' ? possibleCallback.call(...args) : defaultValue;
};
const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {
if (!waitForTransition) {
execute(callback);
return;
}
const durationPadding = 5;
const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding;
let called = false;
const handler = ({
target
}) => {
if (target !== transitionElement) {
return;
}
called = true;
transitionElement.removeEventListener(TRANSITION_END, handler);
execute(callback);
};
transitionElement.addEventListener(TRANSITION_END, handler);
setTimeout(() => {
if (!called) {
triggerTransitionEnd(transitionElement);
}
}, emulatedDuration);
};
/**
* Return the previous/next element of a list.
*
* @param {array} list The list of elements
* @param activeElement The active element
* @param shouldGetNext Choose to get next or previous element
* @param isCycleAllowed
* @return {Element|elem} The proper element
*/
const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {
const listLength = list.length;
let index = list.indexOf(activeElement);
// if the element does not exist in the list return an element
// depending on the direction and if cycle is allowed
if (index === -1) {
return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0];
}
index += shouldGetNext ? 1 : -1;
if (isCycleAllowed) {
index = (index + listLength) % listLength;
}
return list[Math.max(0, Math.min(index, listLength - 1))];
};
/**
* --------------------------------------------------------------------------
* Bootstrap util/config.js
@@ -821,6 +886,20 @@
EventHandler.trigger(this._element, EVENT_CLOSED);
this.dispose();
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Alert.getOrCreateInstance(this);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config](this);
});
}
}
/**
@@ -829,6 +908,12 @@
enableDismissTrigger(Alert, 'close');
/**
* jQuery
*/
defineJQueryPlugin(Alert);
/**
* --------------------------------------------------------------------------
* Bootstrap button.js
@@ -864,6 +949,16 @@
// Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method
this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE$3));
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Button.getOrCreateInstance(this);
if (config === 'toggle') {
data[config]();
}
});
}
}
/**
@@ -877,6 +972,12 @@
data.toggle();
});
/**
* jQuery
*/
defineJQueryPlugin(Button);
/**
* --------------------------------------------------------------------------
* Bootstrap util/swipe.js
@@ -1313,6 +1414,23 @@
}
return order === ORDER_PREV ? DIRECTION_RIGHT : DIRECTION_LEFT;
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Carousel.getOrCreateInstance(this, config);
if (typeof config === 'number') {
data.to(config);
return;
}
if (typeof config === 'string') {
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
}
});
}
}
/**
@@ -1347,6 +1465,12 @@
}
});
/**
* jQuery
*/
defineJQueryPlugin(Carousel);
/**
* --------------------------------------------------------------------------
* Bootstrap collapse.js
@@ -1540,6 +1664,23 @@
element.setAttribute('aria-expanded', isOpen);
}
}
// Static
static jQueryInterface(config) {
const _config = {};
if (typeof config === 'string' && /show|hide/.test(config)) {
_config.toggle = false;
}
return this.each(function () {
const data = Collapse.getOrCreateInstance(this, _config);
if (typeof config === 'string') {
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
}
});
}
}
/**
@@ -1558,6 +1699,12 @@
}
});
/**
* jQuery
*/
defineJQueryPlugin(Collapse);
/**
* --------------------------------------------------------------------------
* Bootstrap dropdown.js
@@ -1831,6 +1978,20 @@
// allow cycling to get the last item in case key equals ARROW_UP_KEY
getNextActiveElement(items, target, key === ARROW_DOWN_KEY$1, !items.includes(target)).focus();
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Dropdown.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
static clearMenus(event) {
if (event.button === RIGHT_MOUSE_BUTTON || event.type === 'keyup' && event.key !== TAB_KEY$1) {
return;
@@ -1906,6 +2067,12 @@
Dropdown.getOrCreateInstance(this).toggle();
});
/**
* jQuery
*/
defineJQueryPlugin(Dropdown);
/**
* --------------------------------------------------------------------------
* Bootstrap util/backdrop.js
@@ -2478,6 +2645,20 @@
this._element.style.paddingLeft = '';
this._element.style.paddingRight = '';
}
// Static
static jQueryInterface(config, relatedTarget) {
return this.each(function () {
const data = Modal.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config](relatedTarget);
});
}
}
/**
@@ -2511,6 +2692,12 @@
});
enableDismissTrigger(Modal);
/**
* jQuery
*/
defineJQueryPlugin(Modal);
/**
* --------------------------------------------------------------------------
* Bootstrap offcanvas.js
@@ -2679,6 +2866,20 @@
EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED);
});
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Offcanvas.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config](this);
});
}
}
/**
@@ -2722,6 +2923,12 @@
});
enableDismissTrigger(Offcanvas);
/**
* jQuery
*/
defineJQueryPlugin(Offcanvas);
/**
* --------------------------------------------------------------------------
* Bootstrap util/sanitizer.js
@@ -3443,8 +3650,28 @@
this.tip = null;
}
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Tooltip.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
* jQuery
*/
defineJQueryPlugin(Tooltip);
/**
* --------------------------------------------------------------------------
* Bootstrap popover.js
@@ -3504,8 +3731,28 @@
_getContent() {
return this._resolvePossibleFunction(this._config.content);
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Popover.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
* jQuery
*/
defineJQueryPlugin(Popover);
/**
* --------------------------------------------------------------------------
* Bootstrap scrollspy.js
@@ -3734,6 +3981,20 @@
node.classList.remove(CLASS_NAME_ACTIVE$1);
}
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = ScrollSpy.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
@@ -3746,6 +4007,12 @@
}
});
/**
* jQuery
*/
defineJQueryPlugin(ScrollSpy);
/**
* --------------------------------------------------------------------------
* Bootstrap tab.js
@@ -3972,6 +4239,20 @@
_getOuterElement(elem) {
return elem.closest(SELECTOR_OUTER) || elem;
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Tab.getOrCreateInstance(this);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
@@ -3996,6 +4277,11 @@
Tab.getOrCreateInstance(element);
}
});
/**
* jQuery
*/
defineJQueryPlugin(Tab);
/**
* --------------------------------------------------------------------------
@@ -4153,6 +4439,19 @@
clearTimeout(this._timeout);
this._timeout = null;
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Toast.getOrCreateInstance(this, config);
if (typeof config === 'string') {
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config](this);
}
});
}
}
/**
@@ -4161,6 +4460,12 @@
enableDismissTrigger(Toast);
/**
* jQuery
*/
defineJQueryPlugin(Toast);
/**
* --------------------------------------------------------------------------
* Bootstrap index.umd.js
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+24 -4
View File
@@ -4,10 +4,10 @@
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./base-component.js'), require('./dom/event-handler.js'), require('./util/component-functions.js')) :
typeof define === 'function' && define.amd ? define(['./base-component', './dom/event-handler', './util/component-functions'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Alert = factory(global.BaseComponent, global.EventHandler, global.ComponentFunctions));
})(this, (function (BaseComponent, EventHandler, componentFunctions_js) { 'use strict';
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./base-component.js'), require('./dom/event-handler.js'), require('./util/component-functions.js'), require('./util/index.js')) :
typeof define === 'function' && define.amd ? define(['./base-component', './dom/event-handler', './util/component-functions', './util/index'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Alert = factory(global.BaseComponent, global.EventHandler, global.ComponentFunctions, global.Index));
})(this, (function (BaseComponent, EventHandler, componentFunctions_js, index_js) { 'use strict';
/**
* --------------------------------------------------------------------------
@@ -56,6 +56,20 @@
EventHandler.trigger(this._element, EVENT_CLOSED);
this.dispose();
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Alert.getOrCreateInstance(this);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config](this);
});
}
}
/**
@@ -64,6 +78,12 @@
componentFunctions_js.enableDismissTrigger(Alert, 'close');
/**
* jQuery
*/
index_js.defineJQueryPlugin(Alert);
return Alert;
}));
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"alert.js","sources":["../src/alert.js"],"sourcesContent":["/**\n * --------------------------------------------------------------------------\n * Bootstrap alert.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport BaseComponent from './base-component.js'\nimport EventHandler from './dom/event-handler.js'\nimport { enableDismissTrigger } from './util/component-functions.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'alert'\nconst DATA_KEY = 'bs.alert'\nconst EVENT_KEY = `.${DATA_KEY}`\n\nconst EVENT_CLOSE = `close${EVENT_KEY}`\nconst EVENT_CLOSED = `closed${EVENT_KEY}`\nconst CLASS_NAME_FADE = 'fade'\nconst CLASS_NAME_SHOW = 'show'\n\n/**\n * Class definition\n */\n\nclass Alert extends BaseComponent {\n // Getters\n static get NAME() {\n return NAME\n }\n\n // Public\n close() {\n const closeEvent = EventHandler.trigger(this._element, EVENT_CLOSE)\n\n if (closeEvent.defaultPrevented) {\n return\n }\n\n this._element.classList.remove(CLASS_NAME_SHOW)\n\n const isAnimated = this._element.classList.contains(CLASS_NAME_FADE)\n this._queueCallback(() => this._destroyElement(), this._element, isAnimated)\n }\n\n // Private\n _destroyElement() {\n this._element.remove()\n EventHandler.trigger(this._element, EVENT_CLOSED)\n this.dispose()\n }\n}\n\n/**\n * Data API implementation\n */\n\nenableDismissTrigger(Alert, 'close')\n\nexport default Alert\n"],"names":["NAME","DATA_KEY","EVENT_KEY","EVENT_CLOSE","EVENT_CLOSED","CLASS_NAME_FADE","CLASS_NAME_SHOW","Alert","BaseComponent","close","closeEvent","EventHandler","trigger","_element","defaultPrevented","classList","remove","isAnimated","contains","_queueCallback","_destroyElement","dispose","enableDismissTrigger"],"mappings":";;;;;;;;;;;EAAA;EACA;EACA;EACA;EACA;EACA;;;EAMA;EACA;EACA;;EAEA,MAAMA,IAAI,GAAG,OAAO;EACpB,MAAMC,QAAQ,GAAG,UAAU;EAC3B,MAAMC,SAAS,GAAG,CAAA,CAAA,EAAID,QAAQ,CAAA,CAAE;EAEhC,MAAME,WAAW,GAAG,CAAA,KAAA,EAAQD,SAAS,CAAA,CAAE;EACvC,MAAME,YAAY,GAAG,CAAA,MAAA,EAASF,SAAS,CAAA,CAAE;EACzC,MAAMG,eAAe,GAAG,MAAM;EAC9B,MAAMC,eAAe,GAAG,MAAM;;EAE9B;EACA;EACA;;EAEA,MAAMC,KAAK,SAASC,aAAa,CAAC;EAChC;IACA,WAAWR,IAAIA,GAAG;EAChB,IAAA,OAAOA,IAAI;EACb,EAAA;;EAEA;EACAS,EAAAA,KAAKA,GAAG;MACN,MAAMC,UAAU,GAAGC,YAAY,CAACC,OAAO,CAAC,IAAI,CAACC,QAAQ,EAAEV,WAAW,CAAC;MAEnE,IAAIO,UAAU,CAACI,gBAAgB,EAAE;EAC/B,MAAA;EACF,IAAA;MAEA,IAAI,CAACD,QAAQ,CAACE,SAAS,CAACC,MAAM,CAACV,eAAe,CAAC;MAE/C,MAAMW,UAAU,GAAG,IAAI,CAACJ,QAAQ,CAACE,SAAS,CAACG,QAAQ,CAACb,eAAe,CAAC;EACpE,IAAA,IAAI,CAACc,cAAc,CAAC,MAAM,IAAI,CAACC,eAAe,EAAE,EAAE,IAAI,CAACP,QAAQ,EAAEI,UAAU,CAAC;EAC9E,EAAA;;EAEA;EACAG,EAAAA,eAAeA,GAAG;EAChB,IAAA,IAAI,CAACP,QAAQ,CAACG,MAAM,EAAE;MACtBL,YAAY,CAACC,OAAO,CAAC,IAAI,CAACC,QAAQ,EAAET,YAAY,CAAC;MACjD,IAAI,CAACiB,OAAO,EAAE;EAChB,EAAA;EACF;;EAEA;EACA;EACA;;AAEAC,4CAAoB,CAACf,KAAK,EAAE,OAAO,CAAC;;;;;;;;"}
{"version":3,"file":"alert.js","sources":["../src/alert.js"],"sourcesContent":["/**\n * --------------------------------------------------------------------------\n * Bootstrap alert.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport BaseComponent from './base-component.js'\nimport EventHandler from './dom/event-handler.js'\nimport { enableDismissTrigger } from './util/component-functions.js'\nimport { defineJQueryPlugin } from './util/index.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'alert'\nconst DATA_KEY = 'bs.alert'\nconst EVENT_KEY = `.${DATA_KEY}`\n\nconst EVENT_CLOSE = `close${EVENT_KEY}`\nconst EVENT_CLOSED = `closed${EVENT_KEY}`\nconst CLASS_NAME_FADE = 'fade'\nconst CLASS_NAME_SHOW = 'show'\n\n/**\n * Class definition\n */\n\nclass Alert extends BaseComponent {\n // Getters\n static get NAME() {\n return NAME\n }\n\n // Public\n close() {\n const closeEvent = EventHandler.trigger(this._element, EVENT_CLOSE)\n\n if (closeEvent.defaultPrevented) {\n return\n }\n\n this._element.classList.remove(CLASS_NAME_SHOW)\n\n const isAnimated = this._element.classList.contains(CLASS_NAME_FADE)\n this._queueCallback(() => this._destroyElement(), this._element, isAnimated)\n }\n\n // Private\n _destroyElement() {\n this._element.remove()\n EventHandler.trigger(this._element, EVENT_CLOSED)\n this.dispose()\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Alert.getOrCreateInstance(this)\n\n if (typeof config !== 'string') {\n return\n }\n\n if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n\n data[config](this)\n })\n }\n}\n\n/**\n * Data API implementation\n */\n\nenableDismissTrigger(Alert, 'close')\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Alert)\n\nexport default Alert\n"],"names":["NAME","DATA_KEY","EVENT_KEY","EVENT_CLOSE","EVENT_CLOSED","CLASS_NAME_FADE","CLASS_NAME_SHOW","Alert","BaseComponent","close","closeEvent","EventHandler","trigger","_element","defaultPrevented","classList","remove","isAnimated","contains","_queueCallback","_destroyElement","dispose","jQueryInterface","config","each","data","getOrCreateInstance","undefined","startsWith","TypeError","enableDismissTrigger","defineJQueryPlugin"],"mappings":";;;;;;;;;;;EAAA;EACA;EACA;EACA;EACA;EACA;;;EAOA;EACA;EACA;;EAEA,MAAMA,IAAI,GAAG,OAAO;EACpB,MAAMC,QAAQ,GAAG,UAAU;EAC3B,MAAMC,SAAS,GAAG,CAAA,CAAA,EAAID,QAAQ,CAAA,CAAE;EAEhC,MAAME,WAAW,GAAG,CAAA,KAAA,EAAQD,SAAS,CAAA,CAAE;EACvC,MAAME,YAAY,GAAG,CAAA,MAAA,EAASF,SAAS,CAAA,CAAE;EACzC,MAAMG,eAAe,GAAG,MAAM;EAC9B,MAAMC,eAAe,GAAG,MAAM;;EAE9B;EACA;EACA;;EAEA,MAAMC,KAAK,SAASC,aAAa,CAAC;EAChC;IACA,WAAWR,IAAIA,GAAG;EAChB,IAAA,OAAOA,IAAI;EACb,EAAA;;EAEA;EACAS,EAAAA,KAAKA,GAAG;MACN,MAAMC,UAAU,GAAGC,YAAY,CAACC,OAAO,CAAC,IAAI,CAACC,QAAQ,EAAEV,WAAW,CAAC;MAEnE,IAAIO,UAAU,CAACI,gBAAgB,EAAE;EAC/B,MAAA;EACF,IAAA;MAEA,IAAI,CAACD,QAAQ,CAACE,SAAS,CAACC,MAAM,CAACV,eAAe,CAAC;MAE/C,MAAMW,UAAU,GAAG,IAAI,CAACJ,QAAQ,CAACE,SAAS,CAACG,QAAQ,CAACb,eAAe,CAAC;EACpE,IAAA,IAAI,CAACc,cAAc,CAAC,MAAM,IAAI,CAACC,eAAe,EAAE,EAAE,IAAI,CAACP,QAAQ,EAAEI,UAAU,CAAC;EAC9E,EAAA;;EAEA;EACAG,EAAAA,eAAeA,GAAG;EAChB,IAAA,IAAI,CAACP,QAAQ,CAACG,MAAM,EAAE;MACtBL,YAAY,CAACC,OAAO,CAAC,IAAI,CAACC,QAAQ,EAAET,YAAY,CAAC;MACjD,IAAI,CAACiB,OAAO,EAAE;EAChB,EAAA;;EAEA;IACA,OAAOC,eAAeA,CAACC,MAAM,EAAE;EAC7B,IAAA,OAAO,IAAI,CAACC,IAAI,CAAC,YAAY;EAC3B,MAAA,MAAMC,IAAI,GAAGlB,KAAK,CAACmB,mBAAmB,CAAC,IAAI,CAAC;EAE5C,MAAA,IAAI,OAAOH,MAAM,KAAK,QAAQ,EAAE;EAC9B,QAAA;EACF,MAAA;EAEA,MAAA,IAAIE,IAAI,CAACF,MAAM,CAAC,KAAKI,SAAS,IAAIJ,MAAM,CAACK,UAAU,CAAC,GAAG,CAAC,IAAIL,MAAM,KAAK,aAAa,EAAE;EACpF,QAAA,MAAM,IAAIM,SAAS,CAAC,CAAA,iBAAA,EAAoBN,MAAM,GAAG,CAAC;EACpD,MAAA;EAEAE,MAAAA,IAAI,CAACF,MAAM,CAAC,CAAC,IAAI,CAAC;EACpB,IAAA,CAAC,CAAC;EACJ,EAAA;EACF;;EAEA;EACA;EACA;;AAEAO,4CAAoB,CAACvB,KAAK,EAAE,OAAO,CAAC;;EAEpC;EACA;EACA;;AAEAwB,6BAAkB,CAACxB,KAAK,CAAC;;;;;;;;"}
+20 -4
View File
@@ -4,10 +4,10 @@
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./base-component.js'), require('./dom/event-handler.js')) :
typeof define === 'function' && define.amd ? define(['./base-component', './dom/event-handler'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Button = factory(global.BaseComponent, global.EventHandler));
})(this, (function (BaseComponent, EventHandler) { 'use strict';
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./base-component.js'), require('./dom/event-handler.js'), require('./util/index.js')) :
typeof define === 'function' && define.amd ? define(['./base-component', './dom/event-handler', './util/index'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Button = factory(global.BaseComponent, global.EventHandler, global.Index));
})(this, (function (BaseComponent, EventHandler, index_js) { 'use strict';
/**
* --------------------------------------------------------------------------
@@ -44,6 +44,16 @@
// Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method
this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE));
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Button.getOrCreateInstance(this);
if (config === 'toggle') {
data[config]();
}
});
}
}
/**
@@ -57,6 +67,12 @@
data.toggle();
});
/**
* jQuery
*/
index_js.defineJQueryPlugin(Button);
return Button;
}));
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"button.js","sources":["../src/button.js"],"sourcesContent":["/**\n * --------------------------------------------------------------------------\n * Bootstrap button.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport BaseComponent from './base-component.js'\nimport EventHandler from './dom/event-handler.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'button'\nconst DATA_KEY = 'bs.button'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\n\nconst CLASS_NAME_ACTIVE = 'active'\nconst SELECTOR_DATA_TOGGLE = '[data-bs-toggle=\"button\"]'\nconst EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`\n\n/**\n * Class definition\n */\n\nclass Button extends BaseComponent {\n // Getters\n static get NAME() {\n return NAME\n }\n\n // Public\n toggle() {\n // Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method\n this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE))\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, event => {\n event.preventDefault()\n\n const button = event.target.closest(SELECTOR_DATA_TOGGLE)\n const data = Button.getOrCreateInstance(button)\n\n data.toggle()\n})\n\nexport default Button\n"],"names":["NAME","DATA_KEY","EVENT_KEY","DATA_API_KEY","CLASS_NAME_ACTIVE","SELECTOR_DATA_TOGGLE","EVENT_CLICK_DATA_API","Button","BaseComponent","toggle","_element","setAttribute","classList","EventHandler","on","document","event","preventDefault","button","target","closest","data","getOrCreateInstance"],"mappings":";;;;;;;;;;;EAAA;EACA;EACA;EACA;EACA;EACA;;;EAKA;EACA;EACA;;EAEA,MAAMA,IAAI,GAAG,QAAQ;EACrB,MAAMC,QAAQ,GAAG,WAAW;EAC5B,MAAMC,SAAS,GAAG,CAAA,CAAA,EAAID,QAAQ,CAAA,CAAE;EAChC,MAAME,YAAY,GAAG,WAAW;EAEhC,MAAMC,iBAAiB,GAAG,QAAQ;EAClC,MAAMC,oBAAoB,GAAG,2BAA2B;EACxD,MAAMC,oBAAoB,GAAG,CAAA,KAAA,EAAQJ,SAAS,CAAA,EAAGC,YAAY,CAAA,CAAE;;EAE/D;EACA;EACA;;EAEA,MAAMI,MAAM,SAASC,aAAa,CAAC;EACjC;IACA,WAAWR,IAAIA,GAAG;EAChB,IAAA,OAAOA,IAAI;EACb,EAAA;;EAEA;EACAS,EAAAA,MAAMA,GAAG;EACP;EACA,IAAA,IAAI,CAACC,QAAQ,CAACC,YAAY,CAAC,cAAc,EAAE,IAAI,CAACD,QAAQ,CAACE,SAAS,CAACH,MAAM,CAACL,iBAAiB,CAAC,CAAC;EAC/F,EAAA;EACF;;EAEA;EACA;EACA;;EAEAS,YAAY,CAACC,EAAE,CAACC,QAAQ,EAAET,oBAAoB,EAAED,oBAAoB,EAAEW,KAAK,IAAI;IAC7EA,KAAK,CAACC,cAAc,EAAE;IAEtB,MAAMC,MAAM,GAAGF,KAAK,CAACG,MAAM,CAACC,OAAO,CAACf,oBAAoB,CAAC;EACzD,EAAA,MAAMgB,IAAI,GAAGd,MAAM,CAACe,mBAAmB,CAACJ,MAAM,CAAC;IAE/CG,IAAI,CAACZ,MAAM,EAAE;EACf,CAAC,CAAC;;;;;;;;"}
{"version":3,"file":"button.js","sources":["../src/button.js"],"sourcesContent":["/**\n * --------------------------------------------------------------------------\n * Bootstrap button.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport BaseComponent from './base-component.js'\nimport EventHandler from './dom/event-handler.js'\nimport { defineJQueryPlugin } from './util/index.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'button'\nconst DATA_KEY = 'bs.button'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\n\nconst CLASS_NAME_ACTIVE = 'active'\nconst SELECTOR_DATA_TOGGLE = '[data-bs-toggle=\"button\"]'\nconst EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`\n\n/**\n * Class definition\n */\n\nclass Button extends BaseComponent {\n // Getters\n static get NAME() {\n return NAME\n }\n\n // Public\n toggle() {\n // Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method\n this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE))\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Button.getOrCreateInstance(this)\n\n if (config === 'toggle') {\n data[config]()\n }\n })\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, event => {\n event.preventDefault()\n\n const button = event.target.closest(SELECTOR_DATA_TOGGLE)\n const data = Button.getOrCreateInstance(button)\n\n data.toggle()\n})\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Button)\n\nexport default Button\n"],"names":["NAME","DATA_KEY","EVENT_KEY","DATA_API_KEY","CLASS_NAME_ACTIVE","SELECTOR_DATA_TOGGLE","EVENT_CLICK_DATA_API","Button","BaseComponent","toggle","_element","setAttribute","classList","jQueryInterface","config","each","data","getOrCreateInstance","EventHandler","on","document","event","preventDefault","button","target","closest","defineJQueryPlugin"],"mappings":";;;;;;;;;;;EAAA;EACA;EACA;EACA;EACA;EACA;;;EAMA;EACA;EACA;;EAEA,MAAMA,IAAI,GAAG,QAAQ;EACrB,MAAMC,QAAQ,GAAG,WAAW;EAC5B,MAAMC,SAAS,GAAG,CAAA,CAAA,EAAID,QAAQ,CAAA,CAAE;EAChC,MAAME,YAAY,GAAG,WAAW;EAEhC,MAAMC,iBAAiB,GAAG,QAAQ;EAClC,MAAMC,oBAAoB,GAAG,2BAA2B;EACxD,MAAMC,oBAAoB,GAAG,CAAA,KAAA,EAAQJ,SAAS,CAAA,EAAGC,YAAY,CAAA,CAAE;;EAE/D;EACA;EACA;;EAEA,MAAMI,MAAM,SAASC,aAAa,CAAC;EACjC;IACA,WAAWR,IAAIA,GAAG;EAChB,IAAA,OAAOA,IAAI;EACb,EAAA;;EAEA;EACAS,EAAAA,MAAMA,GAAG;EACP;EACA,IAAA,IAAI,CAACC,QAAQ,CAACC,YAAY,CAAC,cAAc,EAAE,IAAI,CAACD,QAAQ,CAACE,SAAS,CAACH,MAAM,CAACL,iBAAiB,CAAC,CAAC;EAC/F,EAAA;;EAEA;IACA,OAAOS,eAAeA,CAACC,MAAM,EAAE;EAC7B,IAAA,OAAO,IAAI,CAACC,IAAI,CAAC,YAAY;EAC3B,MAAA,MAAMC,IAAI,GAAGT,MAAM,CAACU,mBAAmB,CAAC,IAAI,CAAC;QAE7C,IAAIH,MAAM,KAAK,QAAQ,EAAE;EACvBE,QAAAA,IAAI,CAACF,MAAM,CAAC,EAAE;EAChB,MAAA;EACF,IAAA,CAAC,CAAC;EACJ,EAAA;EACF;;EAEA;EACA;EACA;;EAEAI,YAAY,CAACC,EAAE,CAACC,QAAQ,EAAEd,oBAAoB,EAAED,oBAAoB,EAAEgB,KAAK,IAAI;IAC7EA,KAAK,CAACC,cAAc,EAAE;IAEtB,MAAMC,MAAM,GAAGF,KAAK,CAACG,MAAM,CAACC,OAAO,CAACpB,oBAAoB,CAAC;EACzD,EAAA,MAAMW,IAAI,GAAGT,MAAM,CAACU,mBAAmB,CAACM,MAAM,CAAC;IAE/CP,IAAI,CAACP,MAAM,EAAE;EACf,CAAC,CAAC;;EAEF;EACA;EACA;;AAEAiB,6BAAkB,CAACnB,MAAM,CAAC;;;;;;;;"}
+23
View File
@@ -325,6 +325,23 @@
}
return order === ORDER_PREV ? DIRECTION_RIGHT : DIRECTION_LEFT;
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Carousel.getOrCreateInstance(this, config);
if (typeof config === 'number') {
data.to(config);
return;
}
if (typeof config === 'string') {
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
}
});
}
}
/**
@@ -359,6 +376,12 @@
}
});
/**
* jQuery
*/
index_js.defineJQueryPlugin(Carousel);
return Carousel;
}));
+1 -1
View File
File diff suppressed because one or more lines are too long
+23
View File
@@ -202,6 +202,23 @@
element.setAttribute('aria-expanded', isOpen);
}
}
// Static
static jQueryInterface(config) {
const _config = {};
if (typeof config === 'string' && /show|hide/.test(config)) {
_config.toggle = false;
}
return this.each(function () {
const data = Collapse.getOrCreateInstance(this, _config);
if (typeof config === 'string') {
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
}
});
}
}
/**
@@ -220,6 +237,12 @@
}
});
/**
* jQuery
*/
index_js.defineJQueryPlugin(Collapse);
return Collapse;
}));
+1 -1
View File
File diff suppressed because one or more lines are too long
+29 -6
View File
@@ -4,10 +4,10 @@
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.EventHandler = factory());
})(this, (function () { 'use strict';
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('../util/index.js')) :
typeof define === 'function' && define.amd ? define(['../util/index'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.EventHandler = factory(global.Index));
})(this, (function (index_js) { 'use strict';
/**
* --------------------------------------------------------------------------
@@ -16,6 +16,7 @@
* --------------------------------------------------------------------------
*/
/**
* Constants
*/
@@ -184,11 +185,33 @@
if (typeof event !== 'string' || !element) {
return null;
}
const $ = index_js.getjQuery();
const typeEvent = getTypeEvent(event);
const inNamespace = event !== typeEvent;
let jQueryEvent = null;
let bubbles = true;
let nativeDispatch = true;
let defaultPrevented = false;
if (inNamespace && $) {
jQueryEvent = $.Event(event, args);
$(element).trigger(jQueryEvent);
bubbles = !jQueryEvent.isPropagationStopped();
nativeDispatch = !jQueryEvent.isImmediatePropagationStopped();
defaultPrevented = jQueryEvent.isDefaultPrevented();
}
const evt = hydrateObj(new Event(event, {
bubbles: true,
bubbles,
cancelable: true
}), args);
element.dispatchEvent(evt);
if (defaultPrevented) {
evt.preventDefault();
}
if (nativeDispatch) {
element.dispatchEvent(evt);
}
if (evt.defaultPrevented && jQueryEvent) {
jQueryEvent.preventDefault();
}
return evt;
}
};
+1 -1
View File
File diff suppressed because one or more lines are too long
+20
View File
@@ -301,6 +301,20 @@
// allow cycling to get the last item in case key equals ARROW_UP_KEY
index_js.getNextActiveElement(items, target, key === ARROW_DOWN_KEY, !items.includes(target)).focus();
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Dropdown.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
static clearMenus(event) {
if (event.button === RIGHT_MOUSE_BUTTON || event.type === 'keyup' && event.key !== TAB_KEY) {
return;
@@ -376,6 +390,12 @@
Dropdown.getOrCreateInstance(this).toggle();
});
/**
* jQuery
*/
index_js.defineJQueryPlugin(Dropdown);
return Dropdown;
}));
+1 -1
View File
File diff suppressed because one or more lines are too long
+20
View File
@@ -261,6 +261,20 @@
this._element.style.paddingLeft = '';
this._element.style.paddingRight = '';
}
// Static
static jQueryInterface(config, relatedTarget) {
return this.each(function () {
const data = Modal.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config](relatedTarget);
});
}
}
/**
@@ -294,6 +308,12 @@
});
componentFunctions_js.enableDismissTrigger(Modal);
/**
* jQuery
*/
index_js.defineJQueryPlugin(Modal);
return Modal;
}));
+1 -1
View File
File diff suppressed because one or more lines are too long
+20
View File
@@ -177,6 +177,20 @@
EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED);
});
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Offcanvas.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config](this);
});
}
}
/**
@@ -220,6 +234,12 @@
});
componentFunctions_js.enableDismissTrigger(Offcanvas);
/**
* jQuery
*/
index_js.defineJQueryPlugin(Offcanvas);
return Offcanvas;
}));
+1 -1
View File
File diff suppressed because one or more lines are too long
+24 -4
View File
@@ -4,10 +4,10 @@
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./tooltip.js')) :
typeof define === 'function' && define.amd ? define(['./tooltip'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Popover = factory(global.Tooltip));
})(this, (function (Tooltip) { 'use strict';
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./tooltip.js'), require('./util/index.js')) :
typeof define === 'function' && define.amd ? define(['./tooltip', './util/index'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Popover = factory(global.Tooltip, global.Index));
})(this, (function (Tooltip, index_js) { 'use strict';
/**
* --------------------------------------------------------------------------
@@ -68,8 +68,28 @@
_getContent() {
return this._resolvePossibleFunction(this._config.content);
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Popover.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
* jQuery
*/
index_js.defineJQueryPlugin(Popover);
return Popover;
}));
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"popover.js","sources":["../src/popover.js"],"sourcesContent":["/**\n * --------------------------------------------------------------------------\n * Bootstrap popover.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport Tooltip from './tooltip.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'popover'\n\nconst SELECTOR_TITLE = '.popover-header'\nconst SELECTOR_CONTENT = '.popover-body'\n\nconst Default = {\n ...Tooltip.Default,\n content: '',\n offset: [0, 8],\n placement: 'right',\n template: '<div class=\"popover\" role=\"tooltip\">' +\n '<div class=\"popover-arrow\"></div>' +\n '<h3 class=\"popover-header\"></h3>' +\n '<div class=\"popover-body\"></div>' +\n '</div>',\n trigger: 'click'\n}\n\nconst DefaultType = {\n ...Tooltip.DefaultType,\n content: '(null|string|element|function)'\n}\n\n/**\n * Class definition\n */\n\nclass Popover extends Tooltip {\n // Getters\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Overrides\n _isWithContent() {\n return this._getTitle() || this._getContent()\n }\n\n // Private\n _getContentForTemplate() {\n return {\n [SELECTOR_TITLE]: this._getTitle(),\n [SELECTOR_CONTENT]: this._getContent()\n }\n }\n\n _getContent() {\n return this._resolvePossibleFunction(this._config.content)\n }\n}\n\nexport default Popover\n"],"names":["NAME","SELECTOR_TITLE","SELECTOR_CONTENT","Default","Tooltip","content","offset","placement","template","trigger","DefaultType","Popover","_isWithContent","_getTitle","_getContent","_getContentForTemplate","_resolvePossibleFunction","_config"],"mappings":";;;;;;;;;;;EAAA;EACA;EACA;EACA;EACA;EACA;;;EAIA;EACA;EACA;;EAEA,MAAMA,IAAI,GAAG,SAAS;EAEtB,MAAMC,cAAc,GAAG,iBAAiB;EACxC,MAAMC,gBAAgB,GAAG,eAAe;EAExC,MAAMC,OAAO,GAAG;IACd,GAAGC,OAAO,CAACD,OAAO;EAClBE,EAAAA,OAAO,EAAE,EAAE;EACXC,EAAAA,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;EACdC,EAAAA,SAAS,EAAE,OAAO;IAClBC,QAAQ,EAAE,sCAAsC,GAC9C,mCAAmC,GACnC,kCAAkC,GAClC,kCAAkC,GAClC,QAAQ;EACVC,EAAAA,OAAO,EAAE;EACX,CAAC;EAED,MAAMC,WAAW,GAAG;IAClB,GAAGN,OAAO,CAACM,WAAW;EACtBL,EAAAA,OAAO,EAAE;EACX,CAAC;;EAED;EACA;EACA;;EAEA,MAAMM,OAAO,SAASP,OAAO,CAAC;EAC5B;IACA,WAAWD,OAAOA,GAAG;EACnB,IAAA,OAAOA,OAAO;EAChB,EAAA;IAEA,WAAWO,WAAWA,GAAG;EACvB,IAAA,OAAOA,WAAW;EACpB,EAAA;IAEA,WAAWV,IAAIA,GAAG;EAChB,IAAA,OAAOA,IAAI;EACb,EAAA;;EAEA;EACAY,EAAAA,cAAcA,GAAG;MACf,OAAO,IAAI,CAACC,SAAS,EAAE,IAAI,IAAI,CAACC,WAAW,EAAE;EAC/C,EAAA;;EAEA;EACAC,EAAAA,sBAAsBA,GAAG;MACvB,OAAO;EACL,MAAA,CAACd,cAAc,GAAG,IAAI,CAACY,SAAS,EAAE;EAClC,MAAA,CAACX,gBAAgB,GAAG,IAAI,CAACY,WAAW;OACrC;EACH,EAAA;EAEAA,EAAAA,WAAWA,GAAG;MACZ,OAAO,IAAI,CAACE,wBAAwB,CAAC,IAAI,CAACC,OAAO,CAACZ,OAAO,CAAC;EAC5D,EAAA;EACF;;;;;;;;"}
{"version":3,"file":"popover.js","sources":["../src/popover.js"],"sourcesContent":["/**\n * --------------------------------------------------------------------------\n * Bootstrap popover.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport Tooltip from './tooltip.js'\nimport { defineJQueryPlugin } from './util/index.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'popover'\n\nconst SELECTOR_TITLE = '.popover-header'\nconst SELECTOR_CONTENT = '.popover-body'\n\nconst Default = {\n ...Tooltip.Default,\n content: '',\n offset: [0, 8],\n placement: 'right',\n template: '<div class=\"popover\" role=\"tooltip\">' +\n '<div class=\"popover-arrow\"></div>' +\n '<h3 class=\"popover-header\"></h3>' +\n '<div class=\"popover-body\"></div>' +\n '</div>',\n trigger: 'click'\n}\n\nconst DefaultType = {\n ...Tooltip.DefaultType,\n content: '(null|string|element|function)'\n}\n\n/**\n * Class definition\n */\n\nclass Popover extends Tooltip {\n // Getters\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Overrides\n _isWithContent() {\n return this._getTitle() || this._getContent()\n }\n\n // Private\n _getContentForTemplate() {\n return {\n [SELECTOR_TITLE]: this._getTitle(),\n [SELECTOR_CONTENT]: this._getContent()\n }\n }\n\n _getContent() {\n return this._resolvePossibleFunction(this._config.content)\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Popover.getOrCreateInstance(this, config)\n\n if (typeof config !== 'string') {\n return\n }\n\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n\n data[config]()\n })\n }\n}\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Popover)\n\nexport default Popover\n"],"names":["NAME","SELECTOR_TITLE","SELECTOR_CONTENT","Default","Tooltip","content","offset","placement","template","trigger","DefaultType","Popover","_isWithContent","_getTitle","_getContent","_getContentForTemplate","_resolvePossibleFunction","_config","jQueryInterface","config","each","data","getOrCreateInstance","TypeError","defineJQueryPlugin"],"mappings":";;;;;;;;;;;EAAA;EACA;EACA;EACA;EACA;EACA;;;EAKA;EACA;EACA;;EAEA,MAAMA,IAAI,GAAG,SAAS;EAEtB,MAAMC,cAAc,GAAG,iBAAiB;EACxC,MAAMC,gBAAgB,GAAG,eAAe;EAExC,MAAMC,OAAO,GAAG;IACd,GAAGC,OAAO,CAACD,OAAO;EAClBE,EAAAA,OAAO,EAAE,EAAE;EACXC,EAAAA,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;EACdC,EAAAA,SAAS,EAAE,OAAO;IAClBC,QAAQ,EAAE,sCAAsC,GAC9C,mCAAmC,GACnC,kCAAkC,GAClC,kCAAkC,GAClC,QAAQ;EACVC,EAAAA,OAAO,EAAE;EACX,CAAC;EAED,MAAMC,WAAW,GAAG;IAClB,GAAGN,OAAO,CAACM,WAAW;EACtBL,EAAAA,OAAO,EAAE;EACX,CAAC;;EAED;EACA;EACA;;EAEA,MAAMM,OAAO,SAASP,OAAO,CAAC;EAC5B;IACA,WAAWD,OAAOA,GAAG;EACnB,IAAA,OAAOA,OAAO;EAChB,EAAA;IAEA,WAAWO,WAAWA,GAAG;EACvB,IAAA,OAAOA,WAAW;EACpB,EAAA;IAEA,WAAWV,IAAIA,GAAG;EAChB,IAAA,OAAOA,IAAI;EACb,EAAA;;EAEA;EACAY,EAAAA,cAAcA,GAAG;MACf,OAAO,IAAI,CAACC,SAAS,EAAE,IAAI,IAAI,CAACC,WAAW,EAAE;EAC/C,EAAA;;EAEA;EACAC,EAAAA,sBAAsBA,GAAG;MACvB,OAAO;EACL,MAAA,CAACd,cAAc,GAAG,IAAI,CAACY,SAAS,EAAE;EAClC,MAAA,CAACX,gBAAgB,GAAG,IAAI,CAACY,WAAW;OACrC;EACH,EAAA;EAEAA,EAAAA,WAAWA,GAAG;MACZ,OAAO,IAAI,CAACE,wBAAwB,CAAC,IAAI,CAACC,OAAO,CAACZ,OAAO,CAAC;EAC5D,EAAA;;EAEA;IACA,OAAOa,eAAeA,CAACC,MAAM,EAAE;EAC7B,IAAA,OAAO,IAAI,CAACC,IAAI,CAAC,YAAY;QAC3B,MAAMC,IAAI,GAAGV,OAAO,CAACW,mBAAmB,CAAC,IAAI,EAAEH,MAAM,CAAC;EAEtD,MAAA,IAAI,OAAOA,MAAM,KAAK,QAAQ,EAAE;EAC9B,QAAA;EACF,MAAA;EAEA,MAAA,IAAI,OAAOE,IAAI,CAACF,MAAM,CAAC,KAAK,WAAW,EAAE;EACvC,QAAA,MAAM,IAAII,SAAS,CAAC,CAAA,iBAAA,EAAoBJ,MAAM,GAAG,CAAC;EACpD,MAAA;EAEAE,MAAAA,IAAI,CAACF,MAAM,CAAC,EAAE;EAChB,IAAA,CAAC,CAAC;EACJ,EAAA;EACF;;EAEA;EACA;EACA;;AAEAK,6BAAkB,CAACb,OAAO,CAAC;;;;;;;;"}
+20
View File
@@ -237,6 +237,20 @@
node.classList.remove(CLASS_NAME_ACTIVE);
}
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = ScrollSpy.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
@@ -249,6 +263,12 @@
}
});
/**
* jQuery
*/
index_js.defineJQueryPlugin(ScrollSpy);
return ScrollSpy;
}));
+1 -1
View File
File diff suppressed because one or more lines are too long
+19
View File
@@ -235,6 +235,20 @@
_getOuterElement(elem) {
return elem.closest(SELECTOR_OUTER) || elem;
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Tab.getOrCreateInstance(this);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
@@ -259,6 +273,11 @@
Tab.getOrCreateInstance(element);
}
});
/**
* jQuery
*/
index_js.defineJQueryPlugin(Tab);
return Tab;
+1 -1
View File
File diff suppressed because one or more lines are too long
+19
View File
@@ -165,6 +165,19 @@
clearTimeout(this._timeout);
this._timeout = null;
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Toast.getOrCreateInstance(this, config);
if (typeof config === 'string') {
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config](this);
}
});
}
}
/**
@@ -173,6 +186,12 @@
componentFunctions_js.enableDismissTrigger(Toast);
/**
* jQuery
*/
index_js.defineJQueryPlugin(Toast);
return Toast;
}));
+1 -1
View File
File diff suppressed because one or more lines are too long
+20
View File
@@ -518,8 +518,28 @@
this.tip = null;
}
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Tooltip.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
* jQuery
*/
index_js.defineJQueryPlugin(Tooltip);
return Tooltip;
}));
+1 -1
View File
File diff suppressed because one or more lines are too long
+29 -1
View File
@@ -81,11 +81,15 @@
if (!object || typeof object !== 'object') {
return false;
}
if (typeof object.jquery !== 'undefined') {
object = object[0];
}
return typeof object.nodeType !== 'undefined';
};
const getElement = object => {
// it's a jQuery object or a node element
if (isElement(object)) {
return object;
return object.jquery ? object[0] : object;
}
if (typeof object === 'string' && object.length > 0) {
return document.querySelector(parseSelector(object));
@@ -158,6 +162,12 @@
const reflow = element => {
element.offsetHeight; // eslint-disable-line no-unused-expressions
};
const getjQuery = () => {
if (window.jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {
return window.jQuery;
}
return null;
};
const DOMContentLoadedCallbacks = [];
const onDOMContentLoaded = callback => {
if (document.readyState === 'loading') {
@@ -175,6 +185,22 @@
}
};
const isRTL = () => document.documentElement.dir === 'rtl';
const defineJQueryPlugin = plugin => {
onDOMContentLoaded(() => {
const $ = getjQuery();
/* istanbul ignore if */
if ($) {
const name = plugin.NAME;
const JQUERY_NO_CONFLICT = $.fn[name];
$.fn[name] = plugin.jQueryInterface;
$.fn[name].Constructor = plugin;
$.fn[name].noConflict = () => {
$.fn[name] = JQUERY_NO_CONFLICT;
return plugin.jQueryInterface;
};
}
});
};
const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => {
return typeof possibleCallback === 'function' ? possibleCallback.call(...args) : defaultValue;
};
@@ -229,6 +255,7 @@
return list[Math.max(0, Math.min(index, listLength - 1))];
};
exports.defineJQueryPlugin = defineJQueryPlugin;
exports.execute = execute;
exports.executeAfterTransition = executeAfterTransition;
exports.findShadowRoot = findShadowRoot;
@@ -236,6 +263,7 @@
exports.getNextActiveElement = getNextActiveElement;
exports.getTransitionDurationFromElement = getTransitionDurationFromElement;
exports.getUID = getUID;
exports.getjQuery = getjQuery;
exports.isDisabled = isDisabled;
exports.isElement = isElement;
exports.isRTL = isRTL;
+1 -1
View File
File diff suppressed because one or more lines are too long
+24
View File
@@ -8,6 +8,7 @@
import BaseComponent from './base-component.js'
import EventHandler from './dom/event-handler.js'
import { enableDismissTrigger } from './util/component-functions.js'
import { defineJQueryPlugin } from './util/index.js'
/**
* Constants
@@ -52,6 +53,23 @@ class Alert extends BaseComponent {
EventHandler.trigger(this._element, EVENT_CLOSED)
this.dispose()
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Alert.getOrCreateInstance(this)
if (typeof config !== 'string') {
return
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`)
}
data[config](this)
})
}
}
/**
@@ -60,4 +78,10 @@ class Alert extends BaseComponent {
enableDismissTrigger(Alert, 'close')
/**
* jQuery
*/
defineJQueryPlugin(Alert)
export default Alert
+18
View File
@@ -7,6 +7,7 @@
import BaseComponent from './base-component.js'
import EventHandler from './dom/event-handler.js'
import { defineJQueryPlugin } from './util/index.js'
/**
* Constants
@@ -36,6 +37,17 @@ class Button extends BaseComponent {
// Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method
this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE))
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Button.getOrCreateInstance(this)
if (config === 'toggle') {
data[config]()
}
})
}
}
/**
@@ -51,4 +63,10 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, event => {
data.toggle()
})
/**
* jQuery
*/
defineJQueryPlugin(Button)
export default Button
+27
View File
@@ -10,6 +10,7 @@ import EventHandler from './dom/event-handler.js'
import Manipulator from './dom/manipulator.js'
import SelectorEngine from './dom/selector-engine.js'
import {
defineJQueryPlugin,
getNextActiveElement,
isRTL,
isVisible,
@@ -402,6 +403,26 @@ class Carousel extends BaseComponent {
return order === ORDER_PREV ? DIRECTION_RIGHT : DIRECTION_LEFT
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Carousel.getOrCreateInstance(this, config)
if (typeof config === 'number') {
data.to(config)
return
}
if (typeof config === 'string') {
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`)
}
data[config]()
}
})
}
}
/**
@@ -444,4 +465,10 @@ EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
}
})
/**
* jQuery
*/
defineJQueryPlugin(Carousel)
export default Carousel
+27
View File
@@ -9,6 +9,7 @@ import BaseComponent from './base-component.js'
import EventHandler from './dom/event-handler.js'
import SelectorEngine from './dom/selector-engine.js'
import {
defineJQueryPlugin,
getElement,
reflow
} from './util/index.js'
@@ -250,6 +251,26 @@ class Collapse extends BaseComponent {
element.setAttribute('aria-expanded', isOpen)
}
}
// Static
static jQueryInterface(config) {
const _config = {}
if (typeof config === 'string' && /show|hide/.test(config)) {
_config.toggle = false
}
return this.each(function () {
const data = Collapse.getOrCreateInstance(this, _config)
if (typeof config === 'string') {
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`)
}
data[config]()
}
})
}
}
/**
@@ -267,4 +288,10 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
}
})
/**
* jQuery
*/
defineJQueryPlugin(Collapse)
export default Collapse
+34 -2
View File
@@ -5,6 +5,8 @@
* --------------------------------------------------------------------------
*/
import { getjQuery } from '../util/index.js'
/**
* Constants
*/
@@ -259,8 +261,38 @@ const EventHandler = {
return null
}
const evt = hydrateObj(new Event(event, { bubbles: true, cancelable: true }), args)
element.dispatchEvent(evt)
const $ = getjQuery()
const typeEvent = getTypeEvent(event)
const inNamespace = event !== typeEvent
let jQueryEvent = null
let bubbles = true
let nativeDispatch = true
let defaultPrevented = false
if (inNamespace && $) {
jQueryEvent = $.Event(event, args)
$(element).trigger(jQueryEvent)
bubbles = !jQueryEvent.isPropagationStopped()
nativeDispatch = !jQueryEvent.isImmediatePropagationStopped()
defaultPrevented = jQueryEvent.isDefaultPrevented()
}
const evt = hydrateObj(new Event(event, { bubbles, cancelable: true }), args)
if (defaultPrevented) {
evt.preventDefault()
}
if (nativeDispatch) {
element.dispatchEvent(evt)
}
if (evt.defaultPrevented && jQueryEvent) {
jQueryEvent.preventDefault()
}
return evt
}
}
+24
View File
@@ -11,6 +11,7 @@ import EventHandler from './dom/event-handler.js'
import Manipulator from './dom/manipulator.js'
import SelectorEngine from './dom/selector-engine.js'
import {
defineJQueryPlugin,
execute,
getElement,
getNextActiveElement,
@@ -335,6 +336,23 @@ class Dropdown extends BaseComponent {
getNextActiveElement(items, target, key === ARROW_DOWN_KEY, !items.includes(target)).focus()
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Dropdown.getOrCreateInstance(this, config)
if (typeof config !== 'string') {
return
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`)
}
data[config]()
})
}
static clearMenus(event) {
if (event.button === RIGHT_MOUSE_BUTTON || (event.type === 'keyup' && event.key !== TAB_KEY)) {
return
@@ -428,4 +446,10 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
Dropdown.getOrCreateInstance(this).toggle()
})
/**
* jQuery
*/
defineJQueryPlugin(Dropdown)
export default Dropdown
+24 -1
View File
@@ -12,7 +12,7 @@ import Backdrop from './util/backdrop.js'
import { enableDismissTrigger } from './util/component-functions.js'
import FocusTrap from './util/focustrap.js'
import {
isRTL, isVisible, reflow
defineJQueryPlugin, isRTL, isVisible, reflow
} from './util/index.js'
import ScrollBarHelper from './util/scrollbar.js'
@@ -313,6 +313,23 @@ class Modal extends BaseComponent {
this._element.style.paddingLeft = ''
this._element.style.paddingRight = ''
}
// Static
static jQueryInterface(config, relatedTarget) {
return this.each(function () {
const data = Modal.getOrCreateInstance(this, config)
if (typeof config !== 'string') {
return
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`)
}
data[config](relatedTarget)
})
}
}
/**
@@ -352,4 +369,10 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
enableDismissTrigger(Modal)
/**
* jQuery
*/
defineJQueryPlugin(Modal)
export default Modal
+24
View File
@@ -12,6 +12,7 @@ import Backdrop from './util/backdrop.js'
import { enableDismissTrigger } from './util/component-functions.js'
import FocusTrap from './util/focustrap.js'
import {
defineJQueryPlugin,
isDisabled,
isVisible
} from './util/index.js'
@@ -205,6 +206,23 @@ class Offcanvas extends BaseComponent {
EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED)
})
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Offcanvas.getOrCreateInstance(this, config)
if (typeof config !== 'string') {
return
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`)
}
data[config](this)
})
}
}
/**
@@ -255,4 +273,10 @@ EventHandler.on(window, EVENT_RESIZE, () => {
enableDismissTrigger(Offcanvas)
/**
* jQuery
*/
defineJQueryPlugin(Offcanvas)
export default Offcanvas
+24
View File
@@ -6,6 +6,7 @@
*/
import Tooltip from './tooltip.js'
import { defineJQueryPlugin } from './util/index.js'
/**
* Constants
@@ -68,6 +69,29 @@ class Popover extends Tooltip {
_getContent() {
return this._resolvePossibleFunction(this._config.content)
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Popover.getOrCreateInstance(this, config)
if (typeof config !== 'string') {
return
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`)
}
data[config]()
})
}
}
/**
* jQuery
*/
defineJQueryPlugin(Popover)
export default Popover
+24 -1
View File
@@ -9,7 +9,7 @@ import BaseComponent from './base-component.js'
import EventHandler from './dom/event-handler.js'
import SelectorEngine from './dom/selector-engine.js'
import {
getElement, isDisabled, isVisible
defineJQueryPlugin, getElement, isDisabled, isVisible
} from './util/index.js'
/**
@@ -258,6 +258,23 @@ class ScrollSpy extends BaseComponent {
node.classList.remove(CLASS_NAME_ACTIVE)
}
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = ScrollSpy.getOrCreateInstance(this, config)
if (typeof config !== 'string') {
return
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`)
}
data[config]()
})
}
}
/**
@@ -270,4 +287,10 @@ EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
}
})
/**
* jQuery
*/
defineJQueryPlugin(ScrollSpy)
export default ScrollSpy
+23 -1
View File
@@ -8,7 +8,7 @@
import BaseComponent from './base-component.js'
import EventHandler from './dom/event-handler.js'
import SelectorEngine from './dom/selector-engine.js'
import { getNextActiveElement, isDisabled } from './util/index.js'
import { defineJQueryPlugin, getNextActiveElement, isDisabled } from './util/index.js'
/**
* Constants
@@ -263,6 +263,23 @@ class Tab extends BaseComponent {
_getOuterElement(elem) {
return elem.closest(SELECTOR_OUTER) || elem
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Tab.getOrCreateInstance(this)
if (typeof config !== 'string') {
return
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`)
}
data[config]()
})
}
}
/**
@@ -289,5 +306,10 @@ EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
Tab.getOrCreateInstance(element)
}
})
/**
* jQuery
*/
defineJQueryPlugin(Tab)
export default Tab
+22 -1
View File
@@ -8,7 +8,7 @@
import BaseComponent from './base-component.js'
import EventHandler from './dom/event-handler.js'
import { enableDismissTrigger } from './util/component-functions.js'
import { reflow } from './util/index.js'
import { defineJQueryPlugin, reflow } from './util/index.js'
/**
* Constants
@@ -192,6 +192,21 @@ class Toast extends BaseComponent {
clearTimeout(this._timeout)
this._timeout = null
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Toast.getOrCreateInstance(this, config)
if (typeof config === 'string') {
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`)
}
data[config](this)
}
})
}
}
/**
@@ -200,4 +215,10 @@ class Toast extends BaseComponent {
enableDismissTrigger(Toast)
/**
* jQuery
*/
defineJQueryPlugin(Toast)
export default Toast
+25 -1
View File
@@ -10,7 +10,7 @@ import BaseComponent from './base-component.js'
import EventHandler from './dom/event-handler.js'
import Manipulator from './dom/manipulator.js'
import {
execute, findShadowRoot, getElement, getUID, isRTL, noop
defineJQueryPlugin, execute, findShadowRoot, getElement, getUID, isRTL, noop
} from './util/index.js'
import { DefaultAllowlist } from './util/sanitizer.js'
import TemplateFactory from './util/template-factory.js'
@@ -605,5 +605,29 @@ class Tooltip extends BaseComponent {
this.tip = null
}
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Tooltip.getOrCreateInstance(this, config)
if (typeof config !== 'string') {
return
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`)
}
data[config]()
})
}
}
/**
* jQuery
*/
defineJQueryPlugin(Tooltip)
export default Tooltip
+33 -1
View File
@@ -76,12 +76,17 @@ const isElement = object => {
return false
}
if (typeof object.jquery !== 'undefined') {
object = object[0]
}
return typeof object.nodeType !== 'undefined'
}
const getElement = object => {
// it's a jQuery object or a node element
if (isElement(object)) {
return object
return object.jquery ? object[0] : object
}
if (typeof object === 'string' && object.length > 0) {
@@ -171,6 +176,14 @@ const reflow = element => {
element.offsetHeight // eslint-disable-line no-unused-expressions
}
const getjQuery = () => {
if (window.jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {
return window.jQuery
}
return null
}
const DOMContentLoadedCallbacks = []
const onDOMContentLoaded = callback => {
@@ -192,6 +205,23 @@ const onDOMContentLoaded = callback => {
const isRTL = () => document.documentElement.dir === 'rtl'
const defineJQueryPlugin = plugin => {
onDOMContentLoaded(() => {
const $ = getjQuery()
/* istanbul ignore if */
if ($) {
const name = plugin.NAME
const JQUERY_NO_CONFLICT = $.fn[name]
$.fn[name] = plugin.jQueryInterface
$.fn[name].Constructor = plugin
$.fn[name].noConflict = () => {
$.fn[name] = JQUERY_NO_CONFLICT
return plugin.jQueryInterface
}
}
})
}
const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => {
return typeof possibleCallback === 'function' ? possibleCallback.call(...args) : defaultValue
}
@@ -254,10 +284,12 @@ const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed
}
export {
defineJQueryPlugin,
execute,
executeAfterTransition,
findShadowRoot,
getElement,
getjQuery,
getNextActiveElement,
getTransitionDurationFromElement,
getUID,
+10
View File
@@ -27,6 +27,16 @@ export const createEvent = (eventName, parameters = {}) => {
return new Event(eventName, parameters)
}
export const jQueryMock = {
elements: undefined,
fn: {},
each(fn) {
for (const element of this.elements) {
fn.call(element)
}
}
}
export const clearBodyAndDocument = () => {
const attributes = ['data-bs-padding-right', 'style']
+17 -1
View File
@@ -11,6 +11,7 @@ const { browsers } = require('./browsers.js')
const ENV = process.env
const BROWSERSTACK = Boolean(ENV.BROWSERSTACK)
const DEBUG = Boolean(ENV.DEBUG)
const JQUERY_TEST = Boolean(ENV.JQUERY)
const frameworks = [
'jasmine'
@@ -60,7 +61,7 @@ const config = {
files: [
'node_modules/hammer-simulator/index.js',
{
pattern: 'js/tests/unit/**/*.spec.js',
pattern: 'js/tests/unit/**/!(jquery).spec.js',
watched: !BROWSERSTACK
}
],
@@ -110,6 +111,21 @@ if (BROWSERSTACK) {
config.customLaunchers = browsers
config.browsers = Object.keys(browsers)
reporters.push('BrowserStack', 'kjhtml')
} else if (JQUERY_TEST) {
frameworks.push('detectBrowsers')
plugins.push(
'karma-chrome-launcher',
'karma-firefox-launcher',
'karma-detect-browsers'
)
config.detectBrowsers = detectBrowsers
config.files = [
'node_modules/jquery/dist/jquery.slim.min.js',
{
pattern: 'js/tests/unit/jquery.spec.js',
watched: false
}
]
} else {
frameworks.push('detectBrowsers')
plugins.push(
+75 -1
View File
@@ -1,6 +1,6 @@
import Alert from '../../src/alert.js'
import { getTransitionDurationFromElement } from '../../src/util/index.js'
import { clearFixture, getFixture } from '../helpers/fixture.js'
import { clearFixture, getFixture, jQueryMock } from '../helpers/fixture.js'
describe('Alert', () => {
let fixtureEl
@@ -141,6 +141,80 @@ describe('Alert', () => {
})
})
describe('jQueryInterface', () => {
it('should handle config passed and toggle existing alert', () => {
fixtureEl.innerHTML = '<div class="alert"></div>'
const alertEl = fixtureEl.querySelector('.alert')
const alert = new Alert(alertEl)
const spy = spyOn(alert, 'close')
jQueryMock.fn.alert = Alert.jQueryInterface
jQueryMock.elements = [alertEl]
jQueryMock.fn.alert.call(jQueryMock, 'close')
expect(spy).toHaveBeenCalled()
})
it('should create new alert instance and call close', () => {
fixtureEl.innerHTML = '<div class="alert"></div>'
const alertEl = fixtureEl.querySelector('.alert')
jQueryMock.fn.alert = Alert.jQueryInterface
jQueryMock.elements = [alertEl]
expect(Alert.getInstance(alertEl)).toBeNull()
jQueryMock.fn.alert.call(jQueryMock, 'close')
expect(fixtureEl.querySelector('.alert')).toBeNull()
})
it('should just create an alert instance without calling close', () => {
fixtureEl.innerHTML = '<div class="alert"></div>'
const alertEl = fixtureEl.querySelector('.alert')
jQueryMock.fn.alert = Alert.jQueryInterface
jQueryMock.elements = [alertEl]
jQueryMock.fn.alert.call(jQueryMock)
expect(Alert.getInstance(alertEl)).not.toBeNull()
expect(fixtureEl.querySelector('.alert')).not.toBeNull()
})
it('should throw an error on undefined method', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const action = 'undefinedMethod'
jQueryMock.fn.alert = Alert.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.alert.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
it('should throw an error on protected method', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const action = '_getConfig'
jQueryMock.fn.alert = Alert.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.alert.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
})
describe('getInstance', () => {
it('should return alert instance', () => {
fixtureEl.innerHTML = '<div></div>'
+8 -1
View File
@@ -124,11 +124,18 @@ describe('Base Component', () => {
expect(DummyClass.getInstance(element)).toBeInstanceOf(DummyClass)
})
it('should accept element, either passed as a CSS selector or DOM element', () => {
it('should accept element, either passed as a CSS selector, jQuery element, or DOM element', () => {
createInstance()
expect(DummyClass.getInstance('#foo')).toEqual(instance)
expect(DummyClass.getInstance(element)).toEqual(instance)
const fakejQueryObject = {
0: element,
jquery: 'foo'
}
expect(DummyClass.getInstance(fakejQueryObject)).toEqual(instance)
})
it('should return null when there is no instance', () => {
+47 -1
View File
@@ -1,5 +1,5 @@
import Button from '../../src/button.js'
import { clearFixture, getFixture } from '../helpers/fixture.js'
import { clearFixture, getFixture, jQueryMock } from '../helpers/fixture.js'
describe('Button', () => {
let fixtureEl
@@ -93,6 +93,52 @@ describe('Button', () => {
})
})
describe('jQueryInterface', () => {
it('should handle config passed and toggle existing button', () => {
fixtureEl.innerHTML = '<button class="btn" data-bs-toggle="button"></button>'
const btnEl = fixtureEl.querySelector('.btn')
const button = new Button(btnEl)
const spy = spyOn(button, 'toggle')
jQueryMock.fn.button = Button.jQueryInterface
jQueryMock.elements = [btnEl]
jQueryMock.fn.button.call(jQueryMock, 'toggle')
expect(spy).toHaveBeenCalled()
})
it('should create new button instance and call toggle', () => {
fixtureEl.innerHTML = '<button class="btn" data-bs-toggle="button"></button>'
const btnEl = fixtureEl.querySelector('.btn')
jQueryMock.fn.button = Button.jQueryInterface
jQueryMock.elements = [btnEl]
jQueryMock.fn.button.call(jQueryMock, 'toggle')
expect(Button.getInstance(btnEl)).not.toBeNull()
expect(btnEl).toHaveClass('active')
})
it('should just create a button instance without calling toggle', () => {
fixtureEl.innerHTML = '<button class="btn" data-bs-toggle="button"></button>'
const btnEl = fixtureEl.querySelector('.btn')
jQueryMock.fn.button = Button.jQueryInterface
jQueryMock.elements = [btnEl]
jQueryMock.fn.button.call(jQueryMock)
expect(Button.getInstance(btnEl)).not.toBeNull()
expect(btnEl).not.toHaveClass('active')
})
})
describe('getInstance', () => {
it('should return button instance', () => {
fixtureEl.innerHTML = '<div></div>'
+61 -1
View File
@@ -3,7 +3,7 @@ import EventHandler from '../../src/dom/event-handler.js'
import { isRTL, noop } from '../../src/util/index.js'
import Swipe from '../../src/util/swipe.js'
import {
clearFixture, createEvent, getFixture
clearFixture, createEvent, getFixture, jQueryMock
} from '../helpers/fixture.js'
describe('Carousel', () => {
@@ -1379,6 +1379,66 @@ describe('Carousel', () => {
})
})
describe('jQueryInterface', () => {
it('should create a carousel', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
jQueryMock.fn.carousel = Carousel.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.carousel.call(jQueryMock)
expect(Carousel.getInstance(div)).not.toBeNull()
})
it('should not re create a carousel', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const carousel = new Carousel(div)
jQueryMock.fn.carousel = Carousel.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.carousel.call(jQueryMock)
expect(Carousel.getInstance(div)).toEqual(carousel)
})
it('should call to if the config is a number', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const carousel = new Carousel(div)
const slideTo = 2
const spy = spyOn(carousel, 'to')
jQueryMock.fn.carousel = Carousel.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.carousel.call(jQueryMock, slideTo)
expect(spy).toHaveBeenCalledWith(slideTo)
})
it('should throw error on undefined method', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const action = 'undefinedMethod'
jQueryMock.fn.carousel = Carousel.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.carousel.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
})
describe('data-api', () => {
it('should init carousels with data-bs-ride="carousel" on load', () => {
fixtureEl.innerHTML = '<div data-bs-ride="carousel"></div>'
+68 -2
View File
@@ -1,6 +1,6 @@
import Collapse from '../../src/collapse.js'
import EventHandler from '../../src/dom/event-handler.js'
import { clearFixture, getFixture } from '../helpers/fixture.js'
import { clearFixture, getFixture, jQueryMock } from '../helpers/fixture.js'
describe('Collapse', () => {
let fixtureEl
@@ -43,7 +43,30 @@ describe('Collapse', () => {
expect(collapseByElement._element).toEqual(collapseEl)
})
it('should allow object in parent config', () => {
it('should allow jquery object in parent config', () => {
fixtureEl.innerHTML = [
'<div class="my-collapse">',
' <div class="item">',
' <a data-bs-toggle="collapse" href="#">Toggle item</a>',
' <div class="collapse">Lorem ipsum</div>',
' </div>',
'</div>'
].join('')
const collapseEl = fixtureEl.querySelector('div.collapse')
const myCollapseEl = fixtureEl.querySelector('.my-collapse')
const fakejQueryObject = {
0: myCollapseEl,
jquery: 'foo'
}
const collapse = new Collapse(collapseEl, {
parent: fakejQueryObject
})
expect(collapse._config.parent).toEqual(myCollapseEl)
})
it('should allow non jquery object in parent config', () => {
fixtureEl.innerHTML = [
'<div class="my-collapse">',
' <div class="item">',
@@ -920,6 +943,49 @@ describe('Collapse', () => {
})
})
describe('jQueryInterface', () => {
it('should create a collapse', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
jQueryMock.fn.collapse = Collapse.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.collapse.call(jQueryMock)
expect(Collapse.getInstance(div)).not.toBeNull()
})
it('should not re create a collapse', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const collapse = new Collapse(div)
jQueryMock.fn.collapse = Collapse.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.collapse.call(jQueryMock)
expect(Collapse.getInstance(div)).toEqual(collapse)
})
it('should throw error on undefined method', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const action = 'undefinedMethod'
jQueryMock.fn.collapse = Collapse.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.collapse.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
})
describe('getInstance', () => {
it('should return collapse instance', () => {
fixtureEl.innerHTML = '<div></div>'
+70 -1
View File
@@ -2,7 +2,7 @@ import EventHandler from '../../src/dom/event-handler.js'
import Dropdown from '../../src/dropdown.js'
import { noop } from '../../src/util/index.js'
import {
clearFixture, createEvent, getFixture
clearFixture, createEvent, getFixture, jQueryMock
} from '../helpers/fixture.js'
describe('Dropdown', () => {
@@ -508,6 +508,32 @@ describe('Dropdown', () => {
})
})
it('should toggle a dropdown with a jquery object reference', () => {
return new Promise(resolve => {
fixtureEl.innerHTML = [
'<div class="dropdown">',
' <button class="btn dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">Dropdown</button>',
' <div class="dropdown-menu">',
' <a class="dropdown-item" href="#">Secondary link</a>',
' </div>',
'</div>'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]')
const dropdown = new Dropdown(btnDropdown, {
reference: { 0: fixtureEl, jquery: 'jQuery' }
})
btnDropdown.addEventListener('shown.bs.dropdown', () => {
expect(btnDropdown).toHaveClass('show')
expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true')
resolve()
})
dropdown.toggle()
})
})
it('should toggle a dropdown with a valid virtual element reference', () => {
return new Promise(resolve => {
fixtureEl.innerHTML = [
@@ -2192,6 +2218,49 @@ describe('Dropdown', () => {
})
})
describe('jQueryInterface', () => {
it('should create a dropdown', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
jQueryMock.fn.dropdown = Dropdown.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.dropdown.call(jQueryMock)
expect(Dropdown.getInstance(div)).not.toBeNull()
})
it('should not re create a dropdown', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const dropdown = new Dropdown(div)
jQueryMock.fn.dropdown = Dropdown.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.dropdown.call(jQueryMock)
expect(Dropdown.getInstance(div)).toEqual(dropdown)
})
it('should throw error on undefined method', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const action = 'undefinedMethod'
jQueryMock.fn.dropdown = Dropdown.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.dropdown.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
})
describe('getInstance', () => {
it('should return dropdown instance', () => {
fixtureEl.innerHTML = '<div></div>'
+60
View File
@@ -0,0 +1,60 @@
/* eslint-env jquery */
import Alert from '../../src/alert.js'
import Button from '../../src/button.js'
import Carousel from '../../src/carousel.js'
import Collapse from '../../src/collapse.js'
import Dropdown from '../../src/dropdown.js'
import Modal from '../../src/modal.js'
import Offcanvas from '../../src/offcanvas.js'
import Popover from '../../src/popover.js'
import ScrollSpy from '../../src/scrollspy.js'
import Tab from '../../src/tab.js'
import Toast from '../../src/toast.js'
import Tooltip from '../../src/tooltip.js'
import { clearFixture, getFixture } from '../helpers/fixture.js'
describe('jQuery', () => {
let fixtureEl
beforeAll(() => {
fixtureEl = getFixture()
})
afterEach(() => {
clearFixture()
})
it('should add all plugins in jQuery', () => {
expect(Alert.jQueryInterface).toEqual(jQuery.fn.alert)
expect(Button.jQueryInterface).toEqual(jQuery.fn.button)
expect(Carousel.jQueryInterface).toEqual(jQuery.fn.carousel)
expect(Collapse.jQueryInterface).toEqual(jQuery.fn.collapse)
expect(Dropdown.jQueryInterface).toEqual(jQuery.fn.dropdown)
expect(Modal.jQueryInterface).toEqual(jQuery.fn.modal)
expect(Offcanvas.jQueryInterface).toEqual(jQuery.fn.offcanvas)
expect(Popover.jQueryInterface).toEqual(jQuery.fn.popover)
expect(ScrollSpy.jQueryInterface).toEqual(jQuery.fn.scrollspy)
expect(Tab.jQueryInterface).toEqual(jQuery.fn.tab)
expect(Toast.jQueryInterface).toEqual(jQuery.fn.toast)
expect(Tooltip.jQueryInterface).toEqual(jQuery.fn.tooltip)
})
it('should use jQuery event system', () => {
return new Promise(resolve => {
fixtureEl.innerHTML = [
'<div class="alert">',
' <button type="button" data-bs-dismiss="alert">x</button>',
'</div>'
].join('')
$(fixtureEl).find('.alert')
.one('closed.bs.alert', () => {
expect($(fixtureEl).find('.alert')).toHaveSize(0)
resolve()
})
$(fixtureEl).find('button').trigger('click')
})
})
})
+91 -1
View File
@@ -2,7 +2,7 @@ import EventHandler from '../../src/dom/event-handler.js'
import Modal from '../../src/modal.js'
import ScrollBarHelper from '../../src/util/scrollbar.js'
import {
clearBodyAndDocument, clearFixture, createEvent, getFixture
clearBodyAndDocument, clearFixture, createEvent, getFixture, jQueryMock
} from '../helpers/fixture.js'
describe('Modal', () => {
@@ -1162,6 +1162,96 @@ describe('Modal', () => {
})
})
})
describe('jQueryInterface', () => {
it('should create a modal', () => {
fixtureEl.innerHTML = '<div class="modal"><div class="modal-dialog"></div></div>'
const div = fixtureEl.querySelector('div')
jQueryMock.fn.modal = Modal.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.modal.call(jQueryMock)
expect(Modal.getInstance(div)).not.toBeNull()
})
it('should create a modal with given config', () => {
fixtureEl.innerHTML = '<div class="modal"><div class="modal-dialog"></div></div>'
const div = fixtureEl.querySelector('div')
jQueryMock.fn.modal = Modal.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.modal.call(jQueryMock, { keyboard: false })
const spy = spyOn(Modal.prototype, 'constructor')
expect(spy).not.toHaveBeenCalledWith(div, { keyboard: false })
const modal = Modal.getInstance(div)
expect(modal).not.toBeNull()
expect(modal._config.keyboard).toBeFalse()
})
it('should not re create a modal', () => {
fixtureEl.innerHTML = '<div class="modal"><div class="modal-dialog"></div></div>'
const div = fixtureEl.querySelector('div')
const modal = new Modal(div)
jQueryMock.fn.modal = Modal.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.modal.call(jQueryMock)
expect(Modal.getInstance(div)).toEqual(modal)
})
it('should throw error on undefined method', () => {
fixtureEl.innerHTML = '<div class="modal"><div class="modal-dialog"></div></div>'
const div = fixtureEl.querySelector('div')
const action = 'undefinedMethod'
jQueryMock.fn.modal = Modal.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.modal.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
it('should call show method', () => {
fixtureEl.innerHTML = '<div class="modal"><div class="modal-dialog"></div></div>'
const div = fixtureEl.querySelector('div')
const modal = new Modal(div)
jQueryMock.fn.modal = Modal.jQueryInterface
jQueryMock.elements = [div]
const spy = spyOn(modal, 'show')
jQueryMock.fn.modal.call(jQueryMock, 'show')
expect(spy).toHaveBeenCalled()
})
it('should not call show method', () => {
fixtureEl.innerHTML = '<div class="modal" data-bs-show="false"><div class="modal-dialog"></div></div>'
const div = fixtureEl.querySelector('div')
jQueryMock.fn.modal = Modal.jQueryInterface
jQueryMock.elements = [div]
const spy = spyOn(Modal.prototype, 'show')
jQueryMock.fn.modal.call(jQueryMock)
expect(spy).not.toHaveBeenCalled()
})
})
describe('getInstance', () => {
it('should return modal instance', () => {
+101 -1
View File
@@ -3,7 +3,7 @@ import Offcanvas from '../../src/offcanvas.js'
import { isVisible } from '../../src/util/index.js'
import ScrollBarHelper from '../../src/util/scrollbar.js'
import {
clearBodyAndDocument, clearFixture, createEvent, getFixture
clearBodyAndDocument, clearFixture, createEvent, getFixture, jQueryMock
} from '../helpers/fixture.js'
describe('Offcanvas', () => {
@@ -738,6 +738,106 @@ describe('Offcanvas', () => {
})
})
describe('jQueryInterface', () => {
it('should create an offcanvas', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
jQueryMock.fn.offcanvas = Offcanvas.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.offcanvas.call(jQueryMock)
expect(Offcanvas.getInstance(div)).not.toBeNull()
})
it('should not re create an offcanvas', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const offCanvas = new Offcanvas(div)
jQueryMock.fn.offcanvas = Offcanvas.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.offcanvas.call(jQueryMock)
expect(Offcanvas.getInstance(div)).toEqual(offCanvas)
})
it('should throw error on undefined method', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const action = 'undefinedMethod'
jQueryMock.fn.offcanvas = Offcanvas.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.offcanvas.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
it('should throw error on protected method', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const action = '_getConfig'
jQueryMock.fn.offcanvas = Offcanvas.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.offcanvas.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
it('should throw error if method "constructor" is being called', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const action = 'constructor'
jQueryMock.fn.offcanvas = Offcanvas.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.offcanvas.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
it('should call offcanvas method', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const spy = spyOn(Offcanvas.prototype, 'show')
jQueryMock.fn.offcanvas = Offcanvas.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.offcanvas.call(jQueryMock, 'show')
expect(spy).toHaveBeenCalled()
})
it('should create a offcanvas with given config', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
jQueryMock.fn.offcanvas = Offcanvas.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.offcanvas.call(jQueryMock, { scroll: true })
const offcanvas = Offcanvas.getInstance(div)
expect(offcanvas).not.toBeNull()
expect(offcanvas._config.scroll).toBeTrue()
})
})
describe('getInstance', () => {
it('should return offcanvas instance', () => {
fixtureEl.innerHTML = '<div></div>'
+75 -1
View File
@@ -1,7 +1,7 @@
import EventHandler from '../../src/dom/event-handler.js'
import Popover from '../../src/popover.js'
import {
clearFixture, getFixture, createEvent
clearFixture, getFixture, jQueryMock, createEvent
} from '../helpers/fixture.js'
describe('Popover', () => {
@@ -361,6 +361,80 @@ describe('Popover', () => {
})
})
describe('jQueryInterface', () => {
it('should create a popover', () => {
fixtureEl.innerHTML = '<a href="#" title="Popover" data-bs-content="https://x.com/getbootstrap">BS X</a>'
const popoverEl = fixtureEl.querySelector('a')
jQueryMock.fn.popover = Popover.jQueryInterface
jQueryMock.elements = [popoverEl]
jQueryMock.fn.popover.call(jQueryMock)
expect(Popover.getInstance(popoverEl)).not.toBeNull()
})
it('should create a popover with a config object', () => {
fixtureEl.innerHTML = '<a href="#" title="Popover">BS X</a>'
const popoverEl = fixtureEl.querySelector('a')
jQueryMock.fn.popover = Popover.jQueryInterface
jQueryMock.elements = [popoverEl]
jQueryMock.fn.popover.call(jQueryMock, {
content: 'Popover content'
})
expect(Popover.getInstance(popoverEl)).not.toBeNull()
})
it('should not re create a popover', () => {
fixtureEl.innerHTML = '<a href="#" title="Popover" data-bs-content="https://x.com/getbootstrap">BS X</a>'
const popoverEl = fixtureEl.querySelector('a')
const popover = new Popover(popoverEl)
jQueryMock.fn.popover = Popover.jQueryInterface
jQueryMock.elements = [popoverEl]
jQueryMock.fn.popover.call(jQueryMock)
expect(Popover.getInstance(popoverEl)).toEqual(popover)
})
it('should throw error on undefined method', () => {
fixtureEl.innerHTML = '<a href="#" title="Popover" data-bs-content="https://x.com/getbootstrap">BS X</a>'
const popoverEl = fixtureEl.querySelector('a')
const action = 'undefinedMethod'
jQueryMock.fn.popover = Popover.jQueryInterface
jQueryMock.elements = [popoverEl]
expect(() => {
jQueryMock.fn.popover.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
it('should should call show method', () => {
fixtureEl.innerHTML = '<a href="#" title="Popover" data-bs-content="https://x.com/getbootstrap">BS X</a>'
const popoverEl = fixtureEl.querySelector('a')
const popover = new Popover(popoverEl)
jQueryMock.fn.popover = Popover.jQueryInterface
jQueryMock.elements = [popoverEl]
const spy = spyOn(popover, 'show')
jQueryMock.fn.popover.call(jQueryMock, 'show')
expect(spy).toHaveBeenCalled()
})
})
describe('getInstance', () => {
it('should return popover instance', () => {
fixtureEl.innerHTML = '<a href="#" title="Popover" data-bs-content="https://x.com/getbootstrap">BS X</a>'
+106 -1
View File
@@ -1,7 +1,7 @@
import EventHandler from '../../src/dom/event-handler.js'
import ScrollSpy from '../../src/scrollspy.js'
import {
clearFixture, createEvent, getFixture
clearFixture, createEvent, getFixture, jQueryMock
} from '../helpers/fixture.js'
describe('ScrollSpy', () => {
@@ -648,6 +648,111 @@ describe('ScrollSpy', () => {
})
})
describe('jQueryInterface', () => {
it('should create a scrollspy', () => {
fixtureEl.innerHTML = getDummyFixture()
const div = fixtureEl.querySelector('.content')
jQueryMock.fn.scrollspy = ScrollSpy.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.scrollspy.call(jQueryMock, { target: '#navBar' })
expect(ScrollSpy.getInstance(div)).not.toBeNull()
})
it('should create a scrollspy with given config', () => {
fixtureEl.innerHTML = getDummyFixture()
const div = fixtureEl.querySelector('.content')
jQueryMock.fn.scrollspy = ScrollSpy.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.scrollspy.call(jQueryMock, { rootMargin: '100px' })
const spy = spyOn(ScrollSpy.prototype, 'constructor')
expect(spy).not.toHaveBeenCalledWith(div, { rootMargin: '100px' })
const scrollspy = ScrollSpy.getInstance(div)
expect(scrollspy).not.toBeNull()
expect(scrollspy._config.rootMargin).toEqual('100px')
})
it('should not re create a scrollspy', () => {
fixtureEl.innerHTML = getDummyFixture()
const div = fixtureEl.querySelector('.content')
const scrollSpy = new ScrollSpy(div)
jQueryMock.fn.scrollspy = ScrollSpy.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.scrollspy.call(jQueryMock)
expect(ScrollSpy.getInstance(div)).toEqual(scrollSpy)
})
it('should call a scrollspy method', () => {
fixtureEl.innerHTML = getDummyFixture()
const div = fixtureEl.querySelector('.content')
const scrollSpy = new ScrollSpy(div)
const spy = spyOn(scrollSpy, 'refresh')
jQueryMock.fn.scrollspy = ScrollSpy.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.scrollspy.call(jQueryMock, 'refresh')
expect(ScrollSpy.getInstance(div)).toEqual(scrollSpy)
expect(spy).toHaveBeenCalled()
})
it('should throw error on undefined method', () => {
fixtureEl.innerHTML = getDummyFixture()
const div = fixtureEl.querySelector('.content')
const action = 'undefinedMethod'
jQueryMock.fn.scrollspy = ScrollSpy.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.scrollspy.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
it('should throw error on protected method', () => {
fixtureEl.innerHTML = getDummyFixture()
const div = fixtureEl.querySelector('.content')
const action = '_getConfig'
jQueryMock.fn.scrollspy = ScrollSpy.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.scrollspy.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
it('should throw error if method "constructor" is being called', () => {
fixtureEl.innerHTML = getDummyFixture()
const div = fixtureEl.querySelector('.content')
const action = 'constructor'
jQueryMock.fn.scrollspy = ScrollSpy.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.scrollspy.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
})
describe('getInstance', () => {
it('should return scrollspy instance', () => {
fixtureEl.innerHTML = getDummyFixture()
+61 -1
View File
@@ -1,6 +1,6 @@
import Tab from '../../src/tab.js'
import {
clearFixture, createEvent, getFixture
clearFixture, createEvent, getFixture, jQueryMock
} from '../helpers/fixture.js'
describe('Tab', () => {
@@ -827,6 +827,66 @@ describe('Tab', () => {
})
})
describe('jQueryInterface', () => {
it('should create a tab', () => {
fixtureEl.innerHTML = '<div class="nav"><div class="nav-link"></div></div>'
const div = fixtureEl.querySelector('.nav > div')
jQueryMock.fn.tab = Tab.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.tab.call(jQueryMock)
expect(Tab.getInstance(div)).not.toBeNull()
})
it('should not re create a tab', () => {
fixtureEl.innerHTML = '<div class="nav"><div class="nav-link"></div></div>'
const div = fixtureEl.querySelector('.nav > div')
const tab = new Tab(div)
jQueryMock.fn.tab = Tab.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.tab.call(jQueryMock)
expect(Tab.getInstance(div)).toEqual(tab)
})
it('should call a tab method', () => {
fixtureEl.innerHTML = '<div class="nav"><div class="nav-link"></div></div>'
const div = fixtureEl.querySelector('.nav > div')
const tab = new Tab(div)
const spy = spyOn(tab, 'show')
jQueryMock.fn.tab = Tab.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.tab.call(jQueryMock, 'show')
expect(Tab.getInstance(div)).toEqual(tab)
expect(spy).toHaveBeenCalled()
})
it('should throw error on undefined method', () => {
fixtureEl.innerHTML = '<div class="nav"><div class="nav-link"></div></div>'
const div = fixtureEl.querySelector('.nav > div')
const action = 'undefinedMethod'
jQueryMock.fn.tab = Tab.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.tab.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
})
describe('getInstance', () => {
it('should return null if there is no instance', () => {
expect(Tab.getInstance(fixtureEl)).toBeNull()
+61 -1
View File
@@ -1,6 +1,6 @@
import Toast from '../../src/toast.js'
import {
clearFixture, createEvent, getFixture
clearFixture, createEvent, getFixture, jQueryMock
} from '../helpers/fixture.js'
describe('Toast', () => {
@@ -536,6 +536,66 @@ describe('Toast', () => {
})
})
describe('jQueryInterface', () => {
it('should create a toast', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
jQueryMock.fn.toast = Toast.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.toast.call(jQueryMock)
expect(Toast.getInstance(div)).not.toBeNull()
})
it('should not re create a toast', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const toast = new Toast(div)
jQueryMock.fn.toast = Toast.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.toast.call(jQueryMock)
expect(Toast.getInstance(div)).toEqual(toast)
})
it('should call a toast method', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const toast = new Toast(div)
const spy = spyOn(toast, 'show')
jQueryMock.fn.toast = Toast.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.toast.call(jQueryMock, 'show')
expect(Toast.getInstance(div)).toEqual(toast)
expect(spy).toHaveBeenCalled()
})
it('should throw error on undefined method', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const action = 'undefinedMethod'
jQueryMock.fn.toast = Toast.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.toast.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
})
describe('getInstance', () => {
it('should return a toast instance', () => {
fixtureEl.innerHTML = '<div></div>'
+101 -1
View File
@@ -2,7 +2,7 @@ import EventHandler from '../../src/dom/event-handler.js'
import Tooltip from '../../src/tooltip.js'
import { noop } from '../../src/util/index.js'
import {
clearFixture, createEvent, getFixture
clearFixture, createEvent, getFixture, jQueryMock
} from '../helpers/fixture.js'
describe('Tooltip', () => {
@@ -582,6 +582,27 @@ describe('Tooltip', () => {
})
})
it('should show a tooltip with a jquery element container', () => {
return new Promise(resolve => {
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
const tooltipEl = fixtureEl.querySelector('a')
const tooltip = new Tooltip(tooltipEl, {
container: {
0: fixtureEl,
jquery: 'jQuery'
}
})
tooltipEl.addEventListener('shown.bs.tooltip', () => {
expect(fixtureEl.querySelector('.tooltip')).not.toBeNull()
resolve()
})
tooltip.show()
})
})
it('should show a tooltip with a selector in container', () => {
return new Promise(resolve => {
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
@@ -1222,6 +1243,25 @@ describe('Tooltip', () => {
expect().nothing()
})
it('should add the content as a child of the element for jQuery elements', () => {
fixtureEl.innerHTML = [
'<a href="#" rel="tooltip" title="Another tooltip">',
' <div id="childContent"></div>',
'</a>'
].join('')
const tooltipEl = fixtureEl.querySelector('a')
const childContent = fixtureEl.querySelector('div')
const tooltip = new Tooltip(tooltipEl, {
html: true
})
tooltip.setContent({ '.tooltip': { 0: childContent, jquery: 'jQuery' } })
tooltip.show()
expect(childContent.parentNode).toEqual(tooltip._getTipElement())
})
it('should add the child text content in the element', () => {
fixtureEl.innerHTML = [
'<a href="#" rel="tooltip" title="Another tooltip">',
@@ -1482,4 +1522,64 @@ describe('Tooltip', () => {
expect(tooltip2._getTitle()).toEqual('nothing')
})
})
describe('jQueryInterface', () => {
it('should create a tooltip', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
jQueryMock.fn.tooltip = Tooltip.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.tooltip.call(jQueryMock)
expect(Tooltip.getInstance(div)).not.toBeNull()
})
it('should not re create a tooltip', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const tooltip = new Tooltip(div)
jQueryMock.fn.tooltip = Tooltip.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.tooltip.call(jQueryMock)
expect(Tooltip.getInstance(div)).toEqual(tooltip)
})
it('should call a tooltip method', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const tooltip = new Tooltip(div)
const spy = spyOn(tooltip, 'show')
jQueryMock.fn.tooltip = Tooltip.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.tooltip.call(jQueryMock, 'show')
expect(Tooltip.getInstance(div)).toEqual(tooltip)
expect(spy).toHaveBeenCalled()
})
it('should throw error on undefined method', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const action = 'undefinedMethod'
jQueryMock.fn.tooltip = Tooltip.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.tooltip.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
})
})
+78
View File
@@ -72,6 +72,18 @@ describe('Util', () => {
expect(Util.isElement({})).toBeFalse()
expect(Util.isElement(fixtureEl.querySelectorAll('.test'))).toBeFalse()
})
it('should detect jQuery element', () => {
fixtureEl.innerHTML = '<div></div>'
const el = fixtureEl.querySelector('div')
const fakejQuery = {
0: el,
jquery: 'foo'
}
expect(Util.isElement(fakejQuery)).toBeTrue()
})
})
describe('getElement', () => {
@@ -91,6 +103,13 @@ describe('Util', () => {
expect(Util.getElement()).toBeNull()
expect(Util.getElement(null)).toBeNull()
expect(Util.getElement(fixtureEl.querySelectorAll('.test'))).toBeNull()
const fakejQueryObject = {
0: el,
jquery: 'foo'
}
expect(Util.getElement(fakejQueryObject)).toEqual(el)
})
})
@@ -406,6 +425,39 @@ describe('Util', () => {
})
})
describe('getjQuery', () => {
const fakejQuery = { trigger() {} }
beforeEach(() => {
Object.defineProperty(window, 'jQuery', {
value: fakejQuery,
writable: true
})
})
afterEach(() => {
window.jQuery = undefined
})
it('should return jQuery object when present', () => {
expect(Util.getjQuery()).toEqual(fakejQuery)
})
it('should not return jQuery object when present if data-bs-no-jquery', () => {
document.body.setAttribute('data-bs-no-jquery', '')
expect(window.jQuery).toEqual(fakejQuery)
expect(Util.getjQuery()).toBeNull()
document.body.removeAttribute('data-bs-no-jquery')
})
it('should not return jQuery if not present', () => {
window.jQuery = undefined
expect(Util.getjQuery()).toBeNull()
})
})
describe('onDOMContentLoaded', () => {
it('should execute callbacks when DOMContentLoaded is fired and should not add more than one listener', () => {
const spy = jasmine.createSpy()
@@ -434,6 +486,32 @@ describe('Util', () => {
})
})
describe('defineJQueryPlugin', () => {
const fakejQuery = { fn: {} }
beforeEach(() => {
Object.defineProperty(window, 'jQuery', {
value: fakejQuery,
writable: true
})
})
afterEach(() => {
window.jQuery = undefined
})
it('should define a plugin on the jQuery instance', () => {
const pluginMock = Util.noop
pluginMock.NAME = 'test'
pluginMock.jQueryInterface = Util.noop
Util.defineJQueryPlugin(pluginMock)
expect(fakejQuery.fn.test).toEqual(pluginMock.jQueryInterface)
expect(fakejQuery.fn.test.Constructor).toEqual(pluginMock)
expect(fakejQuery.fn.test.noConflict).toEqual(jasmine.any(Function))
})
})
describe('execute', () => {
it('should execute if arg is function', () => {
const spy = jasmine.createSpy('spy')
+1319 -2364
View File
File diff suppressed because it is too large Load Diff
+41 -40
View File
@@ -41,17 +41,19 @@
"scripts": {
"start": "npm-run-all --parallel watch docs-serve",
"bundlewatch": "bundlewatch --config .bundlewatch.config.json",
"css": "npm-run-all css-compile css-prefix css-minify css-docs",
"css-compile": "sass --style expanded --source-map --embed-sources --no-error-css scss/bootstrap.scss:dist/css/bootstrap.css scss/bootstrap-grid.scss:dist/css/bootstrap-grid.css scss/bootstrap-reboot.scss:dist/css/bootstrap-reboot.css scss/bootstrap-utilities.scss:dist/css/bootstrap-utilities.css",
"css-docs": "node build/generate-utilities-json.mjs",
"css": "npm-run-all css-compile css-prefix css-rtl css-minify",
"css-compile": "sass --style expanded --source-map --embed-sources --no-error-css scss/:dist/css/",
"css-rtl": "cross-env NODE_ENV=RTL postcss --config build/postcss.config.mjs --dir \"dist/css\" --ext \".rtl.css\" \"dist/css/*.css\" \"!dist/css/*.min.css\" \"!dist/css/*.rtl.css\"",
"css-lint": "npm-run-all --aggregate-output --continue-on-error --parallel css-lint-*",
"css-lint-stylelint": "stylelint \"**/*.{css,scss}\" --cache --cache-location .cache/.stylelintcache",
"css-lint-vars": "fusv scss/ site/src/scss/",
"css-minify": "npm-run-all --aggregate-output --parallel css-minify-*",
"css-minify-main": "cleancss -O1 --format breakWith=lf --with-rebase --source-map --source-map-inline-sources --output dist/css/ --batch --batch-suffix \".min\" \"dist/css/*.css\" \"!dist/css/*.min.css\" \"!dist/css/*.tmp.css\"",
"css-minify-main": "cleancss -O1 --format breakWith=lf --with-rebase --source-map --source-map-inline-sources --output dist/css/ --batch --batch-suffix \".min\" \"dist/css/*.css\" \"!dist/css/*.min.css\" \"!dist/css/*rtl*.css\"",
"css-minify-rtl": "cleancss -O1 --format breakWith=lf --with-rebase --source-map --source-map-inline-sources --output dist/css/ --batch --batch-suffix \".min\" \"dist/css/*rtl.css\" \"!dist/css/*.min.css\"",
"css-prefix": "npm-run-all --aggregate-output --parallel css-prefix-*",
"css-prefix-main": "postcss --config build/postcss.config.mjs --replace \"dist/css/*.css\" \"!dist/css/*.min.css\" \"!dist/css/*.tmp.css\"",
"css-prefix-main": "postcss --config build/postcss.config.mjs --replace \"dist/css/*.css\" \"!dist/css/*.rtl*.css\" \"!dist/css/*.min.css\"",
"css-prefix-examples": "postcss --config build/postcss.config.mjs --replace \"site/src/assets/examples/**/*.css\"",
"css-prefix-examples-rtl": "cross-env-shell NODE_ENV=RTL postcss --config build/postcss.config.mjs --dir \"site/src/assets/examples/\" --ext \".rtl.css\" --base \"site/src/assets/examples/\" \"site/src/assets/examples/{blog,carousel,dashboard,cheatsheet}/*.css\" \"!site/src/assets/examples/{blog,carousel,dashboard,cheatsheet}/*.rtl.css\"",
"css-test": "jasmine --config=scss/tests/jasmine.js",
"js": "npm-run-all js-compile js-minify",
"js-compile": "npm-run-all --aggregate-output --parallel js-compile-*",
@@ -64,25 +66,25 @@
"js-minify-standalone": "terser --compress passes=2 --mangle --comments \"/^!/\" --source-map \"content=dist/js/bootstrap.js.map,includeSources,url=bootstrap.min.js.map\" --output dist/js/bootstrap.min.js dist/js/bootstrap.js",
"js-minify-standalone-esm": "terser --compress passes=2 --mangle --comments \"/^!/\" --source-map \"content=dist/js/bootstrap.esm.js.map,includeSources,url=bootstrap.esm.min.js.map\" --output dist/js/bootstrap.esm.min.js dist/js/bootstrap.esm.js",
"js-minify-bundle": "terser --compress passes=2 --mangle --comments \"/^!/\" --source-map \"content=dist/js/bootstrap.bundle.js.map,includeSources,url=bootstrap.bundle.min.js.map\" --output dist/js/bootstrap.bundle.min.js dist/js/bootstrap.bundle.js",
"js-test": "npm-run-all --aggregate-output --parallel js-test-karma js-test-integration-*",
"js-test": "npm-run-all --aggregate-output --parallel js-test-karma js-test-jquery js-test-integration-*",
"js-debug": "cross-env DEBUG=true npm run js-test-karma",
"js-test-karma": "karma start js/tests/karma.conf.js",
"js-test-integration-bundle": "rollup --config js/tests/integration/rollup.bundle.js",
"js-test-integration-modularity": "rollup --config js/tests/integration/rollup.bundle-modularity.js",
"js-test-cloud": "cross-env BROWSERSTACK=true npm run js-test-karma",
"lint": "npm-run-all --aggregate-output --continue-on-error --parallel js-lint css-lint lockfile-lint lint-mdx",
"lint-mdx": "markdownlint \"site/src/content/**/*.mdx\"",
"js-test-jquery": "cross-env JQUERY=true npm run js-test-karma",
"lint": "npm-run-all --aggregate-output --continue-on-error --parallel js-lint css-lint lockfile-lint",
"docs": "npm-run-all docs-build docs-lint",
"docs-build": "npm run astro-build",
"docs-compile": "npm run docs-build",
"docs-html-validate": "node build/html-validate.mjs",
"docs-lint": "npm-run-all docs-prettier-check docs-html-validate",
"docs-vnu": "node build/vnu-jar.mjs",
"docs-lint": "npm-run-all docs-prettier-check docs-vnu",
"docs-prettier-check": "prettier --config site/.prettierrc.json -c --cache site",
"docs-prettier-format": "prettier --config site/.prettierrc.json --write --cache site",
"docs-serve": "npm run astro-dev",
"docs-serve-only": "npx sirv-cli _site --port 9001",
"lockfile-lint": "lockfile-lint --allowed-hosts npm --allowed-schemes https: --empty-hostname false --type npm --path package-lock.json",
"update-deps": "ncu -u -x @docsearch/js,eslint,eslint-config-xo,eslint-plugin-unicorn,karma-browserstack-launcher,karma-rollup-preprocessor,sass",
"update-deps": "ncu -u -x eslint,eslint-config-xo,eslint-plugin-unicorn,karma-browserstack-launcher,karma-rollup-preprocessor,sass",
"release": "npm-run-all dist release-sri docs-build release-zip*",
"release-sri": "node build/generate-sri.mjs",
"release-version": "node build/change-version.mjs",
@@ -93,6 +95,7 @@
"netlify": "npm-run-all dist release-sri astro-build",
"watch": "npm-run-all --parallel watch-*",
"watch-css-main": "nodemon --watch scss/ --ext scss --exec \"npm-run-all css-lint css-compile css-prefix\"",
"watch-css-dist": "nodemon --watch dist/css/ --ext css --ignore \"dist/css/*.rtl.*\" --exec \"npm run css-rtl\"",
"watch-css-docs": "nodemon --watch site/src/scss/ --ext scss --exec \"npm run css-lint\"",
"watch-css-test": "nodemon --watch scss/ --ext scss,js --exec \"npm run css-test\"",
"watch-js-main": "nodemon --watch js/src/ --ext js --exec \"npm-run-all js-lint js-compile\"",
@@ -105,31 +108,31 @@
"@popperjs/core": "^2.11.8"
},
"devDependencies": {
"@astrojs/check": "^0.9.5",
"@astrojs/markdown-remark": "^6.3.8",
"@astrojs/mdx": "^4.3.10",
"@astrojs/check": "^0.9.4",
"@astrojs/markdown-remark": "^6.3.6",
"@astrojs/mdx": "^4.3.4",
"@astrojs/prism": "^3.3.0",
"@astrojs/sitemap": "^3.6.0",
"@astrojs/sitemap": "^3.5.1",
"@babel/cli": "^7.28.3",
"@babel/core": "^7.28.5",
"@babel/preset-env": "^7.28.5",
"@babel/core": "^7.28.3",
"@babel/preset-env": "^7.28.3",
"@docsearch/js": "^3.9.0",
"@popperjs/core": "^2.11.8",
"@rollup/plugin-babel": "^6.1.0",
"@rollup/plugin-commonjs": "^29.0.0",
"@rollup/plugin-node-resolve": "^16.0.3",
"@rollup/plugin-replace": "^6.0.3",
"@rollup/plugin-babel": "^6.0.4",
"@rollup/plugin-commonjs": "^28.0.6",
"@rollup/plugin-node-resolve": "^16.0.1",
"@rollup/plugin-replace": "^6.0.2",
"@stackblitz/sdk": "^1.11.0",
"@types/js-yaml": "^4.0.9",
"@types/mime": "^4.0.0",
"@types/prismjs": "^1.26.5",
"astro": "^5.15.6",
"astro-auto-import": "^0.4.5",
"autoprefixer": "^10.4.22",
"astro": "^5.13.5",
"astro-auto-import": "^0.4.4",
"autoprefixer": "^10.4.21",
"bundlewatch": "^0.4.1",
"clean-css-cli": "^5.6.3",
"clipboard": "^2.0.11",
"cross-env": "^10.1.0",
"cross-env": "^10.0.0",
"eslint": "8.57.1",
"eslint-config-xo": "0.45.0",
"eslint-plugin-html": "^8.1.3",
@@ -138,14 +141,14 @@
"eslint-plugin-unicorn": "56.0.1",
"find-unused-sass-variables": "^6.1.0",
"github-slugger": "^2.0.0",
"globby": "^15.0.0",
"globby": "^14.1.0",
"hammer-simulator": "0.0.1",
"html-validate": "^8.24.1",
"htmlparser2": "^10.0.0",
"image-size": "^2.0.2",
"ip": "^2.0.1",
"jasmine": "^5.12.0",
"js-yaml": "^4.1.1",
"jasmine": "^5.10.0",
"jquery": "^3.7.1",
"js-yaml": "^4.1.0",
"karma": "^6.4.4",
"karma-browserstack-launcher": "1.4.0",
"karma-chrome-launcher": "^3.2.0",
@@ -156,9 +159,8 @@
"karma-jasmine-html-reporter": "^2.1.0",
"karma-rollup-preprocessor": "7.0.7",
"lockfile-lint": "^4.14.1",
"markdownlint-cli": "^0.45.0",
"mime": "^4.1.0",
"nodemon": "^3.1.11",
"mime": "^4.0.7",
"nodemon": "^3.1.10",
"npm-run-all2": "^8.0.4",
"postcss": "^8.5.6",
"postcss-cli": "^11.0.1",
@@ -167,16 +169,18 @@
"rehype-autolink-headings": "^7.1.0",
"remark": "^15.0.1",
"remark-html": "^16.0.1",
"rollup": "^4.53.2",
"rollup": "^4.50.0",
"rollup-plugin-istanbul": "^5.0.0",
"sass": "^1.90.0",
"rtlcss": "^4.3.0",
"sass": "1.78.0",
"sass-true": "^9.0.0",
"shelljs": "^0.10.0",
"stylelint": "^16.25.0",
"stylelint": "^16.23.1",
"stylelint-config-twbs-bootstrap": "^16.1.0",
"terser": "^5.44.1",
"terser": "^5.44.0",
"unist-util-visit": "^5.0.0",
"zod": "^4.1.12"
"vnu-jar": "24.10.17",
"zod": "^4.1.5"
},
"files": [
"dist/{css,js}/*.{css,js,map}",
@@ -202,8 +206,5 @@
"peerDependencies": {
"@popperjs/core": "^2.11.8"
}
},
"overrides": {
"volar-service-emmet": "0.0.63"
}
}

Some files were not shown because too many files have changed in this diff Show More