diff --git a/src/wp-admin/js/customize-controls.js b/src/wp-admin/js/customize-controls.js index 0abfb775bd..4901b5699f 100644 --- a/src/wp-admin/js/customize-controls.js +++ b/src/wp-admin/js/customize-controls.js @@ -3345,6 +3345,8 @@ value._dirty = false; } ); + api.previewer.send( 'saved', response ); + api.trigger( 'saved', response ); } ); }; diff --git a/src/wp-includes/class-wp-customize-manager.php b/src/wp-includes/class-wp-customize-manager.php index f5aa604468..aa73ed7992 100644 --- a/src/wp-includes/class-wp-customize-manager.php +++ b/src/wp-includes/class-wp-customize-manager.php @@ -805,6 +805,7 @@ final class WP_Customize_Manager { 'activePanels' => array(), 'activeSections' => array(), 'activeControls' => array(), + '_dirty' => array_keys( $this->unsanitized_post_values() ), ); if ( 2 == $this->nonce_tick ) { diff --git a/src/wp-includes/js/customize-preview.js b/src/wp-includes/js/customize-preview.js index 4bf625eb50..1d1802736c 100644 --- a/src/wp-includes/js/customize-preview.js +++ b/src/wp-includes/js/customize-preview.js @@ -84,35 +84,58 @@ }); $( function() { - api.settings = window._wpCustomizeSettings; - if ( ! api.settings ) - return; + var bg, setValue; - var bg; + api.settings = window._wpCustomizeSettings; + if ( ! api.settings ) { + return; + } api.preview = new api.Preview({ url: window.location.href, channel: api.settings.channel }); + /** + * Create/update a setting value. + * + * @param {string} id - Setting ID. + * @param {*} value - Setting value. + * @param {boolean} [createDirty] - Whether to create a setting as dirty. Defaults to false. + */ + setValue = function( id, value, createDirty ) { + var setting = api( id ); + if ( setting ) { + setting.set( value ); + } else { + createDirty = createDirty || false; + setting = api.create( id, value, { + id: id + } ); + + // Mark dynamically-created settings as dirty so they will get posted. + if ( createDirty ) { + setting._dirty = true; + } + } + }; + api.preview.bind( 'settings', function( values ) { - $.each( values, function( id, value ) { - if ( api.has( id ) ) - api( id ).set( value ); - else - api.create( id, value ); - }); + $.each( values, setValue ); }); api.preview.trigger( 'settings', api.settings.values ); + $.each( api.settings._dirty, function( i, id ) { + var setting = api( id ); + if ( setting ) { + setting._dirty = true; + } + } ); + api.preview.bind( 'setting', function( args ) { - var value; - - args = args.slice(); - - if ( value = api( args.shift() ) ) - value.set.apply( value, args ); + var createDirty = true; + setValue.apply( null, args.concat( createDirty ) ); }); api.preview.bind( 'sync', function( events ) { @@ -130,6 +153,16 @@ api.preview.send( 'documentTitle', document.title ); }); + api.preview.bind( 'saved', function( response ) { + api.trigger( 'saved', response ); + } ); + + api.bind( 'saved', function() { + api.each( function( setting ) { + setting._dirty = false; + } ); + } ); + /* * Send a message to the parent customize frame with a list of which * containers and controls are active.