Taxi a dopravní obsluha. Kdy může a kdy nemůže taxík do zákazu vjezdu pro dopravní obsluhu?

21. 8. 2024
Doba čtení: 6 minut

Sdílet

Ilustrační fotografie. Taxi s polepem Bolt. (09/2021)
Autor: Bolt Technology OÜ
Ilustrační fotografie. Taxi s polepem Bolt. (09/2021)
„Mimo dopravní obsluhu“. Zákon u této dodatkové tabulky pak uvádí mj. „vozidlo taxislužby“. Jde o jakýkoli taxík, nebo jen ten s pasažérem? Taxikář dostal pokutu 1500 Kč za porušení zákazu vjezdu.

Jenže tu pokutu stejně platit nemusel, protože se dostatečně dlouho omlouval z jednání o přestupku na úřadě. Přesto žádal omluvu za policejní šikanu a odškodnění ve výši 120 000 Kč.

Provozovatel taxislužby se jako žalobce domáhal po českém státu (České republice, za níž vystupovalo na straně žalované před soudem Ministerstvo financí) písemné omluvy a zaplacení částky 120 000 Kč z titulu náhrady nemajetkové újmy.

Žádal o satisfakci za morální újmu, která mu měla být způsobena nesprávným úředním postupem, spočívajícím v údajně nezákonné a bezdůvodné kontrole příslušníky Policie ČR a v následném vedení přestupkového řízení.

Žalobce totiž nesouhlasil s tím, jak byla Policií ČR a následně správním orgánem vyhodnocena dodatková tabulka E 13 s textem „Mimo dopravní obsluhy“ v souvislosti s dopravní značkou B 11 „Zákaz vjezdu všech motorových vozidel“.

Skutkový stav- kde, kdy a za co dostal taxikář pokutu a jak probíhalo řízení o ní

Žalobce jakožto řidič taxislužby dne 6. 2. 2020 v 16:25 hodin odbočil v Praze z ulice Benešovské do ulice Hradešínské, která je označena svislou dopravní značkou B 11 „Zákaz vjezdu všech motorových vozidel“ s dodatkovou tabulkou E 13 s textem „Mimo dopravní obsluhy“.

Žalobce policisty upozornil, že dopravní obsluhou je i vozidlo taxislužby, policisté však prohlásili, že pouze v případě obsazeného vozidla, žalobce však v Hradešínské ulici nikoho nenakládal ani nevykládal. Žalobce odmítl zaplatit pokutu na místě, policisté ho proto legitimovali a postoupili přestupek do správního řízení.

Pokutovaný taxikář se vyhnul postihu, přesto žádal morální i hmotnou satisfakci

Dne 28. 2. 2020 Magistrát hlavního města Prahy, Odbor dopravně-správních činností, vydal příkaz, na jehož základě žalobci uložil pokutu ve výši 1500 Kč za přestupek (dle ust. § 125c odst. 1 písm. k) zákona č. 361/2000 Sb., o provozu na pozemních komunikacích).

Příkaz byl žalobci doručen dne 15. 3. 2020. Dne 23. 3. 2020 žalobce podal proti příkazu odpor a upozornil správní orgán, že jeho výklad dopravní značky E 13 neodpovídá znění vyhlášky č. 294/2015 Sb., kterou se provádějí pravidla provozu na pozemních komunikacích, ve znění pozdějších předpisů.

Dne 6. 8. 2020 byl žalobce předvolán k ústnímu jednání o přestupku, které bylo nařízeno na den 3. 9. 2020. Pokutovaný taxikář i jeho právní zástupce se opakovaně omluvili z jednání a žádali o odročení, čemuž úřad vyhověl.

Dne 21. 4. 2021 však Magistrát hl. m. Prahy vydal usnesení o zastavení řízení, neboť správní orgán neprojednal věc v zákonem stanovené lhůtě a odpovědnost za přestupek zanikla, usnesení o zastavení řízení nabylo právní moci dne 28. 5. 2021.

Bez ohledu na to byl však taxikář přesvědčen, že se žádného přestupku nedopustil, neboť dle vyhlášky č. 294/2015 Sb. se dopravní obsluhou rozumí rovněž vozidla taxislužby, přičemž podmínka „přepravovaných osob“ je zde stanovena pro jiné případy, nikoliv pro vozidla taxislužby.

Žalobce podal dne 3. 7. 2021 stížnost na policisty, kteří se měli vůči žalobci dopustit nesprávného úředního postupu a policejní šikany. Ministerstvo vnitra však nevyhovělo. A tak věc skončila před soudy. Žalobce neuspěl ani u soudu prvního stupně, ani u soudu odvolacího. Spor se dostal k Nejvyššímu soudu.

Výklad pojmu „dopravní obsluha“ ve vztahu k dodatkové tabulce E 13

Nejvyšší soud se tak ve svém rozsudku (spis. zn. 30 Cdo 3677/2023, ze dne 27. 3. 2024) zabýval výkladem pojmu „dopravní obsluha“ ve vztahu k dopravní značce E 13, uvedené ve vyhlášce č. 294/2015 Sb., potažmo pojmu „poskytování taxislužby“.

Právní úprava

Podle přílohy č. 6 k vyhlášce č. 294/2015 Sb. je-li na dodatkové tabulce použit text s výrazem „dopravní obsluha", rozumí se tím

vozidla zajišťující zásobování nebo lékařské, opravárenské, údržbářské, komunální a podobné služby, vozidla přepravující osobu těžce zdravotně postiženou, vozidla taxislužby a vozidla, jejichž řidiči, provozovatelé nebo přepravované osoby mají v místech za značkou bydliště, ubytování, sídlo nebo nemovitost.

