Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

MediaWiki:Common.js: Difference between revisions

MediaWiki interface page
No edit summary
No edit summary
 
(20 intermediate revisions by the same user not shown)
Line 1: Line 1:
/* Return to a box header after using its bottom collapse control. */
function wizlordsScrollToCollapsedHeader($box) {
if (!$box.length) { return; }
$box.children('.mw-collapsible-content').promise().done(function () {
window.requestAnimationFrame(function () {
window.requestAnimationFrame(function () {
if (!document.documentElement.contains($box[0])) { return; }
var offset = 16;
document.querySelectorAll('.citizen-header, .vector-sticky-header').forEach(function (header) {
var style = window.getComputedStyle(header);
var rect = header.getBoundingClientRect();
if ((style.position === 'fixed' || style.position === 'sticky') &&
rect.height > 0 && rect.top <= 0 && rect.bottom > 0) {
offset = Math.max(offset, rect.bottom + 16);
}
});
$box.children('[aria-expanded]').addBack('[aria-expanded]').attr('aria-expanded', 'false');
var previousMargin = $box[0].style.scrollMarginTop;
$box[0].style.scrollMarginTop = offset + 'px';
$box[0].scrollIntoView({ block: 'start', inline: 'nearest', behavior: 'instant' });
$box[0].style.scrollMarginTop = previousMargin;
});
});
});
}
/* Bottom collapse controls */
/* Bottom collapse controls */
mw.loader.using('jquery.makeCollapsible').then(function () {
mw.loader.using('jquery.makeCollapsible').then(function () {
Line 77: Line 102:
if ($topToggle.length) {
if ($topToggle.length) {
$topToggle.trigger('click');
$topToggle.trigger('click');
wizlordsScrollToCollapsedHeader($collapsible);
}
}
});
});
Line 84: Line 110:
collapseFromBottom('.wizlords-spellbook-collapse-divine', 'wizlords-divine-spellbook');
collapseFromBottom('.wizlords-spellbook-collapse-divine', 'wizlords-divine-spellbook');


$(document).on('click', '.wizlords-collapsible-section-bottom-toggle', function (event) {
$(document).on('click', '.wizlords-collapsible-section-bottom-toggle, .wizlords-lore-collapse', function (event) {
event.preventDefault();
event.preventDefault();


Line 92: Line 118:
if ($topToggle.length) {
if ($topToggle.length) {
$topToggle.trigger('click');
$topToggle.trigger('click');
wizlordsScrollToCollapsedHeader($collapsible);
}
}
});
});
Line 137: Line 164:
.toggleClass('is-open', !isOpen)
.toggleClass('is-open', !isOpen)
.attr('aria-expanded', isOpen ? 'false' : 'true');
.attr('aria-expanded', isOpen ? 'false' : 'true');
if (isOpen) { wizlordsScrollToCollapsedHeader($card); }
}
}


