PageSourceSearch

https://robertocavada.com/wp-content/plugins/advanced-ads/public/assets/js/advanced.js?ver=2.0.17

js robertocavada.com collected 2026-10-02 11:04:59 UTC 19,728 bytes, 674 lines download raw bytes

1/*
2 * advanced ads functions to be used directly within ad codes
3 */
4
5/**
6 * Polyfills
7 */
8(function () {
9	if ( typeof window.CustomEvent !== "function" ) {
10		/**
11		 * CustomEvent polyfill for IE11: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent
12		 *
13		 * @param {string} event Event name.
14		 * @param {object} params Event parameters.
15		 * @returne {object} Custom event.
16		 */
17		function CustomEvent ( event, params ) {
18			params = params || { bubbles: false, cancelable: false, detail: null };
19			var evt = document.createEvent( 'CustomEvent' );
20			evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
21			return evt;
22		}
23
24		window.CustomEvent = CustomEvent;
25	}
26
27	/**
28	 * ReplaceWith polyfill for IE11: https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/replaceWith
29	 */
30	function ReplaceWithPolyfill() {
31		'use-strict'; // For safari, and IE > 10
32		var parent = this.parentNode, i = arguments.length, currentNode;
33		if ( ! parent) {
34			return;
35		}
36		if ( ! i ) {// if there are no arguments
37			parent.removeChild( this );
38		}
39		while ( i-- ) { // i-- decrements i and returns the value of i before the decrement
40			currentNode = arguments[i];
41			if ( typeof currentNode !== 'object' ) {
42				currentNode = this.ownerDocument.createTextNode( currentNode );
43			} else if ( currentNode.parentNode ) {
44				currentNode.parentNode.removeChild( currentNode );
45			}
46			// the value of "i" below is after the decrement
47			if ( ! i ) { // if currentNode is the first argument (currentNode === arguments[0])
48				parent.replaceChild( currentNode, this );
49			} else { // if currentNode isn't the first
50				parent.insertBefore( currentNode, this.nextSibling );
51			}
52		}
53	}
54	if ( ! Element.prototype.replaceWith ) {
55		Element.prototype.replaceWith = ReplaceWithPolyfill;
56	}
57	if ( ! CharacterData.prototype.replaceWith ) {
58		CharacterData.prototype.replaceWith = ReplaceWithPolyfill;
59	}
60	if ( ! DocumentType.prototype.replaceWith ) {
61		DocumentType.prototype.replaceWith = ReplaceWithPolyfill;
62	}
63
64	/**
65	 * Polyfill for NodeList.foreach() because we need to support IE11: https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach
66	 */
67	if ( window.NodeList && ! NodeList.prototype.forEach ) {
68		NodeList.prototype.forEach = function( callback, thisArg ) {
69			var i;
70			var len = this.length;
71
72			thisArg = thisArg || window;
73
74			for ( i = 0; i < len; i++ ) {
75				callback.call( thisArg, this[ i ], i, this );
76			}
77		};
78	}
79
80})();
81
82advads = {
83	/**
84	 * check if localstorage is supported/enabled by client
85	 */
86	supports_localstorage: function () {
87		"use strict";
88		try {
89			if ( ! window || window.localStorage === undefined ) {
90				return false;
91			}
92			// storage might be full or disabled
93			window.localStorage.setItem( "x", "x" );
94			window.localStorage.removeItem( "x" );
95			return true;
96		} catch ( e ) {
97			return false;
98		}
99	},
100	/**
101	 * check if the ad is displayed more than {max} times per session
102	 * every check increases the counter
103	 *
104	 * @param {string} name (no id needed, just any id-formated string)
105	 * @param {type} max number of maximum times the ad can be displayed within the period
106	 * @returns {bool} true if limit is reached
107	 */
108	max_per_session: function ( name, max ) {
109		var num = 1;
110		if ( max === undefined || parseInt( max ) === 0 ) {
111			max = 1;
112		}
113
114		// check if cookie exists and get the value
115		if ( this.cookie_exists( name ) ) {
116			if ( this.get_cookie( name ) >= max ) {
117				return true;
118			}
119			num = num + parseInt( this.get_cookie( name ) );
120		}
121		this.set_cookie( name, num );
122		return false;
123	},
124	/**
125	 * increase a cookie with an integer value by 1
126	 *
127	 * @param {str} name of the cookie
128	 * @param {int} exdays days until cookie expires
129	 */
130	count_up: function ( name, exdays ) {
131		var num = 1;
132
133		// check if cookie exists and get the value
134		if ( this.cookie_exists( name ) ) {
135			num = num + parseInt( this.get_cookie( name ) );
136		}
137		this.set_cookie( name, num );
138	},
139	/**
140	 * return true, if cookie exists
141	 * return false, if not
142	 * if not exists, create it
143	 * use case: to check if something already happened in this page impression
144	 *
145	 * @param {type} name
146	 * @returns {unresolved}
147	 */
148	set_cookie_exists: function ( name ) {
149		if ( get_cookie( name ) ) {
150			return true;
151		}
152		set_cookie( name, '', 0 );
153		return false;
154	},
155	/**
156	 * get a cookie value
157	 *
158	 * @param {string}    name of the cookie
159	 * @return {string} decoded cookie value
160	 */
161	get_cookie: function ( name ) {
162		var i, x, y, ADVcookies = document.cookie.split( ';' );
163		for ( i = 0; i < ADVcookies.length; i ++ ) {
164			x = ADVcookies[i].substr( 0, ADVcookies[i].indexOf( '=' ) );
165			y = ADVcookies[i].substr( ADVcookies[i].indexOf( '=' ) + 1 );
166			x = x.replace( /^\s+|\s+$/g, '' );
167			if ( x === name ) {
168				return decodeURIComponent( y );
169			}
170		}
171	},
172	/**
173	 * set a cookie value
174	 *
175	 * @param {str} name of the cookie
176	 * @param {str} value of the cookie
177	 * @param {int} exdays days until cookie expires
178	 *  set 0 to expire cookie immidiatelly
179	 *  set null to expire cookie in the current session
180	 */
181	set_cookie: function ( name, value, exdays, path, domain, secure ) {
182		// days in seconds
183		var expiry = (
184			exdays == null
185		) ? null : exdays * 24 * 60 * 60;
186		this.set_cookie_sec( name, value, expiry, path, domain, secure );
187	},
188	/**
189	 * set a cookie with expiry given in seconds
190	 *
191	 * @param {str} name of the cookie
192	 * @param {str} value of the cookie
193	 * @param {int} expiry seconds until cookie expires
194	 *  set 0 to expire cookie immidiatelly
195	 *  set null to expire cookie in the current session
196	 */
197	set_cookie_sec: function ( name, value, expiry, path, domain, secure ) {
198		var exdate = new Date();
199		exdate.setSeconds( exdate.getSeconds() + parseInt( expiry ) );
200		document.cookie = name + "=" + encodeURIComponent( value ) +
201						  (
202							  (
203								  expiry == null
204							  ) ? "" : "; expires=" + exdate.toUTCString()
205						  ) +
206						  (
207							  (
208								  path == null
209							  ) ? "; path=/" : "; path=" + path
210						  ) +
211						  (
212							  (
213								  domain == null
214							  ) ? "" : "; domain=" + domain
215						  ) +
216						  (
217							  (
218								  secure == null
219							  ) ? "" : "; secure"
220						  );
221	},
222	/**
223	 * check if a cookie is set and contains a value
224	 *
225	 * @param {str} name of the cookie
226	 * @returns {bool} true, if cookie is set
227	 */
228	cookie_exists: function ( name ) {
229		var c_value = this.get_cookie( name );
230		if ( c_value !== null && c_value !== "" && c_value !== undefined ) {
231			return true;
232		}
233		return false;
234	},
235	/**
236	 * move one element into another
237	 *
238	 * @param {str} element selector of the element that should be moved
239	 * @param {str} target selector of the element where to move
240	 * @param {arr} options
241	 */
242	move: function ( element, target, options ) {
243
244		var el = jQuery( element );
245		var target_string = target;
246
247		if ( typeof options === 'undefined' ) {
248			options = {};
249		}
250		if ( typeof options.css === 'undefined' ) {
251			options.css = {};
252		}
253		if ( typeof options.method === 'undefined' ) {
254			options.method = 'prependTo';
255		}
256
257		// search for abstract target element
258		if ( target === '' && typeof options.target !== 'undefined' ) {
259			switch ( options.target ) {
260				case 'wrapper' : // wrapper
261					var offset = 'left';
262					if ( typeof options.offset !== 'undefined' ) {
263						offset = options.offset;
264					}
265					target = this.find_wrapper( element, offset );
266					break;
267			}
268		}
269
270		// use only visible elements
271		if ( typeof options.moveintohidden === 'undefined' ) {
272			target = jQuery( target ).filter( ':visible' );
273		} else {
274			target = jQuery( target );
275		}
276
277		// print warning in console if the element appears multiple times
278		if ( target.length > 1 ) {
279			console.log( "Advanced Ads: element '" + target_string + "' found " + target.length + " times." );
280		}
281
282		// switch insert method
283		switch ( options.method ) {
284			case 'insertBefore' :
285				el.insertBefore( target );
286				break;
287			case 'insertAfter' :
288				el.insertAfter( target );
289				break;
290			case 'appendTo' :
291				el.appendTo( target );
292				break;
293			case 'prependTo' :
294				el.prependTo( target );
295				break;
296			default :
297				el.prependTo( target );
298		}
299	},
300
301	/**
302	 * Set 'relative' position for a parent element.
303	 *
304	 * @param {str} element selector
305	 */
306	set_parent_relative: function ( element, options ) {
307		var options = typeof options !== 'undefined' ? options : {};
308		var el = jQuery( element );
309		// give "position" style to parent element, if missing
310		var parent = el.parent();
311
312		if ( options.use_grandparent ) {
313			parent = parent.parent();
314		}
315
316		if ( parent.css( 'position' ) === 'static' || parent.css( 'position' ) === '' ) {
317			parent.css( 'position', 'relative' );
318		}
319	},
320
321	/**
322	 * make an absolute position element fixed at the current position
323	 * hint: use only after DOM is fully loaded in order to fix a wrong position
324	 *
325	 * @param {str} element selector
326	 * @param {obj} options
327	 */
328	fix_element: function ( element, options ) {
329		var options = typeof options !== 'undefined' ? options : {};
330
331		var el = jQuery( element );
332
333		if ( options.use_grandparent ) {
334			this.set_parent_relative( el.parent() );
335		} else {
336			this.set_parent_relative( el );
337		}
338
339		// fix element at current position
340		// get position for hidden elements by showing them for a very short time
341		if ( options.is_invisible ) {
342			el.show();
343		}
344		var topoffset = parseInt( el.offset().top );
345		var leftoffset = parseInt( el.offset().left );
346		if ( options.is_invisible ) {
347			el.hide();
348		}
349		if ( 'left' === options.offset ) {
350			// Allow to scale the nested image down when it has `max-width: 100%` and touches the left edge of the viewport.
351			var rightoffset = jQuery( window ).width() - leftoffset - el.outerWidth();
352			el.css( 'position', 'fixed' ).css( 'top', topoffset + 'px' ).css( 'right', rightoffset + 'px' ).css( 'left', '' );
353		} else {
354			// reset "right" to prevent conflicts
355			el.css( 'position', 'fixed' ).css( 'top', topoffset + 'px' ).css( 'left', leftoffset + 'px' ).css( 'right', '' );
356		}
357
358	},
359
360	/**
361	 * find the main wrapper
362	 *  either id or first of its class
363	 *
364	 *  @param {str} element selector
365	 *  @param {str} offset which position of the offset to check (left or right)
366	 *  @return {str} selector
367	 */
368	find_wrapper: function ( element, offset ) {
369		// first margin: auto element after body
370		var returnValue;
371
372		jQuery( 'body' ).children().not('script, .screen-reader-text, .skip-link, ' + element).each( function ( key, value ) {
373			// check offset value
374			var checkedelement = jQuery( value );
375			// check if there is space left or right of the element
376			if ( (
377						offset === 'right' && (
378							checkedelement.offset().left + jQuery( checkedelement ).width() < jQuery( window ).width()
379						)
380					) ||
381					(
382						offset === 'left' && checkedelement.offset().left > 0
383					) ) {
384				// fix element
385				if ( checkedelement.css( 'position' ) === 'static' || checkedelement.css( 'position' ) === '' ) {
386					checkedelement.css( 'position', 'relative' );
387				}
388				// set return value
389				returnValue = value;
390				return false;
391			}
392		} );
393		return returnValue;
394	},
395	/**
396	 * center fixed element on the screen
397	 *
398	 * @param {str} element selector
399	 */
400	center_fixed_element: function ( element ) {
401		var el = jQuery( element );
402		// half window width minus half element width
403		var left = (
404					   jQuery( window ).width() / 2
405				   ) - (
406					   parseInt( el.css( 'width' ) ) / 2
407				   );
408		el.css( 'left', left + 'px' );
409	},
410	/**
411	 * center element vertically on the screen
412	 *
413	 * @param {str} element selector
414	 */
415	center_vertically: function ( element ) {
416		var el = jQuery( element );
417		// half window height minus half element height
418		var left = (
419					   jQuery( window ).height() / 2
420				   ) - (
421					   parseInt( el.css( 'height' ) ) / 2
422				   );
423
424		// Center correctly when the ad is attached to the element that begins lower.
425		if ( el.css( 'position' ) !== 'fixed' ) {
426			left -= topoffset = parseInt( el.offset().top );
427		}
428		el.css( 'top', left + 'px' );
429	},
430	/**
431	 * close an ad and add a cookie
432	 *
433	 * @param {str} element selector
434	 */
435	close: function ( element ) {
436		var wrapper = jQuery( element );
437		// remove the ad
438		wrapper.remove();
439	},
440	/**
441	 * Wait until images are ready.
442	 *
443	 * @param {obj} $el jQuery object.
444	 * @param {function} ready_callback Ready callback.
445	 * derrived from https://github.com/alexanderdickson/waitForImages/blob/master/dist/jquery.waitforimages.js
446	 */
447	wait_for_images: function ( $el, ready_callback ) {
448		var loaded_count = 0;
449		var srcs = [];
450
451		$el.find( 'img[src][src!=""]' ).each( function () {
452			srcs.push( this.src );
453		} );
454
455		if ( srcs.length === 0 ) {
456			ready_callback.call( $el );
457		}
458
459		jQuery.each( srcs, function ( i, src ) {
460			var image = new Image();
461			image.src = src;
462			var events = 'load error';
463
464			jQuery( image ).one( events, function me( event ) {
465				// Remove remaining handler (either 'load' or 'error').
466				jQuery( this ).off( events, me );
467				loaded_count ++;
468
469				if ( loaded_count == srcs.length ) {
470					ready_callback.call( $el[0] );
471					return false;
472				}
473			} );
474		} );
475	},
476
477	privacy: {
478		state: 'unknown',
479		state_executed: false,
480		/**
481		 * Get consent state.
482		 * IIFE so the events fire only once per event.
483		 *
484		 * @return string
485		 *     'not_needed' - consent is not needed.
486		 *     'accepted' - consent was given.
487		 *     'unknown' - consent was not given yet.
488		 */
489		get_state: (
490			function () {
491				return function () {
492					// if we already have a state, return that.
493					if ( window.advads_options.privacy.state !== 'unknown' ) {
494						// make sure this only gets executed once.
495						if ( ! advads.privacy.state_executed ) {
496							advads.privacy.state_executed = true;
497							advads.privacy.dispatch_event( window.advads_options.privacy.state, false );
498						}
499						return advads.privacy.state;
500					}
501
502					// If using the cookie method, fire an initial event, regardless if cookie set or not.
503					if ( window.advads_options.privacy['consent-method'] === 'custom' ) {
504						var cookie_regex = new RegExp( '.*?' + window.advads_options.privacy['custom-cookie-value'] + '[^;]*?' );
505						let cookie       = advads.get_cookie( window.advads_options.privacy['custom-cookie-name'] ) || '';
506
507						// Force the event, if we haven't yet fired one.
508						if ( ! advads.privacy.state_executed ) {
509							advads.privacy.state_executed = true;
510							advads.privacy.dispatch_event( cookie.match( cookie_regex ) ? 'accepted' : 'unknown', true );
511						}
512					}
513
514					// make sure this only gets executed once.
515					advads.privacy.state_executed = true;
516
517					// Run this in an interval (every 0.3s) just in case we are still waiting for consent
518					var cnt                = 0,
519						consentSetInterval = setInterval( function () {
520							// Bail if we have not gotten a consent response after 60 seconds.
521							if ( ++ cnt === 181 ) {
522								clearInterval( consentSetInterval );
523							}
524							switch ( window.advads_options.privacy['consent-method'] ) {
525								case 'custom' :
526									let cookie = advads.get_cookie( window.advads_options.privacy['custom-cookie-name'] ) || '';
527
528									// check if custom cookie is set and matches value.
529									if ( cookie.match( cookie_regex ) ) {
530										clearInterval( consentSetInterval );
531										if ( advads.privacy.state !== 'accepted' ) {
532											advads.privacy.dispatch_event( 'accepted', true );
533										}
534									}
535									break;
536
537								case 'iab_tcf_20' :
538									// Check if window.__tcfapi has been set.
539									if ( typeof window.__tcfapi === 'undefined' ) {
540										return;
541									}
542									clearInterval( consentSetInterval );
543
544									window.__tcfapi( 'addEventListener', 2, function ( TCData, listenerSuccess ) {
545											if ( ! listenerSuccess ) {
546												return;
547											}
548											if (
549												TCData.eventStatus === 'tcloaded'
550												|| TCData.eventStatus === 'useractioncomplete'
551												// if this is google funding choices, eventStatus is not set. Check if either gdpr doesn't apply or if there is a purpose object.
552												|| ( TCData.eventStatus === null && typeof window.googlefc !== 'undefined' && (
553													typeof TCData.purpose !== 'undefined' || ! TCData.gdprApplies
554												) )
555											) {
556												var userAction = TCData.eventStatus === 'useractioncomplete';
557												if ( ! TCData.gdprApplies ) {
558													if ( advads.privacy.state !== 'not_needed' ) {
559														advads.privacy.dispatch_event( 'not_needed', userAction );
560													}
561													return;
562												}
563
564												if ( TCData.purpose.consents[1] ) {
565													if ( advads.privacy.state !== 'accepted' ) {
566														advads.privacy.dispatch_event( 'accepted', userAction );
567													}
568													return;
569												}
570
571												// fire another event, in case the user revokes the previous consent.
572												if ( advads.privacy.state !== 'rejected' ) {
573													advads.privacy.dispatch_event( 'rejected', userAction );
574												}
575											}
576										}
577									);
578									break;
579							}
580						}, 333 );
581
582					return advads.privacy.state;
583				}
584			}
585		)(),
586		/**
587		 * Check if the privacy_method is custom cookie, and non personalized ads are allowed.
588		 *
589		 * @returns {boolean}
590		 */
591		is_adsense_npa_enabled: function () {
592			if ( ! window.advads_options || ! window.advads_options.privacy ) {
593				return true;
594			}
595			return !! (
596				window.advads_options.privacy['show-non-personalized-adsense'] && window.advads_options.privacy['consent-method'] === 'custom'
597			);
598		},
599		/**
600		 * Dispatch a custom event whenever the state changes.
601		 *
602		 * @param {String} state The current privacy state.
603		 * @param {boolean} userAction This is result of action by user.
604		 */
605		dispatch_event: function ( state, userAction ) {
606			var previousState = advads.privacy.state,
607				fire_event    = function () {
608					document.dispatchEvent( new CustomEvent( 'advanced_ads_privacy', {
609						detail: {
610							state: state,
611							previousState: previousState,
612							userAction: userAction
613						}
614					} ) );
615				};
616
617			advads.privacy.state = state;
618
619			console.log( {
620				state: state,
621				previousState: previousState,
622				userAction: userAction
623			} );
624
625			window.advanced_ads_ready_queue.push( fire_event );
626		},
627		/**
628		 * Check if ad is decoded.
629		 *
630		 * @param {integer} id
631		 *
632		 * @returns {boolean}
633		 */
634		is_ad_decoded: function ( id ) {
635			return document.querySelector( 'script[data-tcf="waiting-for-consent"][data-id="' + id + '"]' ) === null;
636		},
637		/**
638		 * Decode ad content.
639		 *
640		 * @param {Element} el
641		 * @param {boolean} [inject=true]
642		 */
643		decode_ad: function ( el, inject ) {
644			// this can also be a number if used in a foreach.
645			inject     = typeof inject === 'boolean' ? inject : true;
646			var string = decodeURIComponent( Array.prototype.map.call( atob( el.textContent ), function ( c ) {
647				return '%' + ( '00' + c.charCodeAt( 0 ).toString( 16 ) ).slice( - 2 );
648			} ).join( '' ) );
649
650			if ( ! inject ) {
651				return string;
652			}
653
654			el.replaceWith( document.createRange().createContextualFragment( string ) );
655		}
656	}
657};
658
659window.advanced_ads_ready_queue.push( advads.privacy.get_state );
660
661document.addEventListener( 'advanced_ads_privacy', function ( event ) {
662	if (
663		(
664			event.detail.state !== 'accepted' && event.detail.state !== 'not_needed'
665		)
666		|| event.detail.userAction
667		|| document.readyState === 'loading'
668	) {
669		return;
670	}
671
672	// Find all scripts waiting for consent and decode them.
673	document.querySelectorAll( 'script[type="text/plain"][data-tcf="waiting-for-consent"]' ).forEach( advads.privacy.decode_ad );
674} );

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.