Zaměstnanec má všechnu práci hotovou. Musí zůstat na pracovišti, nebo může odejít dříve?

3. 6. 2025
Doba čtení: 7 minut

Sdílet

Ilustrační fotografie. (11/2021)
Autor: Geis CZ s.r.o.
Ilustrační fotografie. (11/2021)
Musí zaměstnanec zůstávat na pracovišti do konce pracovní směny, i když už má všechnu práci hotovu a správně vykonánu, nebo může beztrestně opustit pracoviště?

V dnešním článku si odpovíme na otázku, jestli musí zaměstnanec zůstávat až do konce směny, když si svou práci odvede dříve. Odpověď budeme ilustrovat na konkrétním sporu, kdy zaměstnavatel dopisem ze dne 3. 6. 2019 rozvázal pracovní poměr se zaměstnankyní jeho okamžitým zrušením podle § 55 odst. 1 písm. b) zákoníku práce

Jako důvod uvedl, že zaměstnankyně v období od 1. 4. 2018 do 30. 4. 2019 nesprávně vykazovala svou docházku a za těchto 13 měsíců vykázala celkem o 558,25 hodin více, než skutečně odpracovala (resp. vykázala dobu jako odpracovanou a nechala si za ni zaplatit mzdu, ačkoliv během ní nebyla na pracovišti). 

V důsledku toho bylo zaměstnankyni vykonávající práci hlavní pokladní kasina vyplaceno celkem o 82 525 Kč hrubého více, než na co měla nárok, čímž se na úkor zaměstnavatele neoprávněně obohatila.

Argumentace zaměstnankyně, která v pořádku plnila své úkoly, ale chodila z práce dříve

Zaměstnankyně se bránila okamžitému zrušení pracovního poměr soudní cestou, když podala žalobu na určení neplatnosti rozvázání pracovního poměru

Žalobu na neplatný vyhazov podejte do 2 měsíců, jinak právo na odškodnění zaniká. Kdy se lhůta prodlužuje? Přečtěte si také:

Žalobu na neplatný vyhazov podejte do 2 měsíců, jinak právo na odškodnění zaniká. Kdy se lhůta prodlužuje?

Zaměstnavatelem uvedený důvod označila za smyšlený zejména s tím, že vždy měla splněnu veškerou práci, kterou měla mít, což by nešlo stihnout, pokud by nebyla na pracovišti v pracovní době.

Dále uvedla, že její mzda byla určena mzdovým výměrem pevnou částkou za daný měsíc. Pro určení mzdy tak není podstatné, kolik přesně zaměstnanec odpracuje v daném měsíci hodin, protože vždy dostane stejnou mzdu. 

Kde a jak určit výši mzdy? Přečtěte si také:

Kde a jak určit výši mzdy?

Dále též, že byla na vedoucí pozici zařazena s tím, že ji zaměstnavatel považoval za zodpovědnou, důvěryhodnou a samostatnou osobu, nad kterou není nutno vykonávat konstantní dohled.

Soud prvního stupně s vyhazovem na hodinu souhlasil

Soud prvního stupně žalobu zamítl. Vyšel zejména z toho, že zaměstnankyně ze své pozice plánovala směny sobě a podřízeným a sama sobě vykazovala v docházkovém systému počet odpracovaných hodin. 

Rozdíl mezi jí vykázanými odpracovanými hodinami a hodinami, kdy byla přítomna na pracovišti nebo čerpala dovolenou, jak bylo zjištěno za kamerových záznamů, činí 558,25 hodin, přičemž minimálně v případě 509,25 hodin nebyl zjištěn žádný omluvitelný důvod nepřítomnosti zaměstnankyně na pracovišti. 

S odkazem na vymezení pracovní doby v § 78 odst. 1 písm. a) zákoníku práce soud dovodil, že zaměstnanec je povinen být po celou pracovní dobu přítomen na pracovišti (s výjimkou omluvitelných překážek v práci), bez ohledu na to, zda mu zaměstnavatel na danou směnu přidělil práci či zda už ji odpracoval před uplynutím stanovené směny. I po odvedení práce totiž musí být zaměstnanec přítomen na pracovišti pro případ, že by mu chtěl zaměstnavatel přidělit další úkoly.

