/** * WP Data Optimizer — Admin JS (native fetch, no jQuery) * * @package WP_Data_Optimizer */ ( function () { 'use strict'; var WPDO = window.wpdoAdmin || {}; var i18n = WPDO.i18n || {}; document.addEventListener( 'DOMContentLoaded', function () { bindFlushCacheButtons(); bindStatusRefresh(); } ); /** * Announce a message via the shared aria-live region. * Falls back to creating the region on first call. */ function announce( message ) { var region = document.getElementById( 'wpdo-aria-live' ); if ( ! region ) { region = document.createElement( 'div' ); region.id = 'wpdo-aria-live'; region.className = 'wpdo-sr-only'; region.setAttribute( 'role', 'status' ); region.setAttribute( 'aria-live', 'polite' ); region.setAttribute( 'aria-atomic', 'true' ); document.body.appendChild( region ); } region.textContent = ''; setTimeout( function () { region.textContent = message; }, 50 ); } /** * Render an inline admin notice at the top of .wpdo-wrap. * Dismissable by user. Replaces legacy alert() for errors. */ function showNotice( message, type ) { type = type || 'error'; var wrap = document.querySelector( '.wpdo-wrap' ); if ( ! wrap ) { return; } var notice = document.createElement( 'div' ); notice.className = 'notice notice-' + type + ' is-dismissible'; notice.setAttribute( 'role', type === 'error' ? 'alert' : 'status' ); var p = document.createElement( 'p' ); p.textContent = message; notice.appendChild( p ); var dismiss = document.createElement( 'button' ); dismiss.type = 'button'; dismiss.className = 'notice-dismiss'; dismiss.setAttribute( 'aria-label', i18n.dismiss || 'Dismiss' ); dismiss.addEventListener( 'click', function () { notice.remove(); } ); notice.appendChild( dismiss ); // Insert after the H1 so it appears at the top of the content area. var h1 = wrap.querySelector( 'h1' ); if ( h1 && h1.nextSibling ) { wrap.insertBefore( notice, h1.nextSibling ); } else { wrap.prepend( notice ); } announce( message ); } /** * POST to admin-ajax.php using native fetch + FormData. * Returns a Promise resolving to the parsed JSON response. */ function wpdoAjax( actionType, data ) { var body = new FormData(); body.append( 'action', 'wpdo_admin_action' ); body.append( 'nonce', WPDO.nonce || '' ); body.append( 'action_type', actionType ); Object.keys( data || {} ).forEach( function ( key ) { body.append( key, data[ key ] ); } ); return fetch( WPDO.ajaxUrl, { method: 'POST', credentials: 'same-origin', body: body, } ) .then( function ( res ) { if ( ! res.ok ) { throw new Error( 'HTTP ' + res.status ); } return res.json(); } ); } /** * Flush cache button handler — delegated click listener. */ function bindFlushCacheButtons() { document.addEventListener( 'click', function ( e ) { var btn = e.target.closest( '.wpdo-flush-cache' ); if ( ! btn ) { return; } e.preventDefault(); var postType = btn.getAttribute( 'data-post-type' ); if ( ! postType ) { return; } var originalLabel = btn.textContent; btn.disabled = true; btn.textContent = i18n.flushing || 'Flushing…'; announce( btn.textContent ); wpdoAjax( 'flush_cache', { post_type: postType } ) .then( function ( response ) { if ( response && response.success ) { btn.textContent = i18n.flushed || 'Flushed!'; announce( btn.textContent ); setTimeout( function () { btn.disabled = false; btn.textContent = i18n.flushLabel || originalLabel; }, 2000 ); } else { btn.disabled = false; btn.textContent = i18n.flushLabel || originalLabel; var msg = ( response && response.data ) ? String( response.data ) : ( i18n.error || 'Unknown error' ); showNotice( msg, 'error' ); } } ) .catch( function () { btn.disabled = false; btn.textContent = i18n.flushLabel || originalLabel; showNotice( i18n.error || 'Request failed.', 'error' ); } ); } ); } /** * Auto-refresh module status on the Dashboard tab (every 30s). */ function bindStatusRefresh() { var isDashboard = document.querySelector( '.wpdo-wrap' ) && window.location.search.indexOf( 'tab=dashboard' ) !== -1; if ( ! isDashboard ) { return; } var timer = setInterval( function () { if ( ! document.hidden ) { refreshStatus(); } }, 30000 ); window.addEventListener( 'beforeunload', function () { clearInterval( timer ); } ); } function refreshStatus() { wpdoAjax( 'module_status', {} ) .then( function ( response ) { if ( ! response || ! response.success || ! response.data ) { return; } var data = response.data; var changed = 0; var changedSummaries = []; document.querySelectorAll( '.wpdo-state' ).forEach( function ( el ) { var row = el.closest( 'tr' ); var codeEl = row ? row.querySelector( 'code' ) : null; if ( ! codeEl ) { return; } var module = codeEl.textContent; if ( ! module || ! ( module in data ) ) { return; } var newState = data[ module ]; if ( el.textContent === newState ) { return; } el.textContent = newState; el.className = 'wpdo-state wpdo-state-' + newState; changed++; changedSummaries.push( module + ' → ' + newState ); } ); if ( changed > 0 ) { announce( changedSummaries.join( '、' ) ); } } ) .catch( function () { // Fail silently on polling — user will see the stale state; not worth a notice. } ); } } )();