|
|
| (One intermediate revision by the same user not shown) |
| Line 1: |
Line 1: |
| /* RV_DATA_MAIN_PAGE_VIEWPORT_CENTER_V2D_START */ | | /* Search enhancement is maintained in the RoovetData skin. Page layout is rendered by MediaWiki and CSS. */ |
| (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 */
| |