Odvolací soud naopak zohlednil vzorné plnění pracovních úkolů

Naproti tomu odvolací soud shledal okamžité zrušení pracovního poměru neplatným. Přisvědčil soudu prvního stupně v tom, že zaměstnankyně porušila své povinnosti při plnění pracovních úkolů popsaným falšováním docházky. 

Ovšem usoudil, že za situace, kdy bylo současně prokázáno i to, že přestože zaměstnankyně fyzicky na pracovišti přítomna po celou dobu nebyla, svou práci konala, své pracovní povinnosti plnila řádně a včas.

Nepřítomnost zaměstnankyně na pracovišti nelze označit za neomluvené zmeškání práce, neboť toto je pojmově spojeno s tím, že zaměstnanec, který neomluveně zmešká práci, svou práci nekoná a útočí tímto způsobem na majetek svého zaměstnavatele. 

V projednávané věci se však o takový případ nejednalo, neboť i když zaměstnankyně byla fyzicky přítomna na pracovišti v menším rozsahu, než jaký vykázala, své pracovní povinnosti si přesto řádně a včas splnila tak, že úsek, na kterém zastávala vedoucí pozici, bez problémů fungoval.

Soud dospěl i k odlišnému hodnocení intenzity porušení pracovních povinností, které se stalo důvodem okamžitého zrušení pracovního poměru. (Podle § 55 odst. 1 písm. b) zákoníku práce zaměstnavatel může výjimečně pracovní poměr okamžitě zrušit jen tehdy, porušil-li zaměstnanec povinnost vyplývající z právních předpisů vztahujících se k jím vykonávané práci zvlášť hrubým způsobem.) 

Protože zaměstnavatel s ohledem na řádně a včas zaměstnankyní odvedenou práci a bezproblémové fungování jí svěřeného úseku její fyzickou nepřítomnost na pracovišti nekontroloval a tímto způsobem de facto toleroval (v tomto směru jí  po poměrně dlouhou dobu ani nic nevytkl), nedosáhlo porušení pracovních povinností intenzity zvlášť hrubého porušení pracovních povinností, které by zaměstnavatele opravňovalo k rozvázání pracovního poměru okamžitým zrušením. 

Kdy může zaměstnavatel vyhodit pracovníka na hodinu? Přečtěte si také:

Kdy může zaměstnavatel vyhodit pracovníka na hodinu?

Není proto možno dojít ani k závěru, že se ze strany zaměstnankyně se jednalo o nepřímý útok na majetek zaměstnavatele tím, že by se pokusila odčerpat část majetku svého zaměstnavatele bez odpovídajícího protiplnění.  

Předstíral práci a falšoval docházku, vyletěl na hodinu Přečtěte si také:

Předstíral práci a falšoval docházku, vyletěl na hodinu

Při úvaze o intenzitě porušení pracovních povinností si odvolací soud na otázku, zda bylo možno za dané situace po zaměstnavateli chtít, aby ji dával práci ještě po dobu výpovědní doby, odpověděl kladně. 

Za daného stavu dle odvolacího soudu nemohlo dojít k zásadnímu narušení důvěry mezi zaměstnavatelem a zaměstnancem. 

Ztráta důvěry není výpovědním důvodem. To bylo jen v socialismu Přečtěte si také:

Ztráta důvěry není výpovědním důvodem. To bylo jen v socialismu

Nejvyšší soud ovšem řekl, že zaměstnanec nemůže odcházet z práce dříve, ani když má hotovo

Nejvyšší soud ČR ve svém rozsudku (spis. zn. 21 Cdo 2715/2023) ze dne 11. 2. 2025 připomenul, že k základním povinnostem zaměstnance vyplývajícím z pracovního poměru náleží též povinnost podle pokynů zaměstnavatele konat osobně práce podle pracovní smlouvy v rozvržené týdenní pracovní době [§ 38 odst. 1 písm. b) zákoníku práce].  

