: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
const tbody = jQuery( '#mapi-table-wrap tbody' )
const selectedRows = tbody.find( 'tr[data-slotid="' + selectedId + '"]' )
if ( selectedRows.length ) {
openExternalAdsList: function () {
const network = AdvancedAdsAdmin.AdImporter.adNetwork
jQuery( '.mapi-insert-code' ).css( 'display', 'inline' )
jQuery( '.mapi-open-selector' ).css( 'display', 'none' )
jQuery( '.mapi-close-selector-link' ).css( 'display', 'inline' )
jQuery( '.advads-adsense-code' ).css( 'display', 'none' )
jQuery( '#remote-ad-unsupported-ad-type' ).css( 'display', 'none' )
AdvancedAdsAdmin.AdImporter.highlightSelectedRowInExternalAdsList( network.hideIdle )
var SNT = network.getCustomInputs()
SNT.css( 'display', 'none' )
jQuery( '#mapi-wrap' ).css( 'display', 'block' )
if ( ! network.fetchedExternalAds ) {
network.fetchedExternalAds = true
const nbUnits = jQuery( '#mapi-table-wrap tbody tr[data-slotid]' ).length
//usually we start with a preloaded list.
//only reload, when the count is zero (true for new accounts).
AdvancedAdsAdmin.AdImporter.refreshAds()
jQuery( '#wpwrap' ).trigger( 'advads-mapi-adlist-opened' );
* will be called every time the ad type is changed.
* required for onBlur detection
onChangedAdType: function () {
if ( AdvancedAdsAdmin.AdImporter.adNetwork ) {
AdvancedAdsAdmin.AdImporter.adNetwork.onBlur()
AdvancedAdsAdmin.AdImporter.adNetwork = null
setup: function ( adNetwork ) {
AdvancedAdsAdmin.AdImporter.adNetwork = adNetwork
if ( AdvancedAdsAdmin.AdImporter.isSetup ) {
AdvancedAdsAdmin.AdImporter.highlightSelectedRowInExternalAdsList()
AdvancedAdsAdmin.AdImporter.isSetup = true
jQuery( document ).on( 'click', '.prevent-default', function ( ev ) { ev.preventDefault() } )
// handle clicks for the "insert new ... code" anchor
jQuery( document ).on( 'click', '.mapi-insert-code', function ( e ) {
jQuery( '#remote-ad-unsupported-ad-type' ).css( 'display', 'none' );
jQuery( '.advads-adsense-code' ).show()
jQuery( '.mapi-open-selector' ).css( 'display', 'inline' )
jQuery( '.mapi-close-selector-link' ).css( 'display', 'inline' )
jQuery( '.mapi-insert-code' ).css( 'display', 'none' );
jQuery( '#mapi-wrap' ).css( 'display', 'none' )
var SNT = AdvancedAdsAdmin.AdImporter.adNetwork.getCustomInputs()
SNT.css( 'display', 'none' )
// handle clicks for the "get ad code from your linked account" anchor
jQuery( document ).on( 'click', '.mapi-open-selector a', function () {
AdvancedAdsAdmin.AdImporter.openExternalAdsList()
// the close button of the ad unit list
jQuery( document ).on( 'click', '#mapi-close-selector,.mapi-close-selector-link', function () {
jQuery( '#remote-ad-unsupported-ad-type' ).css( 'display', 'none' );
AdvancedAdsAdmin.AdImporter.manualSetup()
//the individual rows of the ad units may contain elements with the mapiaction class
jQuery( document ).on( 'click', '.mapiaction', function ( ev ) {
var action = jQuery( this ).attr( 'data-mapiaction' )
AdvancedAdsAdmin.AdImporter.refreshAds()
if ( jQuery( this ).hasClass( 'disabled' ) ) {
var slotId = jQuery( this ).attr( 'data-slotid' )
AdvancedAdsAdmin.AdImporter.adNetwork.selectAdFromList( slotId )
var slotId = jQuery( this ).attr( 'data-slotid' )
AdvancedAdsAdmin.AdImporter.adNetwork.updateAdFromList( slotId )
if ( 'undefined' != typeof AdvancedAdsAdmin.AdImporter.adNetwork.getMapiAction && 'function' == typeof AdvancedAdsAdmin.AdImporter.adNetwork.getMapiAction( 'toggleidle' ) ) {
AdvancedAdsAdmin.AdImporter.adNetwork.getMapiAction( 'toggleidle' )( ev, this );
AdvancedAdsAdmin.AdImporter.adNetwork.hideIdle = ! AdvancedAdsAdmin.AdImporter.adNetwork.hideIdle
AdvancedAdsAdmin.AdImporter.toggleIdleAds( AdvancedAdsAdmin.AdImporter.adNetwork.hideIdle )
const $inactiveNotice = jQuery( '#mapi-notice-inactive' );
if ( $inactiveNotice.length ) {
$inactiveNotice.toggle( AdvancedAdsAdmin.AdImporter.adNetwork.hideIdle );
AdvancedAdsAdmin.AdImporter.adNetwork.onDomReady()
// AdvancedAdsAdmin.AdImporter.openExternalAdsList();
* call this method to display the manual setup (if available for the current ad network)
* this method is an equivalent to the close ad list button.
jQuery( '.mapi-open-selector,.advads-adsense-show-code' ).css( 'display', 'inline' )
jQuery( '.mapi-insert-code' ).css( 'display', 'inline' )
jQuery( '.mapi-close-selector-link' ).css( 'display', 'none' )
jQuery( '#mapi-wrap' ).css( 'display', 'none' )
var SNT = AdvancedAdsAdmin.AdImporter.adNetwork.getCustomInputs()
SNT.css( 'display', 'block' )
// hide custom layout key if type is not in-feed
if (jQuery('#unit-type').val() !== 'in-feed') {
jQuery('.advads-adsense-layout-key').css('display', 'none')
.next('div').css('display', 'none');
AdvancedAdsAdmin.AdImporter.adNetwork.onManualSetup()
setRemoteErrorMessage ( msg ) {
if ( ! msg ) jQuery( '#remote-ad-code-msg' ).empty()
else jQuery( '#remote-ad-code-msg' ).html( msg )
closeAdSelector: function () {
// close the ad unit selector
setTimeout( function () {
jQuery( '#mapi-wrap' ).animate(
jQuery( '.mapi-open-selector,.advads-adsense-show-code' ).css( 'display', 'inline' )
jQuery( '.mapi-close-selector-link' ).css( 'display', 'none' )
jQuery( '#mapi-wrap' ).css( {
const SNT = AdvancedAdsAdmin.AdImporter.adNetwork.getCustomInputs()
SNT.css( 'display', 'block' )
* updates the UI, (call if the selected unit is supported)
unitIsNotSupported: function ( slotID ) {
jQuery( '#remote-ad-unsupported-ad-type' ).css( 'display', 'block' );
AdsenseMAPI.unsupportedUnits[ slotID ] = 1;
jQuery( '#unit-code' ).val( '' );
jQuery( '#unit-type' ).val( 'normal' );
jQuery( '#ad-layout-key' ).val( '' );
jQuery( 'tr[data-slotid^="ca-"]' ).removeClass( 'selected error' );
var $selectedRow = jQuery('tr[data-slotid="' + slotID + '"]');
$selectedRow.addClass('selected error').css('background-color', '');
this.scrollToSelectedRow($selectedRow);
* updates the UI, (call if the selected unit is NOT supported)
unitIsSupported: function ( slotID ) {
jQuery( '#remote-ad-unsupported-ad-type' ).css( 'display', 'none' )
if ( 'undefined' != typeof AdsenseMAPI.unsupportedUnits[ slotID ] ) {
delete AdsenseMAPI.unsupportedUnits[ slotID ]
jQuery( 'i[data-mapiaction="getCode"][data-slotid="' + slotID + '"]' ).removeClass( 'disabled' )
if ( jQuery( 'tr[data-slotid="' + slotID + '"] .unittype a' ).length ) {
var td = jQuery( 'tr[data-slotid="' + slotID + '"] .unittype' )
var content = jQuery( 'tr[data-slotid="' + slotID + '"] .unittype a' ).attr( 'data-type' )
if ( jQuery( 'tr[data-slotid="' + slotID + '"] .unitsize a' ).length ) {
var td = jQuery( 'tr[data-slotid="' + slotID + '"] .unitsize' )
var content = jQuery( 'tr[data-slotid="' + slotID + '"] .unitsize a' ).attr( 'data-size' )
* updates the UI, (call if the selected unit is NOT supported)
emptyMapiSelector: function ( msg ) {
const nag = '<div class="advads-notice-inline advads-error"><p>' + msg + '</p></div>'
jQuery( '#mapi-loading-overlay' ).css( 'display', 'none' )
jQuery( '#mapi-wrap' ).html( jQuery( nag ) )
refreshAds: function () {
const adNetwork = AdvancedAdsAdmin.AdImporter.adNetwork
jQuery( '#mapi-loading-overlay' ).css( 'display', 'block' );
data: adNetwork.getRefreshAdsParameters(),
success: function ( response, status, XHR ) {
if ( 'undefined' != typeof response.html ) {
jQuery( '#mapi-wrap' ).replaceWith( jQuery( response.html ) )
AdvancedAdsAdmin.AdImporter.openExternalAdsList()
} else if ( 'undefined' != typeof response.msg ) {
AdvancedAdsAdmin.AdImporter.emptyMapiSelector( response.msg )
if ( 'undefined' != typeof response.raw ) {
console.log( response.raw )
jQuery( '#mapi-loading-overlay' ).css( 'display', 'none' )
error: function ( request, status, err ) {
jQuery( '#mapi-loading-overlay' ).css( 'display', 'none' )
toggleIdleAds: function ( hide ) {
if ( 'undefined' == typeof hide ) {
AdvancedAdsAdmin.AdImporter.highlightSelectedRowInExternalAdsList( hide )
* The "abstract" base class for handling external ad units
* Every ad unit will provide you with a set of methods to control the GUI and trigger requests to the server
* while editing an ad that is backed by this network. The main logic takes place in admin/assets/admin.js,
* and the methods in this class are the ones that needed abstraction, depending on the ad network. When you
* need new network-dependant features in the frontend, this is the place to add new methods.
* An AdvancedAdsAdNetwork uses these fields:
* id string The identifier, that is used for this network. Must match with the one used in the PHP code of Advanced Ads
* units array Holds the ad units of this network.
* vars map These are the variables that were transmitted from the underlying PHP class (method: append_javascript_data)
* hideIdle Remembers, wheter idle ads should be displayed in the list;
* fetchedExternalAds Remembers if the external ads list has already been loaded to prevent unneccesary requests
class AdvancedAdsAdNetwork {
* @param id string representing the id of this network. has to match the identifier of the PHP class
this.vars = window[ id + 'AdvancedAdsJS' ]
this.fetchedExternalAds = false
* will be called when an ad network is selected (ad type in edit ad)
console.error( 'Please override onSelected.' )
* will be called when an ad network deselected (ad type in edit ad)
console.error( 'Please override onBlur.' )
* opens the selector list containing the external ad units
console.error( 'Please override openSelector.' )
* returns the network specific id of the currently selected ad unit
console.error( 'Please override getSelectedId.' )
* will be called when an external ad unit has been selected from the selector list
* @param slotId string the external ad unit id
selectAdFromList ( slotId ) {
console.error( 'Please override selectAdFromList.' )
* will be called when an the update button of an external ad unit has been clicked
* TODO: decide wheter to remove this method. not required anymore - the button was removed.
* @param slotId string the external ad unit id
updateAdFromList ( slotId ) {
console.error( 'Please override updateAdFromList.' )
* return the POST params that you want to send to the server when requesting a refresh of the external ad units
* (like nonce and action and everything else that is required)
getRefreshAdsParameters () {
console.error( 'Please override getRefreshAdsParameters.' )
* return the jquery objects for all the custom html elements of this ad type
console.error( 'Please override getCustomInputs.' )
* what to do when the DOM is ready
console.error( 'Please override onDomReady.' )
* when you need custom behaviour for ad networks that support manual setup of ad units, override this method
//no console logging. this is optional
class AdvancedAdsExternalAdUnit {
* todo: this looks like something we could use in general, but where to put it?
jQuery( document ).ready( function () {
// delete an existing row by removing the parent tr tag
// todo: this could be moved to a general file
jQuery( document ).on( 'click', '.advads-tr-remove', function(){
jQuery( this ).closest( 'tr' ).remove();
* If the jQuery function `escapeSelector` does not exist (add in jQuery 3.0) then add it.
if ( typeof jQuery.escapeSelector === 'undefined' ) {
jQuery.escapeSelector = function ( selector ) {
// phpcs:ignore WordPress.WhiteSpace.OperatorSpacing.NoSpaceBefore,WordPress.WhiteSpace.OperatorSpacing.NoSpaceAfter,WordPress.WhiteSpace.OperatorSpacing.NoSpaceBeforeAmp,WordPress.WhiteSpace.OperatorSpacing.NoSpaceAfterAmp -- PHPCS incorrectly reports whitespace errors for this regex
/([$%&()*+,./:;<=>?@\[\\\]^{|}~])/g,