Commit inicial - WordPress Análisis de Precios Unitarios

- WordPress core y plugins
- Tema Twenty Twenty-Four configurado
- Plugin allow-unfiltered-html.php simplificado
- .gitignore configurado para excluir wp-config.php y uploads

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-11-03 21:04:30 -06:00
commit a22573bf0b
24068 changed files with 4993111 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
window.advads_adblocker_image_data = [
'ad',
'bottom-ads',
'bottom_ad',
'logoads',
'movie',
'x28',
'x2x8',
'malwarebytes-banner',
'728x90',
'betindia',
'worldfirst-currencyconversion',
'ml',
'p2',
'clicktoplay',
'download_ad',
'301',
'banner',
'download-bukkake',
'ad2',
'advertise-img',
'bblogo',
'adtech',
'AppStateBanner',
'ads3',
'banner_member',
'adguard-banner',
'mad_ad',
'hdsale',
'porndude',
'1001505_banner',
'Q1-23-CD-Promo-Banner-A',
'500x100',
'300x250',
];

View File

@@ -0,0 +1,445 @@
/* eslint-disable no-unused-vars */
/* eslint-disable camelcase */
/*
* global js functions for Advanced Ads
*/
jQuery(document).ready(function () {
/**
* ADMIN NOTICES
*/
// close button
// .advads-notice-dismiss class can be used to add a custom close button (e.g., link)
jQuery(document).on(
'click',
'.advads-admin-notice .notice-dismiss, .advads-notice-dismiss',
function (event) {
event.preventDefault();
const messagebox = jQuery(this).parents('.advads-admin-notice');
if (messagebox.attr('data-notice') === undefined) return;
const query = {
action: 'advads-close-notice',
notice: messagebox.attr('data-notice'),
nonce: advadsglobal.ajax_nonce,
};
// send query
jQuery.post(ajaxurl, query, function (r) {
messagebox.fadeOut();
});
}
);
// hide notice for 7 days
jQuery(document).on(
'click',
'.advads-admin-notice .advads-notice-hide',
function () {
const messagebox = jQuery(this).parents('.advads-admin-notice');
if (messagebox.attr('data-notice') === undefined) return;
const query = {
action: 'advads-hide-notice',
notice: messagebox.attr('data-notice'),
nonce: advadsglobal.ajax_nonce,
};
// send query
jQuery.post(ajaxurl, query, function (r) {
messagebox.fadeOut();
});
}
);
// autoresponder button
jQuery('body').on('click', '.advads-notices-button-subscribe', function () {
if (this.dataset.notice === undefined) {
return;
}
const messageboxes = jQuery(this).parents('.advads-admin-notice');
if (!messageboxes.length) {
return;
}
const $messagebox = jQuery(messageboxes[0]);
jQuery('<span class="spinner advads-spinner"></span>').insertAfter(
this
);
const query = {
action: 'advads-subscribe-notice',
notice: this.dataset.notice,
nonce: advadsglobal.ajax_nonce,
};
// send and replace with server message
jQuery
.post(ajaxurl, query)
.success(function (response) {
$messagebox
.children('.advads-notice-box_wrapper')
.html('<p>' + response.data.message + '</p>');
$messagebox.addClass('notice-success notice');
})
.fail(function (response) {
$messagebox
.children('.advads-notice-box_wrapper')
.html('<p>' + response.responseJSON.data.message + '</p>');
$messagebox.addClass('notice-error notice');
})
.always(function () {
$messagebox.removeClass('notice-info');
});
});
/**
* Functions for Ad Health Notifications in the backend
*/
// hide button (adds item to "ignore" list)
jQuery(document).on('click', '.advads-ad-health-notice-hide', function () {
const notice = jQuery(this).parents('li');
if (notice.attr('data-notice') === undefined) return;
// var list = notice.parent( 'ul' );
const remove = jQuery(this).hasClass('remove');
// fix height to prevent the box from going smaller first, then show the "show" link and grow again
const notice_box = jQuery('#advads_overview_notices');
notice_box.css('height', notice_box.height() + 'px');
const query = {
action: 'advads-ad-health-notice-hide',
notice: notice.attr('data-notice'),
nonce: advadsglobal.ajax_nonce,
};
// fade out first or remove, so users cant click twice
if (remove) {
notice.remove();
} else {
notice.hide();
}
// show loader
notice_box.find('.advads-loader').show();
advads_ad_health_maybe_remove_list();
// send query
jQuery.post(ajaxurl, query, function (r) {
// update number in menu
advads_ad_health_reload_number_in_menu();
// update show button
advads_ad_health_reload_show_link();
// remove the fixed height
jQuery('#advads_overview_notices').css('height', '');
// remove loader
notice_box.find('.advads-loader').hide();
});
});
// show all hidden notices
jQuery(document).on(
'click',
'.advads-ad-health-notices-show-hidden',
function () {
advads_ad_health_show_hidden();
}
);
/**
* DEACTIVATION FEEDBACK FORM
*/
// show overlay when clicked on "deactivate"
const advads_deactivate_link = jQuery(
'.wp-admin.plugins-php tr[data-slug="advanced-ads"] .row-actions .deactivate a'
);
const advads_deactivate_link_url = advads_deactivate_link.attr('href');
advads_deactivate_link.on('click', function (e) {
e.preventDefault();
// only show feedback form once per 30 days
const c_value = advads_admin_get_cookie(
'advanced_ads_hide_deactivate_feedback'
);
if (c_value === undefined) {
jQuery('#advanced-ads-feedback-overlay').show();
} else {
// click on the link
window.location.href = advads_deactivate_link_url;
}
});
// show text fields
jQuery('#advanced-ads-feedback-content input[type="radio"]').on(
'click',
function () {
// show text field if there is one
jQuery(this)
.parents('li')
.next('li')
.children('input[type="text"], textarea')
.show();
}
);
// handle technical issue feedback in particular
jQuery('#advanced-ads-feedback-content .advanced_ads_disable_help_text').on(
'focus',
function () {
// show text field if there is one
jQuery(this)
.parents('li')
.siblings('.advanced_ads_disable_reply')
.show();
}
);
// send form or close it
jQuery('#advanced-ads-feedback-content .button').on('click', function (e) {
e.preventDefault();
const self = jQuery(this);
// set cookie for 30 days
advads_store_feedback_cookie();
// save if plugin should be disabled
const disable_plugin = self.hasClass(
'advanced-ads-feedback-not-deactivate'
)
? false
: true;
// hide the content of the feedback form
jQuery('#advanced-ads-feedback-content form').hide();
if (self.hasClass('advanced-ads-feedback-submit')) {
// show feedback message
jQuery('#advanced-ads-feedback-after-submit-waiting').show();
if (disable_plugin) {
jQuery(
'#advanced-ads-feedback-after-submit-disabling-plugin'
).show();
}
jQuery.ajax({
type: 'POST',
url: ajaxurl,
dataType: 'json',
data: {
action: 'advads_send_feedback',
feedback: self.hasClass(
'advanced-ads-feedback-not-deactivate'
)
? true
: false,
formdata: jQuery(
'#advanced-ads-feedback-content form'
).serialize(),
},
complete(MLHttpRequest, textStatus, errorThrown) {
// deactivate the plugin and close the popup with a timeout
setTimeout(function () {
jQuery('#advanced-ads-feedback-overlay').remove();
}, 2000);
if (disable_plugin) {
window.location.href = advads_deactivate_link_url;
}
},
});
} else {
// currently not reachable
jQuery('#advanced-ads-feedback-overlay').remove();
window.location.href = advads_deactivate_link_url;
}
});
// close form and disable the plugin without doing anything
jQuery('.advanced-ads-feedback-only-deactivate').on('click', function () {
// hide the content of the feedback form
jQuery('#advanced-ads-feedback-content form').hide();
// show feedback message
jQuery('#advanced-ads-feedback-after-submit-goodbye').show();
jQuery('#advanced-ads-feedback-after-submit-disabling-plugin').show();
// set cookie for 30 days
advads_store_feedback_cookie();
// wait one second
setTimeout(function () {
jQuery('#advanced-ads-feedback-overlay').hide();
window.location.href = advads_deactivate_link_url;
}, 1000);
});
// close button for feedback form
jQuery('#advanced-ads-feedback-overlay-close-button').on(
'click',
function () {
jQuery('#advanced-ads-feedback-overlay').hide();
}
);
jQuery('.advads-help').on('mouseenter', function (event) {
const tooltip = jQuery(event.target).children('.advads-tooltip')[0];
if (typeof tooltip === 'undefined') {
return;
}
// reset inline styles before getting bounding client rect.
tooltip.style.position = '';
tooltip.style.left = '';
tooltip.style.top = '';
const topParentRect = document
.getElementById('wpbody')
.getBoundingClientRect(),
helpRect = event.target.getBoundingClientRect(),
offsets = {
left: Math.ceil(helpRect.left) + 13,
top: Math.ceil(helpRect.top) + 13,
};
let tooltipRect = tooltip.getBoundingClientRect();
tooltip.style.position = 'fixed';
tooltip.style.left = offsets.left + 'px';
tooltip.style.top = offsets.top + 'px';
// check element is not overflowing to the right.
while (tooltipRect.right > topParentRect.right - 20) {
offsets.left -= 10;
tooltip.style.left = offsets.left + 'px';
tooltipRect = tooltip.getBoundingClientRect();
}
// check element is not overflowing bottom of parent and is within viewport.
while (tooltipRect.bottom > Math.min(topParentRect.bottom, jQuery(window).height()) - 20) {
offsets.top -= 10;
tooltip.style.top = offsets.top + 'px';
tooltipRect = tooltip.getBoundingClientRect();
}
});
});
// remove duplicate close buttons
jQuery(window).on('load', function () {
jQuery('a.notice-dismiss').next('button.notice-dismiss').remove();
});
function advads_admin_get_cookie(name) {
let i, x, y;
const 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, '');
if (x === name) {
return unescape(y);
}
}
}
/**
* Store a cookie for 30 days
* The cookie prevents the feedback form from showing multiple times
*/
function advads_store_feedback_cookie() {
const exdate = new Date();
exdate.setSeconds(exdate.getSeconds() + 2592000);
document.cookie =
'advanced_ads_hide_deactivate_feedback=1; expires=' +
exdate.toUTCString() +
'; path=/';
}
/**
* Ad Health Notices in backend
*/
// display notices list (deprecated because we load it without AJAX now)
function advads_display_ad_health_notices() {
const query = {
action: 'advads-ad-health-notice-display',
nonce: advadsglobal.ajax_nonce,
};
const widget = jQuery('#advads_overview_notices .main');
// add loader icon to the widget
widget.html('<span class="advads-loader"></span>');
// send query
jQuery.post(ajaxurl, query, function (r) {
widget.html(r);
// update number in menu
advads_ad_health_reload_number_in_menu();
// update list headlines
advads_ad_health_maybe_remove_list();
// remove widget, if return is empty
if (r === '') {
jQuery('#advads_overview_notices').remove();
}
});
}
// push a notice to the queue
function advads_push_notice(key, attr = '') {
const query = {
action: 'advads-ad-health-notice-push-adminui',
key,
attr,
nonce: advadsglobal.ajax_nonce,
};
// send query
jQuery.post(ajaxurl, query, function (r) {});
}
// show notices of a given type again
function advads_ad_health_show_hidden() {
const notice_box = jQuery('#advads__overview_notices');
const query = {
action: 'advads-ad-health-notice-unignore',
nonce: advadsglobal.ajax_nonce,
};
// show all hidden
jQuery(document)
.find('#advads_overview_notices .advads-ad-health-notices > li:hidden')
.show();
// show loader
notice_box.find('.advads-loader').show();
// update the button
advads_ad_health_reload_show_link();
advads_ad_health_maybe_remove_list();
// send query
jQuery.post(ajaxurl, query, function (r) {
// update issue count
advads_ad_health_reload_number_in_menu();
// hide loader
notice_box.find('.advads-loader').hide();
});
}
// hide list fragments if last item was hidden/removed
function advads_ad_health_maybe_remove_list() {
// get all lists
const lists = jQuery(document).find(
'#advads_overview_notices .advads-ad-health-notices'
);
// check each list separately
lists.each(function (index) {
const list = jQuery(this);
// check if there are visible items in the list
if (list.find('li:visible').length) {
// show parent headline
list.prev('h3').show();
} else {
// hide parent headline
list.prev('h3').hide();
}
});
}
// reload number of notices shown in the sidebar based on element in the problems list
function advads_ad_health_reload_number_in_menu() {
// get number of notices
const number = jQuery(document).find(
'#advads_overview_notices .advads-ad-health-notices > li:visible'
).length;
jQuery('#toplevel_page_advanced-ads .update-count').html(number);
}
// update show X issues link number and visibility
function advads_ad_health_reload_show_link() {
// get number of invisible elements
const number = jQuery(document).find(
'#advads_overview_notices .advads-ad-health-notices > li:hidden'
).length;
const show_link = jQuery('.advads-ad-health-notices-show-hidden');
// update number in the link
jQuery('.advads-ad-health-notices-show-hidden .count').html(number);
// hide of show, depending on number
if (0 === number) {
show_link.hide();
} else {
show_link.show();
}
}
//Radio Toggle visibility
function toggle_visibility(currentElement, toggleElement) {
jQuery(toggleElement).toggle(jQuery(currentElement).val() === 'on');
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
var advanced_ads_adblocker_test = true;

View File

@@ -0,0 +1,534 @@
/**
* Logic for Display and Visitor Conditions forms
*/
jQuery(document).ready(function ($) {
/**
* Pressing the button to add a new condition to the list of conditions
*/
$('.advads-conditions-new select').on('change', function () {
// get the form fieldset and values.
const condition_form_container = $(this).parents('fieldset');
const condition_type = condition_form_container
.find('.advads-conditions-new select')
.val();
const condition_title = condition_form_container
.find('.advads-conditions-new select option:selected')
.text();
let condition_index = parseInt(
condition_form_container.find('.advads-conditions-index').val()
);
const condition_list_target_ID = $.escapeSelector(
condition_form_container.data('condition-list-target')
); // ID of the container into which the new condition is loaded.
const condition_list_target = $('#' + condition_list_target_ID); // container into which the new condition is loaded.
const conditions_form_name = condition_form_container.data(
'condition-form-name'
); // name prefix for the form.
const conditions_connector_default = condition_form_container.data(
'condition-connector-default'
); // default connector option.
const conditions_action =
condition_form_container.data('condition-action'); // action to which to send the AJAX call to.
if (!condition_type || '' == condition_type) {
return;
}
condition_form_container.find('.advads-loader').show(); // show loader.
$.ajax({
type: 'POST',
url: ajaxurl,
data: {
action: conditions_action,
type: condition_type,
index: condition_index,
form_name: conditions_form_name,
nonce: advadsglobal.ajax_nonce,
},
success(r, textStatus, XMLHttpRequest) {
// add.
if (r) {
if ('or' === conditions_connector_default) {
// as used for display conditions.
var connector =
'<input style="display:none;" type="checkbox" name="' +
conditions_form_name +
'[' +
condition_index +
'][connector]" checked="checked" value="or" id="advads-conditions-' +
condition_list_target_ID +
'-' +
condition_index +
'-connector"><label for="advads-conditions-' +
condition_list_target_ID +
'-' +
condition_index +
'-connector">' +
advadstxt.condition_or +
'</label>';
var newline =
'<tr class="advads-conditions-connector advads-conditions-connector-or"><td colspan="3">' +
connector +
'</td></tr><tr><td class="advads-conditions-type" data-condition-type="' +
condition_type +
'">' +
condition_title +
'</td><td>' +
r +
'</td><td><button type="button" class="advads-conditions-remove button">x</button></td></tr>';
} else {
// as used for visitor conditions.
var connector =
'<input type="checkbox" name="' +
conditions_form_name +
'[' +
condition_index +
'][connector]" value="or" id="advads-conditions-' +
condition_list_target_ID +
'-' +
condition_index +
'-connector"><label for="advads-conditions-' +
condition_list_target_ID +
'-' +
condition_index +
'-connector">' +
advadstxt.condition_and +
'</label>';
var newline =
'<tr class="advads-conditions-connector advads-conditions-connector-and"><td colspan="3">' +
connector +
'</td></tr><tr><td class="advads-conditions-type" data-condition-type="' +
condition_type +
'">' +
condition_title +
'</td><td>' +
r +
'</td><td><button type="button" class="advads-conditions-remove button">x</button></td></tr>';
}
condition_list_target.find('tbody').append(newline);
condition_list_target
.find(
'tbody .advads-conditions-single.advads-buttonset'
)
.advads_buttonset();
condition_list_target
.find('tbody .advads-conditions-connector input')
.advads_button();
// increase count.
condition_index++;
condition_form_container
.find('.advads-conditions-index')
.val(condition_index);
// reset select.
condition_form_container.find(
'.advads-conditions-new select'
)[0].selectedIndex = 0;
advads_display_condition_option_not_selected();
const tr = $(this).parents('.advads-conditions-table tr');
condition_list_target.next('input').remove();
}
},
error(MLHttpRequest, textStatus, errorThrown) {
condition_form_container
.find('.advads-conditions-new')
.append(errorThrown);
},
complete(MLHttpRequest, textStatus) {
condition_form_container
.find('.advads-conditions-new .advads-loader')
.hide(); // hide loader.
},
});
});
// disable term in the term list of the appropriate condition by just clicking on it.
$(document).on(
'click',
'.advads-conditions-terms-buttons .button',
function (e) {
$(this).remove();
}
);
// display input field to search for terms.
$(document).on(
'click',
'.advads-conditions-terms-show-search',
function (e) {
e.preventDefault();
// display input field.
$(this).siblings('.advads-conditions-terms-search').show().focus();
// register autocomplete.
advads_register_terms_autocomplete(
$(this).siblings('.advads-conditions-terms-search')
);
$(this).next('br').show();
$(this).hide();
}
);
// function for autocomplete.
function advads_register_terms_autocomplete(self) {
self.autocomplete({
classes: {
'ui-autocomplete': 'advads-ui-autocomplete',
},
source(request, callback) {
// var searchField = request.term;
advads_term_search(self, callback);
},
minLength: 1,
select(event, ui) {
// append new line with input fields.
$(
'<label class="button advads-button advads-ui-state-active"><span class="advads-button-text">' +
ui.item.label +
'<input type="hidden" name="' +
self.data('inputName') +
'" value="' +
ui.item.value +
'"></span></label>'
).appendTo(self.siblings('.advads-conditions-terms-buttons'));
// show / hide other elements
// $( '.advads-display-conditions-individual-post' ).hide();
// $( '.advads-conditions-postids-list .show-search a' ).show();
},
// eslint-disable-next-line no-unused-vars
close(event, ui) {
self.val('');
},
});
}
// remove author from list by clicking on it.
$(document).on(
'click',
'.advads-conditions-authors-buttons .button',
function () {
$(this).remove();
}
);
// display input field to search for author.
$(document).on(
'click',
'.advads-conditions-authors-show-search',
function (e) {
e.preventDefault();
// display input field.
$(this)
.siblings('.advads-conditions-authors-search')
.show()
.focus();
// register autocomplete.
advadsRegisterAuthorAutocomplete(
$(this).siblings('.advads-conditions-authors-search')
);
$(this).next('br').show();
$(this).hide();
}
);
// author search box autocomplete.
function advadsRegisterAuthorAutocomplete(self) {
self.autocomplete({
classes: {
'ui-autocomplete': 'advads-ui-autocomplete',
},
source(request, callback) {
advadsAuthorSearch(self, callback);
},
minLength: 1,
select(event, ui) {
// append new line with input fields.
$(
'<label class="button advads-button advads-ui-state-active"><span class="advads-button-text">' +
ui.item.label +
'<input type="hidden" name="' +
self.data('inputName') +
'" value="' +
ui.item.value +
'"></span></label>'
).appendTo(self.siblings('.advads-conditions-authors-buttons'));
},
close() {
self.val('');
},
});
}
// display input field to search for post, page, etc.
$(document).on(
'click',
'.advads-conditions-postids-show-search',
function (e) {
e.preventDefault();
// display input field.
$(this)
.next()
.find('.advads-display-conditions-individual-post')
.show();
//$( '.advads-conditions-postids-search-line .description' ).hide();
$(this).hide();
}
);
// register autocomplete to display condition individual posts.
// eslint-disable-next-line no-unused-vars
$(document).on(
'focus',
'.advads-display-conditions-individual-post',
// eslint-disable-next-line no-unused-vars
function (e) {
const self = this;
if (!$(this).data('autocomplete')) {
// If the autocomplete wasn't called yet:
$(this)
.autocomplete({
classes: {
'ui-autocomplete': 'advads-ui-autocomplete',
},
source(request, callback) {
const searchParam = request.term;
advads_post_search(searchParam, callback);
},
minLength: 1,
select(event, ui) {
// append new line with input fields
const newline = $(
`<label class="button advads-button advads-ui-state-active"><span class="advads-button-text">${ui.item.label}</span></label>`
);
$(
`<input type="hidden" name="${self.dataset.fieldName}[value][]" value="${ui.item.value}"/>`
).appendTo(newline);
newline.insertBefore(
$(self).parent(
'.advads-conditions-postids-search-line'
)
);
},
// eslint-disable-next-line no-unused-vars
close(event, ui) {
$(self).val('');
},
})
.autocomplete()
.data('ui-autocomplete')._renderItem = function (ul, item) {
ul.addClass(
'advads-conditions-postids-autocomplete-suggestions'
);
return $('<li></li>')
.append(
"<span class='left'>" +
item.label +
"</span>&nbsp;<span class='right'>" +
item.info +
'</span>'
)
.appendTo(ul);
};
}
}
);
// remove individual posts from the display conditions post list.
$(document).on(
'click',
'.advads-conditions-postid-buttons .button',
// eslint-disable-next-line no-unused-vars
function (e) {
$(this).remove();
}
);
// display/hide error message if no option was selected
// is also called on every click.
function advads_display_condition_option_not_selected() {
$('.advads-conditions-not-selected').each(function () {
if ($(this).siblings('input:checked').length) {
$(this).hide();
} else {
$(this).show();
}
});
}
advads_display_condition_option_not_selected();
// update error messages when an item is clicked.
$(document).on(
'click',
'.advads-conditions-terms-buttons input[type="checkbox"], .advads-conditions-single input[type="checkbox"]',
function () {
// needs a slight delay until the buttons are updated.
window.setTimeout(
advads_display_condition_option_not_selected,
200
);
}
);
// activate and toggle conditions connector option.
$('.advads-conditions-connector input').advads_button();
// dynamically change label.
jQuery(document).on(
'click',
'.advads-conditions-connector input',
function () {
if (jQuery(this).is(':checked')) {
jQuery(this)
.next('label')
.find('span')
.html(advadstxt.condition_or);
jQuery(this)
.parents('.advads-conditions-connector')
.addClass('advads-conditions-connector-or')
.removeClass('advads-conditions-connector-and');
} else {
jQuery(this)
.next('label')
.find('span')
.html(advadstxt.condition_and);
jQuery(this)
.parents('.advads-conditions-connector')
.addClass('advads-conditions-connector-and')
.removeClass('advads-conditions-connector-or');
}
}
);
// remove a line with a display or visitor condition.
$(document).on('click', '.advads-conditions-remove', function () {
const tr = $(this).parents('.advads-conditions-table tr');
const table = $(this).closest('.advads-conditions-table');
tr.prev('tr').remove();
tr.remove();
if (table.find('tr').length === 0) {
const fieldset = table.next('fieldset');
table.after(
'<input type="hidden" name="' +
fieldset.data('condition-form-name') +
'[0][type]" value="unknown">'
);
}
});
});
/**
* Callback for term search autocomplete
*
* @param {type} search term
* @param field
* @param {type} callback
* @return {obj} json object with labels and values
*/
function advads_term_search(field, callback) {
// return ['post', 'poster'];
const query = {
action: 'advads-terms-search',
nonce: advadsglobal.ajax_nonce,
};
query.search = field.val();
query.tax = field.data('tagName');
let querying = true;
const results = {};
jQuery.post(
ajaxurl,
query,
function (r) {
querying = false;
const results = [];
if (r) {
r.map(function (element, index) {
results[index] = {
value: element.term_id,
label: element.name,
};
});
}
callback(results);
},
'json'
);
}
/**
* Callback for author search autocomplete
*
* @param {string} search author
* @param {HTMLInputElement} field html input field
* @param {Function} callback Callback function
* @return {Object} JSON object with labels and values
*/
function advadsAuthorSearch(field, callback) {
const query = {
action: 'advads-authors-search',
nonce: advadsglobal.ajax_nonce,
};
query.search = field.val();
let querying = true;
const results = [];
// eslint-disable-next-line no-undef
jQuery.post(
// eslint-disable-next-line no-undef
ajaxurl,
query,
function (r) {
querying = false;
if (r) {
r.map(function (element, index) {
results[index] = {
value: element.data.ID,
label: element.data.display_name,
};
});
}
callback(results);
},
'json'
);
}
/**
* Callback for post search autocomplete
*
* @param {str} searchParam
* @param {type} callback
* @return {obj} json object with labels and values
*/
function advads_post_search(searchParam, callback) {
// return ['post', 'poster'];
const query = {
action: 'advads-post-search',
_ajax_linking_nonce: jQuery('#_ajax_linking_nonce').val(),
search: searchParam,
nonce: advadsglobal.ajax_nonce,
};
let querying = true;
const results = {};
jQuery.post(
ajaxurl,
query,
function (r) {
querying = false;
const results = [];
if (r) {
// eslint-disable-next-line array-callback-return
r.map(function (element, index) {
results[index] = {
label: element.title,
value: element.ID,
info: element.info,
};
});
}
callback(results);
},
'json'
);
}

View File

@@ -0,0 +1,175 @@
// phpcs:disable Generic.WhiteSpace.ScopeIndent.IncorrectExact -- PHPCS can't handle es5 short functions
const modal = element => {
let targetForm;
/**
* Remove the pound sign from the location hash.
*
* @return {string}
*/
const getId = () => window.location.hash.replace( '#', '' );
const showModal = () => {
element.showModal();
element.dispatchEvent( new CustomEvent( 'advads-modal-opened' ) );
// Attach the termination object to the dialog node to allow other's code to plug in.
element.advadsTermination = new Advads_Termination( element );
if ( targetForm ) {
element.advadsTermination.collectValues();
}
};
/**
* If the current hash matches the modal id attribute, open it.
*/
const showIfHashMatches = () => {
if ( getId() === element.id ) {
showModal();
}
};
// Check whether to open modal on page load.
showIfHashMatches();
/**
* Listen to the hashchange event, to check if the current modal needs to be opened.
*/
window.addEventListener( 'hashchange', () => {
showIfHashMatches();
if ( getId() !== 'close' ) {
return;
}
if ( ! targetForm || element.advadsTermination.terminationNotice( true ) ) {
element.close();
}
} );
/**
* Attach a click listener to all links referencing this modal and prevent their default action.
* By changing the hash on every click, we also create a history entry.
*/
document.querySelectorAll( 'a[href$="#' + element.id + '"]' ).forEach( link => {
link.addEventListener( 'click', e => {
e.preventDefault();
showModal();
} );
} );
/**
* On the cancel event, check for termination notice and fire a custom event.
*/
element.addEventListener( 'cancel', event => {
event.preventDefault();
if ( ! targetForm ) {
element.close();
return;
}
if ( element.advadsTermination.terminationNotice( true ) ) {
element.close();
element.advadsTermination.observers.disconnect();
document.dispatchEvent( new CustomEvent( 'advads-modal-canceled', {
detail: {
modal_id: element.id
}
} ) );
}
} );
/**
* On the close event, i.e., a form got submit, empty the hash to prevent form from reopening.
*/
element.addEventListener( 'close', event => {
if ( getId() === element.id ) {
window.location.hash = '';
}
} );
// try if there is a form inside the modal, otherwise continue in catch.
targetForm = element.querySelector( 'form' );
if ( targetForm === null ) {
try {
targetForm = element.querySelector( 'button.advads-modal-close-action' ).form;
} catch ( e ) {
}
}
if ( targetForm ) {
/**
* Listen for the keydown event in all inputs.
* If the enter key is pressed and the modal has a form, submit it, else do nothing.
*/
element.querySelectorAll( 'input' ).forEach( input => {
input.addEventListener( 'keydown', e => {
if ( e.key !== 'Enter' ) {
return;
}
if ( targetForm.reportValidity() ) {
let submitForm = true;
if ( 'function' === typeof window[element.closeValidation.function] && ! window[element.closeValidation.function]( element.closeValidation.modal_id ) ) {
e.preventDefault();
return;
}
/**
* Allow other code to prevent the form submission (and send it using an AJAX call for instance).
*/
submitForm = wp.hooks.applyFilters( 'advanced-ads-submit-modal-form', true, targetForm, element.advadsTermination.initialFormValues, element.advadsTermination.changedFormValues );
if ( ! submitForm ) {
e.preventDefault();
return;
}
targetForm.submit();
}
// if there are inputs, but there is no form associated with them, do nothing.
e.preventDefault();
} );
} );
targetForm.addEventListener( 'submit', () => {
window.location.hash = '';
} );
}
/**
* On the cancel buttons, check termination notice and close the modal.
*/
element.querySelectorAll( '.advads-modal-close, .advads-modal-close-background' ).forEach( button => {
button.addEventListener( 'click', e => {
e.preventDefault();
element.dispatchEvent( new Event( 'cancel' ) );
} );
} );
try {
/**
* If the save button is not a `<button>` element. Close the form without changing the hash.
*/
element.querySelector( 'a.advads-modal-close-action' ).addEventListener( 'click', e => {
e.preventDefault();
element.close();
} );
} catch ( e ) {
}
};
window.addEventListener( 'DOMContentLoaded', () => {
try {
if ( typeof document.querySelector( '.advads-modal[id^=modal-]' ).showModal !== 'function' ) {
return;
}
} catch ( e ) {
return;
}
[...document.getElementsByClassName( 'advads-modal' )].forEach( modal );
} );

View File

@@ -0,0 +1,57 @@
jQuery(document).ready(function ($) {
function getCellValue(row, sortby, index) {
const $td = $(row).find('td');
if ('weight' === sortby) {
return parseInt($td.eq(index).find('select').val()) || 0;
}
if ('ad' === sortby) {
return $td.eq(index).find('a').text().trim();
}
return $td.eq(index).text().trim();
}
function sortAds(sortby, isAscending, table) {
const colIndex = $(table).find(`th[data-sortby=${sortby}]`).index();
const tbody = $(table).find('tbody');
const rows = tbody.find('tr').toArray();
rows.sort(function (a, b) {
const aValue = getCellValue(a, sortby, colIndex);
const bValue = getCellValue(b, sortby, colIndex);
if (isNaN(aValue) || isNaN(bValue)) {
return isAscending
? aValue.localeCompare(bValue)
: bValue.localeCompare(aValue);
}
return isAscending ? aValue - bValue : bValue - aValue;
});
tbody.append(rows);
$(table)
.find('th.group-sort')
.removeClass('asc desc')
.eq(colIndex)
.addClass(isAscending ? 'asc' : 'desc');
}
$('.advads-group-ads').each(function () {
const $this = $(this);
// eslint-disable-next-line prefer-const
let sortStates = {
ad: true,
status: true,
weight: true,
};
$this.find('th.group-sort').on('click', function () {
const sortby = $(this).data('sortby');
sortAds(sortby, sortStates[sortby], this.closest('table'));
sortStates[sortby] = !sortStates[sortby];
});
});
});

View File

@@ -0,0 +1,274 @@
// phpcs:disable Generic.WhiteSpace.ScopeIndent.IncorrectExact -- PHPCS can't handle es5 short functions
function Advads_Termination( element ) {
/**
* Function to reset the changed nodes to default values.
*
* @constructor
*/
function FormValues() {
this.addedNodes = [];
this.removedNodes = [];
};
this.initialFormValues = new FormValues();
this.changedFormValues = new FormValues();
const blocklist = [
'active_post_lock'
];
this.observers = {
list: [],
push: item => {
this.observers.list.push( item );
},
disconnect: () => {
this.observers.list.forEach( observer => {
observer.disconnect();
} );
this.observers.list = [];
}
};
/**
* Set an initial form value.
* Can be used e.g. when a field is updated after an AJAX call.
*
* @param {String} key The key of the value that should be changed in the initial form value array.
* @param {Node} input The input field node.
*
* @returns {void}
*/
this.setInitialValue = ( key, input ) => {
if ( ! input || ! input.value ) {
return;
}
this.initialFormValues[key] = input.value;
};
/**
* Collect input values.
* Checkboxes are true/false, unless they are part of a group.
* Radio buttons have a boolean value on the saved value, only the checked one will be collected.
*
* @param {FormValues} object
* @param {Node} input
* @return {FormValues}
*/
const collectInputValue = function ( object, input ) {
/**
* Collect checkbox group values.
* If there are multiple checkboxes with the same `nome` attribute, collect all values for this group.
*
* @param {NodeList} group Iterable of inputs with the same `name` attribute.
* @return {FormValues}
*/
const collectCheckboxGroup = ( group ) => {
object[group[0].name] = [];
group.forEach( input => {
if ( input.checked ) {
object[input.name].push( input.value );
}
} );
return object;
};
if ( input.type === 'checkbox' ) {
const checkboxGroup = element.querySelectorAll( '[name="' + input.name + '"]' );
if ( checkboxGroup.length > 1 ) {
return collectCheckboxGroup( checkboxGroup, input );
}
object[input.name] = input.checked;
return object;
}
// if a radio button is not checked, don't collect it.
if ( input.type === 'radio' && ! input.checked ) {
return object;
}
object[input.name] = input.value;
return object;
};
/**
* Setup a mutationobserver to check for added and removed form fields.
* This especially applies to conditions.
*
* @type {MutationObserver}
*/
const addedRemovedObserver = new MutationObserver( mutations => {
for ( const mutation of mutations ) {
for ( const removedNode of mutation.removedNodes ) {
const nodes = document.createTreeWalker( removedNode, NodeFilter.SHOW_ELEMENT );
while ( nodes.nextNode() ) {
if ( nodes.currentNode.tagName === 'INPUT' || nodes.currentNode.tagName === 'SELECT' ) {
const index = this.changedFormValues.addedNodes.indexOf( nodes.currentNode.name );
if ( index > - 1 ) {
this.changedFormValues.addedNodes.splice( index, 1 );
} else {
this.changedFormValues.removedNodes.push( nodes.currentNode.name );
}
}
}
}
for ( const addedNode of mutation.addedNodes ) {
if ( addedNode.nodeType === Node.TEXT_NODE ) {
continue;
}
const nodes = document.createTreeWalker( addedNode, NodeFilter.SHOW_ELEMENT );
while ( nodes.nextNode() ) {
if ( nodes.currentNode.tagName === 'INPUT' || nodes.currentNode.tagName === 'SELECT' ) {
if ( nodes.currentNode.name === '' ) {
continue;
}
this.changedFormValues.addedNodes.push( nodes.currentNode.name );
}
}
}
}
} );
// attach the mutation observer to the passed element.
addedRemovedObserver.observe( element, {childList: true, subtree: true} );
this.observers.push( addedRemovedObserver );
/**
* Check if there are inputs that have been changed and if their value is different.
*
* @param {Object} reference The initial values when the modal loaded, indexed by name attribute.
* @param {Object} changed The input values that were changed, indexed by name.
*
* @return {boolean}
*/
this.hasChanged = ( reference, changed ) => {
for ( const name in changed ) {
if ( ! reference.hasOwnProperty( name ) || reference[name].toString() !== changed[name].toString() ) {
return true;
}
}
return false;
};
/**
* If the modal is associated with a form and any values have changed, ask for confirmation to navigate away.
* Returns true if the user agrees with termination, false otherwise.
*
* @param {boolean} reload Whether to reload the page on added and removed nodes (needed for the modal). Default false.
*
* @return {boolean}
*/
this.terminationNotice = ( reload = false ) => {
if ( ! this.hasChanged( this.initialFormValues, this.changedFormValues ) ) {
return true;
}
// ask user for confirmation.
if ( window.confirm( window.advadstxt.confirmation ) ) {
// if we have added or removed nodes, we might need to reload the page.
if ( this.changedFormValues.addedNodes.length || this.changedFormValues.removedNodes.length ) {
if ( reload ) {
window.location.reload();
}
return true;
}
// otherwise, we'll replace the values with the previous values.
for ( const name in this.changedFormValues ) {
const input = element.querySelector( '[name="' + name + '"]' );
if ( input === null ) {
continue;
}
if ( input.type === 'checkbox' ) {
input.checked = this.initialFormValues[name];
} else if ( input.type === 'radio' ) {
let value = (this.initialFormValues[name] !== null && this.initialFormValues[name] !== undefined) ? this.initialFormValues[name] : input.value;
element.querySelector( '[name="' + name + '"][value="' + value + '"]' ).checked = true;
} else {
input.value = this.initialFormValues[name];
}
}
return true;
}
return false;
};
/**
* Set the initial values to the current ones, then reset the changed form values
*/
this.resetInitialValues = () => {
if ( this.changedFormValues.addedNodes.length ) {
for ( const name in this.changedFormValues.addedNodes ) {
this.initialFormValues[name] = this.changedFormValues.addedNodes[name];
}
}
if ( this.changedFormValues.removedNodes.length ) {
for ( const name in this.changedFormValues.removedNodes ) {
if ( this.initialFormValues[name] !== undefined ) {
delete ( this.initialFormValues[name] );
}
}
}
for ( const name in this.changedFormValues ) {
if ( 'removedNodes' === name || 'addedNodes' === name ) {
continue;
}
if ( this.initialFormValues[name] !== undefined ) {
this.initialFormValues[name] = this.changedFormValues[name];
}
}
this.changedFormValues = new FormValues();
};
/**
* Collect inputs in this modal and save their initial and changed values (if any).
*/
this.collectValues = () => {
const isDialog = element.tagName === 'DIALOG';
element.querySelectorAll( 'input, select, textarea' ).forEach( input => {
if ( ! input.name.length || blocklist.includes( input.id ) || blocklist.includes( input.name ) ) {
return;
}
// if the element itself is not a dialog but the input is within a dialog, ignore it. This accounts for split forms, e.g. the placements page where some inputs are hidden in a modal dialog.
if ( ! isDialog && input.closest( 'dialog' ) ) {
return;
}
this.initialFormValues = collectInputValue( this.initialFormValues, input );
// if the input is `hidden` no change event gets triggered. Use MutationObservers to check for changes in the value attribute.
if ( input.type === 'hidden' ) {
const hiddenObserver = new MutationObserver( function ( mutations, observer ) {
mutations.forEach( mutation => {
if ( mutation.attributeName === 'value' ) {
mutation.target.dispatchEvent( new Event( 'input' ) );
}
} );
} );
hiddenObserver.observe( element, {
attributes: true,
subtree: true
} );
this.observers.push( hiddenObserver );
}
input.addEventListener( 'input', event => {
this.changedFormValues = collectInputValue( this.changedFormValues, input );
} );
} );
};
};

View File

@@ -0,0 +1,150 @@
(function ( $ ) {
/**
* Button.
*/
$.fn.advads_button = function() {
var $buttonset = jQuery( this );
var $ancestor = $buttonset.parent();
$buttonset.each( function() {
$this = jQuery( this );
if ( $this.data( 'advads_button' ) ) {
return true;
}
$this.data( 'advads_button', true );
var $button = jQuery( this );
var $label = jQuery( 'label[for="' + $button.attr( 'id' ) + '"]', $ancestor );
var type = $button.attr( 'type' );
$button.addClass( 'advads-accessible' );
$label.addClass( 'advads-button' );
$label.wrapInner( '<span class="advads-button-text"></span>' );
if ( $button.is( ':checked' ) ) {
$label.addClass( 'advads-ui-state-active' );
}
$button.on('change', function() {
var $changed = jQuery( this );
var $label = jQuery( 'label[for="' + $changed.attr( 'id' ) + '"]', $ancestor );
if ( type === 'radio' ) {
$ancestor.find( 'label' ).removeClass( 'advads-ui-state-active' );
}
if ( $changed.is( ':checked' ) ) {
$label.addClass( 'advads-ui-state-active' );
} else {
$label.removeClass( 'advads-ui-state-active' );
}
} );
} );
};
/**
* Buttonset.
*/
$.fn.advads_buttonset = function() {
var $that = jQuery( this );
$that.each( function() {
$buttonset = jQuery( this );
if ( $buttonset.data( 'advads_buttonset' ) ) {
return true;
}
$buttonset.data( 'advads_buttonset', true );
var items = 'input[type=checkbox], input[type=radio]';
var $all_buttons = $buttonset.find( items );
if ( ! $all_buttons.length ) {
return;
}
// Show selected checkboxes first.
if ( jQuery.escapeSelector ) {
$items = jQuery();
$all_buttons.filter( ':checked' ).each( function() {
$items = $items.add( $buttonset.find( 'label[for="' + jQuery.escapeSelector( this.id ) + '"]' ) );
$items = $items.add( this );
} );
$items.prependTo( $buttonset );
}
$buttonset.addClass( 'advads-buttonset' );
$all_buttons.advads_button();
} );
};
/**
* Tooltip.
*
* @param {Function} options.content A function that returns the content.
*/
$.fn.advads_tooltip = function( options ) {
var tooltip;
var tooltip_target;
if ( ! options.content ) {
return this;
}
function open( event ) {
var $target = jQuery( event.currentTarget );
// check if the correct tooltip is already open.
if ( tooltip && $target.is( tooltip_target ) ) {
return;
}
if ( tooltip ) {
tooltip.remove();
tooltip = null;
tooltip_target = null;
}
if ( event.type === 'mouseover' ) {
jQuery( $target ).on( 'mouseleave', close );
}
if ( event.type === 'focusin' ) {
jQuery( $target ).on( 'focusout', close );
}
var content = options.content.call( $target )
if ( content ) {
tooltip = $( '<div>' ).addClass( 'advads-tooltip' );
const parent = typeof options.parent === 'function' ? options.parent.call( this, $target ) : 'body';
$( '<div>' ).addClass( 'advads-tooltip-content' ).appendTo( tooltip );
tooltip.appendTo( parent );
tooltip.find( '.advads-tooltip-content' ).html( content );
position = $target.offset();
position.top += $target.outerHeight() + 15;
tooltip.offset( position );
tooltip_target = $target;
tooltip.show();
}
}
function close( event ) {
if ( tooltip ) {
tooltip.remove();
tooltip = null;
tooltip_target = null;
}
};
this.each( function() {
$this = jQuery( this );
if ( $this.data( 'advads_tooltip' ) ) {
return true;
}
$this.data( 'advads_tooltip', true );
$this.on( 'mouseover focusin', open );
} );
};
} )( jQuery );

View File

@@ -0,0 +1,213 @@
/* eslint-disable camelcase */
const advads_wizard = {
box_order: [
// selectors of elements in the wizard in the correct order
'#post-body-content, #ad-types-box', // show title and type together
'#ad-parameters-box',
'#ad-targeting-box', // display and visitor conditions
],
current_box: '#post-body-content, #ad-types-box', // current active box
one_column: false, // whether the edit screen is in one-column mode
status: false, // what is the current status? true if running, else false
init() {
// status can be "start" to start wizard or nothing to not start it
const _this = this;
jQuery('#advads-wizard-controls-next').on('click', function () {
_this.next();
});
jQuery('#advads-wizard-controls-prev').on('click', function () {
_this.prev();
});
jQuery('#advads-wizard-controls-save').on('click', function (e) {
e.preventDefault();
jQuery('#publish').trigger('click');
}); // save ad
jQuery('#advads-wizard-display-conditions-show').on(
'click',
function () {
_this.show_conditions('#ad-targeting-box');
}
);
jQuery('#advads-wizard-visitor-conditions-show').on(
'click',
function () {
_this.show_conditions('#ad-targeting-box');
}
);
jQuery('.advads-show-in-wizard').hide();
jQuery('#advads-start-wizard').on('click', function () {
_this.start();
});
// end wizard when the button was clicked
jQuery('.advads-stop-wizard').on('click', function () {
_this.close();
});
// jump to next box when ad type is selected
jQuery('#advanced-ad-type input').on('change', function () {
_this.next();
});
},
show_current_box() {
jQuery(this.current_box).removeClass('advads-hide');
},
start() {
// do stuff when wizard is started
if (!this.is_form_valid()) {
return;
}
// show page in 1-column stype
this.status = true;
if (jQuery('#post-body').hasClass('columns-1')) {
this.one_column = true;
} else {
jQuery('#post-body').addClass('columns-1').removeClass('columns-2');
}
// hide all boxes, messages and the headline by adding a hide css class
jQuery(
'#post-body-content, .postbox-container .postbox, h1 ~ div:not(.advads-admin-notice):not(#message.updated), h1'
).addClass('advads-hide');
// display first box
this.show_current_box();
// display close button and controls
jQuery('#advads-stop-wizard, #advads-wizard-controls').removeClass(
'hidden'
);
this.update_nav();
// initially hide some elemente
jQuery('#advads-ad-description').addClass('advads-hide'); // ad description
jQuery('#advads-ad-info').addClass('advads-hide'); // shortcode and php function info
// hide all elements with 'advads-hide-for-wizard' class
jQuery('.advads-hide-in-wizard').hide();
jQuery('.advads-show-in-wizard').show();
jQuery('#advads-start-wizard').hide();
// remove close-class from ad type box
jQuery('#ad-types-box').removeClass('closed');
this.save_hide_wizard(false);
},
close() {
// close the wizard by showing all elements again
this.status = false;
jQuery('.advads-hide').removeClass('advads-hide');
jQuery('#advads-stop-wizard, #advads-wizard-controls').addClass(
'hidden'
);
if (this.one_column !== true) {
jQuery('#post-body').addClass('columns-2').removeClass('columns-1');
}
// reset current box
this.current_box = this.box_order[0];
jQuery('#advads-wizard-welcome').remove(); // close wizard welcome message
// show all elements with 'advads-hide-for-wizard' class
jQuery('.advads-hide-in-wizard').show();
jQuery('.advads-show-in-wizard').hide();
jQuery('#advads-start-wizard').show();
this.save_hide_wizard(true);
},
update_nav() {
// update navigation, display only valid buttons
// display all buttons
jQuery('#advads-wizard-controls button').removeClass('hidden');
// hide next button if there is no next widget
const i = this.box_order.indexOf(this.current_box);
if (i === this.box_order.length - 1) {
jQuery('#advads-wizard-controls-next').addClass('hidden');
}
if (i === 0) {
jQuery('#advads-wizard-controls-prev').addClass('hidden');
}
// hide save button for first boxes
if (i <= 1) {
jQuery('#advads-wizard-controls-save').addClass('hidden');
} else {
jQuery('#advads-wizard-controls-save').removeClass('hidden');
}
},
/**
* Check the form just before some of its fields become hidden.
*/
is_form_valid() {
const form = jQuery('form#post')[0];
if (form.checkValidity && form.reportValidity) {
if (!form.checkValidity()) {
// Highlight invalid fields.
form.reportValidity();
return false;
}
return true;
}
// Disable validation so that hidden invalid fields do not prevent the form from being sent.
form.setAttribute('novalidate', true);
return true;
},
next() {
// show next box
if (!this.is_form_valid()) {
return;
}
if (!this.status) {
return;
}
// get index of current item in box-array
const i = this.box_order.indexOf(this.current_box);
// check if there is a next index
if (this.box_order[i + 1] === undefined) {
return;
}
// hide current element
jQuery(this.current_box).addClass('advads-hide');
// load next element into current
this.current_box = this.box_order[i + 1];
this.show_current_box();
this.update_nav();
},
prev() {
// show previous box
if (!this.is_form_valid()) {
return;
}
// get index of current item in box-array
const i = this.box_order.indexOf(this.current_box);
// check if there is a previous index
if (this.box_order[i - 1] === undefined) {
return;
}
// hide current element
jQuery(this.current_box).addClass('advads-hide');
// load next element into current
this.current_box = this.box_order[i - 1];
this.show_current_box();
this.update_nav();
},
save_hide_wizard(hideWizard) {
// update wizard state (started by default or not?)
jQuery.ajax({
type: 'POST',
url: ajaxurl,
data: {
action: 'advads-save-hide-wizard-state',
hideWizard,
nonce: advadsglobal.ajax_nonce,
},
});
},
show_conditions(box) {
// show the conditions options in display and visitor conditions
jQuery(box).find('.advads-show-in-wizard').hide();
jQuery(box).find('.advads-hide-in-wizard').show();
},
};
jQuery(document).ready(function () {
advads_wizard.init();
});