Použití čistě jazykového výkladu (jinak řečeno pouhé čtení právního předpisu) by tak svědčilo názoru taxikáře, podle kterého smí do oblasti se zákazem vjezdu všech motorových vozidel vjet vozidlo taxislužby, neboť jej jako dopravní obsluhu příloha č. 6 vyhlášky č. 294/2015 Sb. označuje. Takový výklad práva by však byl nepřípustně zjednodušující.

Výklad práva není jen pouhé čtení zákona

Ústavní soud ve své judikatuře opakovaně potvrzuje, že

… naprosto neudržitelným momentem používání práva je jeho aplikace, vycházející pouze z jeho jazykového výkladu. Jazykový výklad představuje pouze prvotní přiblížení se k aplikované právní normě. Je pouze východiskem pro objasnění a ujasnění si jejího smyslu a účelu. Mechanická aplikace… neuvědomující si, a to buď úmyslně, nebo v důsledku nevzdělanosti, smysl a účel právní normy, činí z práva nástroj odcizení a absurdity.

Viz nález pléna Ústavního soudu (ze dne 17. 12. 1997, spis. zn. Pl. ÚS 33/97). Ke stejnému východisku při interpretaci právních norem se ve své judikatuře opakovaně přihlásil i Nejvyšší soud (např. v rozsudku Nejvyššího soudu ČR ze dne 26. 7. 2022, spis. zn. 21 Cdo 1316/2021).

Při výkladu pojmu „dopravní obsluha“ je proto nutné se ptát po účelu právní normy obsažené v příloze č. 6 k vyhlášce č. 294/2015 Sb., na niž odkazuje ust. § 9 dané vyhlášky, a to, s přihlédnutím k jejímu použití rozhodnému pro tuto věc, tj. ve spojení se značkou „Zákaz vjezdu všech motorových vozidel“.

Účel zákazu vjezdu a výjimek z něj

Zákaz vjezdu všech motorových vozidel, jak vyplývá z označení dané značky, ale i jejího popisu (v příloze č. 3 vyhlášky č. 294/2015 Sb.), směřuje k tomu, aby do určité oblasti žádná vozidla nevjížděla. Použitím dodatkové tabulky „mimo dopravní obsluhy“ se však vyjadřuje zájem na tom, aby zákaz vjezdu vozidel nebyl absolutní, nýbrž byl ve výjimečných případech vjezd určitým vozidlům do dané oblasti povolen.

Zákaz vjezdu všech motorových vozidel s výjimkou dopravní obsluhy se v určitém místě stanoví zpravidla tehdy, pokud je zájem na tom, aby byl v dané oblasti snížen průjezd motorových vozidel, a to za účelem nižší hlučnosti, většího dopravního klidu a zčásti samozřejmě i zvýšení bezpečnosti chodců v těchto místech (jak již bylo vyloženo v usnesení Nejvyššího soudu ČR ze dne 30. 3. 2022, spis. zn. 5 Tdo 118/2022).

Kdy má smysl výjimka ze zákazu vjezdu pro dopravní obsluhu

Výjimka ze zákazu vjezdu všech motorových vozidel, která se váže na dopravní obsluhu, předpokládá, že se i daná dopravní obsluha bude vztahovat k předmětné oblasti, do níž je jinak vjezd vozidel zakázán.

Takový závěr odpovídá zásadě, že výjimky je třeba vykládat restriktivně, vyžaduje-li to jejich účel, zde zájem na tom, aby do dané oblasti žádná vozidla nevjížděla. Přijetí názoru prosazovaného taxikářem by bylo výkladem naopak rozšiřujícím v tom smyslu, že vozidlo taxislužby může do zákazu vzejdu vjet bez ohledu na to, zda v dané oblasti dopravní obsluhu pro konkrétního klienta zajišťuje, tj. zda jej nebo ji z této nebo do této oblasti dopravuje.

skoleni_12_6

To by vedlo k rozšíření dané výjimky v rozporu se základním pravidlem, podle kterého do předmětné oblasti žádná vozidla vjíždět nesmějí. Z toho je patrné, že  názor taxikáře se příčí jak účelu základního pravidla zákazu vjezdu všech vozidel, tak i z něj činěné výjimky ve prospěch dopravní obsluhy.

Taxík bez klienta či nejedoucí k zákazníkovi nemůže mít neoprávněné výhody

Nejvyšší soud ČR se v rozsudku (spis. zn. 30 Cdo 3677/2023, ze dne 27. 3. 2024), z uvedených důvodů ztotožnil s názorem nižšího soudu, že smyslem daného dopravního značení není zajistit některým účastníkům privilegované postavení, ale zajištění dopravní obslužnosti v daném místě. Dovolání taxikáře k NS bylo odmítnuto, na žádné odškodnění nemá nárok.

Poznámka editora: Taxi není privilegiem pro výjimky

To, že nějaké vozidlo je v evidenci vozidel taxislužby, tedy lidově řečeno taxíkem (včetně např. vozidel jezdících pro mobilní platformy typu Bolt, Liftago, Uber apod.), ještě neznamená, že automaticky a vždy může vjet do zákazu vjezdu s dodatkovou tabulkou „mimo dopravní obsluhy“.

Zmiňovaná dodatková tabulka pro něj platí jen v případě, že jede pro zákazníka, nebo se zákazníkem do/z dané oblasti za dopravní značkou. A to musí při případné kontrole prokázat.

V případě mobilních aplikací je vše uvedeno v historii objednávek.

V případě jízdy na zavolání jako důkaz slouží buď stvrzenka z taxametru, nebo jiný důkaz (např. svědectví pasažéra, potvrzení volajícího, historie objednávek apod.)

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 »