Skip to content

Commit d273872

Browse files
malbertsclaude
andcommitted
Add a shared Bootstrap component resolver
The four component init scripts (carousel, modal, popover, tooltip) reached Bootstrap only through the window.bootstrap global, which ties them to Extension:Bootstrap's copy. They now obtain the component class from a shared package module: getComponentClass() resolves it from the window.bootstrap global that Extension:Bootstrap and most Bootstrap-bundling skins expose, or from the jQuery plugin bridge that skins such as Tweeki register instead (a Bootstrap jQuery plugin's Constructor is the native component class). The five modules involved are ResourceLoader package modules, so the resolver is shared via require() rather than a page-wide global. No loading change: the shared module depends on ext.bootstrap.scripts and the fix modules depend on the shared module, so the load graph and behaviour are identical on every skin. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 17ee2d2 commit d273872

6 files changed

Lines changed: 49 additions & 16 deletions

‎extension.json‎

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@
9191
"ext.bootstrapComponents.bootstrap.fix": {
9292
"styles": "ext.bootstrapComponents.bootstrap.fix.css"
9393
},
94+
"ext.bootstrapComponents.bootstrap": {
95+
"dependencies": "ext.bootstrap.scripts",
96+
"packageFiles": [ "ext.bootstrapComponents.bootstrap.js" ]
97+
},
9498
"ext.bootstrapComponents.accordion.fix": {
9599
"styles": "ext.bootstrapComponents.accordion.fix.css"
96100
},
@@ -104,28 +108,28 @@
104108
"styles": "ext.bootstrapComponents.card.fix.css"
105109
},
106110
"ext.bootstrapComponents.carousel.fix": {
107-
"dependencies": "ext.bootstrap.scripts",
111+
"dependencies": "ext.bootstrapComponents.bootstrap",
108112
"styles": "ext.bootstrapComponents.carousel.fix.css",
109-
"scripts": "ext.bootstrapComponents.carousel.js"
113+
"packageFiles": [ "ext.bootstrapComponents.carousel.js" ]
110114
},
111115
"ext.bootstrapComponents.modal.fix": {
112-
"dependencies": "ext.bootstrap.scripts",
116+
"dependencies": "ext.bootstrapComponents.bootstrap",
113117
"styles": "ext.bootstrapComponents.modal.fix.css",
114-
"scripts": "ext.bootstrapComponents.modal.js"
118+
"packageFiles": [ "ext.bootstrapComponents.modal.js" ]
115119
},
116120
"ext.bootstrapComponents.modal.vector-fix": {
117121
"styles": "ext.bootstrapComponents.modal.vector-fix.css"
118122
},
119123
"ext.bootstrapComponents.popover.fix": {
120-
"dependencies": "ext.bootstrap.scripts",
121-
"scripts": "ext.bootstrapComponents.popover.js"
124+
"dependencies": "ext.bootstrapComponents.bootstrap",
125+
"packageFiles": [ "ext.bootstrapComponents.popover.js" ]
122126
},
123127
"ext.bootstrapComponents.popover.vector-fix": {
124128
"styles": "ext.bootstrapComponents.popover.vector-fix.css"
125129
},
126130
"ext.bootstrapComponents.tooltip.fix": {
127-
"dependencies": "ext.bootstrap.scripts",
128-
"scripts": "ext.bootstrapComponents.tooltip.js",
131+
"dependencies": "ext.bootstrapComponents.bootstrap",
132+
"packageFiles": [ "ext.bootstrapComponents.tooltip.js" ],
129133
"styles": "ext.bootstrapComponents.tooltip.fix.css"
130134
},
131135
"ext.bootstrapComponents.vector-fix": {
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
'use strict';
2+
3+
// Resolve a Bootstrap component class by name: from the window.bootstrap global that
4+
// Extension:Bootstrap and most Bootstrap-bundling skins expose, or from the jQuery plugin
5+
// bridge that some skins (Tweeki) register instead, where a plugin's Constructor is the
6+
// native component class.
7+
function getComponentClass( name ) {
8+
if ( window.bootstrap && window.bootstrap[ name ] ) {
9+
return window.bootstrap[ name ];
10+
}
11+
const plugin = window.jQuery && window.jQuery.fn[ name.toLowerCase() ];
12+
return ( plugin && plugin.Constructor ) || null;
13+
}
14+
15+
module.exports = {
16+
getComponentClass: getComponentClass
17+
};

‎modules/ext.bootstrapComponents.carousel.js‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
( function () {
2727
'use strict';
2828

29+
const { getComponentClass } = require( 'ext.bootstrapComponents.bootstrap' );
30+
2931
// Wait for DOM to be ready
3032
if ( document.readyState === 'loading' ) {
3133
document.addEventListener( 'DOMContentLoaded', initCarousels );
@@ -34,14 +36,15 @@
3436
}
3537

3638
function initCarousels() {
37-
if ( typeof bootstrap === 'undefined' || !bootstrap.Carousel ) {
39+
const Carousel = getComponentClass( 'Carousel' );
40+
if ( !Carousel ) {
3841
// eslint-disable-next-line no-console
3942
console.warn( 'BootstrapComponents: bootstrap.Carousel is not available; carousels will not cycle.' );
4043
return;
4144
}
4245
const carouselElements = document.querySelectorAll( '.carousel' );
4346
carouselElements.forEach( function ( element ) {
44-
new bootstrap.Carousel( element );
47+
new Carousel( element );
4548
} );
4649
}
4750
}() );

‎modules/ext.bootstrapComponents.modal.js‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
( function () {
66
'use strict';
77

8+
const { getComponentClass } = require( 'ext.bootstrapComponents.bootstrap' );
9+
810
// Wait for DOM to be ready
911
if ( document.readyState === 'loading' ) {
1012
document.addEventListener( 'DOMContentLoaded', initModals );
@@ -13,7 +15,8 @@
1315
}
1416

1517
function initModals() {
16-
if ( typeof bootstrap === 'undefined' || !bootstrap.Modal ) {
18+
const Modal = getComponentClass( 'Modal' );
19+
if ( !Modal ) {
1720
// eslint-disable-next-line no-console
1821
console.warn( 'BootstrapComponents: bootstrap.Modal is not available; modal triggers will not work.' );
1922
return;
@@ -22,7 +25,7 @@
2225
// bootstrap.Modal.getOrCreateInstance(el).show()) work as expected.
2326
const modalList = document.querySelectorAll( '.modal' );
2427
modalList.forEach( function ( modalEl ) {
25-
bootstrap.Modal.getOrCreateInstance( modalEl );
28+
Modal.getOrCreateInstance( modalEl );
2629
} );
2730
}
2831
}() );

‎modules/ext.bootstrapComponents.popover.js‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
( function () {
2727
'use strict';
2828

29+
const { getComponentClass } = require( 'ext.bootstrapComponents.bootstrap' );
30+
2931
// Wait for DOM to be ready
3032
if ( document.readyState === 'loading' ) {
3133
document.addEventListener( 'DOMContentLoaded', initPopovers );
@@ -34,14 +36,15 @@
3436
}
3537

3638
function initPopovers() {
37-
if ( typeof bootstrap === 'undefined' || !bootstrap.Popover ) {
39+
const Popover = getComponentClass( 'Popover' );
40+
if ( !Popover ) {
3841
// eslint-disable-next-line no-console
3942
console.warn( 'BootstrapComponents: bootstrap.Popover is not available; popover triggers will not work.' );
4043
return;
4144
}
4245
const popoverTriggerList = document.querySelectorAll( '[data-bs-toggle="popover"]' );
4346
popoverTriggerList.forEach( function ( popoverTriggerEl ) {
44-
new bootstrap.Popover( popoverTriggerEl, {
47+
new Popover( popoverTriggerEl, {
4548
html: true
4649
} );
4750
} );

‎modules/ext.bootstrapComponents.tooltip.js‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
( function () {
2727
'use strict';
2828

29+
const { getComponentClass } = require( 'ext.bootstrapComponents.bootstrap' );
30+
2931
// Wait for DOM to be ready
3032
if ( document.readyState === 'loading' ) {
3133
document.addEventListener( 'DOMContentLoaded', initTooltips );
@@ -34,14 +36,15 @@
3436
}
3537

3638
function initTooltips() {
37-
if ( typeof bootstrap === 'undefined' || !bootstrap.Tooltip ) {
39+
const Tooltip = getComponentClass( 'Tooltip' );
40+
if ( !Tooltip ) {
3841
// eslint-disable-next-line no-console
3942
console.warn( 'BootstrapComponents: bootstrap.Tooltip is not available; tooltip triggers will not work.' );
4043
return;
4144
}
4245
const tooltipTriggerList = document.querySelectorAll( '[data-bs-toggle="tooltip"]' );
4346
tooltipTriggerList.forEach( function ( tooltipTriggerEl ) {
44-
new bootstrap.Tooltip( tooltipTriggerEl );
47+
new Tooltip( tooltipTriggerEl );
4548
} );
4649
}
4750
}() );

0 commit comments

Comments
 (0)