harness/app-assets/templates/assets/js/modules/ads.js (226 lines of code) (raw):
/*global window,document,define */
define(function () {
'use strict';
var adsReady = false,
initialised = false,
positionPoller,
numberOfMpus = 0,
adsType;
function insertAdPlaceholders(mpuAfterParagraphs) {
var mpu = createMpu(numberOfMpus),
nrParagraph = (parseInt(mpuAfterParagraphs, 10) || 6) - 1,
placeholder = document.createElement('div'),
placeholderSibling = document.querySelector('.article__body > div.prose > :first-child'),
mpuSibling = document.querySelector('.article__body > div.prose > p:nth-of-type(' + nrParagraph + ') ~ p + p');
if (mpuSibling && mpuSibling.parentNode) {
mpuSibling.parentNode.insertBefore(mpu, mpuSibling);
} else {
// do not proceed - not enough paragraphs on page to add advert
return;
}
placeholder.classList.add('advert-slot');
placeholder.classList.add('advert-slot--placeholder');
// To mimic the correct positioning on full width tablet view, we will need an
// empty div to pad out the text so we can position absolutely over it.
if (placeholderSibling && placeholderSibling.parentNode) {
placeholderSibling.parentNode.insertBefore(placeholder, placeholderSibling);
}
adsReady = true;
}
function updateLiveblogAdPlaceholders(reset) {
var i,
advertSlots,
mpu,
block,
blocks = document.querySelectorAll('.article__body > .block');
if (reset) {
advertSlots = document.getElementsByClassName('advert-slot--mpu');
for (i = advertSlots.length; i > 0; i--) {
advertSlots[i-1].parentNode.removeChild(advertSlots[i-1]);
}
numberOfMpus = 0;
}
for (i = 0; i < blocks.length; i++) {
block = blocks[i];
if (i === 1 || i === 6) {
numberOfMpus++;
mpu = createMpu(numberOfMpus);
if (block.nextSibling) {
block.parentNode.insertBefore(mpu, block.nextSibling);
} else {
block.parentNode.appendChild(mpu);
}
}
}
if (reset) {
if (GU.opts.platform === 'android') {
updateAndroidPosition();
} else {
GU.util.signalDevice('ad_moved');
}
}
}
function createMpu(id) {
var mpu = document.createElement('div');
mpu.classList.add('advert-slot');
mpu.classList.add('advert-slot--mpu');
mpu.innerHTML = '<div class="advert-slot__label">' +
'Advertisement' +
'<a class="advert-slot__action" href="x-gu://subscribe">' +
'Hide' +
'<span data-icon=""></span>' +
'</a>' +
'</div>' +
'<div class="advert-slot__wrapper" id="advert-slot__wrapper">' +
'<div class="advert-slot__wrapper__content" id="' + id + '"></div>' +
'</div>';
return mpu;
}
function getMpuPos(formatter) {
var advertPosition,
advertSlots = document.getElementsByClassName('advert-slot__wrapper'),
i,
scrollLeft = document.body.scrollLeft,
scrollTop = document.body.scrollTop,
params = {
x1: -1,
y1: -1,
w1: -1,
h1: -1,
x2: -1,
y2: -1,
w2: -1,
h2: -1
};
if (advertSlots.length) {
for (i = 0; i < advertSlots.length; i++) {
advertPosition = advertSlots[i].getBoundingClientRect();
if (advertPosition.width !== 0 && advertPosition.height !== 0) {
params['x' + (i + 1)] = advertPosition.left + scrollLeft;
params['y' + (i + 1)] = advertPosition.top + scrollTop;
params['w' + (i + 1)] = advertPosition.width;
params['h' + (i + 1)] = advertPosition.height;
}
}
return formatter(params);
} else {
return null;
}
}
function getMpuPosCommaSeparated() {
return getMpuPos(getMpuPosCommaSeparatedCallback);
}
function getMpuPosCommaSeparatedCallback(params) {
if (numberOfMpus > 1) {
return params.x1 + ',' + params.y1 + ',' + params.x2 + ',' + params.y2;
} else {
return params.x1 + ',' + params.y1;
}
}
function getMpuOffset() {
return getMpuPos(getMpuOffsetCallback);
}
function getMpuOffsetCallback(params) {
if (numberOfMpus > 1) {
return params.x1 + '-' + params.y1 + ':' + params.x2 + '-' + params.y2;
} else {
return params.x1 + '-' + params.y1;
}
}
function updateAndroidPosition() {
if (adsType === 'liveblog') {
getMpuPos(updateAndroidPositionLiveblogCallback);
} else {
getMpuPos(updateAndroidPositionDefaultCallback);
}
}
function updateAndroidPositionLiveblogCallback(params) {
var x1 = params.x1,
y1 = params.y1,
w1 = params.w1,
h1 = params.h1,
x2 = params.x2,
y2 = params.y2,
w2 = params.w2,
h2 = params.h2;
window.GuardianJSInterface.mpuLiveblogAdsPosition(x1, y1, w1, h1, x2, y2, w2, h2);
}
function updateAndroidPositionDefaultCallback(params) {
var x1 = params.x1,
y1 = params.y1,
w1 = params.w1,
h1 = params.h1;
window.GuardianJSInterface.mpuAdsPosition(x1, y1, w1, h1);
}
function initMpuPoller() {
poller(1000,
getMpuOffset(),
true
);
}
function poller(interval, adPositions, firstRun) {
var newAdPositions = getMpuOffset();
if (firstRun && GU.opts.platform === 'android') {
updateAndroidPosition();
}
if (newAdPositions !== adPositions) {
if(GU.opts.platform === 'android'){
updateAndroidPosition();
} else {
GU.util.signalDevice('ad_moved');
}
}
positionPoller = setTimeout(poller.bind(null, interval + 50, newAdPositions), interval);
}
function killMpuPoller() {
window.clearTimeout(positionPoller);
positionPoller = null;
}
function fireAdsReady() {
if (!document.body.classList.contains('no-ready') && GU.opts.useAdsReady === 'true') {
GU.util.signalDevice('ads-ready');
}
}
// Used by quizzes to move the advert
function updateMPUPosition(yPos) {
var advertSlot = document.getElementsByClassName('advert-slot__wrapper')[0],
newYPos;
if (advertSlot) {
newYPos = GU.util.getElementOffset(advertSlot).top;
if(newYPos !== yPos){
if (GU.opts.platform === 'android') {
updateAndroidPosition();
} else {
GU.util.signalDevice('ad_moved');
}
}
}
return newYPos;
}
function setupGlobals() {
window.initMpuPoller = initMpuPoller;
window.killMpuPoller = killMpuPoller;
window.getMpuPosCommaSeparated = getMpuPosCommaSeparated;
window.updateLiveblogAdPlaceholders = updateLiveblogAdPlaceholders;
window.applyNativeFunctionCall('initMpuPoller');
}
function ready(config) {
if (!initialised && config.adsEnabled) {
initialised = true;
adsType = config.adsType;
setupGlobals();
if (adsType === 'liveblog') {
adsReady = true;
updateLiveblogAdPlaceholders();
} else {
numberOfMpus = 1;
insertAdPlaceholders(config.mpuAfterParagraphs);
}
if (adsReady) {
if (GU.opts.platform !== 'android') {
initMpuPoller();
}
fireAdsReady();
}
}
}
return {
init: ready,
updateMPUPosition: updateMPUPosition
};
});