跳转到内容

MediaWiki:Common.js:修订间差异

来自次元企鹅情报局百科
Admin留言 | 贡献
创建页面,内容为“这里的任何JavaScript将为所有用户在每次页面加载时加载。:​ ===== 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">关闭 ✕</but…”
(没有差异)

2025年11月12日 (三) 18:22的版本

/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */
/* ===== 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();
  }
})();