MediaWiki:Common.js: Difference between revisions

From LNTwww
Sync Common.js from German wiki
Remove JS navbar link, using native LangLinks
 
(2 intermediate revisions by the same user not shown)
(No difference)

Latest revision as of 14:16, 16 March 2026

/* Das folgende JavaScript wird für alle Benutzer geladen. */

$('body').scrollspy({
    target: '.bs-docs-sidebar',
    offset: 40
});

/* Simple image lightbox with zoom and download */
(function() {
  var overlay = document.createElement('div');
  overlay.id = 'img-lightbox';
  overlay.style.cssText = 'display:none;position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.85);z-index:10000;flex-direction:column;';

  // Scrollable area that fills the screen
  var scrollArea = document.createElement('div');
  scrollArea.style.cssText = 'flex:1;overflow:auto;display:flex;justify-content:center;align-items:center;padding:20px;';

  var img = document.createElement('img');
  img.style.cssText = 'border-radius:4px;box-shadow:0 4px 30px rgba(0,0,0,0.5);transition:max-width 0.2s,max-height 0.2s;';
  scrollArea.appendChild(img);
  overlay.appendChild(scrollArea);

  // Toolbar
  var toolbar = document.createElement('div');
  toolbar.style.cssText = 'display:flex;gap:12px;padding:10px;align-items:center;justify-content:center;flex-shrink:0;';
  var btnStyle = 'background:rgba(255,255,255,0.15);color:white;border:none;padding:6px 14px;border-radius:4px;cursor:pointer;font-size:14px;';

  var zoomIn = document.createElement('button');
  zoomIn.innerHTML = '🔍+ Zoom in';
  zoomIn.style.cssText = btnStyle;
  var zoomOut = document.createElement('button');
  zoomOut.innerHTML = '🔍− Zoom out';
  zoomOut.style.cssText = btnStyle;
  var zoomReset = document.createElement('button');
  zoomReset.innerHTML = '↺ Reset';
  zoomReset.style.cssText = btnStyle;
  var zoomLabel = document.createElement('span');
  zoomLabel.style.cssText = 'color:rgba(255,255,255,0.6);font-size:13px;min-width:45px;text-align:center;';
  var download = document.createElement('a');
  download.innerHTML = '⬇ Download';
  download.style.cssText = btnStyle + 'text-decoration:none;display:inline-block;';
  download.download = '';
  var closeBtn = document.createElement('button');
  closeBtn.innerHTML = '✕ Close';
  closeBtn.style.cssText = btnStyle;

  toolbar.appendChild(zoomOut);
  toolbar.appendChild(zoomLabel);
  toolbar.appendChild(zoomIn);
  toolbar.appendChild(zoomReset);
  toolbar.appendChild(download);
  toolbar.appendChild(closeBtn);
  overlay.appendChild(toolbar);
  document.body.appendChild(overlay);

  var scale = 1;
  var natW = 0, natH = 0;

  function setZoom(s) {
    scale = Math.max(0.1, Math.min(s, 10));
    zoomLabel.textContent = Math.round(scale * 100) + '%';
    // Set image size directly — no CSS transform, so it actually takes up space
    img.style.width = Math.round(natW * scale) + 'px';
    img.style.height = 'auto';
    img.style.maxWidth = 'none';
    img.style.maxHeight = 'none';
    // If image is smaller than viewport, center it; otherwise scroll
    if (img.offsetWidth < scrollArea.clientWidth && img.offsetHeight < scrollArea.clientHeight) {
      scrollArea.style.alignItems = 'center';
      scrollArea.style.justifyContent = 'center';
    } else {
      scrollArea.style.alignItems = 'flex-start';
      scrollArea.style.justifyContent = 'flex-start';
    }
  }

  function fitToScreen() {
    // Calculate scale that fits the image in the viewport
    var maxW = scrollArea.clientWidth - 40;
    var maxH = scrollArea.clientHeight - 40;
    scale = Math.min(1, maxW / natW, maxH / natH);
    setZoom(scale);
  }

  zoomIn.addEventListener('click', function(e) { e.stopPropagation(); setZoom(scale * 1.4); });
  zoomOut.addEventListener('click', function(e) { e.stopPropagation(); setZoom(scale / 1.4); });
  zoomReset.addEventListener('click', function(e) { e.stopPropagation(); fitToScreen(); });
  closeBtn.addEventListener('click', function() { overlay.style.display = 'none'; });

  scrollArea.addEventListener('click', function(e) {
    if (e.target === scrollArea) overlay.style.display = 'none';
  });

  // Scroll wheel zoom
  scrollArea.addEventListener('wheel', function(e) {
    e.preventDefault();
    setZoom(scale * (e.deltaY < 0 ? 1.15 : 0.87));
  }, { passive: false });

  // Keyboard
  document.addEventListener('keydown', function(e) {
    if (overlay.style.display !== 'flex') return;
    if (e.key === 'Escape') overlay.style.display = 'none';
    if (e.key === '+' || e.key === '=') setZoom(scale * 1.3);
    if (e.key === '-') setZoom(scale / 1.3);
    if (e.key === '0') fitToScreen();
  });

  // Intercept image clicks
  document.addEventListener('click', function(e) {
    var link = e.target.closest('.image, a.mw-file-description');
    if (!link) return;
    var thumb = link.querySelector('img');
    if (!thumb) return;

    e.preventDefault();
    e.stopPropagation();

    var thumbSrc = thumb.getAttribute('src') || '';
    var fullSrc;
    if (thumbSrc.indexOf('/thumb/') !== -1) {
      fullSrc = thumbSrc.replace('/thumb/', '/').replace(/\/[^\/]+$/, '');
    } else {
      fullSrc = thumbSrc;
    }

    download.href = fullSrc;
    download.download = fullSrc.split('/').pop();

    // Load image to get natural dimensions, then fit
    img.onload = function() {
      natW = img.naturalWidth;
      natH = img.naturalHeight;
      fitToScreen();
    };
    img.src = fullSrc;
    overlay.style.display = 'flex';
  });
})();
/* Fix collapse arrow: add "collapsed" class to links targeting closed panels */
document.addEventListener('DOMContentLoaded', function() {
  document.querySelectorAll('.panel-title > a[data-toggle="collapse"]').forEach(function(a) {
    var target = document.querySelector(a.getAttribute('href'));
    if (target && !target.classList.contains('show')) {
      a.classList.add('collapsed');
    }
  });
});