mirror of
https://github.com/StarCitizenTools/mediawiki-skins-Citizen.git
synced 2024-11-29 16:45:28 +00:00
146 lines
4.1 KiB
JavaScript
146 lines
4.1 KiB
JavaScript
const config = require( './config.json' );
|
|
|
|
/**
|
|
* Set up scroll affordance for an overflowed element
|
|
* TODO: Move this out of tables when this is used by more stuff
|
|
*
|
|
* @param {HTMLElement} element
|
|
* @return {void}
|
|
*/
|
|
function setupOverflowState( element ) {
|
|
if ( !element.parentNode ) {
|
|
mw.log.error( '[Citizen] Parent node is null or undefined. Cannot proceed with setupOverflowState.' );
|
|
return;
|
|
}
|
|
|
|
const parentNode = element.parentNode;
|
|
let cachedContainerWidth;
|
|
let cachedContentWidth;
|
|
let cachedScrollPosition;
|
|
|
|
const updateOverflowClasses = ( isLeft, isRight ) => {
|
|
parentNode.classList.toggle( 'citizen-overflow--left', isLeft );
|
|
parentNode.classList.toggle( 'citizen-overflow--right', isRight );
|
|
};
|
|
|
|
const updateState = () => {
|
|
const containerWidth = parentNode.offsetWidth;
|
|
const contentWidth = element.scrollWidth;
|
|
const currentPosition = Math.round( parentNode.scrollLeft );
|
|
|
|
if ( isNaN( containerWidth ) || isNaN( contentWidth ) ) {
|
|
mw.log.error( '[Citizen] Invalid width values. Cannot calculate overflow state.' );
|
|
return;
|
|
}
|
|
|
|
if (
|
|
containerWidth === cachedContainerWidth &&
|
|
contentWidth === cachedContentWidth &&
|
|
currentPosition === cachedScrollPosition
|
|
) {
|
|
return;
|
|
}
|
|
|
|
cachedContainerWidth = containerWidth;
|
|
cachedContentWidth = contentWidth;
|
|
cachedScrollPosition = currentPosition;
|
|
|
|
const isAtStart = currentPosition <= 0;
|
|
const isAtEnd = currentPosition + containerWidth >= contentWidth;
|
|
updateOverflowClasses( !isAtStart, !isAtEnd );
|
|
};
|
|
|
|
updateState();
|
|
|
|
parentNode.addEventListener( 'scroll', () => {
|
|
window.requestAnimationFrame( updateState );
|
|
} );
|
|
|
|
const debouncedUpdateState = mw.util.debounce( 250, updateState );
|
|
const isResizeObserverSupported = typeof ResizeObserver === 'function';
|
|
if ( isResizeObserverSupported ) {
|
|
const overflowResizeObserver = new ResizeObserver( debouncedUpdateState );
|
|
overflowResizeObserver.observe( element );
|
|
} else {
|
|
// Fallback mechanism or error handling for environments without ResizeObserver support
|
|
mw.log.warn( '[Citizen] ResizeObserver is not supported in this environment.' );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Wraps a given HTML table element in a new div container with specific classes,
|
|
* ensuring it does not wrap tables with certain ignored classes. It also manages
|
|
* class inheritance from the table to the wrapper and sets up overflow handling.
|
|
*
|
|
* @param {HTMLTableElement} table - The HTML table element to be wrapped.
|
|
* @return {void}
|
|
*/
|
|
function wrapTable( table ) {
|
|
try {
|
|
if (
|
|
!config.wgCitizenTableNowrapClasses ||
|
|
!Array.isArray( config.wgCitizenTableNowrapClasses )
|
|
) {
|
|
mw.log.error( '[Citizen] Invalid or missing $wgCitizenTableNowrapClasses. Cannot proceed with wrapping table.' );
|
|
return;
|
|
}
|
|
|
|
if ( !table || !table.parentNode ) {
|
|
mw.log.error( '[Citizen] Table or table.parentNode is null or undefined.' );
|
|
return;
|
|
}
|
|
|
|
const ignoredClasses = config.wgCitizenTableNowrapClasses;
|
|
|
|
if ( ignoredClasses.some( ( cls ) => table.classList.contains( cls ) ) ) {
|
|
return;
|
|
}
|
|
|
|
const wrapper = document.createElement( 'div' );
|
|
wrapper.className = 'citizen-table-wrapper';
|
|
|
|
const inheritedClasses = [
|
|
'floatleft',
|
|
'floatright'
|
|
];
|
|
|
|
const filteredClasses = inheritedClasses.filter( ( cls ) => table.classList.contains( cls ) );
|
|
|
|
filteredClasses.forEach( ( cls ) => {
|
|
if ( !wrapper.classList.contains( cls ) ) {
|
|
wrapper.classList.add( cls );
|
|
}
|
|
if ( table.classList.contains( cls ) ) {
|
|
table.classList.remove( cls );
|
|
}
|
|
} );
|
|
|
|
table.parentNode.insertBefore( wrapper, table );
|
|
wrapper.appendChild( table );
|
|
|
|
setupOverflowState( table );
|
|
} catch ( error ) {
|
|
mw.log.error( `[Citizen] Error occurred while wrapping table: ${ error.message }` );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initializes the process of wrapping tables within the given body content.
|
|
*
|
|
* @param {HTMLElement} bodyContent - The body content element containing tables to be wrapped.
|
|
* @return {void}
|
|
*/
|
|
function init( bodyContent ) {
|
|
const tables = bodyContent.querySelectorAll( 'table:not( table table )' );
|
|
|
|
if ( tables.length > 0 ) {
|
|
Array.from( tables ).forEach( ( table ) => {
|
|
wrapTable( table );
|
|
} );
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
init: init
|
|
};
|