V průběhu trvání pracovního poměru může být pracovní závazek zaměstnance suspendován jedině, nastane-li některá z překážek v práci, ať je to již překážka v práci na straně zaměstnance (§ 191 a násl. zákoníku práce), nebo překážka v práci na straně zaměstnavatele (§ 207 a násl. zák. práce)

Není-li zde tato právem uznaná nemožnost nebo obtížnost plnění základních pracovněprávních povinností a vykazuje-li zaměstnanec absenci, která není výše uvedeným způsobem aprobována, znamená to, že po celou dobu, kdy nekoná práci podle pracovní smlouvy, nedodržuje základní povinnosti vyplývající z právních předpisů vztahujících se k jím vykonávané práci.

Pět dnů absence je na okamžitý vyhazov – k čemu je ale potřeba přihlédnout?

Nejvyšší soud již dříve poukázal na to, že neomluvené zameškání práce v trvání pěti dnů zpravidla představuje samo o sobě porušení pracovní kázně zvlášť hrubým způsobem a odůvodňuje rozvázání pracovního poměru okamžitým zrušením. (A absence zaměstnankyně byly v součtu ještě delší.)

Za jak dlouhou neomluvenou absenci dostanete vyhazov na hodinu? Přečtěte si také:

Za jak dlouhou neomluvenou absenci dostanete vyhazov na hodinu?

Jednání zaměstnance znamenající porušení pracovní kázně však nelze posuzovat bez přihlédnutí k dalším okolnostem, které mohou mít vliv na celkové zhodnocení případu. Kromě délky nepřítomnosti v práci je nutno přihlédnout zejména k důsledkům nepřítomnosti pro zaměstnavatele, k dosavadnímu postoji zaměstnance k plnění pracovních úkolů, k míře jeho zavinění a ke způsobu a intenzitě porušení jeho konkrétních pracovních povinností. 

Kdy může zaměstnavatel vyhodit pracovníka na hodinu? Přečtěte si také:

Kdy může zaměstnavatel vyhodit pracovníka na hodinu?

Zaměstnavatel absence nevytýkal, protože o nich nevěděl

Ve vztazích zaměstnavatele a zaměstnance je zároveň nezbytný vztah důvěry, spolehlivost zaměstnance a jeho poctivost. 

Při posuzování intenzity porušení pracovních povinností zaměstnankyní je proto nutno přihlédnout v prvé řadě k tomu, že nejde pouze o její absenci na pracovišti, ale i o zastírání této skutečnosti uváděním nesprávného počtu odpracovaných hodin v docházkovém systému. Jednalo se přitom o značný počet hodin. 

Argument, že zaměstnavatel nepřítomnost na pracovišti nevytýkal a dlouhodobě toleroval, není na místě, neboť zaměstnankyně tuto skutečnost před ním zatajovala, o čemž svědčí nejen počet hodin vykazovaných v docházkovém systému, ale i prvotní postoj samotné zaměstnankyně v řízení, neboť ještě v žalobě popírala, že by nebyla na pracovišti v pracovní době; teprve provedeným dokazováním bylo toto její tvrzení vyvráceno.

Zaměstnankyně uváděla zaměstnavatele v omyl o rozsahu skutečně odpracovaných hodin rozhodných pro stanovení jejího mzdového nároku. A v konkrétním případě může být podstatně významnější narušení nezbytné vzájemné důvěry ve vztazích a zpochybnění spolehlivosti zaměstnance ve vztahu k majetku zaměstnavatele než eventuální výše škody.

Narušení důvěry mezi firmou a zaměstnancem je významnější u vedoucích

Z pohledu zájmu na zachování vzájemné důvěry je další závažnou okolností při posuzovaní intenzity porušení pracovních povinností postavení zaměstnankyně jako vedoucí. 

Protože mezi povinnosti vedoucích zaměstnanců patří rovněž povinnost zabezpečovat dodržování právních a vnitřních předpisů [§ 302 písm. f) zákoníku práce], je narušení nezbytné vzájemné důvěry závažnější, zklame-li důvěru zaměstnavatele právě ten, kdo má sám dodržování právních předpisů u zaměstnavatele zabezpečovat. 

