MediaWiki:Common.js
外观
注意:在发布之后,您可能需要清除浏览器缓存才能看到所作出的更改的影响。
- Firefox或Safari:按住Shift的同时单击刷新,或按Ctrl-F5或Ctrl-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 = "";
});
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(使用 embedVideo 语法)
currentPlayer.innerHTML =
'{{#ev:youtube|' + yt + '|width=960|alignment=center}}';
// 滚动到播放器位置
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();
}
})();