mirror of
https://github.com/compiler-explorer/compiler-explorer.git
synced 2025-12-27 07:04:04 -05:00
Cleanup post bootstrap 5 (#7608)
Remove some unnecessary functions and clarify docs. --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -329,9 +329,9 @@ These insights were gathered during the migration process and may be helpful for
|
||||
|
||||
- [x] ~~Create a plan for jQuery removal (if desired)~~ (tracked in [issue #7600](https://github.com/compiler-explorer/compiler-explorer/issues/7600))
|
||||
- [x] ~~Identify non-Bootstrap jQuery usage that would need refactoring~~ (tracked in [issue #7600](https://github.com/compiler-explorer/compiler-explorer/issues/7600))
|
||||
- [ ] Remove the temporary `bootstrap-utils.ts` compatibility layer
|
||||
- [ ] Replace all uses with direct Bootstrap 5 API calls
|
||||
- [ ] Document the native Bootstrap 5 API for future reference
|
||||
- [x] ~~Remove the temporary `bootstrap-utils.ts` compatibility layer~~ (Decision: Keep this utility for the foreseeable future as it provides valuable functionality for jQuery-Bootstrap 5 integration)
|
||||
- [x] ~~Replace all uses with direct Bootstrap 5 API calls~~ (Not necessary - updated documentation to indicate direct API usage when possible)
|
||||
- [x] ~~Document the native Bootstrap 5 API for future reference~~ (Added documentation in the utilities themselves)
|
||||
- [ ] ~~Investigate and fix modal accessibility warnings~~ (tracked in [issue #7602](https://github.com/compiler-explorer/compiler-explorer/issues/7602))
|
||||
- [ ] ~~Address the warning: "Blocked aria-hidden on an element because its descendant retained focus"~~ (part of issue #7602)
|
||||
- [ ] ~~Update modal template markup to leverage Bootstrap 5.3's built-in support for the `inert` attribute~~ (part of issue #7602)
|
||||
|
||||
@@ -23,29 +23,34 @@
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/**
|
||||
* TEMPORARY COMPATIBILITY LAYER
|
||||
* Bootstrap Utilities
|
||||
*
|
||||
* This module provides utilities to help transition from Bootstrap 4's jQuery-based API
|
||||
* to Bootstrap 5's vanilla JavaScript API. This is intended as a temporary solution
|
||||
* during the migration from Bootstrap 4 to 5 and should be removed once the migration
|
||||
* is complete.
|
||||
* This module provides utilities that bridge Bootstrap 5's vanilla JavaScript API
|
||||
* with jQuery-based code in the Compiler Explorer codebase. It centralizes Bootstrap
|
||||
* API interactions to provide consistent behavior across the application.
|
||||
*
|
||||
* The goal is to minimize changes throughout the codebase by centralizing the Bootstrap
|
||||
* API changes in this file, while still allowing for gradual migration to direct API calls.
|
||||
*
|
||||
* @deprecated This module should be removed after the Bootstrap 5 migration is complete.
|
||||
* Key benefits:
|
||||
* - Handles conversion between jQuery objects and DOM elements
|
||||
* - Provides simplified event handling compatible with jQuery patterns
|
||||
* - Maintains consistent API for Bootstrap components
|
||||
* - Simplifies Bootstrap component initialization and management
|
||||
*/
|
||||
|
||||
import $ from 'jquery';
|
||||
|
||||
import 'bootstrap';
|
||||
import {Collapse, Dropdown, Modal, Popover, Tab, Toast, Tooltip} from 'bootstrap';
|
||||
import {Dropdown, Modal, Popover, Toast} from 'bootstrap';
|
||||
|
||||
// Private event listener tracking map
|
||||
const eventListenerMap = new WeakMap<HTMLElement, Map<string, EventListener>>();
|
||||
|
||||
/**
|
||||
* Helper method to get an HTMLElement from various input types
|
||||
*
|
||||
* This is a core utility function that bridges jQuery objects with native DOM elements,
|
||||
* allowing our codebase to work with both paradigms while the Bootstrap 5 API requires
|
||||
* native DOM elements.
|
||||
*
|
||||
* @param elementOrSelector Element, jQuery object, or selector
|
||||
* @returns HTMLElement or null
|
||||
*/
|
||||
@@ -121,36 +126,6 @@ export function setElementEventHandler(
|
||||
setDomElementEventHandler(element, eventName, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a modal
|
||||
* @param elementOrSelector Element or selector for the modal
|
||||
* @param options Modal options
|
||||
* @returns Modal instance
|
||||
* @throws Error if the element cannot be found
|
||||
*/
|
||||
export function initModal(elementOrSelector: string | HTMLElement | JQuery, options?: Partial<Modal.Options>): Modal {
|
||||
const element = getElement(elementOrSelector);
|
||||
if (!element) throw new Error(`Failed to find element for modal: ${elementOrSelector}`);
|
||||
|
||||
return new Modal(element, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a modal if the element exists, returning null otherwise
|
||||
* @param elementOrSelector Element or selector for the modal
|
||||
* @param options Modal options
|
||||
* @returns Modal instance or null if the element cannot be found
|
||||
*/
|
||||
export function initModalIfExists(
|
||||
elementOrSelector: string | HTMLElement | JQuery,
|
||||
options?: Partial<Modal.Options>,
|
||||
): Modal | null {
|
||||
const element = getElement(elementOrSelector);
|
||||
if (!element) return null;
|
||||
|
||||
return new Modal(element, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an existing modal instance for an element
|
||||
* @param elementOrSelector Element or selector for the modal
|
||||
@@ -167,6 +142,12 @@ export function getModalInstance(elementOrSelector: string | HTMLElement | JQuer
|
||||
* Show a modal
|
||||
* @param elementOrSelector Element or selector for the modal
|
||||
* @param relatedTarget Optional related target element
|
||||
*
|
||||
* Note: When possible, prefer direct Bootstrap 5 API:
|
||||
* ```
|
||||
* const modal = Modal.getInstance(element) || new Modal(element);
|
||||
* modal.show(relatedTarget);
|
||||
* ```
|
||||
*/
|
||||
export function showModal(elementOrSelector: string | HTMLElement | JQuery, relatedTarget?: HTMLElement): void {
|
||||
const element = getElement(elementOrSelector);
|
||||
@@ -188,50 +169,25 @@ export function hideModal(elementOrSelector: string | HTMLElement | JQuery): voi
|
||||
if (modal) modal.hide();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a toast
|
||||
* @param elementOrSelector Element or selector for the toast
|
||||
* @param options Toast options
|
||||
* @returns Toast instance
|
||||
*/
|
||||
export function initToast(elementOrSelector: string | HTMLElement | JQuery, options?: Partial<Toast.Options>): Toast {
|
||||
const element = getElement(elementOrSelector);
|
||||
if (!element) throw new Error(`Failed to find element for toast: ${elementOrSelector}`);
|
||||
|
||||
return new Toast(element, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a toast if the element exists
|
||||
* @param elementOrSelector Element or selector for the toast
|
||||
* @param options Toast options
|
||||
* @returns Toast instance or null if element doesn't exist
|
||||
*/
|
||||
export function initToastIfExists(
|
||||
elementOrSelector: string | HTMLElement | JQuery,
|
||||
options?: Partial<Toast.Options>,
|
||||
): Toast | null {
|
||||
const element = getElement(elementOrSelector);
|
||||
if (!element) return null;
|
||||
|
||||
return new Toast(element, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a toast
|
||||
* @param elementOrSelector Element or selector for the toast
|
||||
* @param options Optional Toast options if a new instance needs to be created
|
||||
*/
|
||||
export function showToast(elementOrSelector: string | HTMLElement | JQuery): void {
|
||||
export function showToast(elementOrSelector: string | HTMLElement | JQuery, options?: Partial<Toast.Options>): void {
|
||||
const element = getElement(elementOrSelector);
|
||||
if (!element) return;
|
||||
|
||||
const toast = Toast.getInstance(element) || new Toast(element);
|
||||
const toast = Toast.getInstance(element) || new Toast(element, options);
|
||||
toast.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide a toast
|
||||
* @param elementOrSelector Element or selector for the toast
|
||||
*
|
||||
* Note: When possible, prefer direct Bootstrap 5 API:
|
||||
* `const toast = Toast.getInstance(element); if (toast) toast.hide();`
|
||||
*/
|
||||
export function hideToast(elementOrSelector: string | HTMLElement | JQuery): void {
|
||||
const element = getElement(elementOrSelector);
|
||||
@@ -241,39 +197,6 @@ export function hideToast(elementOrSelector: string | HTMLElement | JQuery): voi
|
||||
if (toast) toast.hide();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a dropdown
|
||||
* @param elementOrSelector Element or selector for the dropdown
|
||||
* @param options Dropdown options
|
||||
* @returns Dropdown instance
|
||||
* @throws Error if the element cannot be found
|
||||
*/
|
||||
export function initDropdown(
|
||||
elementOrSelector: string | HTMLElement | JQuery,
|
||||
options?: Partial<Dropdown.Options>,
|
||||
): Dropdown {
|
||||
const element = getElement(elementOrSelector);
|
||||
if (!element) throw new Error(`Failed to find element for dropdown: ${elementOrSelector}`);
|
||||
|
||||
return new Dropdown(element, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a dropdown if the element exists, returning null otherwise
|
||||
* @param elementOrSelector Element or selector for the dropdown
|
||||
* @param options Dropdown options
|
||||
* @returns Dropdown instance or null if the element cannot be found
|
||||
*/
|
||||
export function initDropdownIfExists(
|
||||
elementOrSelector: string | HTMLElement | JQuery,
|
||||
options?: Partial<Dropdown.Options>,
|
||||
): Dropdown | null {
|
||||
const element = getElement(elementOrSelector);
|
||||
if (!element) return null;
|
||||
|
||||
return new Dropdown(element, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an existing dropdown instance for an element
|
||||
* @param elementOrSelector Element or selector for the dropdown
|
||||
@@ -301,6 +224,9 @@ export function showDropdown(elementOrSelector: string | HTMLElement | JQuery):
|
||||
/**
|
||||
* Hide a dropdown
|
||||
* @param elementOrSelector Element or selector for the dropdown
|
||||
*
|
||||
* Note: When possible, prefer direct Bootstrap 5 API:
|
||||
* `const dropdown = Dropdown.getInstance(element); if (dropdown) dropdown.hide();`
|
||||
*/
|
||||
export function hideDropdown(elementOrSelector: string | HTMLElement | JQuery): void {
|
||||
const element = getElement(elementOrSelector);
|
||||
@@ -310,38 +236,6 @@ export function hideDropdown(elementOrSelector: string | HTMLElement | JQuery):
|
||||
if (dropdown) dropdown.hide();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a tooltip
|
||||
* @param elementOrSelector Element or selector for the tooltip
|
||||
* @param options Tooltip options
|
||||
* @returns Tooltip instance
|
||||
*/
|
||||
export function initTooltip(
|
||||
elementOrSelector: string | HTMLElement | JQuery,
|
||||
options?: Partial<Tooltip.Options>,
|
||||
): Tooltip {
|
||||
const element = getElement(elementOrSelector);
|
||||
if (!element) throw new Error(`Failed to find element for tooltip: ${elementOrSelector}`);
|
||||
|
||||
return new Tooltip(element, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a tooltip if the element exists
|
||||
* @param elementOrSelector Element or selector for the tooltip
|
||||
* @param options Tooltip options
|
||||
* @returns Tooltip instance or null if element doesn't exist
|
||||
*/
|
||||
export function initTooltipIfExists(
|
||||
elementOrSelector: string | HTMLElement | JQuery,
|
||||
options?: Partial<Tooltip.Options>,
|
||||
): Tooltip | null {
|
||||
const element = getElement(elementOrSelector);
|
||||
if (!element) return null;
|
||||
|
||||
return new Tooltip(element, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a popover
|
||||
* @param elementOrSelector Element or selector for the popover
|
||||
@@ -387,62 +281,6 @@ export function getPopoverInstance(elementOrSelector: string | HTMLElement | JQu
|
||||
return Popover.getInstance(element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a tab
|
||||
* @param elementOrSelector Element or selector for the tab
|
||||
* @returns Tab instance
|
||||
*/
|
||||
export function initTab(elementOrSelector: string | HTMLElement | JQuery): Tab {
|
||||
const element = getElement(elementOrSelector);
|
||||
if (!element) throw new Error(`Failed to find element for tab: ${elementOrSelector}`);
|
||||
|
||||
return new Tab(element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a tab if the element exists
|
||||
* @param elementOrSelector Element or selector for the tab
|
||||
* @returns Tab instance or null if element doesn't exist
|
||||
*/
|
||||
export function initTabIfExists(elementOrSelector: string | HTMLElement | JQuery): Tab | null {
|
||||
const element = getElement(elementOrSelector);
|
||||
if (!element) return null;
|
||||
|
||||
return new Tab(element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a collapse
|
||||
* @param elementOrSelector Element or selector for the collapse
|
||||
* @param options Collapse options
|
||||
* @returns Collapse instance
|
||||
*/
|
||||
export function initCollapse(
|
||||
elementOrSelector: string | HTMLElement | JQuery,
|
||||
options?: Partial<Collapse.Options>,
|
||||
): Collapse {
|
||||
const element = getElement(elementOrSelector);
|
||||
if (!element) throw new Error(`Failed to find element for collapse: ${elementOrSelector}`);
|
||||
|
||||
return new Collapse(element, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a collapse if the element exists
|
||||
* @param elementOrSelector Element or selector for the collapse
|
||||
* @param options Collapse options
|
||||
* @returns Collapse instance or null if element doesn't exist
|
||||
*/
|
||||
export function initCollapseIfExists(
|
||||
elementOrSelector: string | HTMLElement | JQuery,
|
||||
options?: Partial<Collapse.Options>,
|
||||
): Collapse | null {
|
||||
const element = getElement(elementOrSelector);
|
||||
if (!element) return null;
|
||||
|
||||
return new Collapse(element, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide an existing popover if it exists
|
||||
* @param elementOrSelector Element or selector for the popover
|
||||
@@ -451,21 +289,3 @@ export function hidePopover(elementOrSelector: string | HTMLElement | JQuery): v
|
||||
const popover = getPopoverInstance(elementOrSelector);
|
||||
if (popover) popover.hide();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show an existing popover if it exists
|
||||
* @param elementOrSelector Element or selector for the popover
|
||||
*/
|
||||
export function showPopover(elementOrSelector: string | HTMLElement | JQuery): void {
|
||||
const popover = getPopoverInstance(elementOrSelector);
|
||||
if (popover) popover.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show an existing modal if it exists (uses existing instance only)
|
||||
* @param elementOrSelector Element or selector for the modal
|
||||
*/
|
||||
export function showModalIfExists(elementOrSelector: string | HTMLElement | JQuery): void {
|
||||
const modal = getModalInstance(elementOrSelector);
|
||||
if (modal) modal.show();
|
||||
}
|
||||
|
||||
@@ -131,7 +131,6 @@ export class Sharing {
|
||||
});
|
||||
this.layout.on('stateChanged', this.onStateChanged.bind(this));
|
||||
|
||||
BootstrapUtils.initModal(this.shareLinkDialog);
|
||||
this.shareLinkDialog.addEventListener('show.bs.modal', this.onOpenModalPane.bind(this));
|
||||
this.shareLinkDialog.addEventListener('hidden.bs.modal', this.onCloseModalPane.bind(this));
|
||||
|
||||
@@ -334,7 +333,7 @@ export class Sharing {
|
||||
|
||||
// Create and show new tooltip
|
||||
try {
|
||||
const tooltip = BootstrapUtils.initTooltip(tooltipEl, {
|
||||
const tooltip = new Tooltip(tooltipEl, {
|
||||
placement: 'bottom',
|
||||
trigger: 'manual',
|
||||
title: message,
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import {Toast} from 'bootstrap';
|
||||
import $ from 'jquery';
|
||||
|
||||
import * as BootstrapUtils from '../bootstrap-utils.js';
|
||||
@@ -123,7 +124,7 @@ export class Alert {
|
||||
delay: dismissTime,
|
||||
};
|
||||
|
||||
BootstrapUtils.initToast(newElement, toastOptions);
|
||||
new Toast(newElement[0], toastOptions);
|
||||
|
||||
if (group !== '') {
|
||||
if (collapseSimilar) {
|
||||
|
||||
Reference in New Issue
Block a user