mirror of
https://github.com/StarCitizenTools/mediawiki-extensions-TabberNeue.git
synced 2024-11-27 09:42:48 +00:00
refactor: separate classes into other files
This commit is contained in:
parent
bbde0ae7bd
commit
476af1352b
|
@ -46,7 +46,10 @@
|
|||
"parseTabName": "TabberNeueParseTabName",
|
||||
"updateLocationOnTabChange": "TabberNeueUpdateLocationOnTabChange"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ext.tabberNeue/Hash.js",
|
||||
"ext.tabberNeue/Transclude.js",
|
||||
"ext.tabberNeue/Util.js"
|
||||
],
|
||||
"messages": [
|
||||
"error"
|
||||
|
|
73
modules/ext.tabberNeue/Hash.js
Normal file
73
modules/ext.tabberNeue/Hash.js
Normal file
|
@ -0,0 +1,73 @@
|
|||
let uniqueHashes;
|
||||
|
||||
/**
|
||||
* Class representing a Hash utility for generating unique hash values.
|
||||
*
|
||||
* @class Hash
|
||||
*/
|
||||
class Hash {
|
||||
/**
|
||||
* Initializes the Hash class by creating a new Set to store unique hashes.
|
||||
*/
|
||||
static init() {
|
||||
uniqueHashes = new Set();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given hash is not unique by verifying if it exists in the Set of unique hashes.
|
||||
*
|
||||
* @param {string} hash - The hash to check for uniqueness.
|
||||
* @return {boolean} - Returns true if the hash is not unique, false otherwise.
|
||||
*/
|
||||
static exists( hash ) {
|
||||
return uniqueHashes.has( hash );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a unique hash based on the input hash by appending a suffix if necessary.
|
||||
*
|
||||
* @param {string} hash - The base hash to make unique.
|
||||
* @return {string} - A unique hash derived from the input hash.
|
||||
*/
|
||||
static makeUnique( hash ) {
|
||||
const match = hash.match( /^(.+)_([0-9]+)$/ );
|
||||
let suffix = match ? parseInt( match[ 2 ], 10 ) + 1 : 1;
|
||||
|
||||
const initialHash = hash;
|
||||
|
||||
let uniqueHash = `${ initialHash }_${ suffix }`;
|
||||
// Increment suffix and generate a new unique hash until a unique one is found
|
||||
while ( Hash.exists( uniqueHash ) ) {
|
||||
suffix++;
|
||||
uniqueHash = `${ initialHash }_${ suffix }`;
|
||||
}
|
||||
|
||||
return uniqueHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a unique hash based on the provided title text.
|
||||
*
|
||||
* @param {string} titleText - The title text to generate the hash from.
|
||||
* @return {string} - A unique hash created from the title text.
|
||||
*/
|
||||
static build( titleText ) {
|
||||
let hash = mw.util.escapeIdForAttribute( titleText );
|
||||
|
||||
if ( Hash.exists( hash ) ) {
|
||||
hash = Hash.makeUnique( hash );
|
||||
}
|
||||
|
||||
uniqueHashes.add( hash );
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the Set of unique hashes, removing all stored hashes.
|
||||
*/
|
||||
static clear() {
|
||||
uniqueHashes.clear();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Hash;
|
138
modules/ext.tabberNeue/Transclude.js
Normal file
138
modules/ext.tabberNeue/Transclude.js
Normal file
|
@ -0,0 +1,138 @@
|
|||
/**
|
||||
* Represents a class that handles transcluding content for a tab within a tabber component.
|
||||
*
|
||||
* @class Transclude
|
||||
*/
|
||||
class Transclude {
|
||||
constructor( activeTabpanel, cacheExpiration = 3600 ) {
|
||||
this.activeTabpanel = activeTabpanel;
|
||||
this.pageTitle = this.activeTabpanel.dataset.mwTabberPageTitle;
|
||||
this.url = this.activeTabpanel.dataset.mwTabberLoadUrl;
|
||||
this.cacheKey = `tabber-transclude-${ encodeURIComponent( this.pageTitle ) }_v1`;
|
||||
this.cacheExpiration = cacheExpiration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the URL format.
|
||||
*
|
||||
* @return {Promise} A Promise that resolves if the URL is valid, and rejects with an Error if the URL is empty, null, or in an invalid format.
|
||||
*/
|
||||
validateUrl() {
|
||||
const urlPattern = /^(https?):\/\/[^\s/$.?#][^\s]*$/;
|
||||
if ( !this.url || this.url.trim() === '' ) {
|
||||
return Promise.reject( new Error( '[TabberNeue] URL is empty or null' ) );
|
||||
}
|
||||
if ( !urlPattern.test( this.url ) ) {
|
||||
return Promise.reject( new Error( `[TabberNeue] Invalid URL format : ${ this.url }` ) );
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the session storage for cached data using the cache key.
|
||||
*
|
||||
* @return {Object|null} The cached data if found, or null if no cached data is found.
|
||||
*/
|
||||
checkCache() {
|
||||
const cachedData = mw.storage.session.getObject( this.cacheKey );
|
||||
if ( cachedData ) {
|
||||
return cachedData;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches data from the specified URL using a GET request.
|
||||
*
|
||||
* @return {Promise} A Promise that resolves with the response text if the network request is successful,
|
||||
* and rejects with an Error if there is an issue with the network request.
|
||||
*/
|
||||
async fetchDataFromUrl() {
|
||||
try {
|
||||
const response = await fetch( this.url, { method: 'GET', timeout: 5000, credentials: 'same-origin' } );
|
||||
if ( !response.ok ) {
|
||||
throw new Error( `Network response was not ok: ${ response.status } - ${ response.statusText }` );
|
||||
}
|
||||
return Promise.resolve( response.text() );
|
||||
} catch ( error ) {
|
||||
return Promise.reject( `[TabberNeue] Error fetching data from URL: ${ this.url }`, error );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the JSON data and extracts the 'parse.text' property.
|
||||
*
|
||||
* @param {string} data - The JSON data to be parsed.
|
||||
* @return {string} The parsed 'parse.text' property from the JSON data.
|
||||
* @throws {Error} If an error occurs while parsing the JSON data.
|
||||
*/
|
||||
parseData( data ) {
|
||||
let parsedData;
|
||||
try {
|
||||
parsedData = JSON.parse( data );
|
||||
parsedData = parsedData.parse.text;
|
||||
} catch ( error ) {
|
||||
mw.log.error( `[TabberNeue] Error occurred while parsing JSON data: ${ error }` );
|
||||
return Promise.reject( new Error( `Error parsing JSON data: ${ error }` ) );
|
||||
}
|
||||
return parsedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Caches the parsed data in the session storage using the cache key.
|
||||
*
|
||||
* @param {string} parsedData - The parsed data to be cached.
|
||||
* @return {string} The cached parsed data.
|
||||
*/
|
||||
cacheData( parsedData ) {
|
||||
mw.storage.session.setObject( this.cacheKey, parsedData, this.cacheExpiration );
|
||||
return parsedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches data by validating the URL, checking the cache, fetching data from the URL,
|
||||
* parsing the data, and caching the parsed data if not found in the cache.
|
||||
*
|
||||
* @return {Promise} A Promise that resolves with the fetched and cached data,
|
||||
* or rejects with an error message if any step fails.
|
||||
*/
|
||||
async fetchData() {
|
||||
try {
|
||||
await this.validateUrl();
|
||||
const cachedData = this.checkCache();
|
||||
if ( cachedData ) {
|
||||
return cachedData;
|
||||
}
|
||||
|
||||
const data = await this.fetchDataFromUrl();
|
||||
const parsedData = this.parseData( data );
|
||||
return this.cacheData( parsedData );
|
||||
} catch ( error ) {
|
||||
return Promise.reject( `[TabberNeue] Error fetching data: ${ error }` );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the page content by fetching data, updating the active tab panel's content,
|
||||
* and handling errors if data fetching fails.
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
async loadPage() {
|
||||
try {
|
||||
this.activeTabpanel.classList.add( 'tabber__panel--loading' );
|
||||
const data = await this.fetchData();
|
||||
if ( data ) {
|
||||
delete this.activeTabpanel.dataset.mwTabberLoadUrl;
|
||||
this.activeTabpanel.classList.remove( 'tabber__panel--loading' );
|
||||
this.activeTabpanel.innerHTML = data;
|
||||
} else {
|
||||
mw.log.error( `[TabberNeue] No valid API response or missing 'parse' field for ${ this.pageTitle } from: ${ this.url }` );
|
||||
}
|
||||
} catch ( error ) {
|
||||
mw.log.error( `[TabberNeue] Failed to load data for ${ this.pageTitle }: ${ error }` );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Transclude;
|
87
modules/ext.tabberNeue/Util.js
Normal file
87
modules/ext.tabberNeue/Util.js
Normal file
|
@ -0,0 +1,87 @@
|
|||
/**
|
||||
* Utility class with methods for common utility functions.
|
||||
*
|
||||
* @class Util
|
||||
*/
|
||||
class Util {
|
||||
/**
|
||||
* Extracts text content from the given HTML string.
|
||||
*
|
||||
* @param {string} html - The HTML string to extract text content from.
|
||||
* @return {string} The extracted text content.
|
||||
*/
|
||||
static extractTextFromHtml( html ) {
|
||||
const tmp = document.createElement( 'div' );
|
||||
tmp.innerHTML = html;
|
||||
return tmp.textContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size (width or height) of the provided element.
|
||||
* Required to calculate the size of hidden elements (e.g. nested tabs)
|
||||
*
|
||||
* @param {Element} element - The element for which to get the size.
|
||||
* @param {string} type - The type of size to retrieve ('width' or 'height').
|
||||
* @return {number} The actual size of the element based on the specified type.
|
||||
*/
|
||||
static getElementSize( element, type ) {
|
||||
if ( !element || !( element instanceof Element ) || ( type !== 'width' && type !== 'height' ) ) {
|
||||
mw.log.error( '[TabberNeue] Invalid element or type provided for getElementSize' );
|
||||
return 0;
|
||||
}
|
||||
|
||||
let value = element.getBoundingClientRect()[ type ];
|
||||
|
||||
if ( value === 0 ) {
|
||||
value = this.getHiddenElementSize( element, type );
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the size of a hidden element by cloning it and calculating the size.
|
||||
*
|
||||
* @param {Element} element - The hidden element to retrieve the size from.
|
||||
* @param {string} type - The type of size to retrieve ('width' or 'height').
|
||||
* @return {number} The size of the hidden element based on the specified type.
|
||||
*/
|
||||
static getHiddenElementSize( element, type ) {
|
||||
const shadowRoot = document.createElement( 'div' ).attachShadow( { mode: 'open' } );
|
||||
const clone = element.cloneNode( true );
|
||||
clone.style.position = 'absolute';
|
||||
clone.style.visibility = 'hidden';
|
||||
shadowRoot.appendChild( clone );
|
||||
try {
|
||||
const value = clone.getBoundingClientRect()[ type ];
|
||||
return value;
|
||||
} finally {
|
||||
clone.parentNode.removeChild( clone );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rounds the scrollLeft value to the nearest integer using Math.ceil.
|
||||
* Used to avoid the fractional pixel issue caused by different browser implementations
|
||||
*
|
||||
* @param {number} val - The scrollLeft value to be rounded.
|
||||
* @return {number} The rounded scrollLeft value.
|
||||
*/
|
||||
static roundScrollLeft( val ) {
|
||||
return Math.ceil( val );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the attributes of the given element based on the provided attributes object.
|
||||
*
|
||||
* @param {Element} element - The element to set attributes for.
|
||||
* @param {Object} attributes - An object containing key-value pairs of attributes to set.
|
||||
*/
|
||||
static setAttributes( element, attributes ) {
|
||||
for ( const key in attributes ) {
|
||||
element.setAttribute( key, attributes[ key ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Util;
|
|
@ -6,303 +6,12 @@
|
|||
* TODO: Split classes into different modules
|
||||
*/
|
||||
const config = require( './config.json' );
|
||||
const Hash = require( './Hash.js' );
|
||||
const Transclude = require( './Transclude.js' );
|
||||
const Util = require( './Util.js' );
|
||||
|
||||
let uniqueHashes;
|
||||
let resizeObserver;
|
||||
|
||||
/**
|
||||
* Class representing a Hash utility for generating unique hash values.
|
||||
*
|
||||
* @class Hash
|
||||
*/
|
||||
class Hash {
|
||||
/**
|
||||
* Initializes the Hash class by creating a new Set to store unique hashes.
|
||||
*/
|
||||
static init() {
|
||||
uniqueHashes = new Set();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given hash is not unique by verifying if it exists in the Set of unique hashes.
|
||||
*
|
||||
* @param {string} hash - The hash to check for uniqueness.
|
||||
* @return {boolean} - Returns true if the hash is not unique, false otherwise.
|
||||
*/
|
||||
static exists( hash ) {
|
||||
return uniqueHashes.has( hash );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a unique hash based on the input hash by appending a suffix if necessary.
|
||||
*
|
||||
* @param {string} hash - The base hash to make unique.
|
||||
* @return {string} - A unique hash derived from the input hash.
|
||||
*/
|
||||
static makeUnique( hash ) {
|
||||
const match = hash.match( /^(.+)_([0-9]+)$/ );
|
||||
let suffix = match ? parseInt( match[ 2 ], 10 ) + 1 : 1;
|
||||
|
||||
const initialHash = hash;
|
||||
|
||||
let uniqueHash = `${ initialHash }_${ suffix }`;
|
||||
// Increment suffix and generate a new unique hash until a unique one is found
|
||||
while ( Hash.exists( uniqueHash ) ) {
|
||||
suffix++;
|
||||
uniqueHash = `${ initialHash }_${ suffix }`;
|
||||
}
|
||||
|
||||
return uniqueHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a unique hash based on the provided title text.
|
||||
*
|
||||
* @param {string} titleText - The title text to generate the hash from.
|
||||
* @return {string} - A unique hash created from the title text.
|
||||
*/
|
||||
static build( titleText ) {
|
||||
let hash = mw.util.escapeIdForAttribute( titleText );
|
||||
|
||||
if ( Hash.exists( hash ) ) {
|
||||
hash = Hash.makeUnique( hash );
|
||||
}
|
||||
|
||||
uniqueHashes.add( hash );
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the Set of unique hashes, removing all stored hashes.
|
||||
*/
|
||||
static clear() {
|
||||
uniqueHashes.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility class with methods for common utility functions.
|
||||
*
|
||||
* @class Util
|
||||
*/
|
||||
class Util {
|
||||
/**
|
||||
* Extracts text content from the given HTML string.
|
||||
*
|
||||
* @param {string} html - The HTML string to extract text content from.
|
||||
* @return {string} The extracted text content.
|
||||
*/
|
||||
static extractTextFromHtml( html ) {
|
||||
const tmp = document.createElement( 'div' );
|
||||
tmp.innerHTML = html;
|
||||
return tmp.textContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size (width or height) of the provided element.
|
||||
* Required to calculate the size of hidden elements (e.g. nested tabs)
|
||||
*
|
||||
* @param {Element} element - The element for which to get the size.
|
||||
* @param {string} type - The type of size to retrieve ('width' or 'height').
|
||||
* @return {number} The actual size of the element based on the specified type.
|
||||
*/
|
||||
static getElementSize( element, type ) {
|
||||
if ( !element || !( element instanceof Element ) || ( type !== 'width' && type !== 'height' ) ) {
|
||||
mw.log.error( '[TabberNeue] Invalid element or type provided for getElementSize' );
|
||||
return 0;
|
||||
}
|
||||
|
||||
let value = element.getBoundingClientRect()[ type ];
|
||||
|
||||
if ( value === 0 ) {
|
||||
value = this.getHiddenElementSize( element, type );
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the size of a hidden element by cloning it and calculating the size.
|
||||
*
|
||||
* @param {Element} element - The hidden element to retrieve the size from.
|
||||
* @param {string} type - The type of size to retrieve ('width' or 'height').
|
||||
* @return {number} The size of the hidden element based on the specified type.
|
||||
*/
|
||||
static getHiddenElementSize( element, type ) {
|
||||
const shadowRoot = document.createElement( 'div' ).attachShadow( { mode: 'open' } );
|
||||
const clone = element.cloneNode( true );
|
||||
clone.style.position = 'absolute';
|
||||
clone.style.visibility = 'hidden';
|
||||
shadowRoot.appendChild( clone );
|
||||
try {
|
||||
const value = clone.getBoundingClientRect()[ type ];
|
||||
return value;
|
||||
} finally {
|
||||
clone.parentNode.removeChild( clone );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rounds the scrollLeft value to the nearest integer using Math.ceil.
|
||||
* Used to avoid the fractional pixel issue caused by different browser implementations
|
||||
*
|
||||
* @param {number} val - The scrollLeft value to be rounded.
|
||||
* @return {number} The rounded scrollLeft value.
|
||||
*/
|
||||
static roundScrollLeft( val ) {
|
||||
return Math.ceil( val );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the attributes of the given element based on the provided attributes object.
|
||||
*
|
||||
* @param {Element} element - The element to set attributes for.
|
||||
* @param {Object} attributes - An object containing key-value pairs of attributes to set.
|
||||
*/
|
||||
static setAttributes( element, attributes ) {
|
||||
for ( const key in attributes ) {
|
||||
element.setAttribute( key, attributes[ key ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a class that handles transcluding content for a tab within a tabber component.
|
||||
*
|
||||
* @class TabberTransclude
|
||||
*/
|
||||
class TabberTransclude {
|
||||
constructor( activeTabpanel, cacheExpiration = 3600 ) {
|
||||
this.activeTabpanel = activeTabpanel;
|
||||
this.pageTitle = this.activeTabpanel.dataset.mwTabberPageTitle;
|
||||
this.url = this.activeTabpanel.dataset.mwTabberLoadUrl;
|
||||
this.cacheKey = `tabber-transclude-${ encodeURIComponent( this.pageTitle ) }_v1`;
|
||||
this.cacheExpiration = cacheExpiration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the URL format.
|
||||
*
|
||||
* @return {Promise} A Promise that resolves if the URL is valid, and rejects with an Error if the URL is empty, null, or in an invalid format.
|
||||
*/
|
||||
validateUrl() {
|
||||
const urlPattern = /^(https?):\/\/[^\s/$.?#][^\s]*$/;
|
||||
if ( !this.url || this.url.trim() === '' ) {
|
||||
return Promise.reject( new Error( '[TabberNeue] URL is empty or null' ) );
|
||||
}
|
||||
if ( !urlPattern.test( this.url ) ) {
|
||||
return Promise.reject( new Error( `[TabberNeue] Invalid URL format : ${ this.url }` ) );
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the session storage for cached data using the cache key.
|
||||
*
|
||||
* @return {Object|null} The cached data if found, or null if no cached data is found.
|
||||
*/
|
||||
checkCache() {
|
||||
const cachedData = mw.storage.session.getObject( this.cacheKey );
|
||||
if ( cachedData ) {
|
||||
return cachedData;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches data from the specified URL using a GET request.
|
||||
*
|
||||
* @return {Promise} A Promise that resolves with the response text if the network request is successful,
|
||||
* and rejects with an Error if there is an issue with the network request.
|
||||
*/
|
||||
async fetchDataFromUrl() {
|
||||
try {
|
||||
const response = await fetch( this.url, { method: 'GET', timeout: 5000, credentials: 'same-origin' } );
|
||||
if ( !response.ok ) {
|
||||
throw new Error( `Network response was not ok: ${ response.status } - ${ response.statusText }` );
|
||||
}
|
||||
return Promise.resolve( response.text() );
|
||||
} catch ( error ) {
|
||||
return Promise.reject( `[TabberNeue] Error fetching data from URL: ${ this.url }`, error );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the JSON data and extracts the 'parse.text' property.
|
||||
*
|
||||
* @param {string} data - The JSON data to be parsed.
|
||||
* @return {string} The parsed 'parse.text' property from the JSON data.
|
||||
* @throws {Error} If an error occurs while parsing the JSON data.
|
||||
*/
|
||||
parseData( data ) {
|
||||
let parsedData;
|
||||
try {
|
||||
parsedData = JSON.parse( data );
|
||||
parsedData = parsedData.parse.text;
|
||||
} catch ( error ) {
|
||||
mw.log.error( `[TabberNeue] Error occurred while parsing JSON data: ${ error }` );
|
||||
return Promise.reject( new Error( `Error parsing JSON data: ${ error }` ) );
|
||||
}
|
||||
return parsedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Caches the parsed data in the session storage using the cache key.
|
||||
*
|
||||
* @param {string} parsedData - The parsed data to be cached.
|
||||
* @return {string} The cached parsed data.
|
||||
*/
|
||||
cacheData( parsedData ) {
|
||||
mw.storage.session.setObject( this.cacheKey, parsedData, this.cacheExpiration );
|
||||
return parsedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches data by validating the URL, checking the cache, fetching data from the URL,
|
||||
* parsing the data, and caching the parsed data if not found in the cache.
|
||||
*
|
||||
* @return {Promise} A Promise that resolves with the fetched and cached data,
|
||||
* or rejects with an error message if any step fails.
|
||||
*/
|
||||
async fetchData() {
|
||||
try {
|
||||
await this.validateUrl();
|
||||
const cachedData = this.checkCache();
|
||||
if ( cachedData ) {
|
||||
return cachedData;
|
||||
}
|
||||
|
||||
const data = await this.fetchDataFromUrl();
|
||||
const parsedData = this.parseData( data );
|
||||
return this.cacheData( parsedData );
|
||||
} catch ( error ) {
|
||||
return Promise.reject( `[TabberNeue] Error fetching data: ${ error }` );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the page content by fetching data, updating the active tab panel's content,
|
||||
* and handling errors if data fetching fails.
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
async loadPage() {
|
||||
try {
|
||||
this.activeTabpanel.classList.add( 'tabber__panel--loading' );
|
||||
const data = await this.fetchData();
|
||||
if ( data ) {
|
||||
delete this.activeTabpanel.dataset.mwTabberLoadUrl;
|
||||
this.activeTabpanel.classList.remove( 'tabber__panel--loading' );
|
||||
this.activeTabpanel.innerHTML = data;
|
||||
} else {
|
||||
mw.log.error( `[TabberNeue] No valid API response or missing 'parse' field for ${ this.pageTitle } from: ${ this.url }` );
|
||||
}
|
||||
} catch ( error ) {
|
||||
mw.log.error( `[TabberNeue] Failed to load data for ${ this.pageTitle }: ${ error }` );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class representing TabberEvent functionality for handling tab events and animations.
|
||||
*
|
||||
|
@ -388,8 +97,8 @@ class TabberEvent {
|
|||
const section = activeTabpanel.closest( '.tabber__section' );
|
||||
|
||||
if ( activeTabpanel.dataset.mwTabberLoadUrl ) {
|
||||
const tabberTransclude = new TabberTransclude( activeTabpanel );
|
||||
tabberTransclude.loadPage();
|
||||
const transclude = new Transclude( activeTabpanel );
|
||||
transclude.loadPage();
|
||||
}
|
||||
|
||||
window.requestAnimationFrame( () => {
|
||||
|
|
Loading…
Reference in a new issue