MediaWiki:Common.js: Difference between revisions
MediaWiki interface page
More actions
No edit summary |
No edit summary |
||
| (17 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 $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( | 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 357: | 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 438: | 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 497: | Line 759: | ||
$(document).on('click', '.wizlords-mobile-spellbook-collapse', function () { | $(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 528: | Line 792: | ||
}); | }); | ||
}() ); | }() ); | ||
/* 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'); | |||
} | |||
}); | |||