Ztráta důvěry není výpovědním důvodem. To bylo jen v socialismu Přečtěte si také:

Ztráta důvěry není výpovědním důvodem. To bylo jen v socialismu

Ve prospěch zaměstnankyně lze zohlednit závěr, že i přes absence odvedla práci, kterou byla povinna odvést, a že vycházela zaměstnavateli vstříc v případě absence jiných pracovníků. Na druhé straně je zde značný rozsah neomluvených absencí a tyto zaměstnankyně vůči svému zaměstnavateli zastírala. 

bitcoin_smenarna

Nejvyšší soud proto rozhodl tak, že okamžité zrušení pracovního poměru je platné. (Rozsudek odvolacího soudu změnil tak, že potvrdil rozsudek soudu prvního stupně ve výroku, jímž soud prvního stupně žalobu o neplatnost okamžitého zrušení pracovního poměru zamítl.)

Na pracovišti být musíte

Zaměstnanec musí být na pracovišti k dispozici po celou rozvrženou pracovní dobu. Nic na této povinnosti nemění ani to, že má veškerou práci splněnou. Z pracoviště odejít dříve, před koncem směny, ani pak nemůže.

Autor článku

Nenadávejte právníkům, zákony netvoří zdaleka jen oni. Oni je pak jen zašmodrchávají ve prospěch svých klientů, třeba zrovna vás. Budu se však snažit vám je vysvětlovat.

