Address findings from security audit: wrap inline JSON.parse in try/catch to prevent consent flow failure on corrupted cookies, allowlist admin tab parameter, clamp consent_expiry server-side, escape all server values in admin JS table builder, fix focus trap listener cleanup, add aria-labelledby and banner focus for screen readers, skip frontend loading during AJAX. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
166 lines
5.0 KiB
JavaScript
166 lines
5.0 KiB
JavaScript
/* global jQuery, attCCAdmin */
|
|
(function($) {
|
|
'use strict';
|
|
|
|
$(function() {
|
|
// Initialize color pickers.
|
|
$('.att-cc-color-picker').wpColorPicker();
|
|
|
|
// Toggle gtag/GTM fields based on tracking mode.
|
|
var $trackingMode = $('#tracking_mode');
|
|
function toggleTrackingFields() {
|
|
var mode = $trackingMode.val();
|
|
$('.att-cc-gtag-row').toggle(mode === 'gtag');
|
|
$('.att-cc-gtm-row').toggle(mode === 'gtm');
|
|
}
|
|
if ($trackingMode.length) {
|
|
toggleTrackingFields();
|
|
$trackingMode.on('change', toggleTrackingFields);
|
|
}
|
|
|
|
// --- Custom Scripts CRUD ---
|
|
|
|
var $modal = $('#att-cc-script-modal');
|
|
var $form = $('#att-cc-script-form');
|
|
var $title = $('#att-cc-script-modal-title');
|
|
var $scriptId = $('#att-cc-script-id');
|
|
|
|
// Open modal for new script.
|
|
$('#att-cc-add-script').on('click', function() {
|
|
resetForm();
|
|
$title.text('Add Script');
|
|
$modal.show();
|
|
});
|
|
|
|
// Close modal.
|
|
$('.att-cc-close-modal, .att-cc-modal__overlay').on('click', function() {
|
|
$modal.hide();
|
|
});
|
|
|
|
// Escape key closes modal.
|
|
$(document).on('keydown', function(e) {
|
|
if (e.key === 'Escape' && $modal.is(':visible')) {
|
|
$modal.hide();
|
|
}
|
|
});
|
|
|
|
// Edit script.
|
|
$(document).on('click', '.att-cc-edit-script', function() {
|
|
var id = $(this).data('id');
|
|
$.post(attCCAdmin.ajaxUrl, {
|
|
action: 'att_cc_get_script',
|
|
nonce: attCCAdmin.nonce,
|
|
script_id: id,
|
|
}, function(response) {
|
|
if (response.success) {
|
|
var s = response.data;
|
|
$scriptId.val(s.id);
|
|
$('#att-cc-script-name').val(s.name);
|
|
$('#att-cc-script-category').val(s.category);
|
|
$('#att-cc-script-placement').val(s.placement);
|
|
$('#att-cc-script-priority').val(s.priority);
|
|
$('#att-cc-script-status').val(s.status);
|
|
$('#att-cc-script-snippet').val(s.snippet);
|
|
$title.text('Edit Script');
|
|
$modal.show();
|
|
}
|
|
});
|
|
});
|
|
|
|
// Delete script.
|
|
$(document).on('click', '.att-cc-delete-script', function() {
|
|
if (!confirm(attCCAdmin.strings.confirmDelete)) {
|
|
return;
|
|
}
|
|
var id = $(this).data('id');
|
|
$.post(attCCAdmin.ajaxUrl, {
|
|
action: 'att_cc_delete_script',
|
|
nonce: attCCAdmin.nonce,
|
|
script_id: id,
|
|
}, function(response) {
|
|
if (response.success) {
|
|
refreshScriptsTable(response.data.scripts);
|
|
} else {
|
|
alert(attCCAdmin.strings.error);
|
|
}
|
|
});
|
|
});
|
|
|
|
// Save script (form submit).
|
|
$form.on('submit', function(e) {
|
|
e.preventDefault();
|
|
|
|
var data = {
|
|
action: 'att_cc_save_script',
|
|
nonce: attCCAdmin.nonce,
|
|
script_id: $scriptId.val(),
|
|
name: $('#att-cc-script-name').val(),
|
|
snippet: $('#att-cc-script-snippet').val(),
|
|
category: $('#att-cc-script-category').val(),
|
|
placement: $('#att-cc-script-placement').val(),
|
|
status: $('#att-cc-script-status').val(),
|
|
priority: $('#att-cc-script-priority').val(),
|
|
};
|
|
|
|
$.post(attCCAdmin.ajaxUrl, data, function(response) {
|
|
if (response.success) {
|
|
$modal.hide();
|
|
refreshScriptsTable(response.data.scripts);
|
|
} else {
|
|
alert(attCCAdmin.strings.error);
|
|
}
|
|
});
|
|
});
|
|
|
|
function resetForm() {
|
|
$scriptId.val('');
|
|
$('#att-cc-script-name').val('');
|
|
$('#att-cc-script-category').val('analytics');
|
|
$('#att-cc-script-placement').val('head');
|
|
$('#att-cc-script-priority').val('10');
|
|
$('#att-cc-script-status').val('active');
|
|
$('#att-cc-script-snippet').val('');
|
|
}
|
|
|
|
function refreshScriptsTable(scripts) {
|
|
var $tbody = $('#att-cc-scripts-list');
|
|
$tbody.empty();
|
|
|
|
if (!scripts || scripts.length === 0) {
|
|
$tbody.append('<tr class="att-cc-no-scripts"><td colspan="6">No custom scripts added yet.</td></tr>');
|
|
return;
|
|
}
|
|
|
|
scripts.forEach(function(s) {
|
|
var eCat = escapeHtml(s.category);
|
|
var eStatus = escapeHtml(s.status);
|
|
var ePlacement = escapeHtml(s.placement);
|
|
var ePriority = escapeHtml(String(s.priority));
|
|
var eId = escapeHtml(String(s.id));
|
|
var row = '<tr data-id="' + eId + '">' +
|
|
'<td class="column-name">' + escapeHtml(s.name) + '</td>' +
|
|
'<td class="column-category"><span class="att-cc-badge att-cc-badge--' + eCat + '">' + capitalize(eCat) + '</span></td>' +
|
|
'<td class="column-placement">' + capitalize(ePlacement) + '</td>' +
|
|
'<td class="column-priority">' + ePriority + '</td>' +
|
|
'<td class="column-status"><span class="att-cc-status att-cc-status--' + eStatus + '">' + capitalize(eStatus) + '</span></td>' +
|
|
'<td class="column-actions">' +
|
|
'<button type="button" class="button button-small att-cc-edit-script" data-id="' + eId + '">Edit</button> ' +
|
|
'<button type="button" class="button button-small button-link-delete att-cc-delete-script" data-id="' + eId + '">Delete</button>' +
|
|
'</td>' +
|
|
'</tr>';
|
|
$tbody.append(row);
|
|
});
|
|
}
|
|
|
|
function escapeHtml(text) {
|
|
var div = document.createElement('div');
|
|
div.appendChild(document.createTextNode(text));
|
|
return div.innerHTML;
|
|
}
|
|
|
|
function capitalize(str) {
|
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
}
|
|
});
|
|
})(jQuery);
|