(function ($) { 'use strict'; /** * All of the code for your admin-facing JavaScript source * should reside in this file. * * Note: It has been assumed you will write jQuery code here, so the * $ function reference has been prepared for usage within the scope * of this function. * * This enables you to define handlers, for when the DOM is ready: * * $(function() { * * }); * * When the window is loaded: * * $( window ).load(function() { * * }); * * ...and/or other possibilities. * * Ideally, it is not considered best practise to attach more than a * single DOM-ready or window-load handler for a particular page. * Although scripts in the WordPress core, Plugins and Themes may be * practising this, we should strive to set a better example in our own work. */ // ======================================== // UTILITY FUNCTIONS (Consolidated to reduce duplication) // ======================================== /** * Get plugin name from config or use default * @returns {string} Plugin name */ function getPluginName() { return window.MetasyncConfig && window.MetasyncConfig.pluginName ? window.MetasyncConfig.pluginName : 'Search Atlas'; } /** * Get OTTO name from config or use default * @returns {string} OTTO name */ function getOttoName() { return window.MetasyncConfig && window.MetasyncConfig.ottoName ? window.MetasyncConfig.ottoName : 'OTTO'; } /** * Update integration status indicator in header * @param {boolean} isIntegrated - Whether the integration is active * @param {string} statusText - Status text to display * @param {string} titleText - Tooltip text */ function updateHeaderStatus(isIntegrated, statusText, titleText) { var $statusIndicator = $('.metasync-integration-status'); if ($statusIndicator.length > 0) { $statusIndicator.removeClass('integrated not-integrated warning'); if (statusText === 'Warning') { $statusIndicator.addClass('warning'); } else if (isIntegrated) { $statusIndicator.addClass('integrated'); } else { $statusIndicator.addClass('not-integrated'); } $statusIndicator.find('.status-text').text(statusText); $statusIndicator.attr('title', titleText); console.log('π Updated header status to: ' + statusText); } // Keep compact header badge in sync with integration status var $badge = $('.metasync-status'); if ($badge.length > 0) { $badge.removeClass('connected disconnected warning'); if (isIntegrated) { $badge.addClass('connected'); $badge.find('.status-text').text('Connected'); } else if (statusText === 'Warning') { $badge.addClass('warning'); $badge.find('.status-text').text('Warning'); } else { $badge.addClass('disconnected'); $badge.find('.status-text').text('Not Connected'); } } // Immediately sync admin bar toolbar status var $adminBarContainer = $('#wp-admin-bar-searchatlas-status'); var $adminBarItem = $adminBarContainer.find('.ab-item'); if ($adminBarItem.length > 0) { var allClasses = 'searchatlas-synced searchatlas-not-synced searchatlas-warning'; var pluginName = (window.MetasyncConfig && window.MetasyncConfig.pluginName) || 'SearchAtlas'; var targetEmoji, targetSvgCode, barClass, barTitle; if (isIntegrated) { targetEmoji = '\uD83D\uDFE2'; targetSvgCode = '1f7e2'; barClass = 'searchatlas-synced'; barTitle = pluginName + ' - Synced'; } else if (statusText === 'Warning') { targetEmoji = '\uD83D\uDFE1'; targetSvgCode = '1f7e1'; barClass = 'searchatlas-warning'; barTitle = pluginName + ' - ' + titleText; } else { targetEmoji = '\uD83D\uDD34'; targetSvgCode = '1f534'; barClass = 'searchatlas-not-synced'; barTitle = pluginName + ' - ' + (titleText || 'Not Synced'); } // Update emoji (SVG image or text fallback) var emojiImg = $adminBarItem.find('img.emoji'); if (emojiImg.length > 0) { emojiImg.attr('alt', targetEmoji); emojiImg.attr('src', emojiImg.attr('src').replace(/1f7e2\.svg|1f534\.svg|1f7e1\.svg/, targetSvgCode + '.svg')); } else { var newHtml = $adminBarItem.html().replace(/\uD83D\uDFE2|\uD83D\uDD34|\uD83D\uDFE1/, targetEmoji); if (!newHtml.includes(targetEmoji) && newHtml.includes(pluginName)) { newHtml = newHtml.replace(pluginName, pluginName + ' ' + targetEmoji); } $adminBarItem.html(newHtml); } $adminBarContainer.removeClass(allClasses).addClass(barClass); $adminBarContainer.attr('title', barTitle); $adminBarItem.attr('title', barTitle); } } /** * Collect whitelabel form fields for submission * @returns {string} Serialized whitelabel field data */ function collectWhitelabelFields() { var whitelabelFields = []; // Text/URL fields var logoField = $('input[name="metasync_options[whitelabel][logo]"]'); var domainField = $('input[name="metasync_options[whitelabel][domain]"]'); var passwordField = $('input[name="metasync_options[whitelabel][settings_password]"]'); if (logoField.length > 0 && logoField.val()) { whitelabelFields.push('metasync_options[whitelabel][logo]=' + encodeURIComponent(logoField.val())); } if (domainField.length > 0 && domainField.val()) { whitelabelFields.push('metasync_options[whitelabel][domain]=' + encodeURIComponent(domainField.val())); } if (passwordField.length > 0 && passwordField.val()) { whitelabelFields.push('metasync_options[whitelabel][settings_password]=' + encodeURIComponent(passwordField.val())); } // Checkbox fields (handle both checked and unchecked) var hideFields = ['hide_dashboard', 'hide_settings', 'hide_indexation_control', 'hide_redirections', 'hide_robots', 'hide_sync_log', 'hide_compatibility', 'hide_advanced']; hideFields.forEach(function (fieldName) { var checkbox = $('input[name="metasync_options[whitelabel][' + fieldName + ']"]'); if (checkbox.length > 0) { var value = checkbox.is(':checked') ? '1' : '0'; whitelabelFields.push('metasync_options[whitelabel][' + fieldName + ']=' + value); } }); return whitelabelFields.join('&'); } /** * Display notice message in plugin area * @param {string} type - Notice type: 'success' or 'error' * @param {string} title - Notice title * @param {string} message - Notice message * @param {string} cssClass - Additional CSS class for the notice * @param {number} autoHideDelay - Auto-hide delay in ms (0 = no auto-hide) */ function showPluginNotice(type, title, message, cssClass, autoHideDelay) { cssClass = cssClass || 'metasync-notice'; autoHideDelay = autoHideDelay || 0; var noticeClass = type === 'success' ? 'notice-success' : 'notice-error'; var noticeHTML = '
' + title + '
' + message + '
Chrome/Edge:
Firefox:
Safari:
Unable to load the dashboard. Please check your connection.
' + '' + 'This data has been permanently removed. You can safely reconnect with a new or existing ' + getPluginName() + ' account.
').text(message)); } // Insert error notice in plugin area var $navWrapper = $('.metasync-nav-wrapper'); if ($navWrapper.length > 0) { $navWrapper.after($errorNotice); } else { // Fallback: insert at top of plugin content area $('.metasync-dashboard-wrap').prepend($errorNotice); } // Scroll to the error message for better visibility $('html, body').animate({ scrollTop: 0 }, 'slow'); setTimeout(function () { $('.metasync-error-wrap').fadeOut(300, function () { $(this).remove(); }); }, 5000); } isSaving = false; }, error: function (xhr, status, error) { // Handle AJAX error var errorMessage = 'There was an error saving the settings. Please try again.'; if (xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message) { errorMessage = xhr.responseJSON.data.message; } var ajaxErrorNotice = '
'; // Insert between navigation menu and page content var $navWrapper = $('.metasync-nav-wrapper'); if ($navWrapper.length > 0) { // Position after navigation menu but before first dashboard card or form $navWrapper.after(ajaxErrorNotice); } else { // Fallback: insert at top of settings page $('.metasync-dashboard-wrap').prepend(ajaxErrorNotice); } // Scroll to the error message for better visibility $('html, body').animate({ scrollTop: 0 }, 'slow'); setTimeout(function () { $('.metasync-ajax-error').fadeOut(300, function () { $(this).remove(); }); }, 5000); isSaving = false; } }); } }; // Enhanced beforeunload message (disabled when saving) var isSaving = false; $(window).on('beforeunload', function (e) { if (hasUnsavedChanges && !isSaving) { var message = 'π You have unsaved changes in MetaSync settings that will be lost if you leave this page.'; e.returnValue = message; // For older browsers return message; } }); // Initialize the detection when page loads setTimeout(initializeUnsavedChangesDetection, 1000); // Small delay to ensure all elements are loaded // Indexation Control form AJAX save functionality function initializeSeoControlsSaveHandler() { // Only initialize if we're on the Indexation Control page if ($('#metaSyncSeoControlsForm').length > 0) { // Override the saveChanges function for Indexation Control form window.saveChanges = function () { var $form = $('#metaSyncSeoControlsForm'); if ($form.length > 0) { // Get form data and submit via AJAX var formData = $form.serialize(); formData += '&action=meta_sync_save_seo_controls'; // Remove the notification immediately var $notification = $('.metasync-unsaved-notification'); if ($notification.length > 0) { $notification.remove(); } // Clear previous messages $('#seo-controls-messages').empty(); $.ajax({ url: ajaxurl || metaSync.ajax_url, type: 'POST', data: formData, dataType: 'json', success: function (response) { if (response.success) { // Show success message above Indexation Control section var $successNotice = $('');
$successP.append($('').text('β
Success! '));
$successP[0].appendChild(document.createTextNode(response.data.message));
$successNotice.append($successP);
$('#seo-controls-messages').empty().append($successNotice);
// Clear unsaved changes state
hasUnsavedChanges = false;
if (typeof updateUnsavedChangesIndicator === 'function') {
updateUnsavedChangesIndicator();
}
// Update initial form data to current state after successful save
var formId = $form.attr('id') || 'metaSyncSeoControlsForm';
initialFormData[formId] = $form.serialize();
// Auto-hide success notice after 5 seconds
setTimeout(function () {
$('#seo-controls-messages .notice-success').fadeOut();
}, 5000);
} else {
// Show error message above Indexation Control section
var $errorNoticeCtrl = $(' ');
$errorPCtrl.append($('').text('β Error! '));
$errorPCtrl[0].appendChild(document.createTextNode(response.data.message || 'Failed to save settings'));
$errorNoticeCtrl.append($errorPCtrl);
$('#seo-controls-messages').empty().append($errorNoticeCtrl);
}
// Make dismiss buttons work
$('#seo-controls-messages .notice-dismissible').each(function () {
var $notice = $(this);
if (!$notice.find('.notice-dismiss').length) {
$notice.append('');
}
$notice.find('.notice-dismiss').on('click', function () {
$notice.fadeOut();
});
});
},
error: function (xhr, status, error) {
// Show error message above Indexation Control section
$('#seo-controls-messages').html(
' β Error! Network error occurred while saving. Please check your connection and try again.