'; document.getElementById('preroll-iframe').onload = function () { setupIframe(); } prerollContainer = document.getElementsByClassName('preroll-container-iframe')[0]; } function setupIframe() { prerollDocument = document.getElementById('preroll-iframe').contentWindow.document; let el = prerollDocument.createElement('style'); prerollDocument.head.appendChild(el); el.innerText = "#adContainer>div:nth-of-type(1),#adContainer>div:nth-of-type(1) > iframe { width: 99% !important;height: 99% !important;max-width: 100%;}#videoContent,body{ width:100vw;height:100vh}body{ font-family:'Helvetica Neue',Arial,sans-serif}#videoContent{ overflow:hidden;background:#000}#adMuteBtn{ width:35px;height:35px;border:0;background:0 0;display:none;position:absolute;fill:rgba(230,230,230,1);bottom:20px;right:25px}"; videoContent = prerollDocument.getElementById('contentElement'); videoContent.style.display = 'none'; videoContent.volume = 1; videoContent.muted = false; const playPromise = videoContent.play(); if (playPromise !== undefined) { playPromise.then(function () { console.log('PREROLL sound allowed'); // setUpIMA(true); videoContent.volume = 1; videoContent.muted = false; setUpIMA(); }).catch(function () { console.log('PREROLL sound forbidden'); videoContent.volume = 0; videoContent.muted = true; setUpIMA(); }); } } function setupDimensions() { prerollWidth = Math.min(iinfoPrerollPosition.offsetWidth, 480); prerollHeight = Math.min(iinfoPrerollPosition.offsetHeight, 320); } function setUpIMA() { google.ima.settings.setDisableCustomPlaybackForIOS10Plus(true); google.ima.settings.setLocale('cs'); google.ima.settings.setNumRedirects(10); // Create the ad display container. createAdDisplayContainer(); // Create ads loader. adsLoader = new google.ima.AdsLoader(adDisplayContainer); // Listen and respond to ads loaded and error events. adsLoader.addEventListener( google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, onAdsManagerLoaded, false); adsLoader.addEventListener( google.ima.AdErrorEvent.Type.AD_ERROR, onAdError, false); // An event listener to tell the SDK that our content video // is completed so the SDK can play any post-roll ads. const contentEndedListener = function () { adsLoader.contentComplete(); }; videoContent.onended = contentEndedListener; // Request video ads. const adsRequest = new google.ima.AdsRequest(); adsRequest.adTagUrl = iinfoVastUrls[iinfoVastUrlIndex]; console.log('Preroll advert: ' + iinfoVastUrls[iinfoVastUrlIndex]); videoContent.muted = false; videoContent.volume = 1; // Specify the linear and nonlinear slot sizes. This helps the SDK to // select the correct creative if multiple are returned. // adsRequest.linearAdSlotWidth = prerollWidth; // adsRequest.linearAdSlotHeight = prerollHeight; adsRequest.nonLinearAdSlotWidth = 0; adsRequest.nonLinearAdSlotHeight = 0; adsLoader.requestAds(adsRequest); } function createAdDisplayContainer() { // We assume the adContainer is the DOM id of the element that will house // the ads. prerollDocument.getElementById('videoContent').style.display = 'none'; adDisplayContainer = new google.ima.AdDisplayContainer( prerollDocument.getElementById('adContainer'), videoContent); } function unmutePrerollAdvert() { adVolume = !adVolume; if (adVolume) { adsManager.setVolume(0.3); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } else { adsManager.setVolume(0); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } } function onAdsManagerLoaded(adsManagerLoadedEvent) { // Get the ads manager. const adsRenderingSettings = new google.ima.AdsRenderingSettings(); adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; adsRenderingSettings.loadVideoTimeout = 12000; // videoContent should be set to the content video element. adsManager = adsManagerLoadedEvent.getAdsManager(videoContent, adsRenderingSettings); // Add listeners to the required events. adsManager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, onAdError); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED, onContentPauseRequested); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED, onContentResumeRequested); adsManager.addEventListener( google.ima.AdEvent.Type.ALL_ADS_COMPLETED, onAdEvent); // Listen to any additional events, if necessary. adsManager.addEventListener(google.ima.AdEvent.Type.LOADED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.COMPLETE, onAdEvent); playAds(); } function playAds() { // Initialize the container. Must be done through a user action on mobile // devices. videoContent.load(); adDisplayContainer.initialize(); // setupDimensions(); try { // Initialize the ads manager. Ad rules playlist will start at this time. adsManager.init(1920, 1080, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will // start at this time; the call will be ignored for ad rules. adsManager.start(); // window.addEventListener('resize', function (event) { // if (adsManager) { // setupDimensions(); // adsManager.resize(prerollWidth, prerollHeight, google.ima.ViewMode.NORMAL); // } // }); } catch (adError) { // An error may be thrown if there was a problem with the VAST response. // videoContent.play(); } } function onAdEvent(adEvent) { const ad = adEvent.getAd(); console.log('Preroll event: ' + adEvent.type); switch (adEvent.type) { case google.ima.AdEvent.Type.LOADED: if (!ad.isLinear()) { videoContent.play(); } prerollDocument.getElementById('adContainer').style.width = '100%'; prerollDocument.getElementById('adContainer').style.maxWidth = '640px'; prerollDocument.getElementById('adContainer').style.height = '360px'; break; case google.ima.AdEvent.Type.STARTED: window.addEventListener('scroll', onActiveView); if (ad.isLinear()) { intervalTimer = setInterval( function () { // Example: const remainingTime = adsManager.getRemainingTime(); // adsManager.pause(); }, 300); // every 300ms } prerollDocument.getElementById('adMuteBtn').style.display = 'block'; break; case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: if (ad.isLinear()) { clearInterval(intervalTimer); } if (prerollLastError === 303) { playYtVideo(); } break; case google.ima.AdEvent.Type.COMPLETE: if (ad.isLinear()) { clearInterval(intervalTimer); } playYtVideo(); break; } } function onAdError(adErrorEvent) { console.log(adErrorEvent.getError()); prerollLastError = adErrorEvent.getError().getErrorCode(); if (!loadNext()) { playYtVideo(); } } function loadNext() { iinfoVastUrlIndex++; if (iinfoVastUrlIndex < iinfoVastUrls.length) { iinfoPrerollPosition.remove(); playPrerollAd(); } else { return false; } adVolume = 1; return true; } function onContentPauseRequested() { videoContent.pause(); } function onContentResumeRequested() { videoContent.play(); } function onActiveView() { if (prerollContainer) { const containerOffset = prerollContainer.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight/1 && containerOffset.bottom > 0.0) { if (prerollPaused) { adsManager.resume(); prerollPaused = false; } return true; } else { if (!prerollPaused) { adsManager.pause(); prerollPaused = true; } } } return false; } function playYtVideo() { iinfoPrerollPosition.remove(); youtubeIframe.style.display = 'block'; youtubeIframe.src += '&autoplay=1&mute=1'; } }
Upozorníme vás na články, které by vám neměly uniknout (maximálně 2x týdně).
'; document.getElementById('outstream-iframe').onload = function () { setupIframe(); } replayScreen = document.getElementById('iinfoOutstreamReplay'); iinfoOutstreamPosition = document.getElementById('iinfoOutstreamPosition'); outstreamContainer = document.getElementsByClassName('outstream-container')[0]; setupReplayScreen(); } function setupIframe() { outstreamDocument = document.getElementById('outstream-iframe').contentWindow.document; let el = outstreamDocument.createElement('style'); outstreamDocument.head.appendChild(el); el.innerText = "#adContainer>div:nth-of-type(1),#adContainer>div:nth-of-type(1) > iframe { width: 99% !important;height: 99% !important;max-width: 100%;}#videoContent,body{ width:100vw;height:100vh}body{ font-family:'Helvetica Neue',Arial,sans-serif}#videoContent{ overflow:hidden;background:#000}#adMuteBtn{ width:35px;height:35px;border:0;background:0 0;display:none;position:absolute;fill:rgba(230,230,230,1);bottom:-5px;right:25px}"; videoContent = outstreamDocument.getElementById('contentElement'); videoContent.style.display = 'none'; videoContent.volume = 1; videoContent.muted = false; if ( location.href.indexOf('rejstriky.finance.cz') !== -1 || location.href.indexOf('finance-rejstrik') !== -1 || location.href.indexOf('firmy.euro.cz') !== -1 || location.href.indexOf('euro-rejstrik') !== -1 || location.href.indexOf('/rejstrik/') !== -1 || location.href.indexOf('/rejstrik-firem/') !== -1) { outstreamDirectPlayed = true; soundAllowed = true; iinfoVastUrlIndex = 0; } if (!outstreamDirectPlayed) { console.log('OUTSTREAM direct'); setUpIMA(true); } else { if (soundAllowed) { const playPromise = videoContent.play(); if (playPromise !== undefined) { playPromise.then(function () { console.log('OUTSTREAM sound allowed'); setUpIMA(false); }).catch(function () { console.log('OUTSTREAM sound forbidden'); renderBanner(); }); } } else { renderBanner(); } } } function getWrapper() { let articleWrapper = document.querySelector('.rs-outstream-placeholder'); // Outstream Placeholder from RedSys manipulation if (articleWrapper && articleWrapper.style.display !== 'block') { articleWrapper.innerHTML = ""; articleWrapper.style.display = 'block'; } // Don't render OutStream on homepages if (articleWrapper === null) { if (document.querySelector('body.p-index')) { return null; } } if (articleWrapper === null) { articleWrapper = document.getElementById('iinfo-outstream'); } if (articleWrapper === null) { articleWrapper = document.querySelector('.layout-main__content .detail__article p:nth-of-type(6)'); } if (articleWrapper === null) { // Euro, Autobible, Zdravi articleWrapper = document.querySelector('.o-article .o-article__text p:nth-of-type(6)'); } if (articleWrapper === null) { articleWrapper = document.getElementById('sidebar'); } if (!articleWrapper) { console.error("Outstream wrapper of article was not found."); } return articleWrapper; } function setupDimensions() { outstreamWidth = Math.min(iinfoOutstreamPosition.offsetWidth, 480); outstreamHeight = Math.min(iinfoOutstreamPosition.offsetHeight, 320); } /** * Sets up IMA ad display container, ads loader, and makes an ad request. */ function setUpIMA(direct) { google.ima.settings.setDisableCustomPlaybackForIOS10Plus(true); google.ima.settings.setLocale('cs'); google.ima.settings.setNumRedirects(10); // Create the ad display container. createAdDisplayContainer(); // Create ads loader. adsLoader = new google.ima.AdsLoader(adDisplayContainer); // Listen and respond to ads loaded and error events. adsLoader.addEventListener( google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, onAdsManagerLoaded, false); adsLoader.addEventListener( google.ima.AdErrorEvent.Type.AD_ERROR, onAdError, false); // An event listener to tell the SDK that our content video // is completed so the SDK can play any post-roll ads. const contentEndedListener = function () { adsLoader.contentComplete(); }; videoContent.onended = contentEndedListener; // Request video ads. const adsRequest = new google.ima.AdsRequest(); if (direct) { adsRequest.adTagUrl = directVast; console.log('Outstream DIRECT CAMPAING advert: ' + directVast); videoContent.muted = true; videoContent.volume = 0; outstreamDirectPlayed = true; } else { adsRequest.adTagUrl = iinfoVastUrls[iinfoVastUrlIndex]; console.log('Outstream advert: ' + iinfoVastUrls[iinfoVastUrlIndex]); videoContent.muted = false; videoContent.volume = 1; } // Specify the linear and nonlinear slot sizes. This helps the SDK to // select the correct creative if multiple are returned. // adsRequest.linearAdSlotWidth = outstreamWidth; // adsRequest.linearAdSlotHeight = outstreamHeight; adsRequest.nonLinearAdSlotWidth = 0; adsRequest.nonLinearAdSlotHeight = 0; adsLoader.requestAds(adsRequest); } function setupReplayScreen() { replayScreen.addEventListener('click', function () { iinfoOutstreamPosition.remove(); iinfoVastUrlIndex = 0; outstreamInit(); }); } /** * Sets the 'adContainer' div as the IMA ad display container. */ function createAdDisplayContainer() { // We assume the adContainer is the DOM id of the element that will house // the ads. outstreamDocument.getElementById('videoContent').style.display = 'none'; adDisplayContainer = new google.ima.AdDisplayContainer( outstreamDocument.getElementById('adContainer'), videoContent); } function unmuteAdvert() { adVolume = !adVolume; if (adVolume) { adsManager.setVolume(0.3); outstreamDocument.getElementById('adMuteBtn').innerHTML = ''; } else { adsManager.setVolume(0); outstreamDocument.getElementById('adMuteBtn').innerHTML = ''; } } /** * Loads the video content and initializes IMA ad playback. */ function playAds() { // Initialize the container. Must be done through a user action on mobile // devices. videoContent.load(); adDisplayContainer.initialize(); // setupDimensions(); try { // Initialize the ads manager. Ad rules playlist will start at this time. adsManager.init(1920, 1080, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will // start at this time; the call will be ignored for ad rules. adsManager.start(); // window.addEventListener('resize', function (event) { // if (adsManager) { // setupDimensions(); // adsManager.resize(outstreamWidth, outstreamHeight, google.ima.ViewMode.NORMAL); // } // }); } catch (adError) { // An error may be thrown if there was a problem with the VAST response. // videoContent.play(); } } /** * Handles the ad manager loading and sets ad event listeners. * @param { !google.ima.AdsManagerLoadedEvent } adsManagerLoadedEvent */ function onAdsManagerLoaded(adsManagerLoadedEvent) { // Get the ads manager. const adsRenderingSettings = new google.ima.AdsRenderingSettings(); adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; adsRenderingSettings.loadVideoTimeout = 12000; // videoContent should be set to the content video element. adsManager = adsManagerLoadedEvent.getAdsManager(videoContent, adsRenderingSettings); // Add listeners to the required events. adsManager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, onAdError); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED, onContentPauseRequested); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED, onContentResumeRequested); adsManager.addEventListener( google.ima.AdEvent.Type.ALL_ADS_COMPLETED, onAdEvent); // Listen to any additional events, if necessary. adsManager.addEventListener(google.ima.AdEvent.Type.LOADED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.COMPLETE, onAdEvent); playAds(); } /** * Handles actions taken in response to ad events. * @param { !google.ima.AdEvent } adEvent */ function onAdEvent(adEvent) { // Retrieve the ad from the event. Some events (for example, // ALL_ADS_COMPLETED) don't have ad object associated. const ad = adEvent.getAd(); console.log('Outstream event: ' + adEvent.type); switch (adEvent.type) { case google.ima.AdEvent.Type.LOADED: // This is the first event sent for an ad - it is possible to // determine whether the ad is a video ad or an overlay. if (!ad.isLinear()) { // Position AdDisplayContainer correctly for overlay. // Use ad.width and ad.height. videoContent.play(); } outstreamDocument.getElementById('adContainer').style.width = '100%'; outstreamDocument.getElementById('adContainer').style.maxWidth = '640px'; outstreamDocument.getElementById('adContainer').style.height = '360px'; break; case google.ima.AdEvent.Type.STARTED: window.addEventListener('scroll', onActiveView); // This event indicates the ad has started - the video player // can adjust the UI, for example display a pause button and // remaining time. if (ad.isLinear()) { // For a linear ad, a timer can be started to poll for // the remaining time. intervalTimer = setInterval( function () { // Example: const remainingTime = adsManager.getRemainingTime(); // adsManager.pause(); }, 300); // every 300ms } outstreamDocument.getElementById('adMuteBtn').style.display = 'block'; break; case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: if (ad.isLinear()) { clearInterval(intervalTimer); } if (outstreamLastError === 303) { if (isBanner) { renderBanner(); } else { replayScreen.style.display = 'flex'; } } break; case google.ima.AdEvent.Type.COMPLETE: // This event indicates the ad has finished - the video player // can perform appropriate UI actions, such as removing the timer for // remaining time detection. if (ad.isLinear()) { clearInterval(intervalTimer); } if (isBanner) { renderBanner(); } else { replayScreen.style.display = 'flex'; } break; } } /** * Handles ad errors. * @param { !google.ima.AdErrorEvent } adErrorEvent */ function onAdError(adErrorEvent) { // Handle the error logging. console.log(adErrorEvent.getError()); outstreamLastError = adErrorEvent.getError().getErrorCode(); if (!loadNext()) { renderBanner(); } } function renderBanner() { if (isBanner) { console.log('Outstream: Render Banner'); iinfoOutstreamPosition.innerHTML = ""; iinfoOutstreamPosition.style.height = "330px"; iinfoOutstreamPosition.appendChild(bannerDiv); } else { console.log('Outstream: Banner is not set'); } } function loadNext() { iinfoVastUrlIndex++; if (iinfoVastUrlIndex < iinfoVastUrls.length) { iinfoOutstreamPosition.remove(); outstreamInit(); } else { return false; } adVolume = 1; return true; } /** * Pauses video content and sets up ad UI. */ function onContentPauseRequested() { videoContent.pause(); // This function is where you should setup UI for showing ads (for example, // display ad timer countdown, disable seeking and more.) // setupUIForAds(); } /** * Resumes video content and removes ad UI. */ function onContentResumeRequested() { videoContent.play(); // This function is where you should ensure that your UI is ready // to play content. It is the responsibility of the Publisher to // implement this function when necessary. // setupUIForContent(); } function onActiveView() { if (outstreamContainer) { const containerOffset = outstreamContainer.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight/1 && containerOffset.bottom > 0.0) { if (outstreamPaused) { adsManager.resume(); outstreamPaused = false; } return true; } else { if (!outstreamPaused) { adsManager.pause(); outstreamPaused = true; } } } return false; } let outstreamInitInterval; if (typeof cpexPackage !== "undefined") { outstreamInitInterval = setInterval(tryToInitializeOutstream, 100); } else { const wrapper = getWrapper(); if (wrapper) { let outstreamInitialized = false; window.addEventListener('scroll', () => { if (!outstreamInitialized) { const containerOffset = wrapper.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight / 1 && containerOffset.bottom > 0.0) { outstreamInit(); outstreamInitialized = true; } } }); } } function tryToInitializeOutstream() { const wrapper = getWrapper(); if (wrapper) { const containerOffset = wrapper.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight / 1 && containerOffset.bottom > 0.0) { if (cpexPackage.adserver.displayed) { clearInterval(outstreamInitInterval); outstreamInit(); } } } else { clearInterval(outstreamInitInterval); } } }
OSZAR »