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
};
})();
})();