if (typeof window.db == 'undefined') window.db = { libs: {} }; (function() { 'use strict'; /** * Ads. * @namespace */ db.libs.ads = (function(){ var name = 'ads'; var ua = window.navigator.userAgent.toLowerCase(); /** * Cached list of all adunits * @memberof db.libs.ads * @static * @type nodelist **/ var adunits; /** * Cached list of all sticky adunits * @memberof db.libs.ads * @static * @type array **/ var stickies = []; /** * Cached list of all fullscreen adunits * @memberof db.libs.ads * @static * @type array **/ var fullscreens = []; /** * Cached list of all scaleable adunits * @memberof db.libs.ads * @static * @type array **/ var scaleable = []; /** * Set wallpaper. This function can be given as a callback to <code>postMessage</code> from within an <code>iframe</code> to allow ads to set the a wallpaper ad. * @public * @example <caption>Example using as a callback and postMessage</caption> * window.parent.postMessage({ callback: 'db.libs.ads.setWallpaper', src: 'http://…', url: 'http://…', frame: window.name }, 'http://dagbadet.no'); * @memberof db.libs.ads * @param {object} message * @param {string} message.frame Name of the frame posting the message * @param {string} message.src Url to image to be used as wallpaper * @param {string} message.url Url to trigger when clicked * @returns {element} */ var setWallpaper = function(message) { var $frame = document.querySelector('iframe[name="' + message.frame + '"]'); if ($frame === null) { console.warn('db.libs.ads.setWallpaper > Adunit iframe missing name attribute.'); return; } $frame.parentNode.style.backgroundImage = 'url(' + message.src + ')'; if (document.querySelector('#adunit-wallpaper') === null) { document.querySelector('main').insertAdjacentHTML('beforebegin', '<a id="adunit-wallpaper" target="_blank" href="#"></a>'); } var $wallpaper = document.querySelector('#adunit-wallpaper'); $wallpaper.style.backgroundImage = 'url(' + message.src + ')'; $wallpaper.style.top = ($frame.getBoundingClientRect().top + document.body.scrollTop) + 'px'; $wallpaper.setAttribute('href', message.url); return $frame.parentNode.parentNode; }; /** * Sets size for adunit. * @public * @example * window.parent.postMessage({ callback: 'db.libs.ads.size', size: 'large-980x300', frame: window.name }, 'http://dagbadet.no'); * @memberof db.libs.ads * @param {object} message * @param {string} message.frame Name of the frame posting the message * @param {string} message.size Classname refering to the desired size */ var setSize = function(message){ var $adunit; if(message.id){ $adunit = document.getElementById(message.id); } else { $adunit = document.querySelector('iframe[name="' + message.frame + '"]').parentNode.parentNode; } if ($adunit === null) { console.warn('db.libs.ads.setSize > Adunit iframe missing name attribute.'); } var size = message.size.match(/small|medium|large/i); if (size !== null) { var re = new RegExp("(^|\\s)" + size + "-\\S+", "g"); $adunit.className = $adunit.className.replace(re, ' ' + message.size); } else { console.warn('db.libs.ads.setSize > Size passed does not match any possible sizes.'); } }; /** * Scale all adunits to fit within given frame. * @private * @memberof db.libs.ads */ var scale = function() { scaleable.forEach(function($adunit, i) { var re = new RegExp("(small|medium|large)-([0-9]{3})x([0-9]{3})-scaled", "i"); var scale = $adunit.className.match(re); var rule = []; var styleId = $adunit.getAttribute('id') + '-scale'; if (scale !== null) { if (document.querySelector('#' + styleId) === null) { var s = document.createElement('style'); s.id = styleId; s.type = 'text/css'; document.getElementsByTagName('head')[0].appendChild(s); } var $style = document.querySelector('#' + styleId); if (scale[1] == 'small') rule.push('@media only screen and (max-width:640px){'); if (scale[1] == 'medium') rule.push('@media only screen and (min-width:641px) and (max-width:1024px){'); if (scale[1] == 'large') rule.push('@media only screen and (min-width:1024px){'); rule.push('#' + $adunit.getAttribute('id') + ' iframe{ transform: scale(' + ((1 / scale[2]) * $adunit.offsetWidth) + '); -webkit-transform: scale(' + ((1 / scale[2]) * $adunit.offsetWidth) + ');}'); rule.push('}'); $style.textContent = rule.join(''); } }); }; /** * Updates poisition and state of sticky adunits. This function is bound to window scroll event and throttled. * @private * @memberof db.libs.ads */ var updateSticky = function() { var top = 0; if(window.pageYOffset !== undefined){ top = window.pageYOffset; } else { top = document.body.scrollTop; } for (var i = 0; i < stickies.length; i++) { if (top > parseInt(stickies[i].getAttribute('data-top')) && !stickies[i].classList.contains('active')) { stickies[i].classList.add('active'); } else if (top < parseInt(stickies[i].getAttribute('data-top')) && stickies[i].classList.contains('active')) { stickies[i].classList.remove('active'); } } }; /** * Updates visibility of fullscreen ads. This function is bound to window scroll event and throttled. * @private * @memberof db.libs.ads */ var updateFullscreen = function(){ var top = 0; if(window.pageYOffset !== undefined){ top = window.pageYOffset; } else { top = document.body.scrollTop; } for (var i = 0; i < fullscreens.length; i++) { if (top > parseInt(fullscreens[i].getAttribute('data-top')) && top < parseInt(fullscreens[i].getAttribute('data-bottom'))) { fullscreens[i].classList.add('active'); if(ua.indexOf('edge/') > -1 || ua.indexOf('trident/') > -1){ fullscreens[i].querySelector('div').style.perspective = '1px'; } if(ua.indexOf('safari') > -1 && ua.indexOf('edge/') == -1 && ua.indexOf('chrome') == -1){ fullscreens[i].querySelector('iframe').style.position = 'absolute'; } if(ua.indexOf('_app_') > -1 && (ua.indexOf('iphone') > -1 || ua.indexOf('ipad') > -1)){ fullscreens[i].querySelector('iframe').style.position = 'absolute'; } } else { fullscreens[i].classList.remove('active'); } } }; var reflowFullscreen = function(){ var height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; for (var f = 0; f < fullscreens.length; f++) { fullscreens[f].setAttribute('data-top', parseInt(fullscreens[f].getBoundingClientRect().top + document.body.scrollTop - height)); fullscreens[f].setAttribute('data-bottom', parseInt(fullscreens[f].getBoundingClientRect().top + document.body.scrollTop + height)); } updateFullscreen(); }; /** * Initialize the component * @public * @memberof db.libs.ads */ var init = function(){ //Check of the ads already have been initialized if( !document.querySelector('html').getAttribute('data-ads') ){ //Set a flag signaling that the ads have been initialized document.querySelector('html').setAttribute('data-ads', 'true'); //Listen for incomming messages from ads. window.addEventListener('message', function(event) { //Check if the callback is within the 'db.libs.ads' namespace try { if (event.data.callback.lastIndexOf('db.libs.ads', 0) === -1) return; var callback = event.data.callback.split('.').pop(); if (typeof db.libs.ads[callback] === typeof Function) { db.libs.ads[callback](event.data); } } catch (e) { return; } }, false); //Create a list of sticky adunits stickies = Array.prototype.filter.call(document.querySelectorAll('.adunit'), function(el){ return el.className.match(/sticky-/); }); var top = 0; if(window.pageYOffset !== undefined){ top = window.pageYOffset; } else { top = document.body.scrollTop; } //Set the initial position for all sticky adunits for (var i = 0; i < stickies.length; i++) { stickies[i].setAttribute('data-top', parseInt(stickies[i].getBoundingClientRect().top + top)); } //Create a list of sticky fullscreen fullscreens = Array.prototype.filter.call(document.querySelectorAll('.adunit'), function(el){ if(window.innerWidth <= 640){ return el.className.match(/small-fullscreen/); } else if(window.innerWidth > 1024){ return el.className.match(/medium-fullscreen/); } else { return el.className.match(/large-fullscreen/); } }); //Set the initial position for all fullscreen adunits var height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; for (var f = 0; f < fullscreens.length; f++) { fullscreens[f].setAttribute('data-top', parseInt(fullscreens[f].getBoundingClientRect().top + document.body.scrollTop - height)); fullscreens[f].setAttribute('data-bottom', parseInt(fullscreens[f].getBoundingClientRect().top + document.body.scrollTop + height)); //If the iOS version is lower than 7 we need to disable the ad. if (/iP(hone|od|ad)/.test(navigator.userAgent)) { var v = (navigator.appVersion).match(/OS (\d+)_(\d+)_?(\d+)?/); var version = [parseInt(v[1], 10), parseInt(v[2], 10), parseInt(v[3] || 0, 10)]; if(version[0] <= 7){ fullscreens[f].classList.add('hide'); fullscreens[f].setAttribute('data-is-configured', 'true'); } } if(ua.indexOf('MSIE ') > -1){ fullscreens[f].className += ' hide'; fullscreens[f].setAttribute('data-is-configured', 'true'); } } if(stickies.length || fullscreens.length){ window.addEventListener('scroll', function(){ window.requestAnimationFrame(updateSticky); window.requestAnimationFrame(updateFullscreen); }); updateSticky(); updateFullscreen(); } if(fullscreens.length){ window.addEventListener('resize', function(){ window.requestAnimationFrame(reflowFullscreen); }); } //Create a list of all scaleable adunits scaleable = Array.prototype.filter.call(document.querySelectorAll('.adunit'), function(el) { return el.className.match(/-scaled/); }); if(scaleable.length){ scale(); } } }; return { init: init, reflow: function() {}, setWallpaper: setWallpaper, setSize: setSize }; })(); })();