跳转到内容

MediaWiki:Common.js

来自次元企鹅情报局百科
Admin留言 | 贡献2025年11月22日 (六) 12:44的版本
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)

注意:在发布之后,您可能需要清除浏览器缓存才能看到所作出的更改的影响。

  • Firefox或Safari:按住Shift的同时单击刷新,或按Ctrl-F5Ctrl-R(Mac为⌘-R
  • Google Chrome:Ctrl-Shift-R(Mac为⌘-Shift-R
  • Edge:按住Ctrl的同时单击刷新,或按Ctrl-F5
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */


/* ===============================================================
   🎬 PV 播放升级 v2.0(高亮 + 动态 iframe + 单例播放)
   =============================================================== */
window.togglePV = function(id, yt) {
    var currentPlayer = document.getElementById(id);
    var currentCard = document.querySelector('[data-pv="' + id + '"]');

    // 关闭所有播放器 + 去掉所有高亮
    document.querySelectorAll('.pv-player').forEach(function(box) {
        box.style.display = "none";
        box.innerHTML = "";
        box.dataset.open = "0";
    });
    document.querySelectorAll('.pv-card').forEach(function(card) {
        card.classList.remove('active');
    });

    // 如果当前已经是打开状态 → 折叠退出
    if (currentPlayer.dataset.open === "1") {
        currentPlayer.dataset.open = "0";
        return;
    }

    // 否则 → 展开当前播放器
    currentPlayer.style.display = "block";
    currentPlayer.dataset.open = "1";

    // 当前卡片加高亮
    if (currentCard) {
        currentCard.classList.add('active');
    }

    // 写入 iframe(YouTube 原生格式)
    const iframe = document.createElement('iframe');
    iframe.width = "100%";
    iframe.height = "540";
    iframe.src = "https://www.youtube.com/embed/" + yt + "?autoplay=1&rel=0&modestbranding=1&playsinline=1";
    iframe.title = "YouTube Player";
    iframe.frameBorder = "0";
    iframe.allow = "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share";
    iframe.referrerPolicy = "strict-origin-when-cross-origin";
    iframe.allowFullscreen = true;

    currentPlayer.appendChild(iframe);

    // 滚动到播放器位置
    currentPlayer.scrollIntoView({
        behavior: "smooth",
        block: "center"
    });
};

/* ===============================================================
   🎥 YouTube 弹窗播放器(你的原版功能保留)
   =============================================================== */
(function () {
  // 解析 a.pg-yt[data-yt] 或 [data-yt-id],点击后弹窗播放
  function buildOverlay() {
    const wrap = document.createElement('div');
    wrap.className = 'pg-yt-overlay';
    wrap.innerHTML = [
      '<div class="pg-yt-modal">',
      '  <button class="pg-yt-close" aria-label="Close">关闭 ✕</button>',
      '  <div class="pg-yt-frame"></div>',
      '</div>'
    ].join('');
    document.body.appendChild(wrap);
    return wrap;
  }

  function ytIdFrom(urlOrId) {
    if (!urlOrId) return null;
    // 已是纯 ID
    if (/^[A-Za-z0-9_-]{11}$/.test(urlOrId)) return urlOrId;
    try {
      const u = new URL(urlOrId, location.href);
      // youtu.be/ID
      if (u.hostname.includes('youtu.be')) return u.pathname.split('/')[1] || null;
      // youtube.com/watch?v=ID
      if (u.searchParams.get('v')) return u.searchParams.get('v');
      // youtube.com/shorts/ID
      const parts = u.pathname.split('/');
      const i = parts.findIndex(p => p === 'shorts');
      if (i >= 0 && parts[i+1]) return parts[i+1];
    } catch(e) {}
    return null;
  }

  function openOverlay(id, opts) {
    const overlay = document.querySelector('.pg-yt-overlay') || buildOverlay();
    const frameBox = overlay.querySelector('.pg-yt-frame');
    const params = new URLSearchParams({
      autoplay: '1',
      modestbranding: '1',
      rel: '0',
      playsinline: '1'
    });
    if (opts && opts.start) params.set('start', String(opts.start));
    const src = 'https://www.youtube.com/embed/' + id + '?' + params.toString();
    frameBox.innerHTML = '<iframe width="100%" height="100%" src="'+src+'" title="YouTube player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>';
    overlay.classList.add('active');
    document.documentElement.style.overflow = 'hidden';
  }

  function closeOverlay() {
    const overlay = document.querySelector('.pg-yt-overlay');
    if (!overlay) return;
    overlay.classList.remove('active');
    const frameBox = overlay.querySelector('.pg-yt-frame');
    frameBox.innerHTML = ''; // 停止视频
    document.documentElement.style.overflow = '';
  }

  function wireEvents() {
    // 委托点击
    document.addEventListener('click', function (e) {
      const a = e.target.closest('a.pg-yt, button.pg-yt, .pg-yt-thumb');
      if (!a) return;
      const raw = a.getAttribute('data-yt') || a.getAttribute('data-yt-id') || a.href;
      const id = ytIdFrom(raw);
      if (!id) return; // 非合法链接则放行
      e.preventDefault();
      const start = a.getAttribute('data-yt-start');
      openOverlay(id, { start: start ? parseInt(start, 10) : undefined });
    });

    document.addEventListener('click', function (e) {
      if (e.target.classList.contains('pg-yt-overlay') ||
          e.target.classList.contains('pg-yt-close')) {
        closeOverlay();
      }
    });

    document.addEventListener('keydown', function (e) {
      if (e.key === 'Escape') closeOverlay();
    });
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', wireEvents);
  } else {
    wireEvents();
  }
})();