1282 lines
39 KiB
JavaScript
1282 lines
39 KiB
JavaScript
(function () {
|
||
if (typeof window.domClosest !== "function") {
|
||
window.domClosest = function (from, selector) {
|
||
var el = from;
|
||
if (!el) return null;
|
||
if (el.nodeType !== 1) el = el.parentElement || el.parentNode;
|
||
if (!el || el.nodeType !== 1 || typeof el.closest !== "function") return null;
|
||
return el.closest(selector);
|
||
};
|
||
}
|
||
|
||
// 参考 jha-1043:绝对地址直播,相对路径走同域 /h5/m3u8/ 代理。
|
||
function isHttpOrHttps(url) {
|
||
return /^https?:\/\//i.test(url || "");
|
||
}
|
||
|
||
function resolvePlayUrl(videoUrl) {
|
||
if (!videoUrl) return "";
|
||
var raw = String(videoUrl).trim();
|
||
if (!raw) return "";
|
||
if (isHttpOrHttps(raw)) return raw;
|
||
var path = raw.replace(/^\/+/, "");
|
||
if (path.indexOf("h5/m3u8/") === 0) {
|
||
return "/" + path;
|
||
}
|
||
return "/h5/m3u8/" + path;
|
||
}
|
||
|
||
var HLS_CONFIG = {
|
||
maxBufferLength: 30,
|
||
maxMaxBufferLength: 60,
|
||
liveSyncDurationCount: 3,
|
||
fragLoadingTimeOut: 20000,
|
||
manifestLoadingTimeOut: 10000,
|
||
};
|
||
|
||
function forceCustomPlayer() {
|
||
var bc = window.BrowserCompat;
|
||
if (bc && bc.forceCustomPlayer) return true;
|
||
var ua = (window.navigator && window.navigator.userAgent) || "";
|
||
return /Quark|MQQBrowser|QQ\/|UCBrowser|UCWEB|MicroMessenger|baidubrowser|bdbrowser|BaiduHD|MiuiBrowser|HuaweiBrowser|HONORBrowser|HBPC|SogouMobileBrowser|VivoBrowser|HeyTapBrowser|OPPOBrowser|HeyTap|QihooBrowser|360Browser|360SE|360EE/i.test(
|
||
ua
|
||
);
|
||
}
|
||
|
||
function isIOSLike() {
|
||
var nav = window.navigator || {};
|
||
var ua = nav.userAgent || "";
|
||
return (
|
||
/iPhone|iPad|iPod/i.test(ua) ||
|
||
(/Macintosh/i.test(ua) && Number(nav.maxTouchPoints) > 1)
|
||
);
|
||
}
|
||
|
||
function canPlayNativeHls() {
|
||
var video = document.createElement("video");
|
||
return !!(
|
||
video &&
|
||
typeof video.canPlayType === "function" &&
|
||
(video.canPlayType("application/vnd.apple.mpegurl") ||
|
||
video.canPlayType("application/x-mpegURL"))
|
||
);
|
||
}
|
||
|
||
function isAppleNativeHlsBrowser() {
|
||
// 真 Safari / iOS Safari:原生 HLS 最稳。国产壳即便报告 mpegurl 也不走这条(易被系统播放器劫持)
|
||
if (forceCustomPlayer()) return false;
|
||
var ua = (window.navigator && window.navigator.userAgent) || "";
|
||
var isSafari =
|
||
/Safari/i.test(ua) &&
|
||
!/Chrome|Chromium|CriOS|FxiOS|EdgiOS|OPiOS|Android|Quark|MQQBrowser|UCBrowser|MicroMessenger|baidubrowser|MiuiBrowser|HuaweiBrowser|HONORBrowser|Sogou/i.test(
|
||
ua
|
||
);
|
||
if (!isIOSLike() && !isSafari) return false;
|
||
return canPlayNativeHls();
|
||
}
|
||
|
||
function canUseHlsJs() {
|
||
if (isAppleNativeHlsBrowser()) return false;
|
||
return (
|
||
typeof window.Hls === "function" &&
|
||
typeof window.Hls.isSupported === "function" &&
|
||
window.Hls.isSupported()
|
||
);
|
||
}
|
||
|
||
/** 非真 Safari 时等 hls.js 脚本就绪,避免 Android 国产壳误走原生 HLS */
|
||
function needsHlsScript() {
|
||
return !isAppleNativeHlsBrowser();
|
||
}
|
||
|
||
function attachHlsJs(video, player) {
|
||
var hlsOk =
|
||
typeof window.Hls === "function" &&
|
||
typeof window.Hls.isSupported === "function" &&
|
||
window.Hls.isSupported();
|
||
if (!hlsOk) return;
|
||
if (isAppleNativeHlsBrowser()) return;
|
||
if (
|
||
player.plugins &&
|
||
player.plugins.hls &&
|
||
typeof player.plugins.hls.destroy === "function"
|
||
) {
|
||
try {
|
||
player.plugins.hls.destroy();
|
||
} catch (err) {}
|
||
}
|
||
|
||
// DPlayer 会先把 m3u8 写进 video.src;夸克/X5 识别后会外跳系统播放器。
|
||
// 先清掉原生 src,仅通过 hls.js(MSE/blob) 喂流。
|
||
var src =
|
||
(video && (video.getAttribute("src") || video.src)) ||
|
||
(player &&
|
||
player.options &&
|
||
player.options.video &&
|
||
player.options.video.url) ||
|
||
"";
|
||
src = resolvePlayUrl(src);
|
||
try {
|
||
video.removeAttribute("src");
|
||
video.src = "";
|
||
if (typeof video.removeAttribute === "function") {
|
||
video.removeAttribute("src");
|
||
}
|
||
if (typeof video.load === "function") video.load();
|
||
} catch (e0) {}
|
||
|
||
applyInlineAttrs(video);
|
||
|
||
var hls = new window.Hls(HLS_CONFIG);
|
||
player.plugins = player.plugins || {};
|
||
player.plugins.hls = hls;
|
||
var recoverCount = 0;
|
||
hls.on(window.Hls.Events.ERROR, function (_evt, data) {
|
||
if (!data || !data.fatal) return;
|
||
if (recoverCount >= 3) return;
|
||
recoverCount += 1;
|
||
try {
|
||
if (data.type === window.Hls.ErrorTypes.NETWORK_ERROR) {
|
||
hls.startLoad();
|
||
} else if (data.type === window.Hls.ErrorTypes.MEDIA_ERROR) {
|
||
hls.recoverMediaError();
|
||
}
|
||
} catch (e) {}
|
||
});
|
||
if (src) hls.loadSource(src);
|
||
hls.attachMedia(video);
|
||
patchVideoInlinePlayback(player);
|
||
}
|
||
|
||
function buildVideoOption(url, pic) {
|
||
var option = { url: url, type: "hls" };
|
||
if (canUseHlsJs()) {
|
||
// Android / 桌面 / 支持 MSE 的壳:hls.js,避免系统播放器接管
|
||
option.type = "hlsjs";
|
||
option.customType = { hlsjs: attachHlsJs };
|
||
} else if (canPlayNativeHls()) {
|
||
// iOS 夸克/微信等无 MSE:只能原生 HLS,配合内联属性尽量页内播放
|
||
option.type = "hls";
|
||
} else {
|
||
option.type = "auto";
|
||
}
|
||
if (pic) option.pic = pic;
|
||
return option;
|
||
}
|
||
|
||
var videoPatchObserver = null;
|
||
var videoPatchedEl = null;
|
||
|
||
function stopVideoPatchWatch() {
|
||
if (videoPatchObserver) {
|
||
try {
|
||
videoPatchObserver.disconnect();
|
||
} catch (e) {}
|
||
videoPatchObserver = null;
|
||
}
|
||
videoPatchedEl = null;
|
||
}
|
||
|
||
/**
|
||
* 只盯 controls 被壳层写回的情况。
|
||
* 注意:不可在 Observer 里无条件 setAttribute(会再次触发回调,卡死页面)。
|
||
*/
|
||
function watchVideoNativeHijack(video) {
|
||
if (!video || !window.MutationObserver) return;
|
||
if (videoPatchedEl === video && videoPatchObserver) return;
|
||
stopVideoPatchWatch();
|
||
videoPatchedEl = video;
|
||
videoPatchObserver = new MutationObserver(function () {
|
||
if (video.controls || video.hasAttribute("controls")) {
|
||
try {
|
||
video.controls = false;
|
||
video.removeAttribute("controls");
|
||
} catch (err) {}
|
||
}
|
||
// 同层关键属性被清掉时再补一次(先 disconnect,避免自触发死循环)
|
||
if (video.getAttribute("x5-video-player-type") !== "h5") {
|
||
try {
|
||
videoPatchObserver.disconnect();
|
||
} catch (e1) {}
|
||
applyInlineAttrs(video);
|
||
try {
|
||
videoPatchObserver.observe(video, {
|
||
attributes: true,
|
||
attributeFilter: ["controls", "x5-video-player-type"],
|
||
});
|
||
} catch (e2) {}
|
||
}
|
||
});
|
||
try {
|
||
videoPatchObserver.observe(video, {
|
||
attributes: true,
|
||
attributeFilter: ["controls", "x5-video-player-type"],
|
||
});
|
||
} catch (e3) {}
|
||
}
|
||
|
||
function applyInlineAttrs(video) {
|
||
if (!video || !video.setAttribute) return;
|
||
// 同层播放关键属性:尽量在 video 创建前写好
|
||
video.setAttribute("playsinline", "true");
|
||
video.setAttribute("webkit-playsinline", "true");
|
||
video.setAttribute("x5-playsinline", "true");
|
||
video.setAttribute("t7-video-player-type", "inline");
|
||
video.setAttribute("x5-video-player-type", "h5");
|
||
// true = X5/夸克同层页内全屏;false 反而容易外跳系统播放器
|
||
video.setAttribute("x5-video-player-fullscreen", "true");
|
||
video.setAttribute("x5-video-orientation", "portrait");
|
||
video.setAttribute("controlslist", "nodownload noplaybackrate noremoteplayback");
|
||
video.setAttribute("disablepictureinpicture", "true");
|
||
video.setAttribute("webkit-airplay", "deny");
|
||
video.setAttribute("x-webkit-airplay", "deny");
|
||
video.removeAttribute("controls");
|
||
video.controls = false;
|
||
try {
|
||
video.playsInline = true;
|
||
} catch (e) {}
|
||
try {
|
||
video.disablePictureInPicture = true;
|
||
} catch (e2) {}
|
||
try {
|
||
if (video.disableRemotePlayback !== undefined) {
|
||
video.disableRemotePlayback = true;
|
||
}
|
||
} catch (e3) {}
|
||
}
|
||
|
||
/** 在 createElement('video') 时就打上同层属性,避免入 DOM 后再补已太晚 */
|
||
function installVideoCreateHook() {
|
||
if (document.__jhaVideoInlineHooked) return;
|
||
document.__jhaVideoInlineHooked = true;
|
||
var rawCreate = document.createElement.bind(document);
|
||
document.createElement = function (tagName, options) {
|
||
var el = rawCreate(tagName, options);
|
||
try {
|
||
if (String(tagName).toLowerCase() === "video") {
|
||
applyInlineAttrs(el);
|
||
}
|
||
} catch (err) {}
|
||
return el;
|
||
};
|
||
}
|
||
|
||
function exitNativeFullscreen(video) {
|
||
if (!video) return;
|
||
try {
|
||
if (typeof video.webkitExitFullscreen === "function") {
|
||
video.webkitExitFullscreen();
|
||
}
|
||
} catch (err) {}
|
||
try {
|
||
if (typeof video.exitFullscreen === "function") {
|
||
video.exitFullscreen();
|
||
}
|
||
} catch (err2) {}
|
||
}
|
||
|
||
function requestWebFullscreen(dp) {
|
||
if (!dp) return;
|
||
try {
|
||
if (dp.fullScreen && typeof dp.fullScreen.request === "function") {
|
||
dp.fullScreen.request("web");
|
||
return;
|
||
}
|
||
} catch (e) {}
|
||
try {
|
||
if (dp.container) {
|
||
dp.container.classList.add("dplayer-fulled");
|
||
document.body.classList.add("dplayer-web-fullscreen-fix");
|
||
}
|
||
} catch (e2) {}
|
||
}
|
||
|
||
/** 拦截 webkitEnterFullscreen,避免夸克/X5 调起系统播放器 */
|
||
function patchNativeFullscreenHooks(dp) {
|
||
var video = dp && dp.video;
|
||
if (!video || video.__fsHooked) return;
|
||
video.__fsHooked = true;
|
||
|
||
if (forceCustomPlayer()) {
|
||
var entering = false;
|
||
var blockNative = function () {
|
||
if (entering) return;
|
||
entering = true;
|
||
try {
|
||
exitNativeFullscreen(video);
|
||
requestWebFullscreen(dp);
|
||
applyInlineAttrs(video);
|
||
} finally {
|
||
entering = false;
|
||
}
|
||
};
|
||
try {
|
||
video.webkitEnterFullscreen = blockNative;
|
||
} catch (e) {}
|
||
try {
|
||
video.webkitEnterFullScreen = blockNative;
|
||
} catch (e2) {}
|
||
}
|
||
|
||
if (!video.__playHooked) {
|
||
video.__playHooked = true;
|
||
var nativePlay = video.play.bind(video);
|
||
video.play = function () {
|
||
applyInlineAttrs(video);
|
||
try {
|
||
return nativePlay();
|
||
} catch (err) {
|
||
return Promise.reject(err);
|
||
}
|
||
};
|
||
}
|
||
}
|
||
|
||
// QQ / 夸克 / UC / 百度等:页内同层播放,避免被系统播放器全屏接管
|
||
function patchVideoInlinePlayback(dp) {
|
||
var video = dp && dp.video;
|
||
if (!video) return;
|
||
applyInlineAttrs(video);
|
||
watchVideoNativeHijack(video);
|
||
patchNativeFullscreenHooks(dp);
|
||
|
||
if (!video.__cnPlayerBound) {
|
||
video.__cnPlayerBound = true;
|
||
var reapply = function () {
|
||
applyInlineAttrs(video);
|
||
};
|
||
video.addEventListener("play", reapply);
|
||
video.addEventListener("playing", reapply);
|
||
video.addEventListener("loadedmetadata", reapply);
|
||
video.addEventListener("x5videoenterfullscreen", reapply);
|
||
video.addEventListener("x5videoexitfullscreen", reapply);
|
||
video.addEventListener("webkitbeginfullscreen", function () {
|
||
if (forceCustomPlayer()) {
|
||
exitNativeFullscreen(video);
|
||
requestWebFullscreen(dp);
|
||
}
|
||
reapply();
|
||
});
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 启用控制条原生播放/暂停,并补绑移动端被跳过的音量按钮。
|
||
* (插件在 isMobile 时不 initVolumeButton;我们已去掉 dplayer-mobile)
|
||
*/
|
||
function enableBarPlayControls(dp) {
|
||
if (!dp || !dp.container) return;
|
||
var el = dp.container;
|
||
|
||
function apply() {
|
||
el.classList.remove("dplayer-mobile");
|
||
if (el.offsetWidth <= 500) {
|
||
el.classList.add("dplayer-arrow");
|
||
}
|
||
}
|
||
|
||
apply();
|
||
if (typeof MutationObserver === "function" && !el.__barControlsObs) {
|
||
var obs = new MutationObserver(function () {
|
||
if (el.classList.contains("dplayer-mobile")) apply();
|
||
});
|
||
obs.observe(el, { attributes: true, attributeFilter: ["class"] });
|
||
el.__barControlsObs = obs;
|
||
}
|
||
|
||
if (!dp.__volumeInited) {
|
||
try {
|
||
if (dp.controller && typeof dp.controller.initVolumeButton === "function") {
|
||
dp.controller.initVolumeButton();
|
||
dp.__volumeInited = true;
|
||
} else {
|
||
bindVolumeMuteFallback(dp);
|
||
}
|
||
} catch (e) {
|
||
bindVolumeMuteFallback(dp);
|
||
}
|
||
}
|
||
}
|
||
|
||
function bindVolumeMuteFallback(dp) {
|
||
if (!dp || dp.__volumeInited) return;
|
||
var icon =
|
||
(dp.template && dp.template.volumeButtonIcon) ||
|
||
(dp.container && dp.container.querySelector(".dplayer-volume-icon"));
|
||
if (!icon || icon.__muteBound) return;
|
||
icon.__muteBound = true;
|
||
dp.__volumeInited = true;
|
||
icon.addEventListener("click", function (event) {
|
||
event.preventDefault();
|
||
event.stopPropagation();
|
||
try {
|
||
if (!dp.video) return;
|
||
dp.video.muted = !dp.video.muted;
|
||
if (typeof dp.switchVolumeIcon === "function") dp.switchVolumeIcon();
|
||
} catch (err) {}
|
||
});
|
||
}
|
||
|
||
/** 包装 DPlayer:任意实例都启用可操作的控制条按钮 */
|
||
function wrapDPlayerCtor() {
|
||
var Ctor = window.DPlayer;
|
||
if (!Ctor || Ctor.__barPlayWrapped) return;
|
||
installVideoCreateHook();
|
||
function Wrapped(options) {
|
||
installVideoCreateHook();
|
||
var dp = new Ctor(options);
|
||
enableBarPlayControls(dp);
|
||
patchVideoInlinePlayback(dp);
|
||
return dp;
|
||
}
|
||
Wrapped.prototype = Ctor.prototype;
|
||
Object.keys(Ctor).forEach(function (k) {
|
||
try {
|
||
Wrapped[k] = Ctor[k];
|
||
} catch (e) {}
|
||
});
|
||
Wrapped.__barPlayWrapped = true;
|
||
window.DPlayer = Wrapped;
|
||
}
|
||
|
||
function safePlay(dp) {
|
||
if (!dp) return;
|
||
try {
|
||
var result = dp.play();
|
||
if (result && typeof result.then === "function") {
|
||
result.catch(function () {
|
||
// 部分夸克/QQ 需再次用户手势;保留封面按钮可重试
|
||
});
|
||
}
|
||
} catch (e) {}
|
||
}
|
||
|
||
var playDp = null;
|
||
var currentPlayMode = "main";
|
||
var mainBadgePC = "";
|
||
var mainBadgeH5 = "";
|
||
var mainCtaLabel = "";
|
||
|
||
function playerRoot() {
|
||
return document.querySelector("[data-play-player]");
|
||
}
|
||
|
||
function isPreviewMode() {
|
||
var root = playerRoot();
|
||
return !!(
|
||
root &&
|
||
(root.getAttribute("data-play-mode") === "preview" ||
|
||
root.classList.contains("play-player--preview") ||
|
||
currentPlayMode === "preview")
|
||
);
|
||
}
|
||
|
||
function canWatchMain() {
|
||
var root = playerRoot();
|
||
return !!(root && root.getAttribute("data-can-watch") === "1");
|
||
}
|
||
|
||
function mainPlayURL() {
|
||
var root = playerRoot();
|
||
var container = document.querySelector(".dplayer-video");
|
||
var fromRoot = root && root.getAttribute("data-main-url");
|
||
var fromBox = container && container.getAttribute("data-main-url");
|
||
return resolvePlayUrl(fromRoot || fromBox || "");
|
||
}
|
||
|
||
function previewPlayURL() {
|
||
var root = playerRoot();
|
||
var container = document.querySelector(".dplayer-video");
|
||
var fromRoot = root && root.getAttribute("data-preview-url");
|
||
var fromBox = container && container.getAttribute("data-preview-url");
|
||
return resolvePlayUrl(fromRoot || fromBox || "");
|
||
}
|
||
|
||
function syncMainCta(mode) {
|
||
var cta = document.querySelector("[data-play-main-cta]");
|
||
if (!cta) return;
|
||
var label = cta.querySelector("[data-play-cta-label]");
|
||
if (!mainCtaLabel && label) mainCtaLabel = label.textContent || "";
|
||
if (mode === "preview") {
|
||
cta.removeAttribute("data-play-coin-open");
|
||
cta.setAttribute("data-play-poster-play", "");
|
||
if (label) label.textContent = "播放预告片";
|
||
return;
|
||
}
|
||
if (!canWatchMain()) {
|
||
cta.removeAttribute("data-play-poster-play");
|
||
cta.setAttribute("data-play-coin-open", "");
|
||
if (label) label.textContent = "解锁播放";
|
||
return;
|
||
}
|
||
cta.removeAttribute("data-play-coin-open");
|
||
cta.setAttribute("data-play-poster-play", "");
|
||
if (label) label.textContent = mainCtaLabel || "立即播放";
|
||
}
|
||
|
||
function hidePosterOverlay() {
|
||
var root = document.querySelector("[data-play-player]");
|
||
if (root) root.classList.add("is-playing");
|
||
var poster = document.querySelector("[data-play-poster]");
|
||
if (poster) poster.classList.add("play-player__cover--hidden");
|
||
var playBtn = document.querySelector("[data-play-poster-play]");
|
||
if (playBtn) playBtn.style.display = "none";
|
||
}
|
||
|
||
function showPosterOverlay() {
|
||
var root = document.querySelector("[data-play-player]");
|
||
if (root) root.classList.remove("is-playing");
|
||
var poster = document.querySelector("[data-play-poster]");
|
||
if (poster) poster.classList.remove("play-player__cover--hidden");
|
||
var playBtn = document.querySelector("[data-play-poster-play]");
|
||
if (playBtn) playBtn.style.display = "";
|
||
}
|
||
|
||
function ensurePosterDecrypt() {
|
||
var poster = document.querySelector(".play-player__cover.lazy[data-src]");
|
||
if (!poster) return;
|
||
if (typeof window.loadLazyNode === "function") {
|
||
window.loadLazyNode(poster);
|
||
return;
|
||
}
|
||
if (typeof window.initLazyImages === "function") {
|
||
window.initLazyImages(poster.parentNode || document, { eager: true });
|
||
}
|
||
}
|
||
|
||
function initDPlayer(initialURL) {
|
||
if (typeof window.DPlayer === "undefined") return null;
|
||
var container = document.querySelector(".dplayer-video");
|
||
if (!container) return null;
|
||
var url = resolvePlayUrl(initialURL || container.getAttribute("data-url") || "");
|
||
if (!url) return null;
|
||
try {
|
||
if (playDp && typeof playDp.destroy === "function") {
|
||
try {
|
||
playDp.destroy();
|
||
} catch (err) {}
|
||
playDp = null;
|
||
stopVideoPatchWatch();
|
||
container.innerHTML = "";
|
||
}
|
||
container.setAttribute("data-url", url);
|
||
installVideoCreateHook();
|
||
playDp = new window.DPlayer({
|
||
container: container,
|
||
autoplay: false,
|
||
preload: "metadata",
|
||
screenshot: false,
|
||
airplay: false,
|
||
chromecast: false,
|
||
hotkey: true,
|
||
mutex: true,
|
||
contextmenu: [],
|
||
video: buildVideoOption(url, ""),
|
||
});
|
||
// DPlayer 无 mobile 开关:去掉 dplayer-mobile,使用带播放/暂停的控制条
|
||
enableBarPlayControls(playDp);
|
||
patchVideoInlinePlayback(playDp);
|
||
if (typeof playDp.on === "function") {
|
||
playDp.on("loadedmetadata", function () {
|
||
patchVideoInlinePlayback(playDp);
|
||
});
|
||
playDp.on("play", function () {
|
||
patchVideoInlinePlayback(playDp);
|
||
hidePosterOverlay();
|
||
});
|
||
}
|
||
return playDp;
|
||
} catch (e) {
|
||
return null;
|
||
}
|
||
}
|
||
|
||
function switchPlayerSource(url) {
|
||
url = resolvePlayUrl(url || "");
|
||
if (!url) return null;
|
||
var container = document.querySelector(".dplayer-video");
|
||
if (container) container.setAttribute("data-url", url);
|
||
if (playDp && typeof playDp.switchVideo === "function") {
|
||
try {
|
||
playDp.switchVideo(buildVideoOption(url, ""));
|
||
patchVideoInlinePlayback(playDp);
|
||
return playDp;
|
||
} catch (e) {}
|
||
}
|
||
return initDPlayer(url);
|
||
}
|
||
|
||
function updatePlayBadge(mode) {
|
||
var pc = document.querySelector("[data-play-badge-pc]");
|
||
var h5 = document.querySelector("[data-play-badge-h5]");
|
||
if (!mainBadgePC && pc) mainBadgePC = pc.textContent || "";
|
||
if (!mainBadgeH5 && h5) mainBadgeH5 = h5.textContent || "";
|
||
if (mode === "preview") {
|
||
if (pc) pc.textContent = "预告片 免费";
|
||
if (h5) h5.textContent = "预告片";
|
||
return;
|
||
}
|
||
if (pc) pc.textContent = mainBadgePC;
|
||
if (h5) h5.textContent = mainBadgeH5;
|
||
}
|
||
|
||
function setPlayMode(mode, options) {
|
||
options = options || {};
|
||
var root = playerRoot();
|
||
if (!root) return;
|
||
var next = mode === "preview" ? "preview" : "main";
|
||
currentPlayMode = next;
|
||
root.setAttribute("data-play-mode", next);
|
||
root.classList.toggle("play-player--preview", next === "preview");
|
||
|
||
var tabs = document.querySelectorAll("[data-play-tab]");
|
||
Array.prototype.forEach.call(tabs, function (tab) {
|
||
tab.classList.toggle("is-active", tab.getAttribute("data-play-tab") === next);
|
||
});
|
||
|
||
var centerBtn = document.querySelector(".play-player__center");
|
||
updatePlayBadge(next);
|
||
syncMainCta(next);
|
||
|
||
if (next === "preview") {
|
||
if (centerBtn) centerBtn.removeAttribute("data-play-coin-open");
|
||
var previewURL = previewPlayURL();
|
||
if (!previewURL) return;
|
||
var dp = switchPlayerSource(previewURL);
|
||
bindPosterPlay(dp);
|
||
showPosterOverlay();
|
||
if (options.autoplay) {
|
||
patchVideoInlinePlayback(dp);
|
||
safePlay(dp);
|
||
hidePosterOverlay();
|
||
}
|
||
return;
|
||
}
|
||
|
||
// 正片
|
||
if (!canWatchMain()) {
|
||
if (centerBtn) centerBtn.setAttribute("data-play-coin-open", "");
|
||
if (playDp) {
|
||
try {
|
||
playDp.pause();
|
||
} catch (e) {}
|
||
}
|
||
showPosterOverlay();
|
||
return;
|
||
}
|
||
|
||
if (centerBtn) centerBtn.removeAttribute("data-play-coin-open");
|
||
var mainURL = mainPlayURL();
|
||
if (!mainURL) return;
|
||
var mainDp = switchPlayerSource(mainURL);
|
||
bindPosterPlay(mainDp);
|
||
showPosterOverlay();
|
||
if (options.autoplay) {
|
||
patchVideoInlinePlayback(mainDp);
|
||
safePlay(mainDp);
|
||
hidePosterOverlay();
|
||
}
|
||
}
|
||
|
||
function bindPlayTabs() {
|
||
var tabs = document.querySelectorAll("[data-play-tab]");
|
||
if (!tabs.length) return;
|
||
Array.prototype.forEach.call(tabs, function (tab) {
|
||
tab.addEventListener("click", function (event) {
|
||
event.preventDefault();
|
||
var mode = tab.getAttribute("data-play-tab") || "main";
|
||
if (mode === currentPlayMode) {
|
||
if (mode === "preview") {
|
||
setPlayMode("preview", { autoplay: true });
|
||
}
|
||
return;
|
||
}
|
||
setPlayMode(mode, { autoplay: mode === "preview" });
|
||
});
|
||
});
|
||
}
|
||
|
||
function bindPosterPlay(dp) {
|
||
var buttons = document.querySelectorAll("[data-play-poster-play]");
|
||
Array.prototype.forEach.call(buttons, function (btn) {
|
||
if (btn.getAttribute("data-play-bound") === "1") return;
|
||
btn.setAttribute("data-play-bound", "1");
|
||
btn.addEventListener("click", function (event) {
|
||
// 预告片直接播放;仅正片为 App 专享时弹下载提示
|
||
if (
|
||
btn.hasAttribute("data-play-coin-open") &&
|
||
!isPreviewMode()
|
||
) {
|
||
return;
|
||
}
|
||
if (btn.tagName === "A") {
|
||
event.preventDefault();
|
||
}
|
||
var mode = isPreviewMode() ? "preview" : "main";
|
||
var active = playDp || dp;
|
||
if (mode === "preview") {
|
||
if (!active) active = switchPlayerSource(previewPlayURL());
|
||
} else if (!canWatchMain()) {
|
||
return;
|
||
} else if (!active) {
|
||
active = switchPlayerSource(mainPlayURL());
|
||
}
|
||
if (!active) return;
|
||
patchVideoInlinePlayback(active);
|
||
safePlay(active);
|
||
hidePosterOverlay();
|
||
});
|
||
});
|
||
}
|
||
|
||
function tryAutoplayPreview() {
|
||
if (!isPreviewMode() || !previewPlayURL()) return;
|
||
setPlayMode("preview", { autoplay: true });
|
||
}
|
||
|
||
function bootPlayer() {
|
||
var root = playerRoot();
|
||
if (!root) return;
|
||
|
||
// 等 DPlayer(及非 Safari 场景下的 hls.js)就绪,避免误走原生 HLS / 未包装构造器
|
||
var libsPending =
|
||
typeof window.DPlayer === "undefined" ||
|
||
(needsHlsScript() && typeof window.Hls === "undefined");
|
||
if (libsPending) {
|
||
if (!bootPlayer._retries) bootPlayer._retries = 0;
|
||
if (bootPlayer._retries < 40) {
|
||
bootPlayer._retries += 1;
|
||
window.setTimeout(bootPlayer, 50);
|
||
}
|
||
return;
|
||
}
|
||
wrapDPlayerCtor();
|
||
|
||
ensurePosterDecrypt();
|
||
bindPlayTabs();
|
||
|
||
var pc = document.querySelector("[data-play-badge-pc]");
|
||
var h5 = document.querySelector("[data-play-badge-h5]");
|
||
if (pc) mainBadgePC = pc.textContent || "";
|
||
if (h5) mainBadgeH5 = h5.textContent || "";
|
||
var ctaLabel = document.querySelector("[data-play-cta-label]");
|
||
if (ctaLabel) mainCtaLabel = ctaLabel.textContent || "";
|
||
|
||
currentPlayMode = root.getAttribute("data-play-mode") || "main";
|
||
|
||
// 预告片:无需登录 / 解锁,可直接初始化并播放
|
||
if (currentPlayMode === "preview" && previewPlayURL()) {
|
||
var previewDp = initDPlayer(previewPlayURL());
|
||
bindPosterPlay(previewDp);
|
||
syncMainCta("preview");
|
||
showPosterOverlay();
|
||
document.addEventListener("eighteen:closed", tryAutoplayPreview, {
|
||
once: true,
|
||
});
|
||
if (
|
||
document.documentElement.classList.contains("eighteen-ok") ||
|
||
!document.querySelector("[data-eighteen].is-open")
|
||
) {
|
||
// 已过年龄门时不强制自动播,等用户点击即可
|
||
}
|
||
return;
|
||
}
|
||
|
||
if (canWatchMain() && mainPlayURL()) {
|
||
var dp = initDPlayer(mainPlayURL());
|
||
bindPosterPlay(dp);
|
||
if (!dp) showPosterOverlay();
|
||
return;
|
||
}
|
||
|
||
// 正片未解锁但有预告:切到预告片模式
|
||
if (previewPlayURL()) {
|
||
setPlayMode("preview", { autoplay: false });
|
||
document.addEventListener("eighteen:closed", tryAutoplayPreview, {
|
||
once: true,
|
||
});
|
||
return;
|
||
}
|
||
|
||
// 正片未解锁:仅绑定 tab / 封面
|
||
bindPosterPlay(null);
|
||
showPosterOverlay();
|
||
}
|
||
|
||
if (document.readyState === "loading") {
|
||
document.addEventListener("DOMContentLoaded", bootPlayer);
|
||
} else {
|
||
bootPlayer();
|
||
}
|
||
})();
|
||
|
||
(function () {
|
||
var root = document.querySelector("[data-play-coin]");
|
||
if (!root) return;
|
||
|
||
var openers = document.querySelectorAll("[data-play-coin-open]");
|
||
var closers = root.querySelectorAll("[data-play-coin-close]");
|
||
var previousOverflow = "";
|
||
|
||
function open() {
|
||
root.classList.add("is-open");
|
||
previousOverflow = document.body.style.overflow;
|
||
document.body.style.overflow = "hidden";
|
||
}
|
||
|
||
function close() {
|
||
root.classList.remove("is-open");
|
||
document.body.style.overflow = previousOverflow;
|
||
}
|
||
|
||
function isPreviewPlayingSurface() {
|
||
var player = document.querySelector("[data-play-player]");
|
||
return !!(
|
||
player &&
|
||
(player.getAttribute("data-play-mode") === "preview" ||
|
||
player.classList.contains("play-player--preview"))
|
||
);
|
||
}
|
||
|
||
Array.prototype.forEach.call(openers, function (btn) {
|
||
btn.addEventListener("click", function () {
|
||
// 预告片模式不弹下载提示;属性被临时移除时也不弹。
|
||
if (!btn.hasAttribute("data-play-coin-open")) return;
|
||
if (isPreviewPlayingSurface()) return;
|
||
open();
|
||
});
|
||
});
|
||
|
||
Array.prototype.forEach.call(closers, function (el) {
|
||
el.addEventListener("click", close);
|
||
});
|
||
|
||
document.addEventListener("keydown", function (event) {
|
||
if (event.key === "Escape" && root.classList.contains("is-open")) {
|
||
close();
|
||
}
|
||
});
|
||
})();
|
||
|
||
(function () {
|
||
var btn = document.querySelector("[data-guess-refresh]");
|
||
var grid = document.querySelector("[data-guess-grid]");
|
||
if (!btn || !grid) return;
|
||
|
||
var loading = false;
|
||
var PLACEHOLDER = "/static/images/placeholder.png?v=2";
|
||
|
||
function toInt(v, fallback) {
|
||
var n = parseInt(v, 10);
|
||
return isNaN(n) ? fallback : n;
|
||
}
|
||
|
||
var videoId = toInt(btn.getAttribute("data-video-id"), 0);
|
||
var playletId = toInt(btn.getAttribute("data-playlet-id"), 0);
|
||
|
||
function nextPage(pageNum, pageSize, totalCount) {
|
||
var totalPages =
|
||
pageSize > 0 && totalCount > 0 ? Math.ceil(totalCount / pageSize) : 0;
|
||
if (totalPages <= 1) return 1;
|
||
if (pageNum < 1) pageNum = 1;
|
||
var next = pageNum + 1;
|
||
return next > totalPages ? 1 : next;
|
||
}
|
||
|
||
function playURL(slug, id) {
|
||
var seg = String(slug || "").trim();
|
||
if (!seg && id > 0) seg = String(id);
|
||
if (!seg) return "#";
|
||
return "/play/" + encodeURIComponent(seg);
|
||
}
|
||
|
||
function videoPlayURL(slug, id) {
|
||
var seg = String(slug || "").trim();
|
||
if (!seg && id > 0) seg = String(id);
|
||
if (!seg) return "/series";
|
||
return "/series-play/" + encodeURIComponent(seg);
|
||
}
|
||
|
||
function tagPageURL(slug, id) {
|
||
var seg = String(slug || "").trim();
|
||
if (!seg && id > 0) seg = String(id);
|
||
if (!seg) return "";
|
||
return "/tags/" + encodeURIComponent(seg);
|
||
}
|
||
|
||
function themeListURL(slug, id) {
|
||
var seg = String(slug || "").trim();
|
||
if (!seg && id > 0) seg = String(id);
|
||
if (!seg) return "/list";
|
||
return "/list/" + encodeURIComponent(seg);
|
||
}
|
||
|
||
function pushNamed(out, seen, names, ids, slugs, asTag) {
|
||
names = names || [];
|
||
ids = ids || [];
|
||
slugs = slugs || [];
|
||
for (var i = 0; i < names.length && out.length < 3; i++) {
|
||
var name = String(names[i] || "").trim();
|
||
if (!name) continue;
|
||
var key = name.toLowerCase();
|
||
if (seen[key]) continue;
|
||
seen[key] = true;
|
||
var id = ids[i] > 0 ? ids[i] : 0;
|
||
var slug = String(slugs[i] || "").trim();
|
||
out.push({
|
||
name: name,
|
||
url: asTag ? tagPageURL(slug, id) : themeListURL(slug, id),
|
||
});
|
||
}
|
||
}
|
||
|
||
function cardTags(item) {
|
||
var out = [];
|
||
var seen = {};
|
||
pushNamed(out, seen, item.tagNames, item.tagIds, item.tagSlugs, true);
|
||
if (out.length < 3) {
|
||
pushNamed(out, seen, item.themeNames, item.themeIds, item.themeSlugs, false);
|
||
}
|
||
return out;
|
||
}
|
||
|
||
function displayName(item) {
|
||
return String((item && (item.playName || item.title)) || "").trim() || "短剧";
|
||
}
|
||
|
||
function updateStatusText(status) {
|
||
return Number(status) === 2 ? "已完结" : "连载中";
|
||
}
|
||
|
||
function escapeHtml(s) {
|
||
return String(s == null ? "" : s)
|
||
.replace(/&/g, "&")
|
||
.replace(/</g, "<")
|
||
.replace(/>/g, ">")
|
||
.replace(/"/g, """)
|
||
.replace(/'/g, "'");
|
||
}
|
||
|
||
function renderMeta(item) {
|
||
var tags = cardTags(item);
|
||
return tags
|
||
.map(function (tag, i) {
|
||
var sep = i ? " " : "";
|
||
var name = escapeHtml(tag.name);
|
||
if (tag.url) {
|
||
return sep + '<a href="' + escapeHtml(tag.url) + '">' + name + "</a>";
|
||
}
|
||
return sep + name;
|
||
})
|
||
.join("");
|
||
}
|
||
|
||
function renderVideoMeta(item) {
|
||
var keys = (item && item.keyworld) || [];
|
||
var parts = [];
|
||
for (var i = 0; i < keys.length && parts.length < 3; i++) {
|
||
var k = String(keys[i] || "").trim();
|
||
if (k) parts.push(escapeHtml(k));
|
||
}
|
||
if (parts.length) return parts.join(" ");
|
||
return escapeHtml((item && item.creatorName) || "");
|
||
}
|
||
|
||
function renderList(list) {
|
||
if (!list || !list.length) {
|
||
grid.innerHTML =
|
||
'<p class="play-comment__text" style="padding:12px 0;color:var(--muted, #888)">暂无推荐</p>';
|
||
return;
|
||
}
|
||
var html = list
|
||
.map(function (item) {
|
||
var href = playURL(item.slug, item.id);
|
||
var name = escapeHtml(displayName(item));
|
||
var meta = renderMeta(item);
|
||
var ep =
|
||
item.totalEpisode > 0
|
||
? "全 " + item.totalEpisode + " 集"
|
||
: updateStatusText(item.updateStatus);
|
||
var cover = escapeHtml(item.cover || "");
|
||
return (
|
||
'<article class="card card--play">' +
|
||
'<a class="card__cover lazy" href="' +
|
||
escapeHtml(href) +
|
||
'" style="--cover:url(' +
|
||
PLACEHOLDER +
|
||
')" data-src="' +
|
||
cover +
|
||
'">' +
|
||
'<span class="card__ep">' +
|
||
escapeHtml(ep) +
|
||
"</span>" +
|
||
"</a>" +
|
||
'<h3 class="card__title"><a href="' +
|
||
escapeHtml(href) +
|
||
'">' +
|
||
name +
|
||
"</a></h3>" +
|
||
'<p class="card__meta">' +
|
||
meta +
|
||
"</p>" +
|
||
"</article>"
|
||
);
|
||
})
|
||
.join("");
|
||
grid.innerHTML = html;
|
||
if (typeof window.initLazyImages === "function") {
|
||
window.initLazyImages(grid);
|
||
}
|
||
}
|
||
|
||
function renderVideoList(list) {
|
||
if (!list || !list.length) {
|
||
grid.innerHTML =
|
||
'<p class="play-comment__text" style="padding:12px 0;color:var(--muted, #888)">暂无推荐</p>';
|
||
return;
|
||
}
|
||
var html = list
|
||
.map(function (item) {
|
||
var href = videoPlayURL(item.slug, item.id);
|
||
var name = escapeHtml(String((item && item.title) || "").trim() || "视频");
|
||
var meta = renderVideoMeta(item);
|
||
var ep =
|
||
item.videoTime > 0 ? String(item.videoTime) + " 分钟" : "";
|
||
var cover = escapeHtml(item.coverImg || "");
|
||
return (
|
||
'<article class="card card--play">' +
|
||
'<a class="card__cover lazy" href="' +
|
||
escapeHtml(href) +
|
||
'" style="--cover:url(' +
|
||
PLACEHOLDER +
|
||
')" data-src="' +
|
||
cover +
|
||
'">' +
|
||
(ep
|
||
? '<span class="card__ep">' + escapeHtml(ep) + "</span>"
|
||
: "") +
|
||
"</a>" +
|
||
'<h3 class="card__title"><a href="' +
|
||
escapeHtml(href) +
|
||
'">' +
|
||
name +
|
||
"</a></h3>" +
|
||
'<p class="card__meta">' +
|
||
meta +
|
||
"</p>" +
|
||
"</article>"
|
||
);
|
||
})
|
||
.join("");
|
||
grid.innerHTML = html;
|
||
if (typeof window.initLazyImages === "function") {
|
||
window.initLazyImages(grid);
|
||
}
|
||
}
|
||
|
||
function readVideoRecommendAll() {
|
||
var el = document.getElementById("video-guess-like-data");
|
||
if (!el) return [];
|
||
try {
|
||
var raw = JSON.parse(el.textContent || "[]");
|
||
return Array.isArray(raw) ? raw : [];
|
||
} catch (err) {
|
||
return [];
|
||
}
|
||
}
|
||
|
||
function slicePage(list, pageNum, pageSize) {
|
||
var total = list.length;
|
||
if (!total) return { list: [], pageNum: 1, totalCount: 0 };
|
||
if (pageNum < 1) pageNum = 1;
|
||
var start = (pageNum - 1) * pageSize;
|
||
if (start >= total) {
|
||
pageNum = 1;
|
||
start = 0;
|
||
}
|
||
return {
|
||
list: list.slice(start, start + pageSize),
|
||
pageNum: pageNum,
|
||
totalCount: total,
|
||
};
|
||
}
|
||
|
||
function setBusy(on) {
|
||
loading = on;
|
||
btn.disabled = !!on;
|
||
btn.classList.toggle("is-loading", !!on);
|
||
}
|
||
|
||
btn.addEventListener("click", function () {
|
||
if (loading) return;
|
||
|
||
var page = toInt(btn.getAttribute("data-page"), 1);
|
||
var pageSize = toInt(btn.getAttribute("data-page-size"), 6);
|
||
var total = toInt(btn.getAttribute("data-total"), 0);
|
||
|
||
// 视频播放页:详情 recommendVideos 客户端换一批(结构对齐短剧猜你喜欢)
|
||
if (videoId > 0) {
|
||
var all = readVideoRecommendAll();
|
||
var targetPage = nextPage(page, pageSize, all.length || total);
|
||
setBusy(true);
|
||
try {
|
||
var sliced = slicePage(all, targetPage, pageSize);
|
||
btn.setAttribute("data-page", String(sliced.pageNum));
|
||
btn.setAttribute("data-page-size", String(pageSize));
|
||
btn.setAttribute("data-total", String(sliced.totalCount));
|
||
renderVideoList(sliced.list);
|
||
} finally {
|
||
setBusy(false);
|
||
}
|
||
return;
|
||
}
|
||
|
||
if (!window.HttpRequest || typeof window.HttpRequest.get !== "function") {
|
||
return;
|
||
}
|
||
|
||
if (playletId <= 0) return;
|
||
|
||
var targetPage = nextPage(page, pageSize, total);
|
||
setBusy(true);
|
||
|
||
window.HttpRequest.get("/api/playlet/guess-like/list", {
|
||
params: {
|
||
playletId: playletId,
|
||
pageNum: targetPage,
|
||
pageSize: pageSize,
|
||
},
|
||
})
|
||
.then(function (res) {
|
||
if (!res || Number(res.code) !== 200 || !res.data) {
|
||
throw new Error((res && res.msg) || "guess-like failed");
|
||
}
|
||
var data = res.data;
|
||
var list = data.list || [];
|
||
var pageNum = toInt(data.pageNum, targetPage);
|
||
var size = toInt(data.pageSize, pageSize);
|
||
var totalCount = toInt(data.totalCount, total);
|
||
if (!list.length && pageNum > 1) {
|
||
return window.HttpRequest.get("/api/playlet/guess-like/list", {
|
||
params: {
|
||
playletId: playletId,
|
||
pageNum: 1,
|
||
pageSize: size,
|
||
},
|
||
}).then(function (retry) {
|
||
if (!retry || Number(retry.code) !== 200 || !retry.data) {
|
||
throw new Error((retry && retry.msg) || "guess-like failed");
|
||
}
|
||
return retry.data;
|
||
});
|
||
}
|
||
return data;
|
||
})
|
||
.then(function (data) {
|
||
btn.setAttribute("data-page", String(toInt(data.pageNum, 1)));
|
||
btn.setAttribute("data-page-size", String(toInt(data.pageSize, pageSize)));
|
||
btn.setAttribute("data-total", String(toInt(data.totalCount, total)));
|
||
renderList(data.list || []);
|
||
})
|
||
.catch(function () {})
|
||
.finally(function () {
|
||
setBusy(false);
|
||
});
|
||
});
|
||
})();
|
||
|
||
// 简介展开:PC 超过 1 行、H5 超过 2 行才显示展开按钮
|
||
(function () {
|
||
var root = document.querySelector("[data-play-synopsis]");
|
||
if (!root) return;
|
||
var textEl = root.querySelector("[data-play-synopsis-text]");
|
||
var moreBtn = root.querySelector("[data-play-synopsis-more]");
|
||
var moreLabel = root.querySelector("[data-play-synopsis-more-label]");
|
||
if (!textEl || !moreBtn) return;
|
||
|
||
function isOverflowing() {
|
||
var expanded = root.classList.contains("is-expanded");
|
||
if (expanded) root.classList.remove("is-expanded");
|
||
var needs = textEl.scrollHeight > textEl.clientHeight + 1;
|
||
if (expanded) root.classList.add("is-expanded");
|
||
return needs;
|
||
}
|
||
|
||
function syncMoreVisibility() {
|
||
var needs = isOverflowing();
|
||
moreBtn.hidden = !needs;
|
||
if (!needs && root.classList.contains("is-expanded")) {
|
||
root.classList.remove("is-expanded");
|
||
if (moreLabel) moreLabel.textContent = "展开";
|
||
moreBtn.setAttribute("aria-expanded", "false");
|
||
}
|
||
}
|
||
|
||
moreBtn.addEventListener("click", function () {
|
||
var expanded = root.classList.toggle("is-expanded");
|
||
if (moreLabel) moreLabel.textContent = expanded ? "收起" : "展开";
|
||
moreBtn.setAttribute("aria-expanded", expanded ? "true" : "false");
|
||
});
|
||
|
||
syncMoreVisibility();
|
||
window.addEventListener("resize", syncMoreVisibility);
|
||
if (document.fonts && document.fonts.ready) {
|
||
document.fonts.ready.then(syncMoreVisibility).catch(function () {});
|
||
}
|
||
})();
|
||
|
||
// 选集:正序 / 倒序(PC tabs + H5 切换共用)
|
||
(function () {
|
||
var grid = document.querySelector("[data-play-episodes-grid]");
|
||
if (!grid) return;
|
||
|
||
var h5Btn = document.querySelector("[data-play-episodes-order]");
|
||
var h5Label = h5Btn && h5Btn.querySelector("[data-play-episodes-order-label]");
|
||
var sortItems = document.querySelectorAll("[data-play-episodes-sort-item]");
|
||
var desc = false;
|
||
|
||
function reverseGrid() {
|
||
var nodes = Array.prototype.slice.call(grid.children);
|
||
if (nodes.length < 2) return;
|
||
nodes.reverse().forEach(function (node) {
|
||
grid.appendChild(node);
|
||
});
|
||
}
|
||
|
||
function syncUI() {
|
||
if (h5Btn) {
|
||
h5Btn.setAttribute("aria-pressed", desc ? "true" : "false");
|
||
h5Btn.classList.toggle("is-desc", desc);
|
||
if (h5Label) h5Label.textContent = desc ? "正序" : "倒序";
|
||
}
|
||
Array.prototype.forEach.call(sortItems, function (item) {
|
||
var isDesc = item.getAttribute("data-play-episodes-sort-item") === "desc";
|
||
var active = isDesc === desc;
|
||
item.classList.toggle("is-active", active);
|
||
item.setAttribute("aria-pressed", active ? "true" : "false");
|
||
});
|
||
}
|
||
|
||
function setOrder(nextDesc) {
|
||
nextDesc = !!nextDesc;
|
||
if (nextDesc === desc) return;
|
||
desc = nextDesc;
|
||
reverseGrid();
|
||
syncUI();
|
||
}
|
||
|
||
if (h5Btn) {
|
||
h5Btn.addEventListener("click", function () {
|
||
setOrder(!desc);
|
||
});
|
||
}
|
||
|
||
Array.prototype.forEach.call(sortItems, function (item) {
|
||
item.addEventListener("click", function () {
|
||
setOrder(item.getAttribute("data-play-episodes-sort-item") === "desc");
|
||
});
|
||
});
|
||
|
||
syncUI();
|
||
})();
|