MediaWiki:Common.js: Unterschied zwischen den Versionen
Keine Bearbeitungszusammenfassung |
Keine Bearbeitungszusammenfassung |
||
| (31 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt) | |||
| Zeile 1: | Zeile 1: | ||
/* === PREPRINT START === */ | /* === PREPRINT START === */ | ||
/* ============================================ | /* ============================================ | ||
PREPRINT v7.17 - JS | PREPRINT v7.17 - JS v260225r1 | ||
============================================ */ | ============================================ */ | ||
| Zeile 14: | Zeile 9: | ||
// Prevent repeated initialization | // Prevent repeated initialization | ||
if (window.preprintInitialized) { | if (window.preprintInitialized) { | ||
return; | return; | ||
} | } | ||
| Zeile 35: | Zeile 29: | ||
var imagesStabilized = false; | var imagesStabilized = false; | ||
// Debug logging with source tracking | // Debug logging with source tracking (silent in production) | ||
function log(adapter, message) { | function log(adapter, message) { | ||
} | } | ||
| Zeile 571: | Zeile 564: | ||
function getLinkage() { | function getLinkage() { | ||
return linkage; | return linkage; | ||
} | |||
/* --- List Repair --- */ | |||
// MW parser ejects template-generated spans (Place) from list items: | |||
// Pattern A (start): <li class="mw-empty-elt"/> + <p><span>...</span>text</p> | |||
// Pattern B (end): <li>text</li> + <p><span>...</span></p> | |||
// Both followed optionally by a continuation list. | |||
// This repairs the DOM before structure analysis. | |||
function repairListPlacement() { | |||
var $output = $('.mw-parser-output'); | |||
if (!$output.length) return; | |||
var repaired = 0; | |||
function findEmptyItem($list) { | |||
var $li = $list.find('li.mw-empty-elt').last(); | |||
if ($li.length) return $li; | |||
var $dd = $list.find('dd').filter(function() { | |||
return this.childNodes.length === 0; | |||
}).last(); | |||
return $dd.length ? $dd : null; | |||
} | |||
function isNestingWrapper(el) { | |||
if (el.tagName !== 'LI') return false; | |||
if (el.children.length !== 1) return false; | |||
if (!/^(UL|OL|DL)$/.test(el.firstElementChild.tagName)) return false; | |||
for (var i = 0; i < el.childNodes.length; i++) { | |||
if (el.childNodes[i].nodeType === 3 && el.childNodes[i].textContent.trim()) return false; | |||
} | |||
return true; | |||
} | |||
$output.find('p').each(function() { | |||
var p = this; | |||
if (!p.parentNode) return; | |||
var first = p.firstChild; | |||
if (!first || first.nodeType !== 1) return; | |||
if (!first.classList.contains('place-lh') && !first.classList.contains('place-oc')) return; | |||
var $p = $(p); | |||
var $prevList = $p.prev('ul, ol, dl'); | |||
if (!$prevList.length) return; | |||
// Pattern A: empty item (Place at start of list item) | |||
var $target = findEmptyItem($prevList); | |||
var isPatternA = $target !== null; | |||
// Pattern B: no empty item (Place at end of list item) | |||
if (!$target) { | |||
$target = $prevList.find('li').last(); | |||
if (!$target.length) $target = $prevList.find('dd').last(); | |||
if (!$target.length) return; | |||
} | |||
if (isPatternA) $target.removeClass('mw-empty-elt'); | |||
// Move <p> contents into target item | |||
while (p.firstChild) { | |||
$target[0].appendChild(p.firstChild); | |||
} | |||
// Merge continuation list if same type follows | |||
var $next = $p.next(); | |||
if ($next.length && $next[0].tagName === $prevList[0].tagName) { | |||
var targetAtRoot = $target[0].parentNode === $prevList[0]; | |||
var children = $next.children().get(); | |||
for (var i = 0; i < children.length; i++) { | |||
if (isNestingWrapper(children[i])) { | |||
var subList = children[i].firstElementChild; | |||
if (targetAtRoot) { | |||
// Pattern B: sub-list becomes child of target | |||
$target[0].appendChild(subList); | |||
} else { | |||
// Pattern A: sub-list items become siblings | |||
var parentList = $target[0].parentNode; | |||
while (subList.firstChild) { | |||
parentList.appendChild(subList.firstChild); | |||
} | |||
} | |||
} else { | |||
$prevList[0].appendChild(children[i]); | |||
} | |||
} | |||
$next.remove(); | |||
} | |||
$p.remove(); | |||
repaired++; | |||
}); | |||
} | } | ||
| Zeile 576: | Zeile 661: | ||
function buildStructure() { | function buildStructure() { | ||
repairListPlacement(); | |||
var parserOutput = $('.mw-parser-output'); | var parserOutput = $('.mw-parser-output'); | ||
var elements = parserOutput.children().toArray(); | var elements = parserOutput.children().toArray(); | ||
| Zeile 662: | Zeile 748: | ||
} | } | ||
}); | }); | ||
// Helper functions (closure) | // Helper functions (closure) | ||
function ensureColumns() { | function ensureColumns() { | ||
| Zeile 706: | Zeile 790: | ||
if (layout && layout[0]) layout[0].style.paddingBottom = ''; | if (layout && layout[0]) layout[0].style.paddingBottom = ''; | ||
$('.preprint-oc-spacer').remove(); | $('.preprint-oc-spacer').remove(); | ||
// Clear inline positioning | // Clear inline positioning set by landscape projection | ||
linkage.forEach(function(link) { | linkage.forEach(function(link) { | ||
link.element[0].style.top = ' | link.element[0].style.top = ''; | ||
link.element[0].style.position = ''; | |||
}); | }); | ||
| Zeile 761: | Zeile 846: | ||
scrollToHash(); | scrollToHash(); | ||
} | } | ||
| Zeile 792: | Zeile 876: | ||
scrollToHash(); | scrollToHash(); | ||
} | } | ||
| Zeile 802: | Zeile 885: | ||
// Disconnect observer to prevent re-entry from our writes | // Disconnect observer to prevent re-entry from our writes | ||
if (layout._ocObserver) layout._ocObserver.disconnect(); | if (layout._ocObserver) layout._ocObserver.disconnect(); | ||
// Save and reset scroll for accurate offset calculations (Minerva scrolls body) | |||
var savedBodyScroll = document.body.scrollTop; | |||
var savedHtmlScroll = document.documentElement.scrollTop; | |||
document.body.scrollTop = 0; | |||
document.documentElement.scrollTop = 0; | |||
// === PHASE 1: CLEAN + READ === | // === PHASE 1: CLEAN + READ === | ||
// Remove all previous | // Remove all previous-cycle artifacts | ||
$('.preprint-oc-spacer').remove(); | $('.preprint-oc-spacer').remove(); | ||
if (layout && layout[0]) layout[0].style.paddingBottom = ''; | if (layout && layout[0]) layout[0].style.paddingBottom = ''; | ||
linkage.forEach(function(link) { | linkage.forEach(function(link) { | ||
link.element[0].style.top = '0px'; | if (link.element[0].style.position !== 'absolute') { | ||
link.element[0].style.position = 'absolute'; | |||
link.element[0].style.top = '0px'; | |||
} | |||
}); | }); | ||
// Force reflow | // Force reflow after cleanup | ||
void document.body.offsetHeight; | void document.body.offsetHeight; | ||
// Read marker positions, OC container offsets, element geometry | // Read marker positions, OC container offsets, element geometry | ||
var items = []; | var items = []; | ||
| Zeile 914: | Zeile 1.002: | ||
}); | }); | ||
// Fix overlaps | // Fix overlaps (type-pair minimum gaps) | ||
var valid = items.filter(function(item) { return item !== null; }); | var valid = items.filter(function(item) { return item !== null; }); | ||
valid.sort(function(a, b) { return a.docTop - b.docTop; }); | valid.sort(function(a, b) { return a.docTop - b.docTop; }); | ||
var | |||
function elementGap(item) { | |||
if (item.link.type === 'place-lh') return 2; | |||
if (item.height >= 50) return 16; | |||
return 4; | |||
} | |||
var lastItem = null; | |||
valid.forEach(function(item) { | valid.forEach(function(item) { | ||
var overlap = | if (lastItem) { | ||
var minGap = Math.max(elementGap(item), elementGap(lastItem)); | |||
var requiredTop = lastItem.docTop + lastItem.height + minGap; | |||
var overlap = requiredTop - item.docTop; | |||
if (overlap > 0) { | |||
item.top += overlap; | |||
item.docTop += overlap; | |||
} | |||
} | } | ||
lastItem = item; | |||
}); | }); | ||
| Zeile 976: | Zeile 1.075: | ||
} | } | ||
// Restore scroll | |||
document.body.scrollTop = savedBodyScroll; | |||
document.documentElement.scrollTop = savedHtmlScroll; | |||
reconcileLayout._running = false; | reconcileLayout._running = false; | ||
| Zeile 988: | Zeile 1.090: | ||
subtree: true, attributes: true, attributeFilter: ['class'] | subtree: true, attributes: true, attributeFilter: ['class'] | ||
}); | }); | ||
// ResizeObserver: catches container width changes not visible to | |||
// window resize (TOC pin/unpin, tool menu toggle, DevTools panel). | |||
// Created once, never disconnected — only fires on actual size change. | |||
if (!layout._resizeObserver && typeof ResizeObserver !== 'undefined') { | |||
layout._resizeObserver = new ResizeObserver(function() { | |||
clearTimeout(layout._resizeDebounce); | |||
layout._resizeDebounce = setTimeout(function() { | |||
if (PAL.isOrientationLocked()) return; | |||
if (document.body.classList.contains('preprint-landscape')) { | |||
reconcileLayout(); | |||
} | |||
}, 200); | |||
}); | |||
layout._resizeObserver.observe(layout[0]); | |||
} | |||
} | } | ||
| Zeile 1.017: | Zeile 1.135: | ||
el.scrollIntoView({ block: 'start' }); | el.scrollIntoView({ block: 'start' }); | ||
window.scrollBy(0, -60); | window.scrollBy(0, -60); | ||
} | } | ||
returnTarget = null; | returnTarget = null; | ||
| Zeile 1.029: | Zeile 1.146: | ||
target.scrollIntoView({ block: 'start' }); | target.scrollIntoView({ block: 'start' }); | ||
window.scrollBy(0, -60); | window.scrollBy(0, -60); | ||
} | } | ||
} | } | ||
| Zeile 1.147: | Zeile 1.263: | ||
getPositionAnchor: getPositionAnchor, | getPositionAnchor: getPositionAnchor, | ||
getLayout: function() { return layout; }, | getLayout: function() { return layout; }, | ||
set returnTarget(id) { returnTarget = id; } | set returnTarget(id) { returnTarget = id; }, | ||
pauseObserver: function() { | |||
if (layout && layout._ocObserver) layout._ocObserver.disconnect(); | |||
}, | |||
resumeObserver: function() { | |||
if (layout && layout[0] && layout._ocObserver) { | |||
layout._ocObserver.observe(layout[0], { | |||
subtree: true, attributes: true, attributeFilter: ['class'] | |||
}); | |||
} | |||
} | |||
}; | }; | ||
})(); | })(); | ||
| Zeile 1.212: | Zeile 1.338: | ||
var $icon = $('<a class="book-nav-icon"></a>'); | var $icon = $('<a class="book-nav-icon"></a>'); | ||
if (isBookRoot) { | if (isBookRoot) { | ||
$icon.attr('href', '/'); | var saved = sessionStorage.getItem('preprint-position'); | ||
if (saved) { | |||
var pos = JSON.parse(saved); | |||
$icon.attr('href', '/wiki/' + pos.article); | |||
} else { | |||
$icon.attr('href', '#'); | |||
$icon.addClass('book-nav-icon-disabled'); | |||
} | |||
} else { | } else { | ||
$icon.attr('href', '/wiki/' + book + (rootAnchor ? '#' + rootAnchor : '')); | $icon.attr('href', '/wiki/' + book + (rootAnchor ? '#' + rootAnchor : '')); | ||
| Zeile 1.227: | Zeile 1.360: | ||
var pos = JSON.parse(saved); | var pos = JSON.parse(saved); | ||
window.location.href = '/wiki/' + pos.article; | window.location.href = '/wiki/' + pos.article; | ||
} | } | ||
// No action when disabled — no homepage fallback | |||
}); | }); | ||
} else { | } else { | ||
| Zeile 1.258: | Zeile 1.390: | ||
} | } | ||
} | } | ||
} | } | ||
| Zeile 1.325: | Zeile 1.455: | ||
$landmark.before($link); | $landmark.before($link); | ||
if (mw.config.get('wgUserName')) { | |||
var style = document.createElement('style'); | |||
style.textContent = '@media(max-width:790px){.book-nav-sidebar{display:none!important}}'; | |||
document.head.appendChild(style); | |||
} | |||
} | } | ||
| Zeile 1.467: | Zeile 1.601: | ||
// Mobile: root page IS the TOC, hide MW-generated one | // Mobile: root page IS the TOC, hide MW-generated one | ||
$('.toc, #toc').hide(); | $('.toc, #toc').hide(); | ||
} else if (isPreprintLayout && bookNavData.length && PAL.isMinerva()) { | } else if (isPreprintLayout && bookNavData.length && PAL.isMinerva()) { | ||
// Mobile book chapters: linear reading, no TOC | // Mobile book chapters: linear reading, no TOC | ||
$('.toc, #toc').hide(); | $('.toc, #toc').hide(); | ||
} | } | ||
// Desktop: TOC always visible (sticky sidebar navigation) | // Desktop: TOC always visible (sticky sidebar navigation) | ||
| Zeile 1.516: | Zeile 1.648: | ||
return; | return; | ||
} | } | ||
// Build structure (Model) | // Build structure (Model) | ||
Model.buildStructure(); | Model.buildStructure(); | ||
| Zeile 1.526: | Zeile 1.656: | ||
setTimeout(function() { | setTimeout(function() { | ||
Model.applyProjection(initialMode); | Model.applyProjection(initialMode); | ||
Model.pauseObserver(); | |||
$('.preprint-layout').addClass('preprint-ready'); | $('.preprint-layout').addClass('preprint-ready'); | ||
Model.resumeObserver(); | |||
window.preprintReadyAt = performance.now(); | window.preprintReadyAt = performance.now(); | ||
}, 50); | }, 50); | ||
| Zeile 1.570: | Zeile 1.702: | ||
PAL.onProjectionChange(function(event) { | PAL.onProjectionChange(function(event) { | ||
// Icon already hidden by onPreProjectionChange | // Icon already hidden by onPreProjectionChange | ||
| Zeile 1.583: | Zeile 1.714: | ||
Features.calculateIconMetrics(); | Features.calculateIconMetrics(); | ||
if (icon) icon.style.visibility = ''; | if (icon) icon.style.visibility = ''; | ||
Model.positionOCElements(); | |||
}, 100); | }, 100); | ||
} else { | } else { | ||
| Zeile 1.616: | Zeile 1.748: | ||
}); | }); | ||
mw.loader.load('/wiki/MediaWiki:Common.js/debug.js?action=raw&ctype=text/javascript'); | // mw.loader.load('/wiki/MediaWiki:Common.js/debug.js?action=raw&ctype=text/javascript'); | ||
}); | }); | ||
})(); | })(); | ||
/* === PREPRINT END === */ | |||
/* Unified Consent System JavaScript | /* === CONSENT START === */ | ||
/* Unified Consent System JavaScript v260224r1 | |||
* Single file for both EN and DE versions | * Single file for both EN and DE versions | ||
* Automatically detects language based on domain | * Automatically detects language based on domain | ||
| Zeile 1.665: | Zeile 1.797: | ||
} | } | ||
// Handle consent acquisition box - 90-day reminder for | // Handle consent acquisition box - 90-day reminder for visitors (spec §8.9) | ||
$(document).ready(function() { | $(document).ready(function() { | ||
var consentBox = document.getElementById('consent-acquisition-box'); | var consentBox = document.getElementById('consent-acquisition-box'); | ||
| Zeile 1.687: | Zeile 1.819: | ||
// ADD THIS LINE: | // ADD THIS LINE: | ||
localStorage.setItem('consent-acquisition-dismissed-until', Date.now() + (90 * 24 * 60 * 60 * 1000)); | localStorage.setItem('consent-acquisition-dismissed-until', Date.now() + (90 * 24 * 60 * 60 * 1000)); | ||
var targetPage = getCurrentLanguage() === 'de' ? | if (mw.config.get('wgUserName')) { | ||
window.location.href = '/wiki/Special:Preferences#mw-prefsection-legal'; | |||
} else { | |||
var targetPage = getCurrentLanguage() === 'de' ? | |||
'/wiki/Transformal_GmbH:Einstellungen' : | |||
'/wiki/Transformal_GmbH:Settings'; | |||
window.location.href = targetPage; | |||
} | |||
}); | }); | ||
}); | }); | ||
| Zeile 1.788: | Zeile 1.924: | ||
} | } | ||
} | } | ||
/* === CONSENT END === */ | |||
/* === CONDITIONAL START === */ | |||
/* Template 'ConditionalContent' - v250925r8 */ | /* Template 'ConditionalContent' - v250925r8 */ | ||
| Zeile 1.848: | Zeile 1.988: | ||
} | } | ||
}); | }); | ||
/* === CONDITIONAL END === */ | |||