Line 161: Line 189:
}
}
});
});
}() );
/* Mobile/tablet class category accordions */
( function () {
var classCategoryQuery = window.matchMedia('(max-width: 899px)');
var classCategoryIcons = [
{
selector: '.wizlords-class-category-accordion-martial',
fileName: 'MartialIcon.png'
},
{
selector: '.wizlords-class-category-accordion-arcane',
fileName: 'ArcaneIcon.png'
},
{
selector: '.wizlords-class-category-accordion-divine',
fileName: 'DivineIcon.png'
}
];
function getClassCategoryAccordionIcon(fileName) {
var scriptPath = mw.config.get('wgScriptPath') || '';
return $('<img>')
.attr('src', scriptPath + '/index.php/Special:FilePath/' + encodeURIComponent(fileName))
.attr('alt', '')
.attr('loading', 'lazy')
.attr('decoding', 'async');
}
function initialiseClassCategoryAccordionIcons() {
classCategoryIcons.forEach(function (category) {
$(category.selector).each(function () {
var $icon = $(this).find('.wizlords-class-category-accordion-icon').first();
if ($icon.length && !$icon.children('img').length) {
$icon.empty().append(getClassCategoryAccordionIcon(category.fileName));
}
});
});
}
function initialiseClassCategoryAccordions() {
initialiseClassCategoryAccordionIcons();
$('.wizlords-class-category-accordion').each(function () {
var $accordion = $(this);
var $heading = $accordion.children('.wizlords-class-category-accordion-heading').first();
var isMobileCitizen = classCategoryQuery.matches && $('body').hasClass('skin-citizen');
var isOpen = $accordion.hasClass('is-open');
if (isMobileCitizen) {
$heading
.attr('role', 'button')
.attr('tabindex', '0')
.attr('aria-expanded', isOpen ? 'true' : 'false');
} else {
$accordion.removeClass('is-open');
$heading
.removeAttr('role')
.removeAttr('tabindex')
.removeAttr('aria-expanded');
}
});
}
function toggleClassCategoryAccordion(heading) {
if (!classCategoryQuery.matches || !$('body').hasClass('skin-citizen')) {
return;
}
var $heading = $(heading);
var $accordion = $heading.closest('.wizlords-class-category-accordion');
var isOpen = $accordion.hasClass('is-open');
$accordion.toggleClass('is-open', !isOpen);
$heading.attr('aria-expanded', isOpen ? 'false' : 'true');
}
$(initialiseClassCategoryAccordions);
if (classCategoryQuery.addEventListener) {
classCategoryQuery.addEventListener('change', initialiseClassCategoryAccordions);
} else if (classCategoryQuery.addListener) {
classCategoryQuery.addListener(initialiseClassCategoryAccordions);
}
$(document).on('click', '.wizlords-class-category-accordion-heading', function () {
toggleClassCategoryAccordion(this);
});
$(document).on('keydown', '.wizlords-class-category-accordion-heading', function (event) {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
toggleClassCategoryAccordion(this);
}
});
}() );
/* Mobile/tablet race culture cards */
( function () {
var cultureCardQuery = window.matchMedia('(max-width: 899px)');
function isMobileCitizenCultureLayout() {
return cultureCardQuery.matches && $('body').hasClass('skin-citizen');
}
function initialiseCultureCards() {
var isActive = isMobileCitizenCultureLayout();
$('.wizlords-culture-card').each(function () {
var $card = $(this);
var isOpen = $card.hasClass('is-open');
if (isActive) {
$card
.attr('data-wizlords-mobile-culture-card', '1')
.attr('role', 'button')
.attr('tabindex', '0')
.attr('aria-expanded', isOpen ? 'true' : 'false');
} else {
$card
.removeClass('is-open')
.removeAttr('data-wizlords-mobile-culture-card')
.removeAttr('role')
.removeAttr('tabindex')
.removeAttr('aria-expanded');
}
});
}
function toggleCultureCard(card) {
if (!isMobileCitizenCultureLayout()) {
return;
}
var $card = $(card);
var isOpen = $card.hasClass('is-open');
$card
.toggleClass('is-open', !isOpen)
.attr('aria-expanded', isOpen ? 'false' : 'true');
}
$(initialiseCultureCards);
if (cultureCardQuery.addEventListener) {
cultureCardQuery.addEventListener('change', initialiseCultureCards);
} else if (cultureCardQuery.addListener) {
cultureCardQuery.addListener(initialiseCultureCards);
}
$(document).on('click', '.wizlords-culture-card', function (event) {
var isCultureHeaderLink = $(event.target).closest('.wizlords-culture-card-header a, .wizlords-culture-card-title a').length;
if (isMobileCitizenCultureLayout() && isCultureHeaderLink) {
event.preventDefault();
event.stopPropagation();
toggleCultureCard(this);
return;
}
if ($(event.target).closest('a').length) {
return;
}
toggleCultureCard(this);
});
$(document).on('keydown', '.wizlords-culture-card', function (event) {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
toggleCultureCard(this);
}
});
}() );
/* Responsive race Available Classes lists */
( function () {
function initialiseRaceAvailableClassLists() {
$('.wizlords-culture-classes + ul, .wizlords-shared-classes ul').each(function () {
var $list = $(this);
var itemCount = $list.children('li').length;
var $sharedClasses = $list.closest('.wizlords-shared-classes');
var isDrakelingList = $sharedClasses
.children('.wizlords-shared-classes-title')
.first()
.text()
.indexOf('Drakelings') !== -1;
$list
.removeClass(function (index, className) {
return (className.match(/(^|\s)count-\d+/g) || []).join(' ');
})
.addClass('wizlords-available-classes-list count-' + itemCount)
.toggleClass('is-multicolumn', itemCount > 4)
.toggleClass('is-short', itemCount <= 4)
.toggleClass('is-drakeling-list', isDrakelingList);
$list
.closest('.wizlords-culture-card-body, .wizlords-shared-classes')
.addClass('wizlords-available-classes');
});
}
$(initialiseRaceAvailableClassLists);
}() );
}() );


Line 212: Line 446:
'Summon Greater Arcane Servant': 'Greater Servant'
'Summon Greater Arcane Servant': 'Greater Servant'
};
};
var tabletSpellTitles = {
'Summon Arcane Servant - Attack': 'Arcane Servant – Attack',
'Summon Arcane Servant - Defend': 'Arcane Servant – Defend',
'Summon Minor Arcane Servant - Attack': 'Minor Arcane Servant – Attack',
'Summon Minor Arcane Servant - Defend': 'Minor Arcane Servant – Defend',
'Summon Greater Arcane Servant': 'Greater Arcane Servant'
};
function getMobileSpellTitle(title) {
if (window.matchMedia('(min-width: 600px) and (max-width: 899px)').matches) {
return tabletSpellTitles[title] || title;
}
return mobileSpellTitles[title] || title;
}
function updateMobileSpellTitles() {
$('.wizlords-mobile-spell-card-title[data-wizlords-source-title]').each(function () {
var $title = $(this);
$title.text(getMobileSpellTitle($title.attr('data-wizlords-source-title')));
});
}


