Loading...
Зарежда се...
Adult
  • Екшън
  • Драма

Rush

R

Филмът разказва за спортното съревнование между привлекателния английски състезател и плейбой Джеймс Хънт и неговия методичен опонент Ники Лауда. Историята се фокусира върху техните напълно различни стилове на и извън състезателната писта, любовните им животи и изключително силната и за двамата 1976... Прочети повече

  • 2013
  • English
  • 02h 03m
  • 7.7 (IMDb)
Подобно съдържание
Виж всички
movie-card
7.4
movie-card
6.5
movie-card
7.5
movie-card
7.5
movie-card
6.4
movie-card
7.8
movie-card
7
movie-card
8.2
movie-card
6.1
movie-card
7.1
// GRID VIEW SUBSCRIPTION TOOLTIP setInterval(function() { if (typeof $.fn.tooltip !== 'function') return; $('.product-premium[data-bs-toggle="tooltip"]:not([data-tooltip-init])').each(function() { $(this).attr('data-tooltip-init', '1').tooltip(); }); }, 1000); // PLAYER TYPE CLASS document.addEventListener('DOMContentLoaded', function() { var videoEl = document.getElementById('videoPlayer'); if (!videoEl) return; var contentType = videoEl.getAttribute('data-contenttype'); var dataType = videoEl.getAttribute('data-type'); var vjsEl = document.querySelector('.video-js'); if (!vjsEl) return; if (contentType === 'livetv') { vjsEl.classList.add('vjs-is-livetv'); } if (dataType === 'YouTube' || dataType === 'youtube') { vjsEl.classList.add('vjs-is-youtube-trailer'); } }); // LIVE TV AUTO-RETRY document.addEventListener('DOMContentLoaded', function() { var videoEl = document.getElementById('videoPlayer'); if (!videoEl || videoEl.getAttribute('data-contenttype') !== 'livetv') return; var player = videojs.getPlayer('videoPlayer') || videojs('videoPlayer'); player.ready(function() { player.on('error', function() { var src = player.currentSrc(); if (!src) return; player.error(null); setTimeout(function() { player.src({ src: src, type: 'application/x-mpegURL' }); player.load(); player.one('canplay', function() { player.muted(false); player.volume(1); }); }, 1500); }); }); }); // PLAYER LOADING OVERLAY document.addEventListener('DOMContentLoaded', function() { var overlay = document.getElementById('playerLoadingOverlay'); if (!overlay) return; var waitingTimer = null; window.showPlayerOverlay = function(force) { var videoEl = document.getElementById('videoPlayer'); var contentType = videoEl ? videoEl.getAttribute('data-contenttype') : null; var access = videoEl ? videoEl.getAttribute('data-movie-access') : null; var canShow = isAuthenticated || (contentType === 'livetv' && access === 'free'); if (!canShow && !force) return; var bgEl = overlay.querySelector('.player-loading-bg'); var posterUrl = window.currentPosterUrl || null; if (bgEl && posterUrl) { bgEl.style.backgroundImage = 'url(' + posterUrl + ')'; } overlay.classList.add('is-visible'); } window.hidePlayerOverlay = function() { clearTimeout(waitingTimer); overlay.classList.remove('is-visible'); } setTimeout(function() { var playWrapper = document.querySelector('.play-button-wrapper'); if (playWrapper) playWrapper.addEventListener('click', function(e) { if (!e.target.closest('#watchNowButton')) return; if (e.target.closest('#liveTvPlayBtn')) return; var videoEl = document.getElementById('videoPlayer'); var contentType = videoEl ? videoEl.getAttribute('data-contenttype') : null; if (contentType === 'livetv') return; var watchBtn = document.getElementById('watchNowButton'); var allowedQualities = JSON.parse((watchBtn ? watchBtn.getAttribute('data-allowed-qualities') : null) || '[]'); var access = videoEl ? videoEl.getAttribute('data-movie-access') : null; var hasAccess = access === 'free' || allowedQualities.length > 0; if (!hasAccess) return; window.showPlayerOverlay(); }); }, 2000); document.addEventListener('click', function(e) { var skipBtn = e.target.closest('.vjs-skip-trainer-button'); if (!skipBtn) return; var videoEl = document.getElementById('videoPlayer'); var watchBtn = document.getElementById('watchNowButton'); var allowedQualities = JSON.parse((watchBtn ? watchBtn.getAttribute('data-allowed-qualities') : null) || '[]'); var access = videoEl ? videoEl.getAttribute('data-movie-access') : null; var hasAccess = access === 'free' || allowedQualities.length > 0; if (!hasAccess) return; window.showPlayerOverlay(); }); document.addEventListener('touchend', function(e) { var skipBtn = e.target.closest('.vjs-skip-trainer-button'); if (!skipBtn) return; var videoEl = document.getElementById('videoPlayer'); var watchBtn = document.getElementById('watchNowButton'); var allowedQualities = JSON.parse((watchBtn ? watchBtn.getAttribute('data-allowed-qualities') : null) || '[]'); var access = videoEl ? videoEl.getAttribute('data-movie-access') : null; var hasAccess = access === 'free' || allowedQualities.length > 0; if (!hasAccess) return; window.showPlayerOverlay(); }); function waitForPlayer() { var player = videojs.getPlayer('videoPlayer'); if (!player) { setTimeout(waitForPlayer, 300); return; } player.on('playing', function() { setTimeout(window.hidePlayerOverlay, 800); }); player.on('waiting', function() { var src = player.currentSource(); var isYouTube = src && src.src && src.src.includes('youtube'); var videoEl = document.getElementById('videoPlayer'); var cvt = videoEl ? videoEl.getAttribute('content-video-type') : null; var watchBtn = document.getElementById('watchNowButton'); var allowedQualities = JSON.parse((watchBtn ? watchBtn.getAttribute('data-allowed-qualities') : null) || '[]'); var access = videoEl ? videoEl.getAttribute('data-movie-access') : null; var hasAccess = access === 'free' || allowedQualities.length > 0; var contentType = videoEl ? videoEl.getAttribute('data-contenttype') : null; if (!isYouTube && cvt !== 'trailer' && hasAccess && contentType !== 'livetv') { clearTimeout(waitingTimer); waitingTimer = setTimeout(function() { window.showPlayerOverlay(); }, 500); } }); player.on('error', window.hidePlayerOverlay); } waitForPlayer(); }); // iOS/ANDROID BUTTON document.addEventListener('DOMContentLoaded', function() { if (!/iPhone|iPad|iPod|Android/i.test(navigator.userAgent)) return; var style = document.createElement('style'); style.innerHTML = '.video-js.vjs-user-inactive .vjs-overlay-skip { opacity: 1 !important; visibility: visible !important; pointer-events: auto !important; transition: none !important; animation: none !important; }'; document.head.appendChild(style); var checkPlayer = setInterval(function() { if (typeof videojs === 'undefined') { clearInterval(checkPlayer); return; } var player = videojs.getPlayer('videoPlayer'); if (!player) return; clearInterval(checkPlayer); player.ready(function() { var bigPlayButtonComponent = player.getChild('BigPlayButton'); if (!bigPlayButtonComponent) return; var videoEl = document.getElementById('videoPlayer'); var isLiveTV = videoEl && videoEl.getAttribute('data-contenttype') === 'livetv'; var isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1); bigPlayButtonComponent.handleClick = function(e) { if (player.paused()) { if (isLiveTV && typeof window.liveTvDoPlay === 'function') { window.liveTvLastPlay = Date.now(); window.liveTvDoPlay(); } else { player.play().catch(function(){}); } } else { player.pause(); } }; (function bindSkipButton() { var skipBtn = document.querySelector('.vjs-skip-trainer-button'); if (!skipBtn) { setTimeout(bindSkipButton, 300); return; } if (skipBtn._skipBound) return; skipBtn._skipBound = true; skipBtn.addEventListener('click', function() { var origUserActive = player.userActive.bind(player); player.userActive = function(val) { if (val === true) return; return origUserActive(val); }; setTimeout(function() { player.userActive = origUserActive; player.userActive(false); }, 3000); }); })(); if (isIOS) { var vjsEl = player.el(); function hideControls() { vjsEl.classList.remove('vjs-user-active'); vjsEl.classList.add('vjs-user-inactive'); var cb = vjsEl.querySelector('.vjs-control-bar'); var bp = vjsEl.querySelector('.vjs-big-play-button'); if (cb) { cb.style.opacity = '0'; cb.style.pointerEvents = 'none'; } if (bp && !player.paused()) { bp.style.opacity = '0'; bp.style.pointerEvents = 'none'; } } function showControls() { vjsEl.classList.add('vjs-user-active'); vjsEl.classList.remove('vjs-user-inactive'); var cb = vjsEl.querySelector('.vjs-control-bar'); var bp = vjsEl.querySelector('.vjs-big-play-button'); if (cb) { cb.style.opacity = ''; cb.style.pointerEvents = ''; } if (bp) { bp.style.opacity = ''; bp.style.pointerEvents = ''; } } var hideTimeout = null; function scheduleHide() { clearTimeout(hideTimeout); hideTimeout = setTimeout(hideControls, 3000); } player.on('play', function() { scheduleHide(); }); player.on('pause', function() { clearTimeout(hideTimeout); showControls(); }); vjsEl.addEventListener('touchend', function(e) { if (e.target.closest('.vjs-control-bar') || e.target.closest('.vjs-big-play-button') || e.target.closest('.vjs-menu') || e.target.closest('.vjs-quality-selector') || e.target.closest('.vjs-custom-menu') || e.target.closest('.vjs-custom-menu-overlay')) return; e.preventDefault(); var cb = vjsEl.querySelector('.vjs-control-bar'); if (cb && cb.style.opacity === '0') { showControls(); scheduleHide(); } else { hideControls(); } }, true); } }); }, 500); }); // LIVE TV WATCH NOW document.addEventListener('DOMContentLoaded', function() { var videoEl = document.getElementById('videoPlayer'); if (!videoEl || videoEl.getAttribute('data-contenttype') !== 'livetv') return; var btn = document.getElementById('liveTvPlayBtn'); if (!btn) return; async function checkSubscription(planId) { try { var base = (typeof baseUrl !== 'undefined' && baseUrl) ? baseUrl : window.location.origin; var r = await fetch(base + '/check-subscription/' + planId); var d = await r.json(); return d.isActive; } catch (e) { return false; } } btn.addEventListener('click', async function() { window.scrollTo({ top: 0, behavior: 'smooth' }); var access = videoEl.getAttribute('data-movie-access'); var planId = videoEl.getAttribute('data-plan-id'); if (!isAuthenticated && access !== 'free') { window.location.href = loginUrl; return; } var player = videojs.getPlayer('videoPlayer'); var hasStarted = player && (player.currentTime() > 0 || !player.paused()); if (hasStarted) return; if (typeof window.liveTvDoPlay === 'function') window.liveTvDoPlay(); if (access === 'paid' && planId) { var ok = await checkSubscription(planId); if (!ok) { if (player) player.pause(); if (window.hidePlayerOverlay) window.hidePlayerOverlay(); $('#DeviceSupport').modal('show'); } } }); }); // CUSTOM VOLUME PANEL START document.addEventListener("DOMContentLoaded", function () { if (typeof videojs !== 'undefined') { const p = videojs.getPlayer('videoPlayer'); if (p) { p.ready(function () { const c = p.controlBar; const i = c.children().findIndex(x => x.name_ === 'VolumePanel'); if (c.volumePanel) c.removeChild(c.volumePanel); c.addChild('VolumePanel', { inline: false, vertical: true }, i); }); } } }); //DISABLE ADS FOR YOUTUBE TRAILER document.addEventListener('DOMContentLoaded', function() { setTimeout(function() { var videoEl = document.getElementById('videoPlayer'); if (!videoEl) return; var dataType = videoEl.getAttribute('data-type'); var cvt = videoEl.getAttribute('content-video-type'); var isYouTubeTrailer = (dataType === 'YouTube' || dataType === 'youtube') && cvt === 'trailer'; if (!isYouTubeTrailer) return; try { var player = videojs('videoPlayer'); player.ads.settings.prerollTimeout = 0; player.ads.settings.postrollTimeout = 0; player.trigger('nopreroll'); player.trigger('nopostroll'); if (player.ads.state === 'BeforePreroll' || player.ads.state === 'Preroll') { player.trigger('adscanceled'); } } catch(e) {} }, 300); }); // DEFAULT SUBTITLES function initSubtitles() { if (typeof videojs === 'undefined') { setTimeout(initSubtitles, 200); return; } const player = videojs.getPlayer('videoPlayer'); if (!player) { setTimeout(initSubtitles, 200); return; } const btn = document.getElementById('watchNowButton') || document.querySelector('[data-subtitle-info]'); if (!btn) return; const subtitles = JSON.parse(btn.getAttribute('data-subtitle-info') || '[]'); if (!subtitles.length) return; const defaultLabel = (subtitles.find(s => s.is_default == 1) || {}).language; function applySubtitles() { var src = player.currentSource(); var isYouTube = src && src.src && src.src.includes('youtube'); if (isYouTube) return; const tracks = player.textTracks(); const hasSubs = Array.from({length: tracks.length}, (_, i) => tracks[i]).some(t => t.kind === 'subtitles'); if (!hasSubs) subtitles.forEach(s => player.addRemoteTextTrack({ kind: 'subtitles', src: s.subtitle_file, srclang: s.language_code, label: s.language }, false)); setTimeout(() => { for (let i = 0; i < player.textTracks().length; i++) { const t = player.textTracks()[i]; if (t.kind === 'subtitles') t.mode = t.label === defaultLabel ? 'showing' : 'disabled'; } }, 300); } const originalSrc = player.src.bind(player); player.src = function(source) { const result = originalSrc(source); const src = (source?.src || source || ''); const type = (source?.type || ''); if (type.includes('youtube') || src.includes('youtube.com')) return result; player.one('loadedmetadata', () => setTimeout(applySubtitles, 200)); return result; }; if (player.ima) player.on('adsadended', () => setTimeout(() => { for (let i = 0; i < player.textTracks().length; i++) { const t = player.textTracks()[i]; if (t.kind === 'subtitles' && t.label === defaultLabel) { t.mode = 'showing'; break; } } }, 200)); } initSubtitles(); // iOS BLACK SCREEN var isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1); if (isIOS) { document.addEventListener("DOMContentLoaded", function() { var videoEl = document.getElementById('videoPlayer'); if (!videoEl) return; var contentType = videoEl.getAttribute('data-contenttype'); if (contentType !== 'livetv') return; function initFix() { if (typeof videojs === 'undefined') { setTimeout(initFix, 200); return; } const player = videojs.getPlayer('videoPlayer'); if (!player) { setTimeout(initFix, 200); return; } player.one('loadstart', function() { var realSrc = player.currentSrc(); if (!realSrc) return; player.src({ type: 'video/youtube', src: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' }); setTimeout(function() { player.src({ type: 'application/x-mpegURL', src: realSrc }); player.play().catch(function(){}); }, 800); }); } initFix(); }); } // REDIRECT TO NEXT EPISODE PAGE document.addEventListener('click', function(e) { var btn = e.target.closest('.season-watch-btn'); if (btn) { var slug = btn.getAttribute('data-episode-slug'); if (slug) { e.preventDefault(); e.stopImmediatePropagation(); window.location.href = '/episode-details/' + slug; } } }); // EPISODE NAME DISPLAY ON ACTIVE EPISODE function updateEpisodeNameTop() { const activeCard = document.querySelector('.season-card.is-playing'); const episodeNameTop = document.getElementById('episodeNameDisplayTop'); const currentEpisodeNameSpan = document.getElementById('currentEpisodeName'); if (activeCard && episodeNameTop && currentEpisodeNameSpan) { const watchBtn = activeCard.querySelector('.season-watch-btn'); if (watchBtn) { const nameBg = watchBtn.getAttribute('data-episode-name-bg'); const nameEn = watchBtn.getAttribute('data-episode-name'); const currentLocale = document.documentElement.lang || 'bg'; if (currentLocale === 'bg' && nameBg) { currentEpisodeNameSpan.textContent = nameBg; } else { currentEpisodeNameSpan.textContent = nameEn; } episodeNameTop.style.display = 'block'; } } else if (episodeNameTop) { episodeNameTop.style.display = 'none'; } } const episodeNameObserver = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.type === 'attributes' && mutation.attributeName === 'class') { updateEpisodeNameTop(); } }); }); document.querySelectorAll('.season-card').forEach(function(card) { episodeNameObserver.observe(card, { attributes: true }); }); updateEpisodeNameTop(); // PLAYER TOOLTIPS document.addEventListener('DOMContentLoaded', function() { var tooltipMap = { 'vjs-fullscreen-control': 'Fullscreen', 'vjs-picture-in-picture-control': 'Picture-in-Picture', 'vjs-subs-caps-button': 'Subtitles', 'vjs-volume-panel': 'Volume', 'vjs-seek-to-live-control': 'Seek to Live', }; var removeOnly = [ 'vjs-backword-button', 'vjs-forword-button', 'vjs-big-play-button', 'vjs-next-episode-button', ]; function fixTitles() { Object.entries(tooltipMap).forEach(function([cls, tooltip]) { var btn = document.querySelector('.' + cls); if (btn) { btn.removeAttribute('title'); btn.setAttribute('data-tooltip', tooltip); } }); removeOnly.forEach(function(cls) { var btn = document.querySelector('.' + cls); if (btn) { btn.removeAttribute('title'); } }); document.querySelectorAll('.vjs-button[title]').forEach(function(btn) { btn.removeAttribute('title'); }); } var checkPlayer = setInterval(function() { if (document.querySelector('.vjs-fullscreen-control')) { fixTitles(); clearInterval(checkPlayer); var observer = new MutationObserver(fixTitles); observer.observe(document.body, { attributes: true, subtree: true, attributeFilter: ['title'] }); } }, 500); }); // NEXT EPISODE BULGARIAN TITLE document.addEventListener('DOMContentLoaded', function() { const currentLang = document.documentElement.lang || 'en'; const episodeButtons = document.querySelectorAll('[data-episode-id]'); episodeButtons.forEach(button => { if (currentLang === 'bg') { const nameBg = button.getAttribute('data-episode-name-bg'); if (nameBg) { button.setAttribute('data-episode-name', nameBg); } } }); }); // QUALITY INFO CHECK SUBSCRIPTONS document.addEventListener('DOMContentLoaded', function () { const watchBtn = document.getElementById('watchNowButton'); if (!watchBtn) return; const allowedQualities = JSON.parse(watchBtn.getAttribute('data-allowed-qualities') || '[]'); let lastAllowedIndex = 0; let autoSelectInProgress = false; window._autoSelectInProgress = false; document.addEventListener('change', function (e) { const select = e.target.closest('.vjs-quality-selector select'); if (!select) return; if (window._autoSelectInProgress) return; const selectedLabel = select.options[select.selectedIndex].text.trim(); const selectedValue = select.options[select.selectedIndex].value; if (!selectedValue || select.selectedIndex === 0) { lastAllowedIndex = 0; return; } if (!allowedQualities.includes(selectedLabel)) { e.stopImmediatePropagation(); e.preventDefault(); select.selectedIndex = lastAllowedIndex; $('#DeviceSupport').modal('show'); } else { lastAllowedIndex = select.selectedIndex; } }, true); }); // CUSTOM ADS OPACITY document.addEventListener('DOMContentLoaded', function() { const modal = document.getElementById('customAdModal'); if (!modal) return; new MutationObserver(function(m) { m.forEach(function(x) { if (x.attributeName === 'style') { if (modal.style.display === 'flex') requestAnimationFrame(() => modal.classList.add('show')); else modal.classList.remove('show'); } }); }).observe(modal, { attributes: true, attributeFilter: ['style'] }); }); // WATCH NOW BUTTON (SCROLL + SKIP TRAILER) setTimeout(function() { var watchBtn = document.getElementById('watchNowButton'); var skipBtn = document.querySelector('.vjs-skip-trainer-button'); if (!watchBtn && !skipBtn) return; function scrollToPlayer() { window.scrollTo({ top: 0, behavior: 'smooth' }); } function canPlay() { var videoEl = document.getElementById('videoPlayer'); var contentType = videoEl ? videoEl.getAttribute('data-contenttype') : null; var access = videoEl ? videoEl.getAttribute('data-movie-access') : null; if (contentType === 'livetv' && access === 'free') return true; return isAuthenticated; } function isVideoStarted() { var player = videojs.getPlayer('videoPlayer'); if (!player) return false; var src = player.currentSource(); var isYouTube = src && src.src && src.src.includes('youtube'); if (isYouTube) return false; return player.currentTime() > 0 || !player.paused(); } if (watchBtn) { watchBtn.addEventListener('click', function(e) { if (!canPlay()) { e.preventDefault(); e.stopImmediatePropagation(); scrollToPlayer(); setTimeout(function() { window.location.href = loginUrl; }, 400); return; } if (isVideoStarted()) { e.preventDefault(); e.stopImmediatePropagation(); scrollToPlayer(); return; } scrollToPlayer(); }, true); } if (skipBtn) { skipBtn.addEventListener('click', function() { if (!canPlay()) return; scrollToPlayer(); }); } }, 2000); // UNMUTE MAIN VIDEO if (document.getElementById('videoPlayer')) { (function() { var player = videojs('videoPlayer'); player.ready(function() { var bigPlayBtn = player.el().querySelector('.vjs-big-play-button'); bigPlayBtn.addEventListener('click', function(e) { if (!player.paused()) { e.stopImmediatePropagation(); player.pause(); } }, true); var origMuted = player.muted.bind(player); var unmuteDone = false; var blockProgrammaticMute = false; player.muted = function(val) { if (val === true && blockProgrammaticMute) return origMuted(); return origMuted(val); }; player.on('playing', function() { if (unmuteDone) return; var src = player.currentSource(); var isYouTube = src && src.src && src.src.includes('youtube'); var isLiveTV = document.getElementById('videoPlayer').getAttribute('data-contenttype') === 'livetv'; if (!isYouTube && !isLiveTV) { unmuteDone = true; blockProgrammaticMute = true; origMuted(false); player.volume(1); var video = document.querySelector('video.vjs-tech'); if (video) { video.muted = false; video.removeAttribute('muted'); video.volume = 1; } var muteBtn = player.el().querySelector('.vjs-mute-control'); if (muteBtn) { muteBtn.addEventListener('click', function() { blockProgrammaticMute = false; }, { once: true, capture: true }); } } }); }); })(); } // ADBLOCK DETECTOR document.addEventListener('DOMContentLoaded', function() { new MutationObserver(function() { var img = document.querySelector('#customAdContent img'); var closeBtn = document.getElementById('customAdCloseBtn'); if (!img || img.dataset.fallbackAdded) return; img.dataset.fallbackAdded = '1'; function showFallback() { img.style.display = 'none'; if (closeBtn) closeBtn.style.display = 'none'; if (document.getElementById('adblock-fallback')) return; var el = document.createElement('div'); el.id = 'adblock-fallback'; el.innerHTML = '

