WikiPartner (talk | contribs) Edited MediaWiki:Common.js |
WikiPartner (talk | contribs) Add WikiPartner styled upload dropdowns |
||
| (24 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
/* | /* ============================================================ | ||
WIKIPARTNER | |||
THEME + USER MENU | |||
============================================================ */ | |||
========================================================= */ | |||
(function () { | (function () { | ||
'use strict'; | 'use strict'; | ||
var | var STORAGE_KEY = 'wikipartner-theme'; | ||
var | var LIGHT = 'light'; | ||
var DARK = 'dark'; | |||
/* ======================================================== | |||
THEME STORAGE | |||
======================================================== */ | |||
function getSavedTheme() { | |||
try { | |||
var saved = window.localStorage.getItem( | |||
STORAGE_KEY | |||
); | |||
if ( | if ( | ||
saved === LIGHT || | |||
saved === DARK | |||
) { | ) { | ||
return | return saved; | ||
} | } | ||
} catch (e) { | |||
/* localStorage unavailable */ | |||
} | } | ||
return | return LIGHT; | ||
} | } | ||
function saveTheme(theme) { | |||
try { | |||
window.localStorage.setItem( | |||
STORAGE_KEY, | |||
theme | |||
); | |||
} catch (e) { | |||
/* localStorage unavailable */ | |||
} | |||
} | |||
/* ======================================================== | |||
CURRENT THEME | |||
======================================================== */ | |||
function getCurrentTheme() { | |||
return document.documentElement | |||
.classList.contains( | |||
'wp-theme-dark' | |||
) | |||
? DARK | |||
: LIGHT; | |||
} | |||
/* ======================================================== | |||
APPLY THEME | |||
======================================================== */ | |||
function applyTheme(theme, shouldSave) { | |||
var html = | |||
document.documentElement; | |||
var isDark = | |||
theme === DARK; | |||
html.classList.toggle( | |||
'wp-theme-dark', | |||
isDark | |||
); | |||
html.classList.toggle( | |||
'wp-theme-light', | |||
!isDark | |||
); | |||
/* | |||
* Keep MediaWiki-compatible theme classes too. | |||
*/ | |||
html.classList.remove( | html.classList.remove( | ||
'skin-theme-clientpref-day', | 'skin-theme-clientpref-day', | ||
| Line 39: | Line 94: | ||
); | ); | ||
html.classList.add( | |||
isDark | |||
? 'skin-theme-clientpref-night' | |||
: 'skin-theme-clientpref-day' | |||
); | |||
html.setAttribute( | |||
'data-wikipartner-theme', | |||
isDark | |||
? DARK | |||
: LIGHT | |||
); | |||
if (shouldSave !== false) { | |||
saveTheme(theme); | |||
} | } | ||
updateThemeButton(); | |||
} | } | ||
function | |||
return | /* ======================================================== | ||
'<svg viewBox="0 0 24 24" aria-hidden="true">' | THEME ICONS | ||
'<path d="M20. | ======================================================== */ | ||
'<path class="wp-theme-star" d="M17.5 | |||
'</svg>'; | function getMoonIcon() { | ||
return [ | |||
'<svg viewBox="0 0 24 24" aria-hidden="true">', | |||
'<path d="M20.3 15.2A8.4 8.4 0 0 1 8.8 3.7 8.5 8.5 0 1 0 11.5 11.5Z"></path>', | |||
'<path class="wp-theme-star" d="M17.5 4v3M16 5.5h3"></path>', | |||
'</svg>' | |||
].join(''); | |||
} | } | ||
function | |||
return | function getSunIcon() { | ||
'<svg viewBox="0 0 24 24" aria-hidden="true">' | return [ | ||
'<circle cx="12" cy="12" r=" | '<svg viewBox="0 0 24 24" aria-hidden="true">', | ||
'<path d="M12 | |||
'</svg>'; | '<circle cx="12" cy="12" r="3.8"></circle>', | ||
'<path d="M12 2.3v2.1"></path>', | |||
'<path d="M12 19.6v2.1"></path>', | |||
'<path d="M4.93 4.93l1.5 1.5"></path>', | |||
'<path d="M17.57 17.57l1.5 1.5"></path>', | |||
'<path d="M2.3 12h2.1"></path>', | |||
'<path d="M19.6 12h2.1"></path>', | |||
'<path d="M4.93 19.07l1.5-1.5"></path>', | |||
'<path d="M17.57 6.43l1.5-1.5"></path>', | |||
'</svg>' | |||
].join(''); | |||
} | } | ||
function | |||
var theme | /* ======================================================== | ||
var isDark = | UPDATE THEME BUTTON | ||
======================================================== */ | |||
function updateThemeButton() { | |||
var button = | |||
document.getElementById( | |||
'wikipartner-theme-toggle' | |||
); | |||
if (!button) { | |||
return; | |||
} | |||
var isDark = | |||
getCurrentTheme() === DARK; | |||
button.innerHTML = | button.innerHTML = | ||
'<span class="wp-theme-icon">' + | '<span class="wp-theme-icon">' + | ||
(isDark ? | ( | ||
isDark | |||
? getSunIcon() | |||
: getMoonIcon() | |||
) + | |||
'</span>'; | '</span>'; | ||
button.setAttribute( | button.setAttribute( | ||
'aria-label', | 'aria-label', | ||
isDark ? 'Switch to light mode' : 'Switch to dark mode' | isDark | ||
? 'Switch to light mode' | |||
: 'Switch to dark mode' | |||
); | ); | ||
button.setAttribute( | button.setAttribute( | ||
'title', | 'title', | ||
isDark ? 'Light mode' : 'Dark mode' | isDark | ||
? 'Light mode' | |||
: 'Dark mode' | |||
); | |||
} | |||
/* ======================================================== | |||
CREATE THEME BUTTON | |||
======================================================== */ | |||
function createThemeToggle(list) { | |||
var existing = | |||
document.getElementById( | |||
'wikipartner-theme-item' | |||
); | |||
if (existing) { | |||
return existing; | |||
} | |||
var item = | |||
document.createElement('li'); | |||
item.id = | |||
'wikipartner-theme-item'; | |||
item.className = | |||
'mw-list-item ' + | |||
'wikipartner-theme-item'; | |||
var button = | |||
document.createElement( | |||
'button' | |||
); | |||
button.id = | |||
'wikipartner-theme-toggle'; | |||
button.className = | |||
'wikipartner-theme-toggle'; | |||
button.type = | |||
'button'; | |||
button.addEventListener( | |||
'click', | |||
function () { | |||
var nextTheme = | |||
getCurrentTheme() === DARK | |||
? LIGHT | |||
: DARK; | |||
applyTheme( | |||
nextTheme, | |||
true | |||
); | |||
} | |||
); | ); | ||
item.appendChild( | |||
button | |||
); | |||
updateThemeButton(); | |||
return item; | |||
} | } | ||
function | |||
/* ======================================================== | |||
HAMBURGER ICON | |||
======================================================== */ | |||
function getMenuIcon() { | |||
return [ | |||
'<span class="wp-menu-bars" aria-hidden="true">', | |||
'<span></span>', | |||
'<span></span>', | |||
'<span></span>', | |||
'</span>' | |||
].join(''); | |||
} | |||
/* ======================================================== | |||
FIND / CLEAN USERNAME | |||
======================================================== */ | |||
function cleanUsernameDuplicates( | |||
primary, | |||
list | |||
) { | |||
var username = | |||
mw.config.get( | |||
'wgUserName' | |||
); | |||
if (!username) { | |||
return; | return; | ||
} | } | ||
/* | /* | ||
* | * MediaWiki's data-user-page already puts | ||
* the username in .wp-user-primary. | |||
* | |||
* Some personal-menu configurations can | |||
* also provide another user-page link. | |||
* Remove that duplicate from the menu. | |||
*/ | */ | ||
var items = | |||
Array.prototype.slice.call( | |||
list.children | |||
); | |||
items.forEach( | |||
function (item) { | |||
var link = | |||
item.querySelector('a'); | |||
var linkText = | |||
link | |||
? link.textContent.trim() | |||
: ''; | |||
var isUserPageId = | |||
item.id === 'pt-userpage' || | |||
item.id === 'pt-userpage-2'; | |||
var isUsername = | |||
linkText === username; | |||
if ( | |||
isUserPageId || | |||
isUsername | |||
) { | |||
/* | |||
* If primary somehow has no username, | |||
* move this one there instead. | |||
*/ | |||
if ( | |||
primary && | |||
!primary.querySelector('li') | |||
) { | |||
primary.appendChild( | |||
item | |||
); | |||
} else { | |||
item.remove(); | |||
} | |||
} | |||
} | |||
); | |||
} | |||
/* ======================================================== | |||
LOGGED OUT LAYOUT | |||
======================================================== */ | |||
function buildLoggedOutLayout( | |||
list, | |||
themeItem | |||
) { | |||
list.classList.remove( | |||
'wp-is-logged-in' | |||
); | |||
list.classList.add( | |||
'wp-is-logged-out' | |||
); | |||
/* | |||
* Desired layout: | |||
* | |||
* Theme | Create account | Log in | |||
*/ | |||
var firstItem = | |||
list.firstElementChild; | |||
if (firstItem) { | |||
list.insertBefore( | |||
themeItem, | |||
firstItem | |||
); | |||
} else { | |||
list.appendChild( | |||
themeItem | |||
); | |||
} | |||
} | |||
/* ======================================================== | |||
LOGGED IN LAYOUT | |||
======================================================== */ | |||
function buildLoggedInLayout( | |||
primary, | |||
list, | |||
themeItem | |||
) { | |||
list.classList.remove( | |||
'wp-is-logged-out' | |||
); | |||
list.classList.add( | |||
'wp-is-logged-in' | |||
); | |||
cleanUsernameDuplicates( | |||
primary, | |||
list | |||
); | |||
/* | |||
* Remove an old dropdown if ResourceLoader | |||
* initialization somehow runs again. | |||
*/ | |||
var oldDropdown = | |||
list.querySelector( | |||
'.wp-user-dropdown' | |||
); | |||
if (oldDropdown) { | |||
return; | |||
} | |||
/* ==================================================== | |||
CREATE HAMBURGER WRAPPER | |||
==================================================== */ | |||
var dropdown = | |||
document.createElement('li'); | |||
dropdown.className = | |||
'wp-user-dropdown'; | |||
/* ==================================================== | |||
HAMBURGER BUTTON | |||
==================================================== */ | |||
var trigger = | |||
document.createElement( | |||
'button' | |||
); | |||
trigger.type = | |||
'button'; | |||
trigger.className = | |||
'wp-user-menu-trigger'; | |||
trigger.setAttribute( | |||
'aria-label', | |||
'Open user menu' | |||
); | |||
trigger.setAttribute( | |||
'title', | |||
'User menu' | |||
); | |||
trigger.setAttribute( | |||
'aria-expanded', | |||
'false' | |||
); | |||
trigger.innerHTML = | |||
getMenuIcon(); | |||
/* ==================================================== | |||
DROPDOWN CONTENT | |||
==================================================== */ | |||
var menu = | |||
document.createElement('ul'); | |||
menu.className = | |||
'wp-user-dropdown-menu'; | |||
menu.hidden = | |||
true; | |||
/* | |||
* Move every existing menu item | |||
* into ☰. | |||
* | |||
* Username is NOT in this list anymore. | |||
* Theme is not inserted yet. | |||
*/ | |||
Array.prototype | |||
.slice.call( | |||
list.children | |||
) | |||
.forEach( | |||
function (item) { | |||
if ( | |||
item !== themeItem && | |||
item !== dropdown | |||
) { | |||
menu.appendChild( | |||
item | |||
); | |||
} | |||
} | |||
); | |||
dropdown.appendChild( | |||
trigger | |||
); | |||
dropdown.appendChild( | |||
menu | |||
); | |||
/* | |||
* Exact layout: | |||
* | |||
* Username | Theme | ☰ | |||
* | |||
* Username lives in .wp-user-primary, | |||
* while theme and hamburger live here. | |||
*/ | |||
list.appendChild( | |||
themeItem | |||
); | |||
list.appendChild( | |||
dropdown | |||
); | |||
/* ==================================================== | |||
OPEN / CLOSE | |||
==================================================== */ | |||
function closeMenu() { | |||
dropdown.classList.remove( | |||
'is-open' | |||
); | |||
menu.hidden = | |||
true; | |||
trigger.setAttribute( | |||
'aria-expanded', | |||
'false' | |||
); | |||
} | |||
function openMenu() { | |||
dropdown.classList.add( | |||
'is-open' | |||
); | |||
menu.hidden = | |||
false; | |||
trigger.setAttribute( | |||
'aria-expanded', | |||
'true' | |||
); | |||
} | |||
/* ==================================================== | |||
CLICK HAMBURGER | |||
==================================================== */ | |||
trigger.addEventListener( | |||
'click', | |||
function (event) { | |||
event.preventDefault(); | |||
event.stopPropagation(); | |||
if ( | |||
dropdown.classList.contains( | |||
'is-open' | |||
) | |||
) { | |||
closeMenu(); | |||
} else { | |||
openMenu(); | |||
} | |||
} | |||
); | |||
/* ==================================================== | |||
CLICK INSIDE MENU | |||
==================================================== */ | |||
menu.addEventListener( | |||
'click', | |||
function (event) { | |||
event.stopPropagation(); | |||
} | |||
); | |||
/* ==================================================== | |||
CLICK OUTSIDE | |||
==================================================== */ | |||
document.addEventListener( | |||
'click', | |||
function (event) { | |||
if ( | |||
!dropdown.contains( | |||
event.target | |||
) | |||
) { | |||
closeMenu(); | |||
} | |||
} | |||
); | |||
/* ==================================================== | |||
ESCAPE | |||
==================================================== */ | |||
document.addEventListener( | |||
'keydown', | |||
function (event) { | |||
if ( | |||
event.key === 'Escape' && | |||
dropdown.classList.contains( | |||
'is-open' | |||
) | |||
) { | |||
closeMenu(); | |||
trigger.focus(); | |||
} | |||
} | |||
); | |||
} | |||
/* ======================================================== | |||
INITIALIZE ACCOUNT AREA | |||
======================================================== */ | |||
function initializeUserArea() { | |||
var primary = | |||
document.querySelector( | |||
'.wp-user-primary' | |||
); | |||
var list = | |||
document.querySelector( | |||
'.wp-user-menu-list' | |||
); | |||
if (!list) { | if (!list) { | ||
return; | |||
} | |||
' | |||
/* | |||
* Empty username container should not | |||
* take up space for anonymous users. | |||
*/ | |||
if ( | |||
primary && | |||
!primary.querySelector('li') | |||
) { | |||
primary.classList.add( | |||
'is-empty' | |||
); | ); | ||
} | } | ||
if (! | |||
var themeItem = | |||
createThemeToggle( | |||
list | |||
); | |||
var username = | |||
mw.config.get( | |||
'wgUserName' | |||
); | |||
if (username) { | |||
buildLoggedInLayout( | |||
primary, | |||
list, | |||
themeItem | |||
); | |||
} else { | |||
buildLoggedOutLayout( | |||
list, | |||
themeItem | |||
); | |||
} | |||
updateThemeButton(); | |||
} | |||
/* ======================================================== | |||
APPLY SAVED THEME | |||
======================================================== */ | |||
applyTheme( | |||
getSavedTheme(), | |||
false | |||
); | |||
/* ======================================================== | |||
START | |||
======================================================== */ | |||
function initialize() { | |||
initializeUserArea(); | |||
} | |||
if ( | |||
document.readyState === | |||
'loading' | |||
) { | |||
document.addEventListener( | |||
'DOMContentLoaded', | |||
initialize | |||
); | |||
} else { | |||
initialize(); | |||
} | |||
})(); | |||
/* ============================================================ | |||
WIKIPARTNER | |||
ARTICLE CONTENTS MENU | |||
============================================================ */ | |||
(function () { | |||
'use strict'; | |||
function initializeArticleContents() { | |||
var toc = document.getElementById('wp-toc'); | |||
var article = document.querySelector( | |||
'.wp-article-body' | |||
); | |||
var sidebarContentsLink = document.getElementById( | |||
'wp-sidebar-contents-link' | |||
); | |||
if (!toc || !article) { | |||
if (sidebarContentsLink) { | |||
sidebarContentsLink.hidden = true; | |||
} | |||
return; | return; | ||
} | } | ||
var | var linksContainer = toc.querySelector( | ||
'.wp-toc-links' | |||
); | |||
if (!linksContainer) { | |||
if (sidebarContentsLink) { | |||
sidebarContentsLink.hidden = true; | |||
} | |||
return; | |||
} | |||
/* ==================================================== | |||
FIND ACTUAL ARTICLE HEADINGS | |||
==================================================== */ | |||
var headings = Array.prototype.slice.call( | |||
article.querySelectorAll( | |||
'h2, h3, h4, h5, h6' | |||
) | |||
); | |||
/* | /* | ||
* | * Keep only real headings with visible text. | ||
*/ | */ | ||
headings = headings.filter( | |||
function (heading) { | |||
var text = | |||
heading.textContent | |||
.replace(/\[edit\]/gi, '') | |||
.trim(); | |||
return text.length > 0; | |||
} | |||
); | |||
/* ==================================================== | |||
NO HEADINGS | |||
HIDE BOTH CONTENTS CONTROLS | |||
==================================================== */ | |||
if (!headings.length) { | |||
toc.classList.remove( | |||
'wp-toc-ready' | |||
); | |||
toc.open = false; | |||
if (sidebarContentsLink) { | |||
sidebarContentsLink.hidden = true; | |||
} | |||
return; | |||
} | } | ||
/* ==================================================== | |||
CLEAR OLD CONTENTS | |||
==================================================== */ | |||
linksContainer.innerHTML = ''; | |||
/* | /* | ||
* | * Hide the old hard-coded "Contents" heading | ||
* | * if it exists in the Mustache template. | ||
*/ | */ | ||
var oldHeading = toc.querySelector( | |||
'.wp-toc-heading' | |||
); | |||
if (oldHeading) { | |||
oldHeading.style.display = 'none'; | |||
} | |||
/* ==================================================== | |||
BUILD LINKS FROM ARTICLE HEADINGS | |||
==================================================== */ | |||
headings.forEach( | |||
function (heading, index) { | |||
/* | |||
* MediaWiki normally gives headings an ID. | |||
* If one does not exist, create a safe fallback. | |||
*/ | |||
if (!heading.id) { | |||
heading.id = | |||
'wikipartner-section-' + | |||
(index + 1); | |||
} | |||
var level = parseInt( | |||
heading.tagName.substring(1), | |||
10 | |||
); | |||
var headingText = | |||
heading.textContent | |||
.replace(/\[edit\]/gi, '') | |||
.trim(); | |||
var link = | |||
document.createElement('a'); | |||
link.href = | |||
'#' + heading.id; | |||
link.className = | |||
'wp-toc-level-' + | |||
level; | |||
link.textContent = | |||
headingText; | |||
/* | |||
* Close the dropdown after | |||
* selecting a heading. | |||
*/ | |||
link.addEventListener( | |||
'click', | |||
function () { | |||
toc.open = false; | |||
} | |||
); | |||
linksContainer.appendChild( | |||
link | |||
); | |||
} | |||
); | |||
/* ==================================================== | |||
HEADINGS FOUND | |||
SHOW BOTH CONTENTS CONTROLS | |||
==================================================== */ | |||
toc.classList.add( | |||
'wp-toc-ready' | |||
); | |||
if (sidebarContentsLink) { | |||
sidebarContentsLink.hidden = false; | |||
sidebarContentsLink.addEventListener( | |||
'click', | |||
function (event) { | |||
event.preventDefault(); | |||
toc.open = true; | |||
toc.scrollIntoView({ | |||
behavior: 'smooth', | |||
block: 'center' | |||
}); | |||
} | |||
); | |||
} | |||
} | } | ||
if (document.readyState === 'loading') { | if (document.readyState === 'loading') { | ||
document.addEventListener('DOMContentLoaded', | |||
document.addEventListener( | |||
'DOMContentLoaded', | |||
initializeArticleContents | |||
); | |||
} else { | |||
initializeArticleContents(); | |||
} | |||
})(); | |||
/* ============================================================ | |||
WIKIPARTNER | |||
WHAT LINKS HERE — CURRENT PAGE URL | |||
============================================================ */ | |||
(function () { | |||
'use strict'; | |||
function initializeWhatLinksHere() { | |||
var link = document.getElementById( | |||
'wp-what-links-here' | |||
); | |||
if (!link) { | |||
return; | |||
} | |||
var pageName = mw.config.get( | |||
'wgPageName' | |||
); | |||
if (!pageName) { | |||
return; | |||
} | |||
mw.loader.using( | |||
'mediawiki.util' | |||
).then( | |||
function () { | |||
link.href = mw.util.getUrl( | |||
'Special:WhatLinksHere/' + pageName | |||
); | |||
} | |||
); | |||
} | |||
if (document.readyState === 'loading') { | |||
document.addEventListener( | |||
'DOMContentLoaded', | |||
initializeWhatLinksHere | |||
); | |||
} else { | |||
initializeWhatLinksHere(); | |||
} | |||
})(); | |||
/* ============================================================ | |||
WIKIPARTNER | |||
ARTICLE SUGGESTION — REVIEWER CONTROL | |||
============================================================ */ | |||
(function () { | |||
'use strict'; | |||
function initializeSuggestionReviewerControl() { | |||
var control = document.getElementById( | |||
'wp-review-suggestion-control' | |||
); | |||
if (!control) { | |||
return; | |||
} | |||
var groups = mw.config.get( | |||
'wgUserGroups' | |||
) || []; | |||
var isReviewer = | |||
groups.indexOf('reviewer') !== -1; | |||
if (isReviewer) { | |||
control.style.display = ''; | |||
} | |||
} | |||
if (document.readyState === 'loading') { | |||
document.addEventListener( | |||
'DOMContentLoaded', | |||
initializeSuggestionReviewerControl | |||
); | |||
} else { | |||
initializeSuggestionReviewerControl(); | |||
} | |||
})(); | |||
/* ============================================================ | |||
WIKIPARTNER | |||
ISSUE REPORT — REVIEWER CONTROL | |||
============================================================ */ | |||
(function () { | |||
'use strict'; | |||
function initializeIssueReviewerControl() { | |||
var control = document.getElementById( | |||
'wp-review-issue-control' | |||
); | |||
if (!control) { | |||
return; | |||
} | |||
var groups = mw.config.get( | |||
'wgUserGroups' | |||
) || []; | |||
var isReviewer = | |||
groups.indexOf('reviewer') !== -1; | |||
if (isReviewer) { | |||
control.style.display = ''; | |||
} | |||
} | |||
if (document.readyState === 'loading') { | |||
document.addEventListener( | |||
'DOMContentLoaded', | |||
initializeIssueReviewerControl | |||
); | |||
} else { | |||
initializeIssueReviewerControl(); | |||
} | |||
})(); | |||
/* ============================================================ | |||
WIKIPARTNER — CREATE DRAFT | |||
Send the Create draft form directly to Draft: source editor. | |||
============================================================ */ | |||
mw.loader.using( 'mediawiki.util' ).then( function () { | |||
if ( mw.config.get( 'wgPageName' ) !== 'WikiPartner:Create_a_draft' ) { | |||
return; | |||
} | |||
var form = document.getElementById( 'wp-create-draft-form' ); | |||
if ( !form ) { | |||
return; | |||
} | |||
form.addEventListener( 'submit', function ( event ) { | |||
var input = form.querySelector( 'input[name="title"]' ); | |||
if ( !input ) { | |||
return; | |||
} | |||
var title = input.value.trim(); | |||
if ( !title ) { | |||
event.preventDefault(); | |||
input.focus(); | |||
return; | |||
} | |||
/* | |||
* Prevent Draft:Draft:Article if somebody manually | |||
* enters the namespace. | |||
*/ | |||
title = title.replace( /^Draft\s*:\s*/i, '' ).trim(); | |||
if ( !title ) { | |||
event.preventDefault(); | |||
input.focus(); | |||
return; | |||
} | |||
event.preventDefault(); | |||
var draftTitle = | |||
'Draft:' + | |||
title.replace( /\s+/g, '_' ); | |||
var url = | |||
mw.config.get( 'wgScript' ) + | |||
'?title=' + | |||
encodeURIComponent( draftTitle ) + | |||
'&action=edit'; | |||
window.location.assign( url ); | |||
} ); | |||
} ); | |||
/* ============================================================ | |||
WIKIPARTNER — MOVED / DELETED PAGE STATES | |||
============================================================ */ | |||
$( function () { | |||
if ( mw.config.get( 'wgAction' ) !== 'view' ) { | |||
return; | |||
} | |||
var content = | |||
document.getElementById( 'mw-content-text' ); | |||
if ( !content ) { | |||
return; | |||
} | |||
var logBox = | |||
content.querySelector( | |||
'.mw-warning-with-logexcerpt' | |||
); | |||
var noArticle = | |||
content.querySelector( | |||
'.noarticletext' | |||
); | |||
if ( !logBox || !noArticle ) { | |||
return; | |||
} | |||
var moveLine = | |||
logBox.querySelector( | |||
'.mw-logline-move' | |||
); | |||
var deleteLine = | |||
logBox.querySelector( | |||
'[class*="mw-logline-delete"]' | |||
); | |||
var type = 'history'; | |||
if ( moveLine ) { | |||
type = 'moved'; | |||
} else if ( deleteLine ) { | |||
type = 'deleted'; | |||
} | |||
document.body.classList.add( | |||
'wp-historical-missing-page', | |||
'wp-page-' + type | |||
); | |||
var messageContent = | |||
logBox.querySelector( | |||
'.cdx-message__content' | |||
) || logBox; | |||
var inner = | |||
messageContent.querySelector( | |||
'.mw-content-ltr' | |||
) || messageContent; | |||
if ( | |||
inner.querySelector( | |||
'.wp-history-status' | |||
) | |||
) { | |||
return; | |||
} | |||
var originalIntro = | |||
inner.querySelector( 'p' ); | |||
if ( originalIntro ) { | |||
originalIntro.classList.add( | |||
'wp-history-original-intro' | |||
); | |||
} | |||
var status = | |||
document.createElement( 'div' ); | |||
status.className = | |||
'wp-history-status'; | |||
var label = | |||
document.createElement( 'div' ); | |||
label.className = | |||
'wp-history-label'; | |||
label.textContent = | |||
'PAGE STATUS'; | |||
var title = | |||
document.createElement( 'div' ); | |||
title.className = | |||
'wp-history-title'; | |||
var description = | |||
document.createElement( 'div' ); | |||
description.className = | |||
'wp-history-description'; | |||
if ( type === 'moved' ) { | |||
title.textContent = | |||
'This page has moved'; | |||
description.textContent = | |||
'This page now exists under a different title. The move record is shown below.'; | |||
} else if ( type === 'deleted' ) { | |||
title.textContent = | |||
'This page was deleted'; | |||
description.textContent = | |||
'This title does not currently contain a WikiPartner page. The deletion record is shown below for reference.'; | |||
} else { | } else { | ||
title.textContent = | |||
'This page is no longer available'; | |||
description.textContent = | |||
'This title has a recent deletion or move record. Details are shown below.'; | |||
} | } | ||
status.append( | |||
label, | |||
title, | |||
description | |||
); | |||
if ( moveLine ) { | |||
var links = | |||
Array.prototype.slice.call( | |||
moveLine.querySelectorAll( 'a' ) | |||
); | |||
var sourceIndex = | |||
links.findIndex( | |||
function ( link ) { | |||
return link.classList.contains( 'new' ); | |||
} | |||
); | |||
var targetLink = null; | |||
if ( | |||
sourceIndex !== -1 && | |||
links[ sourceIndex + 1 ] | |||
) { | |||
targetLink = | |||
links[ sourceIndex + 1 ]; | |||
} | |||
if ( | |||
targetLink && | |||
targetLink.href | |||
) { | |||
var currentButton = | |||
document.createElement( 'a' ); | |||
currentButton.className = | |||
'wp-history-current-button'; | |||
currentButton.href = | |||
targetLink.href; | |||
currentButton.textContent = | |||
'View current page'; | |||
status.appendChild( | |||
currentButton | |||
); | |||
} | |||
} | |||
if ( type === 'deleted' ) { | |||
var logLink = | |||
logBox.querySelector( | |||
'a[title="Special:Log"]' | |||
); | |||
if ( logLink ) { | |||
var historyButton = | |||
document.createElement( 'a' ); | |||
historyButton.className = | |||
'wp-history-log-button'; | |||
historyButton.href = | |||
logLink.href; | |||
historyButton.textContent = | |||
'View log entry'; | |||
status.appendChild( | |||
historyButton | |||
); | |||
} | |||
} | |||
inner.insertBefore( | |||
status, | |||
inner.firstChild | |||
); | |||
} ); | |||
/* ============================================================ | |||
WIKIPARTNER — DRAFT RECREATE WARNING | |||
============================================================ */ | |||
$( function () { | |||
if ( | |||
Number( mw.config.get( 'wgNamespaceNumber' ) ) !== 3000 || | |||
mw.config.get( 'wgAction' ) !== 'edit' || | |||
mw.config.get( 'wgArticleId' ) | |||
) { | |||
return; | |||
} | |||
var warning = | |||
document.querySelector( | |||
'.mw-warning-with-logexcerpt, .cdx-message--warning' | |||
); | |||
if ( !warning ) { | |||
return; | |||
} | |||
var moveLine = | |||
warning.querySelector( '.mw-logline-move' ); | |||
var deleteLine = | |||
warning.querySelector( | |||
'[class*="mw-logline-delete"]' | |||
); | |||
if ( !moveLine && !deleteLine ) { | |||
return; | |||
} | |||
document.body.classList.add( | |||
'wp-draft-recreate-page' | |||
); | |||
var content = | |||
warning.querySelector( | |||
'.cdx-message__content' | |||
) || warning; | |||
var inner = | |||
content.querySelector( | |||
'.mw-content-ltr' | |||
) || content; | |||
var paragraphs = | |||
Array.prototype.slice.call( | |||
inner.querySelectorAll( ':scope > p' ) | |||
); | |||
if ( paragraphs[ 0 ] ) { | |||
paragraphs[ 0 ].innerHTML = | |||
'<span class="wp-recreate-label">Notice</span>' + | |||
'<strong class="wp-recreate-title">' + | |||
( | |||
moveLine | |||
? 'This draft was previously moved' | |||
: 'This draft was previously deleted' | |||
) + | |||
'</strong>'; | |||
} | |||
if ( paragraphs[ 1 ] ) { | |||
paragraphs[ 1 ].textContent = | |||
moveLine | |||
? 'Check the move record below before recreating this draft.' | |||
: 'Check the deletion record below before recreating this draft.'; | |||
paragraphs[ 1 ].classList.add( | |||
'wp-recreate-description' | |||
); | |||
} | |||
} ); | |||
/* ============================================================ | |||
WIKIPARTNER — PAGE TOOL MENUS | |||
Draft tools + Admin tools | |||
============================================================ */ | |||
mw.loader.using( [ | |||
'mediawiki.api', | |||
'mediawiki.util' | |||
] ).then( function () { | |||
$( function () { | |||
var namespace = | |||
Number( mw.config.get( 'wgNamespaceNumber' ) ); | |||
var articleId = | |||
Number( mw.config.get( 'wgArticleId' ) || 0 ); | |||
var action = | |||
mw.config.get( 'wgAction' ); | |||
var pageName = | |||
mw.config.get( 'wgPageName' ); | |||
var pageTitle = | |||
mw.config.get( 'wgTitle' ); | |||
var groups = | |||
mw.config.get( 'wgUserGroups' ) || []; | |||
/* ---------------------------------------------------- | |||
PERMISSION GROUPS | |||
Later we can add: | |||
'reviewer' | |||
'editor' | |||
without rebuilding Draft tools. | |||
---------------------------------------------------- */ | |||
var draftToolGroups = [ | |||
'sysop' | |||
]; | |||
var adminToolGroups = [ | |||
'sysop' | |||
]; | |||
function userHasGroup( allowedGroups ) { | |||
return allowedGroups.some( | |||
function ( group ) { | |||
return groups.indexOf( group ) !== -1; | |||
} | |||
); | |||
} | |||
var canUseDraftTools = | |||
userHasGroup( draftToolGroups ); | |||
var canUseAdminTools = | |||
userHasGroup( adminToolGroups ); | |||
/* | |||
* Existing pages in normal view only. | |||
*/ | |||
if ( | |||
action !== 'view' || | |||
!articleId || | |||
namespace === -1 | |||
) { | |||
return; | |||
} | |||
var heading = | |||
document.querySelector( | |||
'.wp-article-header .firstHeading, .firstHeading, #firstHeading' | |||
); | |||
if ( !heading ) { | |||
return; | |||
} | |||
var header = | |||
heading.closest( '.wp-article-header' ) || | |||
heading.parentElement; | |||
if ( !header ) { | |||
return; | |||
} | |||
/* ---------------------------------------------------- | |||
SHARED ACTION AREA | |||
---------------------------------------------------- */ | |||
var actions = | |||
document.createElement( 'div' ); | |||
actions.className = | |||
'wp-title-tools'; | |||
header.appendChild( actions ); | |||
/* ==================================================== | |||
SHARED DROPDOWN FUNCTION | |||
==================================================== */ | |||
function createToolMenu( | |||
className, | |||
label | |||
) { | |||
var wrapper = | |||
document.createElement( 'div' ); | |||
wrapper.className = | |||
'wp-tool-menu ' + className; | |||
var trigger = | |||
document.createElement( 'button' ); | |||
trigger.type = | |||
'button'; | |||
trigger.className = | |||
'wp-tool-menu-trigger'; | |||
trigger.setAttribute( | |||
'aria-expanded', | |||
'false' | |||
); | |||
trigger.setAttribute( | |||
'aria-haspopup', | |||
'true' | |||
); | |||
var triggerText = | |||
document.createElement( 'span' ); | |||
triggerText.textContent = | |||
label; | |||
var arrow = | |||
document.createElement( 'span' ); | |||
arrow.className = | |||
'wp-tool-menu-arrow'; | |||
arrow.setAttribute( | |||
'aria-hidden', | |||
'true' | |||
); | |||
arrow.textContent = | |||
'▾'; | |||
trigger.append( | |||
triggerText, | |||
arrow | |||
); | |||
var menu = | |||
document.createElement( 'div' ); | |||
menu.className = | |||
'wp-tool-menu-dropdown'; | |||
menu.hidden = true; | |||
wrapper.append( | |||
trigger, | |||
menu | |||
); | |||
trigger.addEventListener( | |||
'click', | |||
function ( event ) { | |||
event.stopPropagation(); | |||
/* | |||
* Close every other menu first. | |||
*/ | |||
document | |||
.querySelectorAll( | |||
'.wp-tool-menu-dropdown' | |||
) | |||
.forEach( | |||
function ( otherMenu ) { | |||
if ( otherMenu !== menu ) { | |||
otherMenu.hidden = true; | |||
var otherTrigger = | |||
otherMenu | |||
.parentElement | |||
.querySelector( | |||
'.wp-tool-menu-trigger' | |||
); | |||
if ( otherTrigger ) { | |||
otherTrigger.setAttribute( | |||
'aria-expanded', | |||
'false' | |||
); | |||
} | |||
} | |||
} | |||
); | |||
var opening = | |||
menu.hidden; | |||
menu.hidden = | |||
!opening; | |||
trigger.setAttribute( | |||
'aria-expanded', | |||
opening ? 'true' : 'false' | |||
); | |||
} | |||
); | |||
return { | |||
wrapper: wrapper, | |||
trigger: trigger, | |||
menu: menu | |||
}; | |||
} | |||
/* ==================================================== | |||
DRAFT TOOLS | |||
==================================================== */ | |||
if ( | |||
namespace === 3000 && | |||
canUseDraftTools | |||
) { | |||
document.body.classList.add( | |||
'wp-has-draft-tools' | |||
); | |||
var draftTools = | |||
createToolMenu( | |||
'wp-draft-tools', | |||
'Draft tools' | |||
); | |||
/* ------------------------------------------------ | |||
Publish | |||
------------------------------------------------ */ | |||
var publish = | |||
document.createElement( 'button' ); | |||
publish.type = | |||
'button'; | |||
publish.className = | |||
'wp-tool-menu-item wp-draft-publish-item'; | |||
publish.textContent = | |||
'Publish'; | |||
draftTools.menu.appendChild( | |||
publish | |||
); | |||
actions.appendChild( | |||
draftTools.wrapper | |||
); | |||
/* ================================================ | |||
PUBLISH MODAL | |||
================================================ */ | |||
var overlay = | |||
document.createElement( 'div' ); | |||
overlay.className = | |||
'wp-publish-modal-overlay'; | |||
overlay.hidden = true; | |||
var modal = | |||
document.createElement( 'div' ); | |||
modal.className = | |||
'wp-publish-modal'; | |||
modal.setAttribute( | |||
'role', | |||
'dialog' | |||
); | |||
modal.setAttribute( | |||
'aria-modal', | |||
'true' | |||
); | |||
modal.setAttribute( | |||
'aria-labelledby', | |||
'wp-publish-modal-title' | |||
); | |||
var modalTitle = | |||
document.createElement( 'div' ); | |||
modalTitle.id = | |||
'wp-publish-modal-title'; | |||
modalTitle.className = | |||
'wp-publish-modal-title'; | |||
modalTitle.textContent = | |||
'Publish this draft?'; | |||
var modalText = | |||
document.createElement( 'div' ); | |||
modalText.className = | |||
'wp-publish-modal-text'; | |||
var targetName = | |||
document.createElement( 'strong' ); | |||
targetName.textContent = | |||
pageTitle || | |||
'this article'; | |||
modalText.append( | |||
'This will publish ', | |||
targetName, | |||
' in the main WikiPartner article space. The “Draft:” prefix will be removed automatically.' | |||
); | |||
var modalNote = | |||
document.createElement( 'div' ); | |||
modalNote.className = | |||
'wp-publish-modal-note'; | |||
modalNote.textContent = | |||
'The draft will be moved with its revision history.'; | |||
var modalActions = | |||
document.createElement( 'div' ); | |||
modalActions.className = | |||
'wp-publish-modal-actions'; | |||
var cancel = | |||
document.createElement( 'button' ); | |||
cancel.type = | |||
'button'; | |||
cancel.className = | |||
'wp-publish-modal-cancel'; | |||
cancel.textContent = | |||
'Cancel'; | |||
var confirm = | |||
document.createElement( 'button' ); | |||
confirm.type = | |||
'button'; | |||
confirm.className = | |||
'wp-publish-modal-confirm'; | |||
confirm.textContent = | |||
'Publish article'; | |||
modalActions.append( | |||
cancel, | |||
confirm | |||
); | |||
modal.append( | |||
modalTitle, | |||
modalText, | |||
modalNote, | |||
modalActions | |||
); | |||
overlay.appendChild( | |||
modal | |||
); | |||
document.body.appendChild( | |||
overlay | |||
); | |||
function openPublishModal() { | |||
draftTools.menu.hidden = true; | |||
draftTools.trigger.setAttribute( | |||
'aria-expanded', | |||
'false' | |||
); | |||
modalNote.classList.remove( | |||
'wp-publish-modal-error' | |||
); | |||
modalNote.textContent = | |||
'The draft will be moved with its revision history.'; | |||
overlay.hidden = false; | |||
document.body.classList.add( | |||
'wp-publish-modal-open' | |||
); | |||
confirm.focus(); | |||
} | |||
function closePublishModal() { | |||
if ( confirm.disabled ) { | |||
return; | |||
} | |||
overlay.hidden = true; | |||
document.body.classList.remove( | |||
'wp-publish-modal-open' | |||
); | |||
draftTools.trigger.focus(); | |||
} | |||
publish.addEventListener( | |||
'click', | |||
openPublishModal | |||
); | |||
cancel.addEventListener( | |||
'click', | |||
closePublishModal | |||
); | |||
overlay.addEventListener( | |||
'click', | |||
function ( event ) { | |||
if ( event.target === overlay ) { | |||
closePublishModal(); | |||
} | |||
} | |||
); | |||
/* ------------------------------------------------ | |||
ACTUAL PUBLISH | |||
------------------------------------------------ */ | |||
confirm.addEventListener( | |||
'click', | |||
function () { | |||
if ( | |||
!pageName || | |||
!pageTitle | |||
) { | |||
return; | |||
} | |||
confirm.disabled = true; | |||
cancel.disabled = true; | |||
confirm.textContent = | |||
'Publishing…'; | |||
var api = | |||
new mw.Api(); | |||
api.postWithToken( | |||
'csrf', | |||
{ | |||
action: 'move', | |||
from: | |||
pageName, | |||
to: | |||
pageTitle, | |||
reason: | |||
'Published approved WikiPartner draft', | |||
movetalk: | |||
1, | |||
noredirect: | |||
1, | |||
format: | |||
'json' | |||
} | |||
) | |||
.done( | |||
function () { | |||
window.location.href = | |||
mw.util.getUrl( | |||
pageTitle | |||
); | |||
} | |||
) | |||
.fail( | |||
function ( | |||
code, | |||
data | |||
) { | |||
confirm.disabled = | |||
false; | |||
cancel.disabled = | |||
false; | |||
confirm.textContent = | |||
'Publish article'; | |||
var message = | |||
'The draft could not be published.'; | |||
if ( | |||
data && | |||
data.error && | |||
data.error.info | |||
) { | |||
message += | |||
' ' + | |||
data.error.info; | |||
} | |||
modalNote.textContent = | |||
message; | |||
modalNote.classList.add( | |||
'wp-publish-modal-error' | |||
); | |||
} | |||
); | |||
} | |||
); | |||
} | |||
/* ==================================================== | |||
ADMIN TOOLS | |||
==================================================== */ | |||
if ( canUseAdminTools ) { | |||
document.body.classList.add( | |||
'wp-has-admin-tools' | |||
); | |||
var adminTools = | |||
createToolMenu( | |||
'wp-admin-tools', | |||
'Admin tools' | |||
); | |||
/* Move */ | |||
var move = | |||
document.createElement( 'a' ); | |||
move.className = | |||
'wp-tool-menu-item'; | |||
move.href = | |||
mw.util.getUrl( | |||
'Special:MovePage/' + | |||
pageName | |||
); | |||
move.textContent = | |||
'Move'; | |||
/* Purge cache */ | |||
var purge = | |||
document.createElement( 'a' ); | |||
purge.className = | |||
'wp-tool-menu-item'; | |||
purge.href = | |||
mw.util.getUrl( | |||
pageName, | |||
{ | |||
action: 'purge' | |||
} | |||
); | |||
purge.textContent = | |||
'Purge cache'; | |||
/* Delete */ | |||
var remove = | |||
document.createElement( 'a' ); | |||
remove.className = | |||
'wp-tool-menu-item wp-tool-menu-delete'; | |||
remove.href = | |||
mw.util.getUrl( | |||
pageName, | |||
{ | |||
action: 'delete' | |||
} | |||
); | |||
remove.textContent = | |||
'Delete'; | |||
adminTools.menu.append( | |||
move, | |||
purge, | |||
remove | |||
); | |||
actions.appendChild( | |||
adminTools.wrapper | |||
); | |||
} | |||
/* ==================================================== | |||
GLOBAL MENU CLOSING | |||
==================================================== */ | |||
document.addEventListener( | |||
'click', | |||
function ( event ) { | |||
document | |||
.querySelectorAll( | |||
'.wp-tool-menu' | |||
) | |||
.forEach( | |||
function ( wrapper ) { | |||
if ( | |||
wrapper.contains( | |||
event.target | |||
) | |||
) { | |||
return; | |||
} | |||
var menu = | |||
wrapper.querySelector( | |||
'.wp-tool-menu-dropdown' | |||
); | |||
var trigger = | |||
wrapper.querySelector( | |||
'.wp-tool-menu-trigger' | |||
); | |||
if ( menu ) { | |||
menu.hidden = true; | |||
} | |||
if ( trigger ) { | |||
trigger.setAttribute( | |||
'aria-expanded', | |||
'false' | |||
); | |||
} | |||
} | |||
); | |||
} | |||
); | |||
document.addEventListener( | |||
'keydown', | |||
function ( event ) { | |||
if ( event.key !== 'Escape' ) { | |||
return; | |||
} | |||
if ( !overlay || overlay.hidden ) { | |||
document | |||
.querySelectorAll( | |||
'.wp-tool-menu-dropdown' | |||
) | |||
.forEach( | |||
function ( menu ) { | |||
menu.hidden = true; | |||
} | |||
); | |||
document | |||
.querySelectorAll( | |||
'.wp-tool-menu-trigger' | |||
) | |||
.forEach( | |||
function ( trigger ) { | |||
trigger.setAttribute( | |||
'aria-expanded', | |||
'false' | |||
); | |||
} | |||
); | |||
} else { | |||
closePublishModal(); | |||
} | |||
} | |||
); | |||
} ); | |||
} ); | |||
/* ============================================================ | |||
WIKIPARTNER — MOVE / DELETE ADMIN PAGES | |||
============================================================ */ | |||
$( function () { | |||
var pageName = | |||
mw.config.get( 'wgPageName' ) || ''; | |||
var action = | |||
mw.config.get( 'wgAction' ) || ''; | |||
var content = | |||
document.getElementById( 'mw-content-text' ); | |||
if ( !content ) { | |||
return; | |||
} | |||
var isMove = | |||
/^Special:(?:MovePage|Movepage)\//i.test( | |||
pageName | |||
); | |||
var isDelete = | |||
action === 'delete'; | |||
if ( !isMove && !isDelete ) { | |||
return; | |||
} | |||
document.body.classList.add( | |||
isMove | |||
? 'wp-admin-move-page' | |||
: 'wp-admin-delete-page' | |||
); | |||
/* | |||
* Find the main MediaWiki action form. | |||
*/ | |||
var form = | |||
content.querySelector( 'form' ); | |||
if ( !form ) { | |||
return; | |||
} | |||
form.classList.add( | |||
'wp-admin-action-form' | |||
); | |||
/* | |||
* Find the direct child of #mw-content-text | |||
* which contains the form. | |||
*/ | |||
var formBlock = | |||
form; | |||
while ( | |||
formBlock.parentElement && | |||
formBlock.parentElement !== content | |||
) { | |||
formBlock = | |||
formBlock.parentElement; | |||
} | |||
/* -------------------------------------------------------- | |||
HIDE LONG DEFAULT INTRO PARAGRAPHS | |||
-------------------------------------------------------- */ | |||
var node = | |||
content.firstElementChild; | |||
while ( | |||
node && | |||
node !== formBlock | |||
) { | |||
if ( | |||
node.tagName === 'P' | |||
) { | |||
node.classList.add( | |||
'wp-admin-native-intro' | |||
); | |||
} | |||
node = | |||
node.nextElementSibling; | |||
} | |||
/* -------------------------------------------------------- | |||
MOVE PAGE INTRO | |||
-------------------------------------------------------- */ | |||
if ( isMove ) { | |||
var intro = | |||
document.createElement( 'div' ); | |||
intro.className = | |||
'wp-admin-action-intro'; | |||
intro.innerHTML = | |||
'<strong>Move this page</strong>' + | |||
'<span>Move the page to a new title while keeping its revision history. Leave a redirect if the old title should continue pointing to the new one.</span>'; | |||
content.insertBefore( | |||
intro, | |||
content.firstElementChild | |||
); | |||
/* | |||
* Shorten the Category move warning while | |||
* preserving its important meaning. | |||
*/ | |||
var moveWarning = | |||
content.querySelector( | |||
'.cdx-message--warning, ' + | |||
'.mw-message-box-warning, ' + | |||
'.warningbox' | |||
); | |||
if ( | |||
moveWarning && | |||
/category page/i.test( | |||
moveWarning.textContent | |||
) | |||
) { | |||
var warningContent = | |||
moveWarning.querySelector( | |||
'.cdx-message__content' | |||
) || | |||
moveWarning; | |||
warningContent.textContent = | |||
'Moving a category page does not recategorize pages from the old category.'; | |||
} | |||
} | |||
/* -------------------------------------------------------- | |||
DELETE PAGE NOTICE | |||
-------------------------------------------------------- */ | |||
if ( isDelete ) { | |||
var deleteNotice = | |||
document.createElement( 'div' ); | |||
deleteNotice.className = | |||
'wp-admin-delete-notice'; | |||
var deleteLabel = | |||
document.createElement( 'div' ); | |||
deleteLabel.className = | |||
'wp-admin-delete-label'; | |||
deleteLabel.textContent = | |||
'Warning'; | |||
var deleteTitle = | |||
document.createElement( 'strong' ); | |||
deleteTitle.className = | |||
'wp-admin-delete-title'; | |||
deleteTitle.textContent = | |||
'You are about to delete this page'; | |||
var deleteText = | |||
document.createElement( 'div' ); | |||
deleteText.className = | |||
'wp-admin-delete-text'; | |||
deleteText.append( | |||
'Deleting this page removes it from normal view. Review its ' | |||
); | |||
var historyLink = | |||
document.createElement( 'a' ); | |||
historyLink.href = | |||
mw.util.getUrl( | |||
pageName, | |||
{ | |||
action: 'history' | |||
} | |||
); | |||
historyLink.textContent = | |||
'page history'; | |||
deleteText.append( | |||
historyLink, | |||
' before continuing.' | |||
); | |||
deleteNotice.append( | |||
deleteLabel, | |||
deleteTitle, | |||
deleteText | |||
); | |||
content.insertBefore( | |||
deleteNotice, | |||
content.firstElementChild | |||
); | |||
} | |||
/* -------------------------------------------------------- | |||
TAG SUBMIT BUTTON | |||
-------------------------------------------------------- */ | |||
var submitButtons = | |||
form.querySelectorAll( | |||
'input[type="submit"], button[type="submit"]' | |||
); | |||
submitButtons.forEach( | |||
function ( button ) { | |||
button.classList.add( | |||
'wp-admin-action-submit' | |||
); | |||
if ( isDelete ) { | |||
button.classList.add( | |||
'wp-admin-danger-submit' | |||
); | |||
} | |||
} | |||
); | |||
/* -------------------------------------------------------- | |||
HIDE ADMIN META LINKS | |||
-------------------------------------------------------- */ | |||
content | |||
.querySelectorAll( 'a' ) | |||
.forEach( | |||
function ( link ) { | |||
var text = | |||
link.textContent | |||
.trim(); | |||
if ( | |||
/^Edit (move|deletion) reasons$/i.test( | |||
text | |||
) | |||
) { | |||
link.classList.add( | |||
'wp-admin-meta-link-hidden' | |||
); | |||
} | |||
} | |||
); | |||
/* -------------------------------------------------------- | |||
REMOVE EMPTY LOG SECTIONS | |||
-------------------------------------------------------- */ | |||
content | |||
.querySelectorAll( 'h2' ) | |||
.forEach( | |||
function ( heading ) { | |||
var headingText = | |||
heading.textContent | |||
.trim(); | |||
if ( | |||
!/^(Move log|Deletion log|Page creation log)$/i.test( | |||
headingText | |||
) | |||
) { | |||
return; | |||
} | |||
var sectionNodes = []; | |||
var next = | |||
heading.nextElementSibling; | |||
while ( | |||
next && | |||
next.tagName !== 'H2' | |||
) { | |||
sectionNodes.push( | |||
next | |||
); | |||
next = | |||
next.nextElementSibling; | |||
} | |||
var sectionText = | |||
sectionNodes | |||
.map( | |||
function ( item ) { | |||
return item.textContent; | |||
} | |||
) | |||
.join( ' ' ); | |||
var hasRealLog = | |||
sectionNodes.some( | |||
function ( item ) { | |||
return ( | |||
item.matches && | |||
item.matches( | |||
'[class*="mw-logline-"]' | |||
) | |||
) || | |||
( | |||
item.querySelector && | |||
item.querySelector( | |||
'[class*="mw-logline-"]' | |||
) | |||
); | |||
} | |||
); | |||
if ( | |||
!hasRealLog && | |||
/No matching items in log/i.test( | |||
sectionText | |||
) | |||
) { | |||
heading.style.display = | |||
'none'; | |||
sectionNodes.forEach( | |||
function ( item ) { | |||
item.style.display = | |||
'none'; | |||
} | |||
); | |||
} | |||
} | |||
); | |||
} ); | |||
/* ============================================================ | |||
WIKIPARTNER — ENHANCED FILE PAGE | |||
============================================================ */ | |||
$( function () { | |||
if ( | |||
Number( mw.config.get( 'wgNamespaceNumber' ) ) !== 6 || | |||
mw.config.get( 'wgAction' ) !== 'view' || | |||
!mw.config.get( 'wgArticleId' ) | |||
) { | |||
return; | |||
} | |||
if ( | |||
document.querySelector( | |||
'.wp-file-overview' | |||
) | |||
) { | |||
return; | |||
} | |||
var preview = | |||
document.querySelector( | |||
'.fullImageLink' | |||
); | |||
var originalFile = | |||
document.querySelector( | |||
'.fullMedia' | |||
); | |||
var information = | |||
document.getElementById( | |||
'mw-imagepage-content' | |||
); | |||
if ( | |||
!preview || | |||
!information | |||
) { | |||
return; | |||
} | |||
var parent = | |||
preview.parentNode; | |||
/* -------------------------------------------------------- | |||
OVERVIEW | |||
-------------------------------------------------------- */ | |||
var overview = | |||
document.createElement( 'div' ); | |||
overview.className = | |||
'wp-file-overview'; | |||
parent.insertBefore( | |||
overview, | |||
preview | |||
); | |||
/* -------------------------------------------------------- | |||
PREVIEW CARD | |||
-------------------------------------------------------- */ | |||
var previewCard = | |||
document.createElement( 'section' ); | |||
previewCard.className = | |||
'wp-file-preview-card'; | |||
var previewTitle = | |||
document.createElement( 'div' ); | |||
previewTitle.className = | |||
'wp-file-preview-title'; | |||
previewTitle.textContent = | |||
'Image preview'; | |||
previewCard.appendChild( | |||
previewTitle | |||
); | |||
previewCard.appendChild( | |||
preview | |||
); | |||
if ( originalFile ) { | |||
previewCard.appendChild( | |||
originalFile | |||
); | |||
} | |||
overview.appendChild( | |||
previewCard | |||
); | |||
/* -------------------------------------------------------- | |||
FILE INFORMATION | |||
-------------------------------------------------------- */ | |||
information.classList.add( | |||
'wp-file-details' | |||
); | |||
overview.appendChild( | |||
information | |||
); | |||
document.body.classList.add( | |||
'wp-file-page-enhanced' | |||
); | |||
} ); | |||
/* ============================================================ | |||
WIKIPARTNER — SPECIAL:UPLOAD CUSTOM SELECTS | |||
============================================================ */ | |||
(function () { | |||
'use strict'; | |||
function enhanceWikiPartnerSelect(select) { | |||
if ( | |||
!select || | |||
select.dataset.wpSelectEnhanced === '1' | |||
) { | |||
return; | |||
} | |||
select.dataset.wpSelectEnhanced = '1'; | |||
var wrapper = | |||
document.createElement('div'); | |||
wrapper.className = | |||
'wp-select'; | |||
var button = | |||
document.createElement('button'); | |||
button.type = | |||
'button'; | |||
button.className = | |||
'wp-select-button'; | |||
button.id = | |||
select.id + '-button'; | |||
button.setAttribute( | |||
'aria-haspopup', | |||
'listbox' | |||
); | |||
button.setAttribute( | |||
'aria-expanded', | |||
'false' | |||
); | |||
var menu = | |||
document.createElement('div'); | |||
menu.className = | |||
'wp-select-menu'; | |||
menu.id = | |||
select.id + '-menu'; | |||
menu.setAttribute( | |||
'role', | |||
'listbox' | |||
); | |||
menu.hidden = | |||
true; | |||
button.setAttribute( | |||
'aria-controls', | |||
menu.id | |||
); | |||
var items = []; | |||
Array.prototype.forEach.call( | |||
select.options, | |||
function (option, index) { | |||
var item = | |||
document.createElement( | |||
'button' | |||
); | |||
item.type = | |||
'button'; | |||
item.className = | |||
'wp-select-option'; | |||
item.textContent = | |||
option.textContent; | |||
item.setAttribute( | |||
'role', | |||
'option' | |||
); | |||
item.tabIndex = | |||
-1; | |||
item.addEventListener( | |||
'click', | |||
function () { | |||
select.selectedIndex = | |||
index; | |||
select.dispatchEvent( | |||
new Event( | |||
'change', | |||
{ | |||
bubbles: true | |||
} | |||
) | |||
); | |||
sync(); | |||
close(); | |||
button.focus(); | |||
} | |||
); | |||
items.push(item); | |||
menu.appendChild(item); | |||
} | |||
); | |||
function sync() { | |||
var selected = | |||
select.options[ | |||
select.selectedIndex | |||
] || select.options[0]; | |||
button.textContent = | |||
selected | |||
? selected.textContent | |||
: ''; | |||
items.forEach( | |||
function (item, index) { | |||
var active = | |||
index === | |||
select.selectedIndex; | |||
item.classList.toggle( | |||
'is-selected', | |||
active | |||
); | |||
item.setAttribute( | |||
'aria-selected', | |||
active | |||
? 'true' | |||
: 'false' | |||
); | |||
} | |||
); | |||
} | |||
function closeOthers() { | |||
document.querySelectorAll( | |||
'.wp-select.is-open' | |||
).forEach( | |||
function (other) { | |||
if (other === wrapper) { | |||
return; | |||
} | |||
other.classList.remove( | |||
'is-open' | |||
); | |||
var otherMenu = | |||
other.querySelector( | |||
'.wp-select-menu' | |||
); | |||
var otherButton = | |||
other.querySelector( | |||
'.wp-select-button' | |||
); | |||
if (otherMenu) { | |||
otherMenu.hidden = true; | |||
} | |||
if (otherButton) { | |||
otherButton.setAttribute( | |||
'aria-expanded', | |||
'false' | |||
); | |||
} | |||
} | |||
); | |||
} | |||
function open() { | |||
closeOthers(); | |||
menu.hidden = | |||
false; | |||
wrapper.classList.add( | |||
'is-open' | |||
); | |||
button.setAttribute( | |||
'aria-expanded', | |||
'true' | |||
); | |||
var selectedItem = | |||
menu.querySelector( | |||
'.is-selected' | |||
); | |||
if (selectedItem) { | |||
selectedItem.focus(); | |||
} | |||
} | |||
function close() { | |||
menu.hidden = | |||
true; | |||
wrapper.classList.remove( | |||
'is-open' | |||
); | |||
button.setAttribute( | |||
'aria-expanded', | |||
'false' | |||
); | |||
} | |||
button.addEventListener( | |||
'click', | |||
function () { | |||
if ( | |||
wrapper.classList.contains( | |||
'is-open' | |||
) | |||
) { | |||
close(); | |||
} else { | |||
open(); | |||
} | |||
} | |||
); | |||
button.addEventListener( | |||
'keydown', | |||
function (event) { | |||
if ( | |||
event.key === 'ArrowDown' || | |||
event.key === 'ArrowUp' || | |||
event.key === 'Enter' || | |||
event.key === ' ' | |||
) { | |||
event.preventDefault(); | |||
open(); | |||
} | |||
} | |||
); | |||
menu.addEventListener( | |||
'keydown', | |||
function (event) { | |||
var current = | |||
items.indexOf( | |||
document.activeElement | |||
); | |||
if (event.key === 'Escape') { | |||
event.preventDefault(); | |||
close(); | |||
button.focus(); | |||
return; | |||
} | |||
if ( | |||
event.key !== 'ArrowDown' && | |||
event.key !== 'ArrowUp' | |||
) { | |||
return; | |||
} | |||
event.preventDefault(); | |||
if (current < 0) { | |||
current = | |||
select.selectedIndex; | |||
} | |||
if (event.key === 'ArrowDown') { | |||
current = | |||
Math.min( | |||
current + 1, | |||
items.length - 1 | |||
); | |||
} else { | |||
current = | |||
Math.max( | |||
current - 1, | |||
0 | |||
); | |||
} | |||
items[current].focus(); | |||
} | |||
); | |||
document.addEventListener( | |||
'click', | |||
function (event) { | |||
if ( | |||
!wrapper.contains( | |||
event.target | |||
) | |||
) { | |||
close(); | |||
} | |||
} | |||
); | |||
select.addEventListener( | |||
'change', | |||
sync | |||
); | |||
var parent = | |||
select.parentNode; | |||
parent.insertBefore( | |||
wrapper, | |||
select | |||
); | |||
wrapper.appendChild( | |||
select | |||
); | |||
wrapper.appendChild( | |||
button | |||
); | |||
wrapper.appendChild( | |||
menu | |||
); | |||
select.classList.add( | |||
'wp-select-native' | |||
); | |||
var label = | |||
document.querySelector( | |||
'label[for="' + | |||
select.id + | |||
'"]' | |||
); | |||
if (label) { | |||
label.setAttribute( | |||
'for', | |||
button.id | |||
); | |||
} | |||
sync(); | |||
} | |||
function initWikiPartnerUploadSelects() { | |||
if ( | |||
!document.body.classList.contains( | |||
'mw-special-Upload' | |||
) | |||
) { | |||
return; | |||
} | |||
[ | |||
'wpWikiPartnerCreatorType', | |||
'wpWikiPartnerLicense' | |||
].forEach( | |||
function (id) { | |||
enhanceWikiPartnerSelect( | |||
document.getElementById(id) | |||
); | |||
} | |||
); | |||
} | |||
if ( | |||
document.readyState === 'loading' | |||
) { | |||
document.addEventListener( | |||
'DOMContentLoaded', | |||
initWikiPartnerUploadSelects | |||
); | |||
} else { | |||
initWikiPartnerUploadSelects(); | |||
} | |||
})(); | })(); | ||
Latest revision as of 10:55, 2 September 2026
/* ============================================================
WIKIPARTNER
THEME + USER MENU
============================================================ */
(function () {
'use strict';
var STORAGE_KEY = 'wikipartner-theme';
var LIGHT = 'light';
var DARK = 'dark';
/* ========================================================
THEME STORAGE
======================================================== */
function getSavedTheme() {
try {
var saved = window.localStorage.getItem(
STORAGE_KEY
);
if (
saved === LIGHT ||
saved === DARK
) {
return saved;
}
} catch (e) {
/* localStorage unavailable */
}
return LIGHT;
}
function saveTheme(theme) {
try {
window.localStorage.setItem(
STORAGE_KEY,
theme
);
} catch (e) {
/* localStorage unavailable */
}
}
/* ========================================================
CURRENT THEME
======================================================== */
function getCurrentTheme() {
return document.documentElement
.classList.contains(
'wp-theme-dark'
)
? DARK
: LIGHT;
}
/* ========================================================
APPLY THEME
======================================================== */
function applyTheme(theme, shouldSave) {
var html =
document.documentElement;
var isDark =
theme === DARK;
html.classList.toggle(
'wp-theme-dark',
isDark
);
html.classList.toggle(
'wp-theme-light',
!isDark
);
/*
* Keep MediaWiki-compatible theme classes too.
*/
html.classList.remove(
'skin-theme-clientpref-day',
'skin-theme-clientpref-night',
'skin-theme-clientpref-os'
);
html.classList.add(
isDark
? 'skin-theme-clientpref-night'
: 'skin-theme-clientpref-day'
);
html.setAttribute(
'data-wikipartner-theme',
isDark
? DARK
: LIGHT
);
if (shouldSave !== false) {
saveTheme(theme);
}
updateThemeButton();
}
/* ========================================================
THEME ICONS
======================================================== */
function getMoonIcon() {
return [
'<svg viewBox="0 0 24 24" aria-hidden="true">',
'<path d="M20.3 15.2A8.4 8.4 0 0 1 8.8 3.7 8.5 8.5 0 1 0 11.5 11.5Z"></path>',
'<path class="wp-theme-star" d="M17.5 4v3M16 5.5h3"></path>',
'</svg>'
].join('');
}
function getSunIcon() {
return [
'<svg viewBox="0 0 24 24" aria-hidden="true">',
'<circle cx="12" cy="12" r="3.8"></circle>',
'<path d="M12 2.3v2.1"></path>',
'<path d="M12 19.6v2.1"></path>',
'<path d="M4.93 4.93l1.5 1.5"></path>',
'<path d="M17.57 17.57l1.5 1.5"></path>',
'<path d="M2.3 12h2.1"></path>',
'<path d="M19.6 12h2.1"></path>',
'<path d="M4.93 19.07l1.5-1.5"></path>',
'<path d="M17.57 6.43l1.5-1.5"></path>',
'</svg>'
].join('');
}
/* ========================================================
UPDATE THEME BUTTON
======================================================== */
function updateThemeButton() {
var button =
document.getElementById(
'wikipartner-theme-toggle'
);
if (!button) {
return;
}
var isDark =
getCurrentTheme() === DARK;
button.innerHTML =
'<span class="wp-theme-icon">' +
(
isDark
? getSunIcon()
: getMoonIcon()
) +
'</span>';
button.setAttribute(
'aria-label',
isDark
? 'Switch to light mode'
: 'Switch to dark mode'
);
button.setAttribute(
'title',
isDark
? 'Light mode'
: 'Dark mode'
);
}
/* ========================================================
CREATE THEME BUTTON
======================================================== */
function createThemeToggle(list) {
var existing =
document.getElementById(
'wikipartner-theme-item'
);
if (existing) {
return existing;
}
var item =
document.createElement('li');
item.id =
'wikipartner-theme-item';
item.className =
'mw-list-item ' +
'wikipartner-theme-item';
var button =
document.createElement(
'button'
);
button.id =
'wikipartner-theme-toggle';
button.className =
'wikipartner-theme-toggle';
button.type =
'button';
button.addEventListener(
'click',
function () {
var nextTheme =
getCurrentTheme() === DARK
? LIGHT
: DARK;
applyTheme(
nextTheme,
true
);
}
);
item.appendChild(
button
);
updateThemeButton();
return item;
}
/* ========================================================
HAMBURGER ICON
======================================================== */
function getMenuIcon() {
return [
'<span class="wp-menu-bars" aria-hidden="true">',
'<span></span>',
'<span></span>',
'<span></span>',
'</span>'
].join('');
}
/* ========================================================
FIND / CLEAN USERNAME
======================================================== */
function cleanUsernameDuplicates(
primary,
list
) {
var username =
mw.config.get(
'wgUserName'
);
if (!username) {
return;
}
/*
* MediaWiki's data-user-page already puts
* the username in .wp-user-primary.
*
* Some personal-menu configurations can
* also provide another user-page link.
* Remove that duplicate from the menu.
*/
var items =
Array.prototype.slice.call(
list.children
);
items.forEach(
function (item) {
var link =
item.querySelector('a');
var linkText =
link
? link.textContent.trim()
: '';
var isUserPageId =
item.id === 'pt-userpage' ||
item.id === 'pt-userpage-2';
var isUsername =
linkText === username;
if (
isUserPageId ||
isUsername
) {
/*
* If primary somehow has no username,
* move this one there instead.
*/
if (
primary &&
!primary.querySelector('li')
) {
primary.appendChild(
item
);
} else {
item.remove();
}
}
}
);
}
/* ========================================================
LOGGED OUT LAYOUT
======================================================== */
function buildLoggedOutLayout(
list,
themeItem
) {
list.classList.remove(
'wp-is-logged-in'
);
list.classList.add(
'wp-is-logged-out'
);
/*
* Desired layout:
*
* Theme | Create account | Log in
*/
var firstItem =
list.firstElementChild;
if (firstItem) {
list.insertBefore(
themeItem,
firstItem
);
} else {
list.appendChild(
themeItem
);
}
}
/* ========================================================
LOGGED IN LAYOUT
======================================================== */
function buildLoggedInLayout(
primary,
list,
themeItem
) {
list.classList.remove(
'wp-is-logged-out'
);
list.classList.add(
'wp-is-logged-in'
);
cleanUsernameDuplicates(
primary,
list
);
/*
* Remove an old dropdown if ResourceLoader
* initialization somehow runs again.
*/
var oldDropdown =
list.querySelector(
'.wp-user-dropdown'
);
if (oldDropdown) {
return;
}
/* ====================================================
CREATE HAMBURGER WRAPPER
==================================================== */
var dropdown =
document.createElement('li');
dropdown.className =
'wp-user-dropdown';
/* ====================================================
HAMBURGER BUTTON
==================================================== */
var trigger =
document.createElement(
'button'
);
trigger.type =
'button';
trigger.className =
'wp-user-menu-trigger';
trigger.setAttribute(
'aria-label',
'Open user menu'
);
trigger.setAttribute(
'title',
'User menu'
);
trigger.setAttribute(
'aria-expanded',
'false'
);
trigger.innerHTML =
getMenuIcon();
/* ====================================================
DROPDOWN CONTENT
==================================================== */
var menu =
document.createElement('ul');
menu.className =
'wp-user-dropdown-menu';
menu.hidden =
true;
/*
* Move every existing menu item
* into ☰.
*
* Username is NOT in this list anymore.
* Theme is not inserted yet.
*/
Array.prototype
.slice.call(
list.children
)
.forEach(
function (item) {
if (
item !== themeItem &&
item !== dropdown
) {
menu.appendChild(
item
);
}
}
);
dropdown.appendChild(
trigger
);
dropdown.appendChild(
menu
);
/*
* Exact layout:
*
* Username | Theme | ☰
*
* Username lives in .wp-user-primary,
* while theme and hamburger live here.
*/
list.appendChild(
themeItem
);
list.appendChild(
dropdown
);
/* ====================================================
OPEN / CLOSE
==================================================== */
function closeMenu() {
dropdown.classList.remove(
'is-open'
);
menu.hidden =
true;
trigger.setAttribute(
'aria-expanded',
'false'
);
}
function openMenu() {
dropdown.classList.add(
'is-open'
);
menu.hidden =
false;
trigger.setAttribute(
'aria-expanded',
'true'
);
}
/* ====================================================
CLICK HAMBURGER
==================================================== */
trigger.addEventListener(
'click',
function (event) {
event.preventDefault();
event.stopPropagation();
if (
dropdown.classList.contains(
'is-open'
)
) {
closeMenu();
} else {
openMenu();
}
}
);
/* ====================================================
CLICK INSIDE MENU
==================================================== */
menu.addEventListener(
'click',
function (event) {
event.stopPropagation();
}
);
/* ====================================================
CLICK OUTSIDE
==================================================== */
document.addEventListener(
'click',
function (event) {
if (
!dropdown.contains(
event.target
)
) {
closeMenu();
}
}
);
/* ====================================================
ESCAPE
==================================================== */
document.addEventListener(
'keydown',
function (event) {
if (
event.key === 'Escape' &&
dropdown.classList.contains(
'is-open'
)
) {
closeMenu();
trigger.focus();
}
}
);
}
/* ========================================================
INITIALIZE ACCOUNT AREA
======================================================== */
function initializeUserArea() {
var primary =
document.querySelector(
'.wp-user-primary'
);
var list =
document.querySelector(
'.wp-user-menu-list'
);
if (!list) {
return;
}
/*
* Empty username container should not
* take up space for anonymous users.
*/
if (
primary &&
!primary.querySelector('li')
) {
primary.classList.add(
'is-empty'
);
}
var themeItem =
createThemeToggle(
list
);
var username =
mw.config.get(
'wgUserName'
);
if (username) {
buildLoggedInLayout(
primary,
list,
themeItem
);
} else {
buildLoggedOutLayout(
list,
themeItem
);
}
updateThemeButton();
}
/* ========================================================
APPLY SAVED THEME
======================================================== */
applyTheme(
getSavedTheme(),
false
);
/* ========================================================
START
======================================================== */
function initialize() {
initializeUserArea();
}
if (
document.readyState ===
'loading'
) {
document.addEventListener(
'DOMContentLoaded',
initialize
);
} else {
initialize();
}
})();
/* ============================================================
WIKIPARTNER
ARTICLE CONTENTS MENU
============================================================ */
(function () {
'use strict';
function initializeArticleContents() {
var toc = document.getElementById('wp-toc');
var article = document.querySelector(
'.wp-article-body'
);
var sidebarContentsLink = document.getElementById(
'wp-sidebar-contents-link'
);
if (!toc || !article) {
if (sidebarContentsLink) {
sidebarContentsLink.hidden = true;
}
return;
}
var linksContainer = toc.querySelector(
'.wp-toc-links'
);
if (!linksContainer) {
if (sidebarContentsLink) {
sidebarContentsLink.hidden = true;
}
return;
}
/* ====================================================
FIND ACTUAL ARTICLE HEADINGS
==================================================== */
var headings = Array.prototype.slice.call(
article.querySelectorAll(
'h2, h3, h4, h5, h6'
)
);
/*
* Keep only real headings with visible text.
*/
headings = headings.filter(
function (heading) {
var text =
heading.textContent
.replace(/\[edit\]/gi, '')
.trim();
return text.length > 0;
}
);
/* ====================================================
NO HEADINGS
HIDE BOTH CONTENTS CONTROLS
==================================================== */
if (!headings.length) {
toc.classList.remove(
'wp-toc-ready'
);
toc.open = false;
if (sidebarContentsLink) {
sidebarContentsLink.hidden = true;
}
return;
}
/* ====================================================
CLEAR OLD CONTENTS
==================================================== */
linksContainer.innerHTML = '';
/*
* Hide the old hard-coded "Contents" heading
* if it exists in the Mustache template.
*/
var oldHeading = toc.querySelector(
'.wp-toc-heading'
);
if (oldHeading) {
oldHeading.style.display = 'none';
}
/* ====================================================
BUILD LINKS FROM ARTICLE HEADINGS
==================================================== */
headings.forEach(
function (heading, index) {
/*
* MediaWiki normally gives headings an ID.
* If one does not exist, create a safe fallback.
*/
if (!heading.id) {
heading.id =
'wikipartner-section-' +
(index + 1);
}
var level = parseInt(
heading.tagName.substring(1),
10
);
var headingText =
heading.textContent
.replace(/\[edit\]/gi, '')
.trim();
var link =
document.createElement('a');
link.href =
'#' + heading.id;
link.className =
'wp-toc-level-' +
level;
link.textContent =
headingText;
/*
* Close the dropdown after
* selecting a heading.
*/
link.addEventListener(
'click',
function () {
toc.open = false;
}
);
linksContainer.appendChild(
link
);
}
);
/* ====================================================
HEADINGS FOUND
SHOW BOTH CONTENTS CONTROLS
==================================================== */
toc.classList.add(
'wp-toc-ready'
);
if (sidebarContentsLink) {
sidebarContentsLink.hidden = false;
sidebarContentsLink.addEventListener(
'click',
function (event) {
event.preventDefault();
toc.open = true;
toc.scrollIntoView({
behavior: 'smooth',
block: 'center'
});
}
);
}
}
if (document.readyState === 'loading') {
document.addEventListener(
'DOMContentLoaded',
initializeArticleContents
);
} else {
initializeArticleContents();
}
})();
/* ============================================================
WIKIPARTNER
WHAT LINKS HERE — CURRENT PAGE URL
============================================================ */
(function () {
'use strict';
function initializeWhatLinksHere() {
var link = document.getElementById(
'wp-what-links-here'
);
if (!link) {
return;
}
var pageName = mw.config.get(
'wgPageName'
);
if (!pageName) {
return;
}
mw.loader.using(
'mediawiki.util'
).then(
function () {
link.href = mw.util.getUrl(
'Special:WhatLinksHere/' + pageName
);
}
);
}
if (document.readyState === 'loading') {
document.addEventListener(
'DOMContentLoaded',
initializeWhatLinksHere
);
} else {
initializeWhatLinksHere();
}
})();
/* ============================================================
WIKIPARTNER
ARTICLE SUGGESTION — REVIEWER CONTROL
============================================================ */
(function () {
'use strict';
function initializeSuggestionReviewerControl() {
var control = document.getElementById(
'wp-review-suggestion-control'
);
if (!control) {
return;
}
var groups = mw.config.get(
'wgUserGroups'
) || [];
var isReviewer =
groups.indexOf('reviewer') !== -1;
if (isReviewer) {
control.style.display = '';
}
}
if (document.readyState === 'loading') {
document.addEventListener(
'DOMContentLoaded',
initializeSuggestionReviewerControl
);
} else {
initializeSuggestionReviewerControl();
}
})();
/* ============================================================
WIKIPARTNER
ISSUE REPORT — REVIEWER CONTROL
============================================================ */
(function () {
'use strict';
function initializeIssueReviewerControl() {
var control = document.getElementById(
'wp-review-issue-control'
);
if (!control) {
return;
}
var groups = mw.config.get(
'wgUserGroups'
) || [];
var isReviewer =
groups.indexOf('reviewer') !== -1;
if (isReviewer) {
control.style.display = '';
}
}
if (document.readyState === 'loading') {
document.addEventListener(
'DOMContentLoaded',
initializeIssueReviewerControl
);
} else {
initializeIssueReviewerControl();
}
})();
/* ============================================================
WIKIPARTNER — CREATE DRAFT
Send the Create draft form directly to Draft: source editor.
============================================================ */
mw.loader.using( 'mediawiki.util' ).then( function () {
if ( mw.config.get( 'wgPageName' ) !== 'WikiPartner:Create_a_draft' ) {
return;
}
var form = document.getElementById( 'wp-create-draft-form' );
if ( !form ) {
return;
}
form.addEventListener( 'submit', function ( event ) {
var input = form.querySelector( 'input[name="title"]' );
if ( !input ) {
return;
}
var title = input.value.trim();
if ( !title ) {
event.preventDefault();
input.focus();
return;
}
/*
* Prevent Draft:Draft:Article if somebody manually
* enters the namespace.
*/
title = title.replace( /^Draft\s*:\s*/i, '' ).trim();
if ( !title ) {
event.preventDefault();
input.focus();
return;
}
event.preventDefault();
var draftTitle =
'Draft:' +
title.replace( /\s+/g, '_' );
var url =
mw.config.get( 'wgScript' ) +
'?title=' +
encodeURIComponent( draftTitle ) +
'&action=edit';
window.location.assign( url );
} );
} );
/* ============================================================
WIKIPARTNER — MOVED / DELETED PAGE STATES
============================================================ */
$( function () {
if ( mw.config.get( 'wgAction' ) !== 'view' ) {
return;
}
var content =
document.getElementById( 'mw-content-text' );
if ( !content ) {
return;
}
var logBox =
content.querySelector(
'.mw-warning-with-logexcerpt'
);
var noArticle =
content.querySelector(
'.noarticletext'
);
if ( !logBox || !noArticle ) {
return;
}
var moveLine =
logBox.querySelector(
'.mw-logline-move'
);
var deleteLine =
logBox.querySelector(
'[class*="mw-logline-delete"]'
);
var type = 'history';
if ( moveLine ) {
type = 'moved';
} else if ( deleteLine ) {
type = 'deleted';
}
document.body.classList.add(
'wp-historical-missing-page',
'wp-page-' + type
);
var messageContent =
logBox.querySelector(
'.cdx-message__content'
) || logBox;
var inner =
messageContent.querySelector(
'.mw-content-ltr'
) || messageContent;
if (
inner.querySelector(
'.wp-history-status'
)
) {
return;
}
var originalIntro =
inner.querySelector( 'p' );
if ( originalIntro ) {
originalIntro.classList.add(
'wp-history-original-intro'
);
}
var status =
document.createElement( 'div' );
status.className =
'wp-history-status';
var label =
document.createElement( 'div' );
label.className =
'wp-history-label';
label.textContent =
'PAGE STATUS';
var title =
document.createElement( 'div' );
title.className =
'wp-history-title';
var description =
document.createElement( 'div' );
description.className =
'wp-history-description';
if ( type === 'moved' ) {
title.textContent =
'This page has moved';
description.textContent =
'This page now exists under a different title. The move record is shown below.';
} else if ( type === 'deleted' ) {
title.textContent =
'This page was deleted';
description.textContent =
'This title does not currently contain a WikiPartner page. The deletion record is shown below for reference.';
} else {
title.textContent =
'This page is no longer available';
description.textContent =
'This title has a recent deletion or move record. Details are shown below.';
}
status.append(
label,
title,
description
);
if ( moveLine ) {
var links =
Array.prototype.slice.call(
moveLine.querySelectorAll( 'a' )
);
var sourceIndex =
links.findIndex(
function ( link ) {
return link.classList.contains( 'new' );
}
);
var targetLink = null;
if (
sourceIndex !== -1 &&
links[ sourceIndex + 1 ]
) {
targetLink =
links[ sourceIndex + 1 ];
}
if (
targetLink &&
targetLink.href
) {
var currentButton =
document.createElement( 'a' );
currentButton.className =
'wp-history-current-button';
currentButton.href =
targetLink.href;
currentButton.textContent =
'View current page';
status.appendChild(
currentButton
);
}
}
if ( type === 'deleted' ) {
var logLink =
logBox.querySelector(
'a[title="Special:Log"]'
);
if ( logLink ) {
var historyButton =
document.createElement( 'a' );
historyButton.className =
'wp-history-log-button';
historyButton.href =
logLink.href;
historyButton.textContent =
'View log entry';
status.appendChild(
historyButton
);
}
}
inner.insertBefore(
status,
inner.firstChild
);
} );
/* ============================================================
WIKIPARTNER — DRAFT RECREATE WARNING
============================================================ */
$( function () {
if (
Number( mw.config.get( 'wgNamespaceNumber' ) ) !== 3000 ||
mw.config.get( 'wgAction' ) !== 'edit' ||
mw.config.get( 'wgArticleId' )
) {
return;
}
var warning =
document.querySelector(
'.mw-warning-with-logexcerpt, .cdx-message--warning'
);
if ( !warning ) {
return;
}
var moveLine =
warning.querySelector( '.mw-logline-move' );
var deleteLine =
warning.querySelector(
'[class*="mw-logline-delete"]'
);
if ( !moveLine && !deleteLine ) {
return;
}
document.body.classList.add(
'wp-draft-recreate-page'
);
var content =
warning.querySelector(
'.cdx-message__content'
) || warning;
var inner =
content.querySelector(
'.mw-content-ltr'
) || content;
var paragraphs =
Array.prototype.slice.call(
inner.querySelectorAll( ':scope > p' )
);
if ( paragraphs[ 0 ] ) {
paragraphs[ 0 ].innerHTML =
'<span class="wp-recreate-label">Notice</span>' +
'<strong class="wp-recreate-title">' +
(
moveLine
? 'This draft was previously moved'
: 'This draft was previously deleted'
) +
'</strong>';
}
if ( paragraphs[ 1 ] ) {
paragraphs[ 1 ].textContent =
moveLine
? 'Check the move record below before recreating this draft.'
: 'Check the deletion record below before recreating this draft.';
paragraphs[ 1 ].classList.add(
'wp-recreate-description'
);
}
} );
/* ============================================================
WIKIPARTNER — PAGE TOOL MENUS
Draft tools + Admin tools
============================================================ */
mw.loader.using( [
'mediawiki.api',
'mediawiki.util'
] ).then( function () {
$( function () {
var namespace =
Number( mw.config.get( 'wgNamespaceNumber' ) );
var articleId =
Number( mw.config.get( 'wgArticleId' ) || 0 );
var action =
mw.config.get( 'wgAction' );
var pageName =
mw.config.get( 'wgPageName' );
var pageTitle =
mw.config.get( 'wgTitle' );
var groups =
mw.config.get( 'wgUserGroups' ) || [];
/* ----------------------------------------------------
PERMISSION GROUPS
Later we can add:
'reviewer'
'editor'
without rebuilding Draft tools.
---------------------------------------------------- */
var draftToolGroups = [
'sysop'
];
var adminToolGroups = [
'sysop'
];
function userHasGroup( allowedGroups ) {
return allowedGroups.some(
function ( group ) {
return groups.indexOf( group ) !== -1;
}
);
}
var canUseDraftTools =
userHasGroup( draftToolGroups );
var canUseAdminTools =
userHasGroup( adminToolGroups );
/*
* Existing pages in normal view only.
*/
if (
action !== 'view' ||
!articleId ||
namespace === -1
) {
return;
}
var heading =
document.querySelector(
'.wp-article-header .firstHeading, .firstHeading, #firstHeading'
);
if ( !heading ) {
return;
}
var header =
heading.closest( '.wp-article-header' ) ||
heading.parentElement;
if ( !header ) {
return;
}
/* ----------------------------------------------------
SHARED ACTION AREA
---------------------------------------------------- */
var actions =
document.createElement( 'div' );
actions.className =
'wp-title-tools';
header.appendChild( actions );
/* ====================================================
SHARED DROPDOWN FUNCTION
==================================================== */
function createToolMenu(
className,
label
) {
var wrapper =
document.createElement( 'div' );
wrapper.className =
'wp-tool-menu ' + className;
var trigger =
document.createElement( 'button' );
trigger.type =
'button';
trigger.className =
'wp-tool-menu-trigger';
trigger.setAttribute(
'aria-expanded',
'false'
);
trigger.setAttribute(
'aria-haspopup',
'true'
);
var triggerText =
document.createElement( 'span' );
triggerText.textContent =
label;
var arrow =
document.createElement( 'span' );
arrow.className =
'wp-tool-menu-arrow';
arrow.setAttribute(
'aria-hidden',
'true'
);
arrow.textContent =
'▾';
trigger.append(
triggerText,
arrow
);
var menu =
document.createElement( 'div' );
menu.className =
'wp-tool-menu-dropdown';
menu.hidden = true;
wrapper.append(
trigger,
menu
);
trigger.addEventListener(
'click',
function ( event ) {
event.stopPropagation();
/*
* Close every other menu first.
*/
document
.querySelectorAll(
'.wp-tool-menu-dropdown'
)
.forEach(
function ( otherMenu ) {
if ( otherMenu !== menu ) {
otherMenu.hidden = true;
var otherTrigger =
otherMenu
.parentElement
.querySelector(
'.wp-tool-menu-trigger'
);
if ( otherTrigger ) {
otherTrigger.setAttribute(
'aria-expanded',
'false'
);
}
}
}
);
var opening =
menu.hidden;
menu.hidden =
!opening;
trigger.setAttribute(
'aria-expanded',
opening ? 'true' : 'false'
);
}
);
return {
wrapper: wrapper,
trigger: trigger,
menu: menu
};
}
/* ====================================================
DRAFT TOOLS
==================================================== */
if (
namespace === 3000 &&
canUseDraftTools
) {
document.body.classList.add(
'wp-has-draft-tools'
);
var draftTools =
createToolMenu(
'wp-draft-tools',
'Draft tools'
);
/* ------------------------------------------------
Publish
------------------------------------------------ */
var publish =
document.createElement( 'button' );
publish.type =
'button';
publish.className =
'wp-tool-menu-item wp-draft-publish-item';
publish.textContent =
'Publish';
draftTools.menu.appendChild(
publish
);
actions.appendChild(
draftTools.wrapper
);
/* ================================================
PUBLISH MODAL
================================================ */
var overlay =
document.createElement( 'div' );
overlay.className =
'wp-publish-modal-overlay';
overlay.hidden = true;
var modal =
document.createElement( 'div' );
modal.className =
'wp-publish-modal';
modal.setAttribute(
'role',
'dialog'
);
modal.setAttribute(
'aria-modal',
'true'
);
modal.setAttribute(
'aria-labelledby',
'wp-publish-modal-title'
);
var modalTitle =
document.createElement( 'div' );
modalTitle.id =
'wp-publish-modal-title';
modalTitle.className =
'wp-publish-modal-title';
modalTitle.textContent =
'Publish this draft?';
var modalText =
document.createElement( 'div' );
modalText.className =
'wp-publish-modal-text';
var targetName =
document.createElement( 'strong' );
targetName.textContent =
pageTitle ||
'this article';
modalText.append(
'This will publish ',
targetName,
' in the main WikiPartner article space. The “Draft:” prefix will be removed automatically.'
);
var modalNote =
document.createElement( 'div' );
modalNote.className =
'wp-publish-modal-note';
modalNote.textContent =
'The draft will be moved with its revision history.';
var modalActions =
document.createElement( 'div' );
modalActions.className =
'wp-publish-modal-actions';
var cancel =
document.createElement( 'button' );
cancel.type =
'button';
cancel.className =
'wp-publish-modal-cancel';
cancel.textContent =
'Cancel';
var confirm =
document.createElement( 'button' );
confirm.type =
'button';
confirm.className =
'wp-publish-modal-confirm';
confirm.textContent =
'Publish article';
modalActions.append(
cancel,
confirm
);
modal.append(
modalTitle,
modalText,
modalNote,
modalActions
);
overlay.appendChild(
modal
);
document.body.appendChild(
overlay
);
function openPublishModal() {
draftTools.menu.hidden = true;
draftTools.trigger.setAttribute(
'aria-expanded',
'false'
);
modalNote.classList.remove(
'wp-publish-modal-error'
);
modalNote.textContent =
'The draft will be moved with its revision history.';
overlay.hidden = false;
document.body.classList.add(
'wp-publish-modal-open'
);
confirm.focus();
}
function closePublishModal() {
if ( confirm.disabled ) {
return;
}
overlay.hidden = true;
document.body.classList.remove(
'wp-publish-modal-open'
);
draftTools.trigger.focus();
}
publish.addEventListener(
'click',
openPublishModal
);
cancel.addEventListener(
'click',
closePublishModal
);
overlay.addEventListener(
'click',
function ( event ) {
if ( event.target === overlay ) {
closePublishModal();
}
}
);
/* ------------------------------------------------
ACTUAL PUBLISH
------------------------------------------------ */
confirm.addEventListener(
'click',
function () {
if (
!pageName ||
!pageTitle
) {
return;
}
confirm.disabled = true;
cancel.disabled = true;
confirm.textContent =
'Publishing…';
var api =
new mw.Api();
api.postWithToken(
'csrf',
{
action: 'move',
from:
pageName,
to:
pageTitle,
reason:
'Published approved WikiPartner draft',
movetalk:
1,
noredirect:
1,
format:
'json'
}
)
.done(
function () {
window.location.href =
mw.util.getUrl(
pageTitle
);
}
)
.fail(
function (
code,
data
) {
confirm.disabled =
false;
cancel.disabled =
false;
confirm.textContent =
'Publish article';
var message =
'The draft could not be published.';
if (
data &&
data.error &&
data.error.info
) {
message +=
' ' +
data.error.info;
}
modalNote.textContent =
message;
modalNote.classList.add(
'wp-publish-modal-error'
);
}
);
}
);
}
/* ====================================================
ADMIN TOOLS
==================================================== */
if ( canUseAdminTools ) {
document.body.classList.add(
'wp-has-admin-tools'
);
var adminTools =
createToolMenu(
'wp-admin-tools',
'Admin tools'
);
/* Move */
var move =
document.createElement( 'a' );
move.className =
'wp-tool-menu-item';
move.href =
mw.util.getUrl(
'Special:MovePage/' +
pageName
);
move.textContent =
'Move';
/* Purge cache */
var purge =
document.createElement( 'a' );
purge.className =
'wp-tool-menu-item';
purge.href =
mw.util.getUrl(
pageName,
{
action: 'purge'
}
);
purge.textContent =
'Purge cache';
/* Delete */
var remove =
document.createElement( 'a' );
remove.className =
'wp-tool-menu-item wp-tool-menu-delete';
remove.href =
mw.util.getUrl(
pageName,
{
action: 'delete'
}
);
remove.textContent =
'Delete';
adminTools.menu.append(
move,
purge,
remove
);
actions.appendChild(
adminTools.wrapper
);
}
/* ====================================================
GLOBAL MENU CLOSING
==================================================== */
document.addEventListener(
'click',
function ( event ) {
document
.querySelectorAll(
'.wp-tool-menu'
)
.forEach(
function ( wrapper ) {
if (
wrapper.contains(
event.target
)
) {
return;
}
var menu =
wrapper.querySelector(
'.wp-tool-menu-dropdown'
);
var trigger =
wrapper.querySelector(
'.wp-tool-menu-trigger'
);
if ( menu ) {
menu.hidden = true;
}
if ( trigger ) {
trigger.setAttribute(
'aria-expanded',
'false'
);
}
}
);
}
);
document.addEventListener(
'keydown',
function ( event ) {
if ( event.key !== 'Escape' ) {
return;
}
if ( !overlay || overlay.hidden ) {
document
.querySelectorAll(
'.wp-tool-menu-dropdown'
)
.forEach(
function ( menu ) {
menu.hidden = true;
}
);
document
.querySelectorAll(
'.wp-tool-menu-trigger'
)
.forEach(
function ( trigger ) {
trigger.setAttribute(
'aria-expanded',
'false'
);
}
);
} else {
closePublishModal();
}
}
);
} );
} );
/* ============================================================
WIKIPARTNER — MOVE / DELETE ADMIN PAGES
============================================================ */
$( function () {
var pageName =
mw.config.get( 'wgPageName' ) || '';
var action =
mw.config.get( 'wgAction' ) || '';
var content =
document.getElementById( 'mw-content-text' );
if ( !content ) {
return;
}
var isMove =
/^Special:(?:MovePage|Movepage)\//i.test(
pageName
);
var isDelete =
action === 'delete';
if ( !isMove && !isDelete ) {
return;
}
document.body.classList.add(
isMove
? 'wp-admin-move-page'
: 'wp-admin-delete-page'
);
/*
* Find the main MediaWiki action form.
*/
var form =
content.querySelector( 'form' );
if ( !form ) {
return;
}
form.classList.add(
'wp-admin-action-form'
);
/*
* Find the direct child of #mw-content-text
* which contains the form.
*/
var formBlock =
form;
while (
formBlock.parentElement &&
formBlock.parentElement !== content
) {
formBlock =
formBlock.parentElement;
}
/* --------------------------------------------------------
HIDE LONG DEFAULT INTRO PARAGRAPHS
-------------------------------------------------------- */
var node =
content.firstElementChild;
while (
node &&
node !== formBlock
) {
if (
node.tagName === 'P'
) {
node.classList.add(
'wp-admin-native-intro'
);
}
node =
node.nextElementSibling;
}
/* --------------------------------------------------------
MOVE PAGE INTRO
-------------------------------------------------------- */
if ( isMove ) {
var intro =
document.createElement( 'div' );
intro.className =
'wp-admin-action-intro';
intro.innerHTML =
'<strong>Move this page</strong>' +
'<span>Move the page to a new title while keeping its revision history. Leave a redirect if the old title should continue pointing to the new one.</span>';
content.insertBefore(
intro,
content.firstElementChild
);
/*
* Shorten the Category move warning while
* preserving its important meaning.
*/
var moveWarning =
content.querySelector(
'.cdx-message--warning, ' +
'.mw-message-box-warning, ' +
'.warningbox'
);
if (
moveWarning &&
/category page/i.test(
moveWarning.textContent
)
) {
var warningContent =
moveWarning.querySelector(
'.cdx-message__content'
) ||
moveWarning;
warningContent.textContent =
'Moving a category page does not recategorize pages from the old category.';
}
}
/* --------------------------------------------------------
DELETE PAGE NOTICE
-------------------------------------------------------- */
if ( isDelete ) {
var deleteNotice =
document.createElement( 'div' );
deleteNotice.className =
'wp-admin-delete-notice';
var deleteLabel =
document.createElement( 'div' );
deleteLabel.className =
'wp-admin-delete-label';
deleteLabel.textContent =
'Warning';
var deleteTitle =
document.createElement( 'strong' );
deleteTitle.className =
'wp-admin-delete-title';
deleteTitle.textContent =
'You are about to delete this page';
var deleteText =
document.createElement( 'div' );
deleteText.className =
'wp-admin-delete-text';
deleteText.append(
'Deleting this page removes it from normal view. Review its '
);
var historyLink =
document.createElement( 'a' );
historyLink.href =
mw.util.getUrl(
pageName,
{
action: 'history'
}
);
historyLink.textContent =
'page history';
deleteText.append(
historyLink,
' before continuing.'
);
deleteNotice.append(
deleteLabel,
deleteTitle,
deleteText
);
content.insertBefore(
deleteNotice,
content.firstElementChild
);
}
/* --------------------------------------------------------
TAG SUBMIT BUTTON
-------------------------------------------------------- */
var submitButtons =
form.querySelectorAll(
'input[type="submit"], button[type="submit"]'
);
submitButtons.forEach(
function ( button ) {
button.classList.add(
'wp-admin-action-submit'
);
if ( isDelete ) {
button.classList.add(
'wp-admin-danger-submit'
);
}
}
);
/* --------------------------------------------------------
HIDE ADMIN META LINKS
-------------------------------------------------------- */
content
.querySelectorAll( 'a' )
.forEach(
function ( link ) {
var text =
link.textContent
.trim();
if (
/^Edit (move|deletion) reasons$/i.test(
text
)
) {
link.classList.add(
'wp-admin-meta-link-hidden'
);
}
}
);
/* --------------------------------------------------------
REMOVE EMPTY LOG SECTIONS
-------------------------------------------------------- */
content
.querySelectorAll( 'h2' )
.forEach(
function ( heading ) {
var headingText =
heading.textContent
.trim();
if (
!/^(Move log|Deletion log|Page creation log)$/i.test(
headingText
)
) {
return;
}
var sectionNodes = [];
var next =
heading.nextElementSibling;
while (
next &&
next.tagName !== 'H2'
) {
sectionNodes.push(
next
);
next =
next.nextElementSibling;
}
var sectionText =
sectionNodes
.map(
function ( item ) {
return item.textContent;
}
)
.join( ' ' );
var hasRealLog =
sectionNodes.some(
function ( item ) {
return (
item.matches &&
item.matches(
'[class*="mw-logline-"]'
)
) ||
(
item.querySelector &&
item.querySelector(
'[class*="mw-logline-"]'
)
);
}
);
if (
!hasRealLog &&
/No matching items in log/i.test(
sectionText
)
) {
heading.style.display =
'none';
sectionNodes.forEach(
function ( item ) {
item.style.display =
'none';
}
);
}
}
);
} );
/* ============================================================
WIKIPARTNER — ENHANCED FILE PAGE
============================================================ */
$( function () {
if (
Number( mw.config.get( 'wgNamespaceNumber' ) ) !== 6 ||
mw.config.get( 'wgAction' ) !== 'view' ||
!mw.config.get( 'wgArticleId' )
) {
return;
}
if (
document.querySelector(
'.wp-file-overview'
)
) {
return;
}
var preview =
document.querySelector(
'.fullImageLink'
);
var originalFile =
document.querySelector(
'.fullMedia'
);
var information =
document.getElementById(
'mw-imagepage-content'
);
if (
!preview ||
!information
) {
return;
}
var parent =
preview.parentNode;
/* --------------------------------------------------------
OVERVIEW
-------------------------------------------------------- */
var overview =
document.createElement( 'div' );
overview.className =
'wp-file-overview';
parent.insertBefore(
overview,
preview
);
/* --------------------------------------------------------
PREVIEW CARD
-------------------------------------------------------- */
var previewCard =
document.createElement( 'section' );
previewCard.className =
'wp-file-preview-card';
var previewTitle =
document.createElement( 'div' );
previewTitle.className =
'wp-file-preview-title';
previewTitle.textContent =
'Image preview';
previewCard.appendChild(
previewTitle
);
previewCard.appendChild(
preview
);
if ( originalFile ) {
previewCard.appendChild(
originalFile
);
}
overview.appendChild(
previewCard
);
/* --------------------------------------------------------
FILE INFORMATION
-------------------------------------------------------- */
information.classList.add(
'wp-file-details'
);
overview.appendChild(
information
);
document.body.classList.add(
'wp-file-page-enhanced'
);
} );
/* ============================================================
WIKIPARTNER — SPECIAL:UPLOAD CUSTOM SELECTS
============================================================ */
(function () {
'use strict';
function enhanceWikiPartnerSelect(select) {
if (
!select ||
select.dataset.wpSelectEnhanced === '1'
) {
return;
}
select.dataset.wpSelectEnhanced = '1';
var wrapper =
document.createElement('div');
wrapper.className =
'wp-select';
var button =
document.createElement('button');
button.type =
'button';
button.className =
'wp-select-button';
button.id =
select.id + '-button';
button.setAttribute(
'aria-haspopup',
'listbox'
);
button.setAttribute(
'aria-expanded',
'false'
);
var menu =
document.createElement('div');
menu.className =
'wp-select-menu';
menu.id =
select.id + '-menu';
menu.setAttribute(
'role',
'listbox'
);
menu.hidden =
true;
button.setAttribute(
'aria-controls',
menu.id
);
var items = [];
Array.prototype.forEach.call(
select.options,
function (option, index) {
var item =
document.createElement(
'button'
);
item.type =
'button';
item.className =
'wp-select-option';
item.textContent =
option.textContent;
item.setAttribute(
'role',
'option'
);
item.tabIndex =
-1;
item.addEventListener(
'click',
function () {
select.selectedIndex =
index;
select.dispatchEvent(
new Event(
'change',
{
bubbles: true
}
)
);
sync();
close();
button.focus();
}
);
items.push(item);
menu.appendChild(item);
}
);
function sync() {
var selected =
select.options[
select.selectedIndex
] || select.options[0];
button.textContent =
selected
? selected.textContent
: '';
items.forEach(
function (item, index) {
var active =
index ===
select.selectedIndex;
item.classList.toggle(
'is-selected',
active
);
item.setAttribute(
'aria-selected',
active
? 'true'
: 'false'
);
}
);
}
function closeOthers() {
document.querySelectorAll(
'.wp-select.is-open'
).forEach(
function (other) {
if (other === wrapper) {
return;
}
other.classList.remove(
'is-open'
);
var otherMenu =
other.querySelector(
'.wp-select-menu'
);
var otherButton =
other.querySelector(
'.wp-select-button'
);
if (otherMenu) {
otherMenu.hidden = true;
}
if (otherButton) {
otherButton.setAttribute(
'aria-expanded',
'false'
);
}
}
);
}
function open() {
closeOthers();
menu.hidden =
false;
wrapper.classList.add(
'is-open'
);
button.setAttribute(
'aria-expanded',
'true'
);
var selectedItem =
menu.querySelector(
'.is-selected'
);
if (selectedItem) {
selectedItem.focus();
}
}
function close() {
menu.hidden =
true;
wrapper.classList.remove(
'is-open'
);
button.setAttribute(
'aria-expanded',
'false'
);
}
button.addEventListener(
'click',
function () {
if (
wrapper.classList.contains(
'is-open'
)
) {
close();
} else {
open();
}
}
);
button.addEventListener(
'keydown',
function (event) {
if (
event.key === 'ArrowDown' ||
event.key === 'ArrowUp' ||
event.key === 'Enter' ||
event.key === ' '
) {
event.preventDefault();
open();
}
}
);
menu.addEventListener(
'keydown',
function (event) {
var current =
items.indexOf(
document.activeElement
);
if (event.key === 'Escape') {
event.preventDefault();
close();
button.focus();
return;
}
if (
event.key !== 'ArrowDown' &&
event.key !== 'ArrowUp'
) {
return;
}
event.preventDefault();
if (current < 0) {
current =
select.selectedIndex;
}
if (event.key === 'ArrowDown') {
current =
Math.min(
current + 1,
items.length - 1
);
} else {
current =
Math.max(
current - 1,
0
);
}
items[current].focus();
}
);
document.addEventListener(
'click',
function (event) {
if (
!wrapper.contains(
event.target
)
) {
close();
}
}
);
select.addEventListener(
'change',
sync
);
var parent =
select.parentNode;
parent.insertBefore(
wrapper,
select
);
wrapper.appendChild(
select
);
wrapper.appendChild(
button
);
wrapper.appendChild(
menu
);
select.classList.add(
'wp-select-native'
);
var label =
document.querySelector(
'label[for="' +
select.id +
'"]'
);
if (label) {
label.setAttribute(
'for',
button.id
);
}
sync();
}
function initWikiPartnerUploadSelects() {
if (
!document.body.classList.contains(
'mw-special-Upload'
)
) {
return;
}
[
'wpWikiPartnerCreatorType',
'wpWikiPartnerLicense'
].forEach(
function (id) {
enhanceWikiPartnerSelect(
document.getElementById(id)
);
}
);
}
if (
document.readyState === 'loading'
) {
document.addEventListener(
'DOMContentLoaded',
initWikiPartnerUploadSelects
);
} else {
initWikiPartnerUploadSelects();
}
})();