function getSpellIcon(iconType) {
function getSpellIcon(iconType) {
Line 237: Line 495:
function buildMobileSpellCard($sourceCard, iconType) {
function buildMobileSpellCard($sourceCard, iconType) {
var title = $.trim($sourceCard.children('.wizlords-spell-card-title').first().text());
var title = $.trim($sourceCard.children('.wizlords-spell-card-title').first().text());
var mobileTitle = mobileSpellTitles[title] || title;
var $card = $('<div>').addClass('wizlords-mobile-spell-card');
var $card = $('<div>').addClass('wizlords-mobile-spell-card');
var $icon = $('<div>').addClass('wizlords-mobile-spell-card-icon').append(getSpellIcon(iconType));
var $icon = $('<div>').addClass('wizlords-mobile-spell-card-icon').append(getSpellIcon(iconType));
var $title = $('<div>').addClass('wizlords-mobile-spell-card-title').text(mobileTitle);
var $title = $('<div>')
.addClass('wizlords-mobile-spell-card-title')
.attr('data-wizlords-source-title', title)
.text(getMobileSpellTitle(title));
var $summary = $('<div>').addClass('wizlords-mobile-spell-card-summary').text(spellSummaries[title] || '');
var $summary = $('<div>').addClass('wizlords-mobile-spell-card-summary').text(spellSummaries[title] || '');
var $rules = $('<div>').addClass('wizlords-mobile-spell-card-rules');
var $rules = $('<div>').addClass('wizlords-mobile-spell-card-rules');
Line 252: Line 512:
.append($title)
.append($title)
.append($summary)
.append($summary)
.append($rules);
}
function buildMobileServantRulesCard($sourceRules) {
var title = $.trim($sourceRules.children('.wizlords-servant-rules-title').first().text());
var $card = $('<div>')
.addClass('wizlords-mobile-servant-rules-card')
.attr('role', 'button')
.attr('tabindex', '0')
.attr('aria-expanded', 'false');
var $title = $('<div>').addClass('wizlords-mobile-servant-rules-title').text(title);
var $rules = $('<div>').addClass('wizlords-mobile-servant-rules-content');
var $content = $sourceRules.children('.mw-collapsible-content').first();
$rules.append($content.children().clone());
return $card
.append($title)
.append($rules);
.append($rules);
}
}
Line 297: Line 575:
$currentCategory.append(buildMobileSpellCard($(this), iconType));
$currentCategory.append(buildMobileSpellCard($(this), iconType));
});
});
}
if ($node.hasClass('wizlords-servant-rules')) {
if (!$currentCategory) {
$currentCategory = $('<div>').addClass('wizlords-mobile-spell-category');
$body.append($currentCategory);
}
$currentCategory
.append($('<div>').addClass('wizlords-mobile-servant-rules-divider'))
.append(buildMobileServantRulesCard($node));
}
}
});
});
$body.append(
$('<div>')
.addClass('wizlords-mobile-spellbook-collapse')
.attr('role', 'button')
.attr('tabindex', '0')
.attr('aria-label', 'Collapse ' + title)
);