' + adblockTitle + '

' + adblockMessage + '

'; document.getElementById('customAdContent').appendChild(el); } img.addEventListener('error', showFallback); img.addEventListener('load', function() { img.dataset.loaded = '1'; }); setTimeout(function() { if (img.dataset.loaded) return; if (img.complete && img.naturalWidth > 0) return; showFallback(); }, 2000); }).observe(document.body, { childList: true, subtree: true }); }); // FULLSCREEN MODAL $(document).on('show.bs.modal', '#DeviceSupport', function() { if (document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement) { document.exitFullscreen && document.exitFullscreen(); document.webkitExitFullscreen && document.webkitExitFullscreen(); document.mozCancelFullScreen && document.mozCancelFullScreen(); } }); // CUSTOM AD MODAL FULLSCREEN document.addEventListener('DOMContentLoaded', function() { const videoPlayer = document.getElementById('videoPlayer'); const modal = document.getElementById('customAdModal'); const overlay = document.getElementById('playerLoadingOverlay'); if (!videoPlayer) return; document.addEventListener('fullscreenchange', function() { const fsElement = document.fullscreenElement; if (modal) { if (fsElement && fsElement !== modal.parentElement) { fsElement.appendChild(modal); } else if (!fsElement) { document.querySelector('.video-player').appendChild(modal); } modal.style.pointerEvents = 'auto'; modal.style.zIndex = '2147483647'; document.getElementById('customAdCloseBtn').style.pointerEvents = 'auto'; document.getElementById('customAdCloseBtn').style.zIndex = '2147483647'; } if (overlay) { if (fsElement) { fsElement.appendChild(overlay); } else { document.querySelector('.video-player').appendChild(overlay); } overlay.style.zIndex = '2147483647'; } }); }); // HLS QUALITY SELECTOR FOR LIVE TV (function() { var checkPlayer = setInterval(function() { if (typeof videojs === 'undefined') return; var player = videojs.getPlayer('videoPlayer'); if (!player || !player.isReady_) return; clearInterval(checkPlayer); function tryBuildSelector() { if (document.querySelector('.vjs-quality-selector')) return; var ql = player.qualityLevels(); if (!ql || ql.length === 0) return; var selector = document.createElement('div'); selector.classList.add('vjs-quality-selector'); var select = document.createElement('select'); var autoOption = document.createElement('option'); autoOption.value = -1; autoOption.innerText = 'Auto'; select.appendChild(autoOption); var levels = []; for (var i = 0; i < ql.length; i++) { levels.push({ index: i, height: ql[i].height }); } levels.sort(function(a, b) { return b.height - a.height; }); levels.forEach(function(level) { var opt = document.createElement('option'); opt.value = level.index; opt.innerText = level.height ? level.height + 'p' : 'Level ' + level.index; select.appendChild(opt); }); select.addEventListener('change', function() { var val = parseInt(this.value); for (var i = 0; i < ql.length; i++) { ql[i].enabled = (val === -1 || val === i); } }); selector.appendChild(select); player.controlBar.el().appendChild(selector); } player.on('loadedmetadata', tryBuildSelector); player.on('playing', tryBuildSelector); }, 500); })(); // BACKWORD/FORWORD BUTTONS FOR LIVE TV window.addEventListener('load', function() { var videoEl = document.getElementById('videoPlayer'); if (!videoEl || videoEl.getAttribute('data-contenttype') !== 'livetv') return; var attempts = 0; function waitForPlayer() { attempts++; if (attempts > 60) return; if (typeof videojs === 'undefined') { setTimeout(waitForPlayer, 300); return; } var player = videojs.getPlayer('videoPlayer'); if (!player) { setTimeout(waitForPlayer, 300); return; } player.ready(function() { try { var Button = videojs.getComponent('Button'); if (!Button) { setTimeout(waitForPlayer, 300); return; } if (!videojs.getComponent('BackwordButton')) { class BackwordButton extends Button { constructor(player, options) { super(player, options); this.addClass('vjs-backword-button'); this.player_ = player; } createEl() { var el = document.getElementById('videoPlayer'); var n = el ? parseInt(el.getAttribute('data-backward-seconds') || '', 10) : NaN; var s = Number.isFinite(n) && n > 0 ? n : 10; var button = super.createEl('button', { className: 'vjs-backword-button vjs-control vjs-button' }); button.setAttribute('aria-label', 'Backward ' + s + ' seconds'); button.innerHTML = `${s}s`; return button; } handleClick() { var el = document.getElementById('videoPlayer'); var n = el ? parseInt(el.getAttribute('data-backward-seconds') || '', 10) : NaN; var s = Number.isFinite(n) && n > 0 ? n : 10; this.player_.currentTime(Math.max(0, this.player_.currentTime() - s)); } } videojs.registerComponent('BackwordButton', BackwordButton); } if (!videojs.getComponent('ForwordButton')) { class ForwordButton extends Button { constructor(player, options) { super(player, options); this.addClass('vjs-forword-button'); this.player_ = player; } createEl() { var el = document.getElementById('videoPlayer'); var n = el ? parseInt(el.getAttribute('data-forward-seconds') || '', 10) : NaN; var s = Number.isFinite(n) && n > 0 ? n : 10; var button = super.createEl('button', { className: 'vjs-forword-button vjs-control vjs-button' }); button.setAttribute('aria-label', 'Forward ' + s + ' seconds'); button.innerHTML = `${s}s`; return button; } handleClick() { var el = document.getElementById('videoPlayer'); var n = el ? parseInt(el.getAttribute('data-forward-seconds') || '', 10) : NaN; var s = Number.isFinite(n) && n > 0 ? n : 10; var dur = this.player_.duration(); this.player_.currentTime(Math.min(dur || Infinity, this.player_.currentTime() + s)); } } videojs.registerComponent('ForwordButton', ForwordButton); } var BackwordCtor = videojs.getComponent('BackwordButton'); var ForwordCtor = videojs.getComponent('ForwordButton'); var root = player.el(); var backwordBtn = new BackwordCtor(player); backwordBtn.name_ = 'BackwordButton'; player.addChild(backwordBtn); var forwordBtn = new ForwordCtor(player); forwordBtn.name_ = 'ForwordButton'; player.addChild(forwordBtn); var backwordEl = backwordBtn.el(); var forwordEl = forwordBtn.el(); backwordEl.classList.add('vjs-overlay-skip', 'vjs-overlay-backword'); forwordEl.classList.add('vjs-overlay-skip', 'vjs-overlay-forword'); if (backwordEl.parentNode !== root) { backwordEl.parentNode && backwordEl.parentNode.removeChild(backwordEl); root.appendChild(backwordEl); } if (forwordEl.parentNode !== root) { forwordEl.parentNode && forwordEl.parentNode.removeChild(forwordEl); root.appendChild(forwordEl); } backwordEl.style.display = 'none'; forwordEl.style.display = 'none'; player.on('play', function() { backwordEl.style.display = ''; forwordEl.style.display = ''; }); } catch(e) {} }); } waitForPlayer(); }); // LIVE TV NO-AUTOPLAY & NO-MUTE document.addEventListener('DOMContentLoaded', function () { var videoEl = document.getElementById('videoPlayer'); if (!videoEl || videoEl.getAttribute('data-contenttype') !== 'livetv') return; var isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1); var playerReady = false; var attempts = 0; async function hasAccess() { var access = videoEl.getAttribute('data-movie-access'); var planId = videoEl.getAttribute('data-plan-id'); if (access === 'free') return true; if (!isAuthenticated) return false; if (access === 'paid' && planId) { try { var base = (typeof baseUrl !== 'undefined' && baseUrl) ? baseUrl : window.location.origin; var r = await fetch(base + '/check-subscription/' + planId); var d = await r.json(); return d.isActive; } catch(e) { return false; } } return true; } function waitForPlayer() { if (++attempts > 40) return; var playerEl = document.querySelector('.video-js'); if (!playerEl || !window.videojs) return setTimeout(waitForPlayer, 300); var player = videojs.getPlayer(playerEl); if (!player || playerReady) return setTimeout(waitForPlayer, 300); playerReady = true; var userMuted = false; player.on('volumechange', function() { userMuted = player.muted(); }); if (isIOS) { var origPlay = player.play.bind(player); var userInteracted = false; player.on('play', function() { if (!userInteracted) { userInteracted = true; player.play = origPlay; if (!userMuted) { player.muted(false); player.volume(1); } document.querySelectorAll('[poster]').forEach(function(el) { el.removeAttribute('poster'); }); } }); window.liveTvDoPlay = async function() { if (!userInteracted && typeof window.showPlayerOverlay === 'function') window.showPlayerOverlay(true); var ok = await hasAccess(); if (!ok) { if (typeof window.hidePlayerOverlay === 'function') window.hidePlayerOverlay(); $('#DeviceSupport').modal('show'); return; } if (userInteracted) { if (player.paused()) { window.liveTvLastPlay = Date.now(); origPlay().catch(function(){}); } return; } if (typeof window.showPlayerOverlay === 'function') window.showPlayerOverlay(); userInteracted = true; player.play = origPlay; window.liveTvLastPlay = Date.now(); origPlay().then(function() { if (!userMuted) { player.muted(false); player.volume(1); } document.querySelectorAll('[poster]').forEach(function(el) { el.removeAttribute('poster'); }); }).catch(function(){}); }; player.play = function() { if (!userInteracted) return Promise.resolve(); return origPlay(); }; new MutationObserver(function() { var bp = playerEl.querySelector('.vjs-big-play-button'); if (!bp) return; if (!userInteracted && window.getComputedStyle(bp).display === 'none') { bp.style.display = 'block'; } }).observe(playerEl, { attributes: true, subtree: true, attributeFilter: ['style', 'class'] }); return; } var originalPlay = player.play.bind(player); var firstPlayDone = false; var isLoading = false; async function doFirstPlay() { if (firstPlayDone || isLoading) return; isLoading = true; if (typeof window.showPlayerOverlay === 'function') window.showPlayerOverlay(true); var ok = await hasAccess(); if (!ok) { isLoading = false; if (typeof window.hidePlayerOverlay === 'function') window.hidePlayerOverlay(); $('#DeviceSupport').modal('show'); return; } var src = player.currentSrc(); if (src && src.includes('.m3u8')) { player.src({ src: src, type: 'application/x-mpegURL' }); player.load(); setTimeout(function () { if (!userMuted) { player.muted(false); player.volume(1); } document.querySelectorAll('[poster]').forEach(function(el) { el.removeAttribute('poster'); }); originalPlay().finally(function () { isLoading = false; firstPlayDone = true; player.play = originalPlay; }); }, 200); return; } if (!userMuted) { player.muted(false); player.volume(1); } document.querySelectorAll('[poster]').forEach(function(el) { el.removeAttribute('poster'); }); originalPlay().finally(function () { isLoading = false; firstPlayDone = true; player.play = originalPlay; }); } window.liveTvDoPlay = async function() { if (firstPlayDone) { var ok = await hasAccess(); if (!ok) { $('#DeviceSupport').modal('show'); return; } if (player.paused()) player.play(); return; } doFirstPlay(); }; player.play = function () { if (!firstPlayDone) return Promise.resolve(); if (isLoading) return Promise.resolve(); return originalPlay(); }; var bigPlayBtn = playerEl.querySelector('.vjs-big-play-button'); if (bigPlayBtn) { function onTouchStart(e) { if (!firstPlayDone) { doFirstPlay(); } else { bigPlayBtn.removeEventListener('touchstart', onTouchStart, true); } } bigPlayBtn.addEventListener('touchstart', onTouchStart, { capture: true, passive: true }); bigPlayBtn.addEventListener('click', function(e) { e.preventDefault(); e.stopImmediatePropagation(); if (!firstPlayDone) doFirstPlay(); else if (player.paused()) player.play(); else player.pause(); }, true); } } waitForPlayer(); }); // CUSTOM AD TIMER const customAdModal = document.getElementById('customAdModal'); const adModalObserver = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.attributeName === 'style') { const modal = mutation.target; if (modal.style.display !== 'none' && modal.style.display !== '') { startAdTimer(); } } }); }); if (customAdModal) { adModalObserver.observe(customAdModal, { attributes: true }); } // PLAYER TITLE OVERLAY document.addEventListener('DOMContentLoaded', function() { const videoEl = document.getElementById('videoPlayer'); if (!videoEl) return; const currentLang = document.documentElement.lang || 'en'; const isLiveTvPage = window.location.pathname.includes('/livetv-details/'); if (isLiveTvPage) { // --- LIVE TV: build overlay from EPG data in the page --- const epgTitleEl = document.querySelector('.epg-current strong'); const epgTimeEl = document.querySelector('.epg-current .epg-time'); const epgCategoryEls = document.querySelectorAll('.epg-categories .badge'); const epgTitle = epgTitleEl?.textContent?.trim(); if (!epgTitle) return; const overlay = document.createElement('div'); overlay.id = 'playerTitleOverlay'; if (epgCategoryEls.length > 0) { const catRow = document.createElement('div'); catRow.className = 'player-epg-categories'; epgCategoryEls.forEach(function(cat) { const badge = document.createElement('span'); badge.className = 'player-epg-category-badge'; badge.textContent = cat.textContent.trim(); catRow.appendChild(badge); }); overlay.appendChild(catRow); } const titleRow = document.createElement('div'); titleRow.className = 'player-epg-title-row'; const titleSpan = document.createElement('span'); titleSpan.className = 'player-epg-title'; titleSpan.textContent = epgTitle; titleRow.appendChild(titleSpan); if (epgTimeEl?.textContent?.trim()) { const timeSpan = document.createElement('span'); timeSpan.className = 'player-epg-time'; timeSpan.textContent = epgTimeEl.textContent.trim(); titleRow.appendChild(timeSpan); } overlay.appendChild(titleRow); videoEl.appendChild(overlay); return; } // --- VOD / EPISODES: existing logic --- const rawTitle = document.title.split(' | ')[0].trim(); const isEpisodePage = window.location.pathname.includes('/episode-details/'); let titleText = ''; if (rawTitle.includes(' / ')) { const parts = rawTitle.split(' / '); titleText = currentLang === 'bg' ? parts[0].trim() : parts[1].replace(/\(\d{4}\)/, '').trim(); } else { titleText = rawTitle.replace(/\(\d{4}\)/, '').trim(); } const episodeName = document.querySelector('#currentEpisodeName')?.textContent?.trim(); if (episodeName && isEpisodePage) { titleText = episodeName; } if (!titleText) return; const titleOverlay = document.createElement('div'); titleOverlay.id = 'playerTitleOverlay'; titleOverlay.textContent = titleText; videoEl.appendChild(titleOverlay); }); // CUSTOM VJS MENU (QUALITY + SUBTITLES) (function() { var playerEl = document.querySelector('.video-js'); if (!playerEl) return; var isLive = window.location.pathname.includes('/livetv-details/'); var lang = document.documentElement.lang === 'bg' ? 'bg' : 'en'; var i18n = { bg: { quality: 'Качество', subs: 'Субтитри', off: 'Изключени', none: 'Няма налични' }, en: { quality: 'Quality', subs: 'Subtitles', off: 'Off', none: 'None available' } }[lang]; var overlay = document.createElement('div'); overlay.className = 'vjs-custom-menu-overlay'; playerEl.appendChild(overlay); var sheet = document.createElement('div'); sheet.className = 'vjs-custom-menu'; sheet.innerHTML = `
${!isLive ? `` : ''}
`; playerEl.appendChild(sheet); var activeTab = 'quality'; var currentSelectedQuality = null; function parseQualityNumber(text) { var lower = text.toLowerCase().trim(); if (lower === 'auto') return -1; if (/^4k$/i.test(lower) || /^4к$/i.test(lower)) return 4000; if (/^8k$/i.test(lower) || /^8к$/i.test(lower)) return 8000; var match = lower.match(/(\d+)/); if (match) return parseInt(match[1], 10); return 0; } function getQualityIcon(qualityText) { var num = parseQualityNumber(qualityText); if (num >= 720) return '\uEA8E'; return '\uEA90'; } function updateBadge(select, btn) { var badge = btn.querySelector('.vjs-quality-badge'); if (!badge) return; if (!currentSelectedQuality) { var watchBtn = document.getElementById('watchNowButton'); var allowedQualities = []; try { allowedQualities = JSON.parse((watchBtn ? watchBtn.getAttribute('data-allowed-qualities') : null) || '[]'); } catch(e) {} var availableLabels = Array.from(select.options).map(function(opt) { return opt.text.trim(); }); var qualityPriority = ['1080p', '720p', '480p']; for (var i = 0; i < qualityPriority.length; i++) { if (allowedQualities.includes(qualityPriority[i]) && availableLabels.includes(qualityPriority[i])) { currentSelectedQuality = qualityPriority[i]; break; } } } var qualityText = currentSelectedQuality || (select.options[select.selectedIndex] ? select.options[select.selectedIndex].text.trim() : ''); if (!qualityText || qualityText.toLowerCase() === 'auto') { badge.textContent = ''; badge.style.display = 'none'; return; } badge.textContent = getQualityIcon(qualityText); badge.style.display = 'flex'; } function handleItemClick(body, el, item, onSelect) { var previousActive = body.querySelector('.vjs-custom-menu-item.active'); var previousQuality = currentSelectedQuality; body.querySelectorAll('.vjs-custom-menu-item').forEach(function(i) { i.classList.remove('active'); }); el.classList.add('active'); currentSelectedQuality = item.label; onSelect(item); setTimeout(function() { var select = document.querySelector('.vjs-quality-selector select'); if (select && select.selectedIndex !== item.value) { body.querySelectorAll('.vjs-custom-menu-item').forEach(function(i) { i.classList.remove('active'); }); if (previousActive) previousActive.classList.add('active'); currentSelectedQuality = previousQuality; } }, 100); setTimeout(closeMenu, 180); } function renderItems(items, onSelect) { var body = sheet.querySelector('.vjs-custom-menu-body'); body.innerHTML = ''; if (!items.length) { var empty = document.createElement('div'); empty.className = 'vjs-custom-menu-item'; empty.innerHTML = `${i18n.none}`; body.appendChild(empty); return; } items.forEach(function(item) { var el = document.createElement('div'); el.className = 'vjs-custom-menu-item' + (item.selected ? ' active' : ''); el.innerHTML = `${item.label}`; var startY = 0; el.addEventListener('touchstart', function(e) { startY = e.touches[0].clientY; }, { passive: true }); el.addEventListener('touchend', function(e) { if (Math.abs(e.changedTouches[0].clientY - startY) > 10) return; e.preventDefault(); handleItemClick(body, el, item, onSelect); }); el.addEventListener('click', function() { handleItemClick(body, el, item, onSelect); }); body.appendChild(el); }); } function getQualityItems() { var select = document.querySelector('.vjs-quality-selector select'); if (!select) return []; var watchBtn = document.getElementById('watchNowButton'); var allowedQualities = []; try { allowedQualities = JSON.parse((watchBtn ? watchBtn.getAttribute('data-allowed-qualities') : null) || '[]'); } catch(e) {} var availableLabels = Array.from(select.options).map(function(opt) { return opt.text.trim(); }); var qualityPriority = ['1080p', '720p', '480p']; var bestQuality = currentSelectedQuality; if (!bestQuality) { for (var i = 0; i < qualityPriority.length; i++) { if (allowedQualities.includes(qualityPriority[i]) && availableLabels.includes(qualityPriority[i])) { bestQuality = qualityPriority[i]; break; } } } var items = Array.from(select.options).map(function(opt, i) { return { label: opt.text.trim(), value: i, selected: bestQuality ? opt.text.trim() === bestQuality : select.selectedIndex === i }; }); items.sort(function(a, b) { var an = parseQualityNumber(a.label), bn = parseQualityNumber(b.label); if (an === -1) return 1; if (bn === -1) return -1; return bn - an; }); return items; } function getSubsItems() { var player = videojs.getPlayer('videoPlayer'); if (!player) return []; var tracks = player.textTracks(); var items = [{ label: i18n.off, kind: 'off', selected: true }]; for (var i = 0; i < tracks.length; i++) { if ((tracks[i].kind === 'subtitles' || tracks[i].kind === 'captions') && !/^(CC\d+|cc708_\d+)$/i.test((tracks[i].label || '').trim())) { var isActive = tracks[i].mode === 'showing'; if (isActive) items[0].selected = false; items.push({ label: tracks[i].label || tracks[i].language, track: tracks[i], selected: isActive }); } } return items; } function loadTab(tab) { if (tab === 'quality') { renderItems(getQualityItems(), function(item) { var select = document.querySelector('.vjs-quality-selector select'); if (!select) return; select.selectedIndex = item.value; select.dispatchEvent(new Event('change', { bubbles: true })); }); } else { renderItems(getSubsItems(), function(item) { var player = videojs.getPlayer('videoPlayer'); if (!player) return; var tracks = player.textTracks(); for (var i = 0; i < tracks.length; i++) { if (tracks[i].kind === 'subtitles' || tracks[i].kind === 'captions') { tracks[i].mode = 'disabled'; } } if (item.track) item.track.mode = 'showing'; }); } } function switchTab(tab) { activeTab = tab; sheet.querySelectorAll('.vjs-custom-menu-tab').forEach(function(t) { t.classList.toggle('active', t.dataset.tab === tab); }); loadTab(tab); } function openMenu(tab) { switchTab(tab || activeTab); overlay.classList.add('open'); sheet.classList.add('open'); } function closeMenu() { overlay.classList.remove('open'); sheet.classList.remove('open'); } overlay.addEventListener('click', closeMenu); overlay.addEventListener('touchend', function(e) { e.preventDefault(); closeMenu(); }); var closeBtn = sheet.querySelector('.vjs-custom-menu-close'); closeBtn.addEventListener('click', closeMenu); closeBtn.addEventListener('touchend', function(e) { e.preventDefault(); closeMenu(); }); sheet.querySelectorAll('.vjs-custom-menu-tab').forEach(function(t) { t.addEventListener('click', function() { switchTab(t.dataset.tab); }); t.addEventListener('touchend', function(e) { e.preventDefault(); switchTab(t.dataset.tab); }); }); window.initQualityPopup = function initQualityPopup() { if (typeof videojs === 'undefined' || !videojs.getPlayer('videoPlayer')) { setTimeout(initQualityPopup, 200); return; } var qualitySelector = document.querySelector('.vjs-quality-selector'); if (!qualitySelector) { setTimeout(initQualityPopup, 300); return; } var select = qualitySelector.querySelector('select'); if (!select || !select.options.length) { setTimeout(initQualityPopup, 300); return; } select.style.display = 'none'; if (qualitySelector.querySelector('.vjs-quality-popup-button')) return; var btn = document.createElement('div'); btn.className = 'vjs-quality-popup-button vjs-menu-button vjs-menu-button-popup vjs-control vjs-button'; btn.innerHTML = ``; updateBadge(select, btn); select.addEventListener('change', function() { updateBadge(select, btn); }); new MutationObserver(function() { updateBadge(select, btn); }).observe(select, { childList: true, subtree: true }); btn.querySelector('button').addEventListener('click', function(e) { e.stopImmediatePropagation(); e.preventDefault(); openMenu('quality'); }, true); btn.querySelector('button').addEventListener('touchend', function(e) { e.stopImmediatePropagation(); e.preventDefault(); openMenu('quality'); }, true); btn.querySelector('button').addEventListener('touchstart', function(e) { e.stopPropagation(); e.stopImmediatePropagation(); }, true); qualitySelector.appendChild(btn); } function interceptSubtitles() { if (isLive) return; var subsBtn = document.querySelector('.vjs-subs-caps-button button'); if (!subsBtn) { setTimeout(interceptSubtitles, 800); return; } if (subsBtn._customMenuBound) return; subsBtn._customMenuBound = true; subsBtn.addEventListener('click', function(e) { e.stopImmediatePropagation(); e.preventDefault(); openMenu('subs'); }, true); subsBtn.addEventListener('touchend', function(e) { e.stopImmediatePropagation(); e.preventDefault(); openMenu('subs'); }, true); } function init() { initQualityPopup(); interceptSubtitles(); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', function() { setTimeout(init, 1500); }); } else { setTimeout(init, 1500); } })(); // QUALITY CANPLAY document.addEventListener('change', function(e) { if (!e.target.closest('.vjs-quality-selector')) return; var videoEl = document.getElementById('videoPlayer'); if (videoEl && videoEl.getAttribute('data-contenttype') === 'livetv') return; var p = videojs.getPlayer('videoPlayer'); if (!p) return; if (window.showPlayerOverlay) window.showPlayerOverlay(true); p.one('canplay', function() { if (window.hidePlayerOverlay) window.hidePlayerOverlay(); if (p.paused()) { p.play().catch(function(){}); } }); }); // LIVE TEXT (function() { new MutationObserver(function(mutations, obs) { var liveText = document.querySelector('.vjs-seek-to-live-text'); if (liveText && document.documentElement.lang === 'bg') { liveText.textContent = 'НА ЖИВО'; obs.disconnect(); } }).observe(document.body, { childList: true, subtree: true }); })(); // DISABLED LOGS FROM CONSOLE if (window.videojs) { videojs.log.level('off'); } const _warn = console.warn; console.warn = function(...args) { if (args[0] && typeof args[0] === 'string' && args[0].includes('selectProfileModal')) return; _warn.apply(console, args); }; // KEYBOARD SHORTCUTS PLAYER document.addEventListener('keydown', function(e) { if (typeof videojs === 'undefined') return; var tag = e.target.tagName; if (tag === 'INPUT' || tag === 'TEXTAREA') return; var player = videojs.getPlayer('videoPlayer'); if (!player) return; var videoEl = document.getElementById('videoPlayer'); var contentType = videoEl ? videoEl.getAttribute('data-contenttype') : null; switch (e.key) { case 'ArrowRight': { e.preventDefault(); var fwdAttr = videoEl ? parseInt(videoEl.getAttribute('data-forward-seconds') || '', 10) : NaN; var fwdSeconds = Number.isFinite(fwdAttr) && fwdAttr > 0 ? fwdAttr : 10; var duration = player.duration(); player.currentTime(Math.min(duration, player.currentTime() + fwdSeconds)); break; } case 'ArrowLeft': { e.preventDefault(); var backAttr = videoEl ? parseInt(videoEl.getAttribute('data-backward-seconds') || '', 10) : NaN; var backSeconds = Number.isFinite(backAttr) && backAttr > 0 ? backAttr : 10; player.currentTime(Math.max(0, player.currentTime() - backSeconds)); break; } case 'ArrowUp': { e.preventDefault(); var newVolUp = Math.min(1, player.volume() + 0.1); player.volume(newVolUp); break; } case 'ArrowDown': { e.preventDefault(); var newVolDown = Math.max(0, player.volume() - 0.1); player.volume(newVolDown); break; } case 'f': case 'F': { e.preventDefault(); if (player.isFullscreen()) { player.exitFullscreen(); } else { player.requestFullscreen(); } break; } } });