: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* advanced ads functions to be used directly within ad codes
if ( typeof window.CustomEvent !== "function" ) {
* CustomEvent polyfill for IE11: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent
* @param {string} event Event name.
* @param {object} params Event parameters.
* @returne {object} Custom event.
function CustomEvent ( event, params ) {
params = params || { bubbles: false, cancelable: false, detail: null };
var evt = document.createEvent( 'CustomEvent' );
evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
window.CustomEvent = CustomEvent;
* ReplaceWith polyfill for IE11: https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/replaceWith
function ReplaceWithPolyfill() {
'use-strict'; // For safari, and IE > 10
var parent = this.parentNode, i = arguments.length, currentNode;
if ( ! i ) {// if there are no arguments
parent.removeChild( this );
while ( i-- ) { // i-- decrements i and returns the value of i before the decrement
currentNode = arguments[i];
if ( typeof currentNode !== 'object' ) {
currentNode = this.ownerDocument.createTextNode( currentNode );
} else if ( currentNode.parentNode ) {
currentNode.parentNode.removeChild( currentNode );
// the value of "i" below is after the decrement
if ( ! i ) { // if currentNode is the first argument (currentNode === arguments[0])
parent.replaceChild( currentNode, this );
} else { // if currentNode isn't the first
parent.insertBefore( currentNode, this.nextSibling );
if ( ! Element.prototype.replaceWith ) {
Element.prototype.replaceWith = ReplaceWithPolyfill;
if ( ! CharacterData.prototype.replaceWith ) {
CharacterData.prototype.replaceWith = ReplaceWithPolyfill;
if ( ! DocumentType.prototype.replaceWith ) {
DocumentType.prototype.replaceWith = ReplaceWithPolyfill;
* Polyfill for NodeList.foreach() because we need to support IE11: https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach
if ( window.NodeList && ! NodeList.prototype.forEach ) {
NodeList.prototype.forEach = function( callback, thisArg ) {
thisArg = thisArg || window;
for ( i = 0; i < len; i++ ) {
callback.call( thisArg, this[ i ], i, this );
* check if localstorage is supported/enabled by client
supports_localstorage: function () {
if ( ! window || window.localStorage === undefined ) {
// storage might be full or disabled
window.localStorage.setItem( "x", "x" );
window.localStorage.removeItem( "x" );
* check if the ad is displayed more than {max} times per session
* every check increases the counter
* @param {string} name (no id needed, just any id-formated string)
* @param {type} max number of maximum times the ad can be displayed within the period
* @returns {bool} true if limit is reached
max_per_session: function ( name, max ) {
if ( max === undefined || parseInt( max ) === 0 ) {
// check if cookie exists and get the value
if ( this.cookie_exists( name ) ) {
if ( this.get_cookie( name ) >= max ) {
num = num + parseInt( this.get_cookie( name ) );
this.set_cookie( name, num );
* increase a cookie with an integer value by 1
* @param {str} name of the cookie
* @param {int} exdays days until cookie expires
count_up: function ( name, exdays ) {
// check if cookie exists and get the value
if ( this.cookie_exists( name ) ) {
num = num + parseInt( this.get_cookie( name ) );
this.set_cookie( name, num );
* return true, if cookie exists
* if not exists, create it
* use case: to check if something already happened in this page impression
set_cookie_exists: function ( name ) {
if ( get_cookie( name ) ) {
set_cookie( name, '', 0 );
* @param {string} name of the cookie
* @return {string} decoded cookie value
get_cookie: function ( name ) {
var i, x, y, ADVcookies = document.cookie.split( ';' );
for ( i = 0; i < ADVcookies.length; i ++ ) {
x = ADVcookies[i].substr( 0, ADVcookies[i].indexOf( '=' ) );
y = ADVcookies[i].substr( ADVcookies[i].indexOf( '=' ) + 1 );
x = x.replace( /^\s+|\s+$/g, '' );
return decodeURIComponent( y );
* @param {str} name of the cookie
* @param {str} value of the cookie
* @param {int} exdays days until cookie expires
* set 0 to expire cookie immidiatelly
* set null to expire cookie in the current session
set_cookie: function ( name, value, exdays, path, domain, secure ) {
) ? null : exdays * 24 * 60 * 60;
this.set_cookie_sec( name, value, expiry, path, domain, secure );
* set a cookie with expiry given in seconds
* @param {str} name of the cookie
* @param {str} value of the cookie
* @param {int} expiry seconds until cookie expires
* set 0 to expire cookie immidiatelly
* set null to expire cookie in the current session
set_cookie_sec: function ( name, value, expiry, path, domain, secure ) {
exdate.setSeconds( exdate.getSeconds() + parseInt( expiry ) );
document.cookie = name + "=" + encodeURIComponent( value ) +
) ? "" : "; expires=" + exdate.toUTCString()
) ? "; path=/" : "; path=" + path
) ? "" : "; domain=" + domain
* check if a cookie is set and contains a value
* @param {str} name of the cookie
* @returns {bool} true, if cookie is set
cookie_exists: function ( name ) {
var c_value = this.get_cookie( name );
if ( c_value !== null && c_value !== "" && c_value !== undefined ) {
* move one element into another
* @param {str} element selector of the element that should be moved
* @param {str} target selector of the element where to move
move: function ( element, target, options ) {
var el = jQuery( element );
var target_string = target;
if ( typeof options === 'undefined' ) {
if ( typeof options.css === 'undefined' ) {
if ( typeof options.method === 'undefined' ) {
options.method = 'prependTo';
// search for abstract target element
if ( target === '' && typeof options.target !== 'undefined' ) {
switch ( options.target ) {
case 'wrapper' : // wrapper
if ( typeof options.offset !== 'undefined' ) {
target = this.find_wrapper( element, offset );
// use only visible elements
if ( typeof options.moveintohidden === 'undefined' ) {
target = jQuery( target ).filter( ':visible' );
target = jQuery( target );
// print warning in console if the element appears multiple times
if ( target.length > 1 ) {
console.log( "Advanced Ads: element '" + target_string + "' found " + target.length + " times." );
switch ( options.method ) {
el.insertBefore( target );
el.insertAfter( target );
* Set 'relative' position for a parent element.
* @param {str} element selector
set_parent_relative: function ( element, options ) {
var options = typeof options !== 'undefined' ? options : {};
var el = jQuery( element );
// give "position" style to parent element, if missing
var parent = el.parent();
if ( options.use_grandparent ) {
parent = parent.parent();
if ( parent.css( 'position' ) === 'static' || parent.css( 'position' ) === '' ) {
parent.css( 'position', 'relative' );
* make an absolute position element fixed at the current position
* hint: use only after DOM is fully loaded in order to fix a wrong position
* @param {str} element selector
fix_element: function ( element, options ) {
var options = typeof options !== 'undefined' ? options : {};
var el = jQuery( element );
if ( options.use_grandparent ) {
this.set_parent_relative( el.parent() );
this.set_parent_relative( el );
// fix element at current position
// get position for hidden elements by showing them for a very short time
if ( options.is_invisible ) {
var topoffset = parseInt( el.offset().top );
var leftoffset = parseInt( el.offset().left );
if ( options.is_invisible ) {
if ( 'left' === options.offset ) {
// Allow to scale the nested image down when it has `max-width: 100%` and touches the left edge of the viewport.
var rightoffset = jQuery( window ).width() - leftoffset - el.outerWidth();
el.css( 'position', 'fixed' ).css( 'top', topoffset + 'px' ).css( 'right', rightoffset + 'px' ).css( 'left', '' );
// reset "right" to prevent conflicts
el.css( 'position', 'fixed' ).css( 'top', topoffset + 'px' ).css( 'left', leftoffset + 'px' ).css( 'right', '' );
* either id or first of its class
* @param {str} element selector
* @param {str} offset which position of the offset to check (left or right)
find_wrapper: function ( element, offset ) {
// first margin: auto element after body
jQuery( 'body' ).children().each( function ( key, value ) {
// exclude current element
if ( value.id !== element.substring( 1 ) ) {
var checkedelement = jQuery( value );
// check if there is space left or right of the element
checkedelement.offset().left + jQuery( checkedelement ).width() < jQuery( window ).width()
offset === 'left' && checkedelement.offset().left > 0
if ( checkedelement.css( 'position' ) === 'static' || checkedelement.css( 'position' ) === '' ) {
checkedelement.css( 'position', 'relative' );
* center fixed element on the screen
* @param {str} element selector
center_fixed_element: function ( element ) {
var el = jQuery( element );
// half window width minus half element width
jQuery( window ).width() / 2
parseInt( el.css( 'width' ) ) / 2
el.css( 'left', left + 'px' );
* center element vertically on the screen
* @param {str} element selector
center_vertically: function ( element ) {
var el = jQuery( element );
// half window height minus half element height
jQuery( window ).height() / 2
parseInt( el.css( 'height' ) ) / 2
// Center correctly when the ad is attached to the element that begins lower.
if ( el.css( 'position' ) !== 'fixed' ) {
left -= topoffset = parseInt( el.offset().top );
el.css( 'top', left + 'px' );
* close an ad and add a cookie
* @param {str} element selector
close: function ( element ) {
var wrapper = jQuery( element );
* Wait until images are ready.
* @param {obj} $el jQuery object.
* @param {function} ready_callback Ready callback.
* derrived from https://github.com/alexanderdickson/waitForImages/blob/master/dist/jquery.waitforimages.js
wait_for_images: function ( $el, ready_callback ) {
$el.find( 'img[src][src!=""]' ).each( function () {
if ( srcs.length === 0 ) {
ready_callback.call( $el );
jQuery.each( srcs, function ( i, src ) {
var events = 'load error';
jQuery( image ).one( events, function me( event ) {
// Remove remaining handler (either 'load' or 'error').
jQuery( this ).off( events, me );
if ( loaded_count == srcs.length ) {
ready_callback.call( $el[0] );
* IIFE so the events fire only once per event.
* 'not_needed' - consent is not needed.
* 'accepted' - consent was given.
* 'unknown' - consent was not given yet.
// if we already have a state, return that.
if ( window.advads_options.privacy.state !== 'unknown' ) {
// make sure this only gets executed once.
if ( ! advads.privacy.state_executed ) {
advads.privacy.state_executed = true;
advads.privacy.dispatch_event( window.advads_options.privacy.state, false );