/** * WP Data Optimizer — Settings per-section instant save. * * Each .wpdo-settings-section card has a "儲存此區塊" button that posts only * that section's fields via AJAX, updating options without a full page reload. * * @since 3.0.2 */ /* global wpdoSettings */ ( function () { 'use strict'; if ( typeof wpdoSettings === 'undefined' ) { return; } const { ajaxUrl, nonce, i18n } = wpdoSettings; /** * Collect form fields within a section into a FormData object. * Unchecked checkboxes are intentionally omitted (server does isset() ? '1' : '0'). * * @param {HTMLElement} section * @returns {FormData} */ function collectFields( section ) { const fd = new FormData(); section.querySelectorAll( 'input, select, textarea' ).forEach( ( el ) => { if ( ! el.name ) { return; } if ( el.type === 'checkbox' ) { if ( el.checked ) { fd.append( el.name, el.value ); } } else if ( el.type === 'radio' ) { if ( el.checked ) { fd.append( el.name, el.value ); } } else { fd.append( el.name, el.value ); } } ); return fd; } /** * Show a transient status message, then fade it out after 2.5s. * * @param {HTMLElement} statusEl * @param {string} message * @param {boolean} isError */ function showStatus( statusEl, message, isError ) { statusEl.textContent = message; statusEl.style.color = isError ? 'var(--color-error, #b03d3d)' : 'var(--color-success, #5a8c5a)'; statusEl.classList.add( 'visible' ); clearTimeout( statusEl._wpdo_timer ); statusEl._wpdo_timer = setTimeout( () => { statusEl.classList.remove( 'visible' ); }, 2500 ); } document.addEventListener( 'click', function ( e ) { const btn = e.target.closest( '.wpdo-section-save' ); if ( ! btn ) { return; } const section = btn.closest( '.wpdo-settings-section' ); const statusEl = btn.nextElementSibling; const sectionKey = section ? section.dataset.section : ''; if ( ! sectionKey ) { return; } const originalLabel = btn.textContent; btn.disabled = true; btn.textContent = i18n.saving; const fd = collectFields( section ); fd.append( 'action', 'wpdo_save_settings_section' ); fd.append( '_ajax_nonce', nonce ); fd.append( 'section', sectionKey ); fetch( ajaxUrl, { method : 'POST', credentials : 'same-origin', body : fd, } ) .then( ( r ) => r.json() ) .then( ( data ) => { if ( data.success ) { showStatus( statusEl, i18n.saved, false ); } else { showStatus( statusEl, i18n.error, true ); } } ) .catch( () => { showStatus( statusEl, i18n.error, true ); } ) .finally( () => { btn.disabled = false; btn.textContent = originalLabel; } ); } ); } )();