MediaWiki:Common.js:修订间差异
外观
创建页面,内容为“→这里的任何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();
}
})();