return $book;
return $book;
Line 320: Line 617:
function initialiseMobileSpellCards() {
function initialiseMobileSpellCards() {
buildMobileSpellbooks();
buildMobileSpellbooks();
updateMobileSpellTitles();


$('.wizlords-spellbooks-mobile').attr('aria-hidden', spellbookQuery.matches ? 'false' : 'true');
$('.wizlords-spellbooks-mobile').attr('aria-hidden', spellbookQuery.matches ? 'false' : 'true');
Line 331: Line 629:
} else {
} else {
$header.removeAttr('aria-expanded');
$header.removeAttr('aria-expanded');
}
});
$('.wizlords-mobile-spellbook-collapse').each(function () {
var $control = $(this);
var isOpen = $control.closest('.wizlords-mobile-spellbook').hasClass('is-open');
if (spellbookQuery.matches) {
$control.attr('aria-expanded', isOpen ? 'true' : 'false');
} else {
$control.removeAttr('aria-expanded');
}
}
});
});
Line 351: Line 660:
$card
$card
.removeAttr('data-wizlords-mobile-spell-card')
.removeAttr('data-wizlords-mobile-spell-card')
.removeAttr('role')
.removeAttr('tabindex')
.removeAttr('aria-expanded')
.removeClass('is-open');
}
});
$('.wizlords-mobile-servant-rules-card').each(function () {
var $card = $(this);
if (spellbookQuery.matches) {
$card
.attr('role', 'button')
.attr('tabindex', '0');
if (!$card.hasClass('is-open')) {
$card.attr('aria-expanded', 'false');
}
} else {
$card
.removeAttr('role')
.removeAttr('role')
.removeAttr('tabindex')
.removeAttr('tabindex')
Line 370: Line 699:
.toggleClass('is-open', !isOpen)
.toggleClass('is-open', !isOpen)
.attr('aria-expanded', isOpen ? 'false' : 'true');
.attr('aria-expanded', isOpen ? 'false' : 'true');
if (isOpen) { wizlordsScrollToCollapsedHeader($card); }
}
}


Line 382: Line 712:


$book.toggleClass('is-open', !isOpen);
$book.toggleClass('is-open', !isOpen);
$header.attr('aria-expanded', isOpen ? 'false' : 'true');
$book
.find('.wizlords-mobile-spellbook-header, .wizlords-mobile-spellbook-collapse')
.attr('aria-expanded', isOpen ? 'false' : 'true');
}
 
function toggleMobileServantRulesCard(card) {
if (!spellbookQuery.matches) {
return;
}
 
var $card = $(card);
var isOpen = $card.hasClass('is-open');
 
$card
.toggleClass('is-open', !isOpen)
.attr('aria-expanded', isOpen ? 'false' : 'true');
}
}


Line 399: Line 744:


toggleMobileSpellCard(this);
toggleMobileSpellCard(this);
});
$(document).on('click', '.wizlords-mobile-servant-rules-card', function (event) {
if ($(event.target).closest('a').length) {
return;
}
toggleMobileServantRulesCard(this);
});
});


$(document).on('click', '.wizlords-mobile-spellbook-header', function () {
$(document).on('click', '.wizlords-mobile-spellbook-header', function () {
toggleMobileSpellbook(this);
toggleMobileSpellbook(this);
});
$(document).on('click', '.wizlords-mobile-spellbook-collapse', function () {
var $book = $(this).closest('.wizlords-mobile-spellbook');
toggleMobileSpellbook($book.children('.wizlords-mobile-spellbook-header').first());
wizlordsScrollToCollapsedHeader($book);
});
});


Line 409: Line 768:
event.preventDefault();
event.preventDefault();
toggleMobileSpellCard(this);
toggleMobileSpellCard(this);
}
});
$(document).on('keydown', '.wizlords-mobile-servant-rules-card', function (event) {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
toggleMobileServantRulesCard(this);
}
}
});
});
Line 416: Line 782:
event.preventDefault();
event.preventDefault();
toggleMobileSpellbook(this);
toggleMobileSpellbook(this);
}
});
$(document).on('keydown', '.wizlords-mobile-spellbook-collapse', function (event) {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
toggleMobileSpellbook($(this).closest('.wizlords-mobile-spellbook').children('.wizlords-mobile-spellbook-header').first());
}
}
});
});
}() );
}() );
/* Mobile lore profiles reuse MediaWiki's desktop collapse state. */
mw.loader.using('jquery.makeCollapsible').then(function () {
var query = window.matchMedia('(max-width: 599px)');
function prepareLoreProfiles() {
$('.wizlords-lore-profile > .wizlords-collapsible-section-title').each(function () {
var title = $(this);
if (query.matches) {
title.attr({ role: 'button', tabindex: '0',
'aria-expanded': title.parent().hasClass('mw-collapsed') ? 'false' : 'true' });
} else {
title.removeAttr('role tabindex aria-expanded');
}
});
}
$(prepareLoreProfiles);
if (query.addEventListener) { query.addEventListener('change', prepareLoreProfiles); }
$(document).on('click', '.wizlords-lore-profile > .wizlords-collapsible-section-title, .wizlords-lore-profile > .wizlords-lore-profile-mobile-icon', function () {
if (!query.matches) { return; }
var $profile = $(this).parent();
var wasOpen = !$profile.hasClass('mw-collapsed');
$profile.children('.mw-collapsible-toggle').first().trigger('click');
prepareLoreProfiles();
if (wasOpen) { wizlordsScrollToCollapsedHeader($profile); }
});
$(document).on('keydown', '.wizlords-lore-profile > .wizlords-collapsible-section-title, .wizlords-lore-profile > .wizlords-lore-profile-mobile-icon', function (event) {
if (query.matches && (event.key === 'Enter' || event.key === ' ')) {
event.preventDefault();
$(this).trigger('click');
}
});
});
$(document).on('keydown', '.wizlords-lore-collapse', function (event) {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
$(this).trigger('click');
}
});