MediaWiki:Common.js: Difference between revisions
Remove non-Main header DOM grouping and restore native structure v2T |
Relocate exact non-Main account controls by ID v2U |
||
| Line 742: | Line 742: | ||
/* RV_DATA_HEADER_CLICK_FIX_V2O_END */ | /* RV_DATA_HEADER_CLICK_FIX_V2O_END */ | ||
/* | /* RV_DATA_EXACT_HEADER_CONTROLS_V2U_START */ | ||
(function () { | (function () { | ||
"use strict"; | "use strict"; | ||
| Line 760: | Line 760: | ||
} | } | ||
function | var observer = null; | ||
var | var attempts = 0; | ||
var maximumAttempts = 40; | |||
function directText(element) { | |||
var text = ""; | |||
if (!element) { | |||
return text; | |||
} | |||
Array.prototype.forEach.call( | |||
element.childNodes, | |||
function (node) { | |||
if ( | |||
node.nodeType === 3 | |||
&& | |||
node.nodeValue | |||
) { | |||
text += | |||
node.nodeValue.trim(); | |||
} | |||
} | |||
); | |||
return text; | |||
} | |||
function markEmptyAncestors( | |||
startingElement, | |||
stopElement | |||
) { | |||
var current = | |||
startingElement; | |||
while ( | |||
current | |||
&& | |||
current !== stopElement | |||
&& | |||
current !== document.body | |||
) { | |||
var interactive = | |||
current.querySelector( | |||
[ | |||
"a", | |||
"button", | |||
"label", | |||
"input", | |||
".vector-dropdown" | |||
].join(",") | |||
); | |||
if ( | |||
!interactive | |||
&& | |||
directText(current) === "" | |||
) { | |||
current.classList.add( | |||
"rv-header-empty-shell" | |||
); | |||
} | |||
current = | |||
current.parentElement; | |||
} | |||
} | |||
function locateTopAccountItem(id) { | |||
var element = | |||
document.getElementById(id); | |||
if (!element) { | |||
return null; | |||
} | |||
/* | |||
* The top header uses the -2 IDs. | |||
* Do not use duplicate account links inside | |||
* the Personal tools dropdown. | |||
*/ | |||
if ( | |||
element.closest( | |||
"#vector-user-links-dropdown .vector-dropdown-content" | |||
) | |||
) { | |||
return null; | |||
} | |||
return element; | |||
} | |||
function installExactHeaderRow() { | |||
attempts += 1; | |||
var headerEnd = | |||
document.querySelector( | |||
".vector-header-end" | |||
); | |||
var appearance = | |||
document.getElementById( | document.getElementById( | ||
" | "vector-appearance-dropdown" | ||
); | |||
var createAccount = | |||
locateTopAccountItem( | |||
"pt-createaccount-2" | |||
); | |||
var login = | |||
locateTopAccountItem( | |||
"pt-login-2" | |||
); | ); | ||
var personalTools = | |||
document. | document.getElementById( | ||
" | "vector-user-links-dropdown" | ||
); | ); | ||
return; | if ( | ||
!headerEnd | |||
|| | |||
!createAccount | |||
|| | |||
!login | |||
) { | |||
return false; | |||
} | } | ||
var | var host = | ||
document.getElementById( | |||
"rv-exact-header-controls" | |||
); | |||
if (! | if (!host) { | ||
host = | |||
document.createElement( | |||
"div" | |||
); | |||
host.id = | |||
"rv-exact-header-controls"; | |||
host.className = | |||
"rv-exact-header-controls"; | |||
headerEnd.insertBefore( | |||
host, | |||
headerEnd.firstChild | |||
host | |||
); | ); | ||
} | } | ||
host. | var controls = [ | ||
host | appearance, | ||
createAccount, | |||
login, | |||
personalTools | |||
]; | |||
controls.forEach( | |||
function (control) { | |||
if (!control) { | |||
return; | |||
} | |||
var oldParent = | |||
control.parentElement; | |||
if ( | |||
control.parentElement !== host | |||
) { | |||
host.appendChild( | |||
control | |||
); | |||
} | |||
markEmptyAncestors( | |||
oldParent, | |||
headerEnd | |||
); | |||
} | |||
); | |||
host.setAttribute( | |||
"data-rv-exact-header", | |||
"2u" | |||
); | |||
host.setAttribute( | |||
"data-rv-control-count", | |||
String( | |||
controls.filter( | |||
function (control) { | |||
return Boolean(control); | |||
} | |||
).length | |||
) | |||
); | ); | ||
document.body.setAttribute( | document.body.setAttribute( | ||
"data-rv- | "data-rv-exact-header-ready", | ||
" | "2u" | ||
); | |||
document.body.setAttribute( | |||
"data-rv-exact-header-count", | |||
host.getAttribute( | |||
"data-rv-control-count" | |||
) | |||
); | |||
return true; | |||
} | |||
function tryInstall() { | |||
var installed = | |||
installExactHeaderRow(); | |||
if ( | |||
installed | |||
|| | |||
attempts >= maximumAttempts | |||
) { | |||
if (observer) { | |||
observer.disconnect(); | |||
observer = null; | |||
} | |||
return; | |||
} | |||
window.setTimeout( | |||
tryInstall, | |||
100 | |||
); | ); | ||
} | } | ||
| Line 810: | Line 1,002: | ||
function () { | function () { | ||
window.requestAnimationFrame( | window.requestAnimationFrame( | ||
tryInstall | |||
); | ); | ||
} | } | ||
); | ); | ||
} | } | ||
observer = | |||
new MutationObserver( | |||
function () { | |||
if ( | |||
document.getElementById( | |||
"rv-exact-header-controls" | |||
) | |||
) { | |||
observer.disconnect(); | |||
observer = null; | |||
return; | |||
} | |||
tryInstall(); | |||
} | |||
); | |||
observer.observe( | |||
document.documentElement, | |||
{ | |||
childList: true, | |||
subtree: true | |||
} | |||
); | |||
if ( | if ( | ||
| Line 840: | Line 1,058: | ||
window.setTimeout( | window.setTimeout( | ||
initialize, | initialize, | ||
200 | |||
); | ); | ||
window.setTimeout( | window.setTimeout( | ||
initialize, | initialize, | ||
700 | |||
); | ); | ||
}()); | }()); | ||
/* | /* RV_DATA_EXACT_HEADER_CONTROLS_V2U_END */ | ||
Revision as of 19:29, 20 July 2026
/* RV_DATA_MAIN_PAGE_VIEWPORT_CENTER_V2D_START */
(function () {
"use strict";
if (
!document.body ||
!document.body.classList.contains(
"page-Main_Page"
)
) {
return;
}
var animationFrame = 0;
var resizeTimer = 0;
function setImportant(element, property, value) {
if (!element) {
return;
}
element.style.setProperty(
property,
value,
"important"
);
}
function releaseAncestorClipping(home) {
var current = home.parentElement;
while (
current &&
current !== document.body
) {
setImportant(
current,
"overflow-x",
"visible"
);
current = current.parentElement;
}
setImportant(
document.body,
"overflow-x",
"hidden"
);
setImportant(
document.documentElement,
"overflow-x",
"hidden"
);
}
function centerHomepage() {
var home = document.querySelector(
".rdx-home"
);
if (!home) {
return;
}
releaseAncestorClipping(home);
var viewportWidth =
document.documentElement.clientWidth ||
window.innerWidth ||
0;
if (!viewportWidth) {
return;
}
var gutter;
if (viewportWidth <= 700) {
gutter = 0;
} else if (viewportWidth <= 1100) {
gutter = 16;
} else {
gutter = 32;
}
var availableWidth =
viewportWidth - (gutter * 2);
var targetWidth = Math.min(
1180,
availableWidth
);
targetWidth = Math.max(
320,
targetWidth
);
/*
* Reset all earlier CSS positioning before
* measuring the element's natural browser
* location.
*/
setImportant(
home,
"position",
"relative"
);
setImportant(
home,
"left",
"0"
);
setImportant(
home,
"right",
"auto"
);
setImportant(
home,
"width",
targetWidth + "px"
);
setImportant(
home,
"max-width",
"none"
);
setImportant(
home,
"margin-left",
"0"
);
setImportant(
home,
"margin-right",
"0"
);
setImportant(
home,
"transform",
"none"
);
/*
* Force layout calculation after removing
* all previous transforms.
*/
void home.offsetWidth;
var rectangle =
home.getBoundingClientRect();
var desiredLeft = Math.round(
(viewportWidth - targetWidth) / 2
);
var correction = Math.round(
desiredLeft - rectangle.left
);
setImportant(
home,
"transform",
"translate3d(" +
correction +
"px, 0, 0)"
);
home.setAttribute(
"data-rdx-viewport-centered",
"true"
);
home.setAttribute(
"data-rdx-viewport-width",
String(viewportWidth)
);
home.setAttribute(
"data-rdx-target-width",
String(targetWidth)
);
home.setAttribute(
"data-rdx-original-left",
String(
Math.round(rectangle.left)
)
);
home.setAttribute(
"data-rdx-correction",
String(correction)
);
/*
* Verify the rendered result and perform one
* final adjustment for sub-pixel browser
* rounding or delayed Vector layout changes.
*/
window.requestAnimationFrame(
function () {
var finalRectangle =
home.getBoundingClientRect();
var remainingDifference =
Math.round(
desiredLeft -
finalRectangle.left
);
if (
Math.abs(
remainingDifference
) > 1
) {
correction +=
remainingDifference;
setImportant(
home,
"transform",
"translate3d(" +
correction +
"px, 0, 0)"
);
home.setAttribute(
"data-rdx-correction",
String(correction)
);
}
home.setAttribute(
"data-rdx-final-left",
String(
Math.round(
home
.getBoundingClientRect()
.left
)
)
);
}
);
}
function queueCentering() {
if (animationFrame) {
window.cancelAnimationFrame(
animationFrame
);
}
animationFrame =
window.requestAnimationFrame(
function () {
animationFrame =
window.requestAnimationFrame(
centerHomepage
);
}
);
}
function delayedCentering() {
window.clearTimeout(
resizeTimer
);
resizeTimer = window.setTimeout(
queueCentering,
80
);
}
if (
document.readyState === "loading"
) {
document.addEventListener(
"DOMContentLoaded",
queueCentering,
{
once: true
}
);
} else {
queueCentering();
}
window.addEventListener(
"load",
queueCentering
);
window.addEventListener(
"resize",
delayedCentering
);
if (window.visualViewport) {
window.visualViewport.addEventListener(
"resize",
delayedCentering
);
}
/*
* Vector and ResourceLoader can finish portions
* of their layout after DOM ready. Recheck after
* those delayed changes.
*/
window.setTimeout(
queueCentering,
250
);
window.setTimeout(
queueCentering,
750
);
window.setTimeout(
queueCentering,
1500
);
}());
/* RV_DATA_MAIN_PAGE_VIEWPORT_CENTER_V2D_END */
/* RV_DATA_HEADER_CLICK_FIX_V2O_START */
(function () {
"use strict";
if (
!document.body ||
!document.body.classList.contains(
"page-Main_Page"
)
) {
return;
}
function important(
element,
property,
value
) {
if (!element) {
return;
}
element.style.setProperty(
property,
value,
"important"
);
}
function moveToolsOnce() {
var views =
document.getElementById(
"p-views"
);
var tools =
document.getElementById(
"vector-page-tools-dropdown"
)
||
document.querySelector(
".vector-page-tools-landmark"
);
if (
!views ||
!tools ||
!views.parentNode
) {
return;
}
if (
tools.parentNode !==
views.parentNode
||
tools.previousElementSibling !==
views
) {
views.parentNode.insertBefore(
tools,
views.nextSibling
);
}
tools.classList.add(
"rv-tools-inline"
);
tools.setAttribute(
"data-rv-tools-inline",
"2o"
);
}
function getHeaderTargets() {
var selectors = [
"#vector-appearance-dropdown > .vector-dropdown-label",
"#vector-appearance-dropdown button",
"#pt-createaccount-2 > a",
"#pt-createaccount > a",
"#pt-login-2 > a",
"#pt-login > a",
"#vector-user-links-dropdown > .vector-dropdown-label",
"#vector-user-links-dropdown button"
];
var targets = [];
selectors.forEach(
function (selector) {
document
.querySelectorAll(selector)
.forEach(
function (element) {
if (
targets.indexOf(
element
) === -1
) {
targets.push(
element
);
}
}
);
}
);
return targets;
}
function raiseHeaderControls() {
var headerContainer =
document.querySelector(
".vector-header-container"
);
var header =
document.querySelector(
".vector-header"
);
var headerEnd =
document.querySelector(
".vector-header-end"
);
important(
headerContainer,
"position",
"relative"
);
important(
headerContainer,
"z-index",
"2147482000"
);
important(
headerContainer,
"overflow",
"visible"
);
important(
headerContainer,
"pointer-events",
"auto"
);
important(
header,
"position",
"relative"
);
important(
header,
"z-index",
"1"
);
important(
header,
"overflow",
"visible"
);
important(
header,
"pointer-events",
"auto"
);
important(
headerEnd,
"position",
"relative"
);
important(
headerEnd,
"z-index",
"100"
);
important(
headerEnd,
"overflow",
"visible"
);
important(
headerEnd,
"pointer-events",
"auto"
);
getHeaderTargets().forEach(
function (target) {
important(
target,
"position",
"relative"
);
important(
target,
"z-index",
"110"
);
important(
target,
"pointer-events",
"auto"
);
important(
target,
"touch-action",
"manipulation"
);
target.setAttribute(
"data-rv-click-ready",
"2o"
);
}
);
}
function auditHeaderTargets() {
var report = [];
getHeaderTargets().forEach(
function (target) {
var rectangle =
target.getBoundingClientRect();
if (
rectangle.width <= 0
||
rectangle.height <= 0
) {
return;
}
var x =
Math.round(
rectangle.left
+
rectangle.width / 2
);
var y =
Math.round(
rectangle.top
+
rectangle.height / 2
);
var topElement =
document.elementFromPoint(
x,
y
);
var related = Boolean(
topElement
&&
(
topElement === target
||
target.contains(
topElement
)
||
topElement.contains(
target
)
)
);
report.push({
target:
target.id
||
target.className
||
target.tagName,
text:
(
target.textContent
||
target.getAttribute(
"aria-label"
)
||
""
).trim(),
clickable: related,
topElement:
topElement
?
(
topElement.id
||
topElement.className
||
topElement.tagName
)
:
null
});
}
);
window.roovetHeaderClickAudit =
report;
document.body.setAttribute(
"data-rv-header-click-ready",
"2o"
);
document.body.setAttribute(
"data-rv-header-target-count",
String(report.length)
);
document.body.setAttribute(
"data-rv-header-clickable-count",
String(
report.filter(
function (entry) {
return entry.clickable;
}
).length
)
);
}
function initialize() {
moveToolsOnce();
raiseHeaderControls();
window.requestAnimationFrame(
function () {
raiseHeaderControls();
auditHeaderTargets();
}
);
}
if (
document.readyState ===
"loading"
) {
document.addEventListener(
"DOMContentLoaded",
initialize,
{
once: true
}
);
} else {
initialize();
}
window.addEventListener(
"load",
initialize,
{
once: true
}
);
/*
* Vector and ResourceLoader may finish individual
* controls shortly after page load.
*/
window.setTimeout(
initialize,
150
);
window.setTimeout(
initialize,
500
);
window.setTimeout(
initialize,
1200
);
}());
/* RV_DATA_HEADER_CLICK_FIX_V2O_END */
/* RV_DATA_EXACT_HEADER_CONTROLS_V2U_START */
(function () {
"use strict";
if (
!document.body
||
document.body.classList.contains(
"page-Main_Page"
)
||
!document.body.classList.contains(
"skin-vector-2022"
)
) {
return;
}
var observer = null;
var attempts = 0;
var maximumAttempts = 40;
function directText(element) {
var text = "";
if (!element) {
return text;
}
Array.prototype.forEach.call(
element.childNodes,
function (node) {
if (
node.nodeType === 3
&&
node.nodeValue
) {
text +=
node.nodeValue.trim();
}
}
);
return text;
}
function markEmptyAncestors(
startingElement,
stopElement
) {
var current =
startingElement;
while (
current
&&
current !== stopElement
&&
current !== document.body
) {
var interactive =
current.querySelector(
[
"a",
"button",
"label",
"input",
".vector-dropdown"
].join(",")
);
if (
!interactive
&&
directText(current) === ""
) {
current.classList.add(
"rv-header-empty-shell"
);
}
current =
current.parentElement;
}
}
function locateTopAccountItem(id) {
var element =
document.getElementById(id);
if (!element) {
return null;
}
/*
* The top header uses the -2 IDs.
* Do not use duplicate account links inside
* the Personal tools dropdown.
*/
if (
element.closest(
"#vector-user-links-dropdown .vector-dropdown-content"
)
) {
return null;
}
return element;
}
function installExactHeaderRow() {
attempts += 1;
var headerEnd =
document.querySelector(
".vector-header-end"
);
var appearance =
document.getElementById(
"vector-appearance-dropdown"
);
var createAccount =
locateTopAccountItem(
"pt-createaccount-2"
);
var login =
locateTopAccountItem(
"pt-login-2"
);
var personalTools =
document.getElementById(
"vector-user-links-dropdown"
);
if (
!headerEnd
||
!createAccount
||
!login
) {
return false;
}
var host =
document.getElementById(
"rv-exact-header-controls"
);
if (!host) {
host =
document.createElement(
"div"
);
host.id =
"rv-exact-header-controls";
host.className =
"rv-exact-header-controls";
headerEnd.insertBefore(
host,
headerEnd.firstChild
);
}
var controls = [
appearance,
createAccount,
login,
personalTools
];
controls.forEach(
function (control) {
if (!control) {
return;
}
var oldParent =
control.parentElement;
if (
control.parentElement !== host
) {
host.appendChild(
control
);
}
markEmptyAncestors(
oldParent,
headerEnd
);
}
);
host.setAttribute(
"data-rv-exact-header",
"2u"
);
host.setAttribute(
"data-rv-control-count",
String(
controls.filter(
function (control) {
return Boolean(control);
}
).length
)
);
document.body.setAttribute(
"data-rv-exact-header-ready",
"2u"
);
document.body.setAttribute(
"data-rv-exact-header-count",
host.getAttribute(
"data-rv-control-count"
)
);
return true;
}
function tryInstall() {
var installed =
installExactHeaderRow();
if (
installed
||
attempts >= maximumAttempts
) {
if (observer) {
observer.disconnect();
observer = null;
}
return;
}
window.setTimeout(
tryInstall,
100
);
}
function initialize() {
window.requestAnimationFrame(
function () {
window.requestAnimationFrame(
tryInstall
);
}
);
}
observer =
new MutationObserver(
function () {
if (
document.getElementById(
"rv-exact-header-controls"
)
) {
observer.disconnect();
observer = null;
return;
}
tryInstall();
}
);
observer.observe(
document.documentElement,
{
childList: true,
subtree: true
}
);
if (
document.readyState === "loading"
) {
document.addEventListener(
"DOMContentLoaded",
initialize,
{
once: true
}
);
} else {
initialize();
}
window.addEventListener(
"load",
initialize,
{
once: true
}
);
window.setTimeout(
initialize,
200
);
window.setTimeout(
initialize,
700
);
}());
/* RV_DATA_EXACT_HEADER_CONTROLS_V2U_END */