$conf, $runtime; function_exists('chdir') AND chdir(APP_PATH); $r = 'mysql' == $conf['cache']['type'] ? website_set('runtime', $runtime) : cache_set('runtime', $runtime); } function runtime_truncate() { global $conf; 'mysql' == $conf['cache']['type'] ? website_set('runtime', '') : cache_delete('runtime'); } register_shutdown_function('runtime_save'); ?>theme customizer - Customiser `active_callback` not working on control with `postMessage` transport method|Programmer puzzle solving
最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

theme customizer - Customiser `active_callback` not working on control with `postMessage` transport method

matteradmin9PV0评论

I have 4x custom settings within 2x custom sections, with the second setting in each section relying on an active_callback to show/hide it.

In both cases the active_callback checks the value of the first custom setting from that section, and it was working perfectly until I started using transport => postMessage for the first setting (all settings below, as it's easier to show them than it is explain them).

There are no JS errors, so I assume it must be something to do with how the active callback is fired (I.e. perhaps it's not when postMessage is used).

While I can add some additional JS to cover my requirements, I'd be curious to know whether or not this is expected behavior, and if it is, whether or not there is a way to fix my problem.

Here are the settings (registered using the customize_register action hook)...

/**
 * Create the custom 'Archive Pages' section and register settings
 */
function register_settings_archive_template($wp_customise){

    $wp_customise->add_section('section_template_archive' , array(
        'title'             => __('Archive Pages', TEXT_DOMAIN),
        'priority'          => 60
    ));

    /**
     * Link tile size (overrides General setting)
     */

    $wp_customise->add_setting('archive_link_tile_size', array(
        'default'   => 'default',
        'transport' => 'postMessage'
    ));

    $wp_customise->add_control('archive_link_tile_size', array(
        'label'         => __('Link tile size', TEXT_DOMAIN),
        'section'       => 'section_template_archive',
        'type'          => 'radio',
        'choices'       => array(
            'default'   => __('Default', TEXT_DOMAIN),
            'large'     => __('Large', TEXT_DOMAIN),
            'small'     => __('Small', TEXT_DOMAIN)
        ),
        'description'   => __('The size of link tile that you wish to dsipay on archive pages.', TEXT_DOMAIN),
    ));

    /**
     * Show 'More...' link
     */

    $wp_customise->add_setting('archive_show_more_link', array(
        'default'   => false,
        'transport' => 'postMessage'
    ));

    $wp_customise->add_control('archive_show_more_link', array(
        'label'             => __('Show link to Link/Post', TEXT_DOMAIN),
        'section'           => 'section_template_archive',
        'type'              => 'checkbox',
        'description'       => __('Whether or not to show the \'More...\' link underneath a large link tile on archive pages.  Note that links cannot be displayed in conjunction with \'Small\' Link Tiles.', TEXT_DOMAIN),
        'active_callback'   => '_check_is_link_tile_size_large'
    ));

}

/**
 * Create the custom 'Search Results' section and register settings
 */
function register_settings_search_template($wp_customise){

    $wp_customise->add_section('section_template_search' , array(
        'title'             => __('Search Results', TEXT_DOMAIN),
        'priority'          => 60
    ));

    /**
     * Link tile size (overrides General setting)
     */

    $wp_customise->add_setting('search_link_tile_size', array(
        'default'   => 'default',
        'transport' => 'postMessage'
    ));

    $wp_customise->add_control('search_link_tile_size', array(
        'label'         => __('Link tile size', TEXT_DOMAIN),
        'section'       => 'section_template_search',
        'type'          => 'radio',
        'choices'       => array(
            'default'   => __('Default', TEXT_DOMAIN),
            'large'     => __('Large', TEXT_DOMAIN),
            'small'     => __('Small', TEXT_DOMAIN)
        ),
        'description'   => __('The size of link tile that you wish to dsipay on the search results page.', TEXT_DOMAIN)
    ));

    /**
     * Show 'More...' link
     */

    $wp_customise->add_setting('search_show_more_link', array(
        'default'   => false,
        'transport' => 'postMessage'
    ));

    $wp_customise->add_control('search_show_more_link', array(
        'label'             => __('Show link to Link/Post', TEXT_DOMAIN),
        'section'           => 'section_template_search',
        'type'              => 'checkbox',
        'description'       => __('Whether or not to show the \'More...\' link underneath a large link tile on the search results page.  Note that links cannot be displayed in conjunction with \'Small\' Link Tiles.', TEXT_DOMAIN),
        'active_callback'   => '_check_is_link_tile_size_large'
    ));

}

And here is the active callback...

public function _check_is_link_tile_size_large($control){

    $control_id = $control->id;

    switch($control_id):

        case 'archive_show_more_link' :
            $validation_setting = 'archive_link_tile_size';
            break;

        case 'search_show_more_link' :
            $validation_setting = 'search_link_tile_size';
            break;

    endswitch;

    return ($control->manager->get_setting($validation_setting)->value() === 'large');

}

Update

I should have added this in the first place, but here is the JS that I am using to update the above settings via postMessage -

(function($){

    var api = wp.customize;

    CustomiseArchivePages();    // Customise settings in the Archive Pages section
    CustomiseSearchResults();   // Customise settings in the Search Results section

    /**
     * Customise settings in the Archive Pages section
     */
    function CustomiseArchivePages(){

        /** Link Tile size */
        api('archive_link_tile_size', function(value){
            value.bind(function(newval){
                PreviewLinkTile(newval, api.get().archive_show_more_link);
            });
        });

        /** Show/hide 'More...' button  */
        api('archive_show_more_link', function(value){
            value.bind(function(newval){
                PreviewLinkTile(api.get().archive_link_tile_size, newval);
            }); 
        });

    }

    /**
     * Customise settings in the Search Results section
     */
    function CustomiseSearchResults(){

        /** Search box placeholder text */
        api('search_box_placeholder', function(value){
            value.bind(function(newval){
                $('input.s').attr('placeholder', newval);
            });
        });

        /** Link Tile size */
        api('search_link_tile_size', function(value){
            value.bind(function(newval){
                PreviewLinkTile(newval, api.get().search_show_more_link);
            });
        });

        /** Show/hide 'More...' button  */
        api('search_show_more_link', function(value){
            value.bind(function(newval){
                PreviewLinkTile(api.get().search_link_tile_size, newval);
            });
        });

    }

    /**
     * Set the link tile size and show/hide the 'More...' button on link tiles
     *
     * @param required string linkTileSize          The size of the link tiles that are being displayed
     * @param required string showMoreInfoButton    Whether or not to show the 'More...' button
     */
    function PreviewLinkTile(linkTileSize, showMoreInfoButton){

        var linksContainer = $('#links-container'),         // The links container
            linkTiles = $('.link-tile', linksContainer);    // Every individual link tile

        linkTileSize = (linkTileSize !== 'default') ? linkTileSize : api.get().general_link_tile_size;  // If the new size is default, grab the default size

        /**
         * Set the link tile size
         */
        switch(linkTileSize){

            case 'large' :

                /** Set the links container classes */
                linksContainer.removeClass('uk-grid-width-1-2 uk-grid-width-small-1-3 uk-grid-width-medium-1-4 uk-grid-width-large-1-5')
                    .addClass('uk-grid-width-1-1 uk-grid-width-small-1-1 uk-grid-width-medium-1-2 uk-grid-width-large-1-3');

                /** Set the link tile class */
                linkTiles.removeClass('link-tile-small')
                    .addClass('link-tile-large');

                break;

            case 'small' :

                /** Set the links container classes */
                linksContainer.removeClass('uk-grid-width-1-1 uk-grid-width-small-1-1 uk-grid-width-medium-1-2 uk-grid-width-large-1-3')
                    .addClass('uk-grid-width-1-2 uk-grid-width-small-1-3 uk-grid-width-medium-1-4 uk-grid-width-large-1-5');

                /** Set the link tile class */
                linkTiles.removeClass('link-tile-large')
                    .addClass('link-tile-small');

                break;

            default :
                console.log('An unexpected error occured when customising the Link Tile size: The new size could not be determined.');
                break;

        }

        /**
         * Show/hide the 'More...' button
         */
        if(showMoreInfoButton && linkTileSize === 'large'){
            linkTiles.addClass('show-more-button');
        } else {
            linkTiles.removeClass('show-more-button');
        }

    }

})(jQuery);

I have 4x custom settings within 2x custom sections, with the second setting in each section relying on an active_callback to show/hide it.

In both cases the active_callback checks the value of the first custom setting from that section, and it was working perfectly until I started using transport => postMessage for the first setting (all settings below, as it's easier to show them than it is explain them).

There are no JS errors, so I assume it must be something to do with how the active callback is fired (I.e. perhaps it's not when postMessage is used).

While I can add some additional JS to cover my requirements, I'd be curious to know whether or not this is expected behavior, and if it is, whether or not there is a way to fix my problem.

Here are the settings (registered using the customize_register action hook)...

/**
 * Create the custom 'Archive Pages' section and register settings
 */
function register_settings_archive_template($wp_customise){

    $wp_customise->add_section('section_template_archive' , array(
        'title'             => __('Archive Pages', TEXT_DOMAIN),
        'priority'          => 60
    ));

    /**
     * Link tile size (overrides General setting)
     */

    $wp_customise->add_setting('archive_link_tile_size', array(
        'default'   => 'default',
        'transport' => 'postMessage'
    ));

    $wp_customise->add_control('archive_link_tile_size', array(
        'label'         => __('Link tile size', TEXT_DOMAIN),
        'section'       => 'section_template_archive',
        'type'          => 'radio',
        'choices'       => array(
            'default'   => __('Default', TEXT_DOMAIN),
            'large'     => __('Large', TEXT_DOMAIN),
            'small'     => __('Small', TEXT_DOMAIN)
        ),
        'description'   => __('The size of link tile that you wish to dsipay on archive pages.', TEXT_DOMAIN),
    ));

    /**
     * Show 'More...' link
     */

    $wp_customise->add_setting('archive_show_more_link', array(
        'default'   => false,
        'transport' => 'postMessage'
    ));

    $wp_customise->add_control('archive_show_more_link', array(
        'label'             => __('Show link to Link/Post', TEXT_DOMAIN),
        'section'           => 'section_template_archive',
        'type'              => 'checkbox',
        'description'       => __('Whether or not to show the \'More...\' link underneath a large link tile on archive pages.  Note that links cannot be displayed in conjunction with \'Small\' Link Tiles.', TEXT_DOMAIN),
        'active_callback'   => '_check_is_link_tile_size_large'
    ));

}

/**
 * Create the custom 'Search Results' section and register settings
 */
function register_settings_search_template($wp_customise){

    $wp_customise->add_section('section_template_search' , array(
        'title'             => __('Search Results', TEXT_DOMAIN),
        'priority'          => 60
    ));

    /**
     * Link tile size (overrides General setting)
     */

    $wp_customise->add_setting('search_link_tile_size', array(
        'default'   => 'default',
        'transport' => 'postMessage'
    ));

    $wp_customise->add_control('search_link_tile_size', array(
        'label'         => __('Link tile size', TEXT_DOMAIN),
        'section'       => 'section_template_search',
        'type'          => 'radio',
        'choices'       => array(
            'default'   => __('Default', TEXT_DOMAIN),
            'large'     => __('Large', TEXT_DOMAIN),
            'small'     => __('Small', TEXT_DOMAIN)
        ),
        'description'   => __('The size of link tile that you wish to dsipay on the search results page.', TEXT_DOMAIN)
    ));

    /**
     * Show 'More...' link
     */

    $wp_customise->add_setting('search_show_more_link', array(
        'default'   => false,
        'transport' => 'postMessage'
    ));

    $wp_customise->add_control('search_show_more_link', array(
        'label'             => __('Show link to Link/Post', TEXT_DOMAIN),
        'section'           => 'section_template_search',
        'type'              => 'checkbox',
        'description'       => __('Whether or not to show the \'More...\' link underneath a large link tile on the search results page.  Note that links cannot be displayed in conjunction with \'Small\' Link Tiles.', TEXT_DOMAIN),
        'active_callback'   => '_check_is_link_tile_size_large'
    ));

}

And here is the active callback...

public function _check_is_link_tile_size_large($control){

    $control_id = $control->id;

    switch($control_id):

        case 'archive_show_more_link' :
            $validation_setting = 'archive_link_tile_size';
            break;

        case 'search_show_more_link' :
            $validation_setting = 'search_link_tile_size';
            break;

    endswitch;

    return ($control->manager->get_setting($validation_setting)->value() === 'large');

}

Update

I should have added this in the first place, but here is the JS that I am using to update the above settings via postMessage -

(function($){

    var api = wp.customize;

    CustomiseArchivePages();    // Customise settings in the Archive Pages section
    CustomiseSearchResults();   // Customise settings in the Search Results section

    /**
     * Customise settings in the Archive Pages section
     */
    function CustomiseArchivePages(){

        /** Link Tile size */
        api('archive_link_tile_size', function(value){
            value.bind(function(newval){
                PreviewLinkTile(newval, api.get().archive_show_more_link);
            });
        });

        /** Show/hide 'More...' button  */
        api('archive_show_more_link', function(value){
            value.bind(function(newval){
                PreviewLinkTile(api.get().archive_link_tile_size, newval);
            }); 
        });

    }

    /**
     * Customise settings in the Search Results section
     */
    function CustomiseSearchResults(){

        /** Search box placeholder text */
        api('search_box_placeholder', function(value){
            value.bind(function(newval){
                $('input.s').attr('placeholder', newval);
            });
        });

        /** Link Tile size */
        api('search_link_tile_size', function(value){
            value.bind(function(newval){
                PreviewLinkTile(newval, api.get().search_show_more_link);
            });
        });

        /** Show/hide 'More...' button  */
        api('search_show_more_link', function(value){
            value.bind(function(newval){
                PreviewLinkTile(api.get().search_link_tile_size, newval);
            });
        });

    }

    /**
     * Set the link tile size and show/hide the 'More...' button on link tiles
     *
     * @param required string linkTileSize          The size of the link tiles that are being displayed
     * @param required string showMoreInfoButton    Whether or not to show the 'More...' button
     */
    function PreviewLinkTile(linkTileSize, showMoreInfoButton){

        var linksContainer = $('#links-container'),         // The links container
            linkTiles = $('.link-tile', linksContainer);    // Every individual link tile

        linkTileSize = (linkTileSize !== 'default') ? linkTileSize : api.get().general_link_tile_size;  // If the new size is default, grab the default size

        /**
         * Set the link tile size
         */
        switch(linkTileSize){

            case 'large' :

                /** Set the links container classes */
                linksContainer.removeClass('uk-grid-width-1-2 uk-grid-width-small-1-3 uk-grid-width-medium-1-4 uk-grid-width-large-1-5')
                    .addClass('uk-grid-width-1-1 uk-grid-width-small-1-1 uk-grid-width-medium-1-2 uk-grid-width-large-1-3');

                /** Set the link tile class */
                linkTiles.removeClass('link-tile-small')
                    .addClass('link-tile-large');

                break;

            case 'small' :

                /** Set the links container classes */
                linksContainer.removeClass('uk-grid-width-1-1 uk-grid-width-small-1-1 uk-grid-width-medium-1-2 uk-grid-width-large-1-3')
                    .addClass('uk-grid-width-1-2 uk-grid-width-small-1-3 uk-grid-width-medium-1-4 uk-grid-width-large-1-5');

                /** Set the link tile class */
                linkTiles.removeClass('link-tile-large')
                    .addClass('link-tile-small');

                break;

            default :
                console.log('An unexpected error occured when customising the Link Tile size: The new size could not be determined.');
                break;

        }

        /**
         * Show/hide the 'More...' button
         */
        if(showMoreInfoButton && linkTileSize === 'large'){
            linkTiles.addClass('show-more-button');
        } else {
            linkTiles.removeClass('show-more-button');
        }

    }

})(jQuery);
Share Improve this question edited Dec 16, 2015 at 16:26 David Gard asked Dec 14, 2015 at 16:14 David GardDavid Gard 3,3105 gold badges26 silver badges39 bronze badges 3
  • Yes, it is expected that if using postMessage, the active_callback wouldn't fire because it is only called when the preview refreshes. If you want to re-evaluate the active_callback handlers, you can refresh the preview via wp.customize.previewer.refresh() – Weston Ruter Commented Dec 15, 2015 at 5:48
  • 1 Thanks, but if I refresh then it totally destroys the point of using postMessage in the first place. Plus wp.customize.previewer.refresh() generates an error... – David Gard Commented Dec 15, 2015 at 11:02
  • Yes, good point. See my answer below. – Weston Ruter Commented Dec 16, 2015 at 6:11
Add a comment  | 

1 Answer 1

Reset to default 5

Because postMessage uses JavaScript entirely, any PHP active_callback will not get called unless the preview refreshes (e.g. via wp.customize.previewer.refresh()). So what you need to do is implement the active callback in JavaScript instead, like so:

wp.customize.bind( 'ready', function () {
    wp.customize.control( 'archive_show_more_link', function( control ) {
        var setting = wp.customize( 'archive_link_tile_size' );
        control.active.set( 'large' === setting.get() );
        setting.bind( function( value ) {
            control.active.set( 'large' === value );
        } );
    } );

    wp.customize.control( 'search_show_more_link', function( control ) {
        var setting = wp.customize( 'search_link_tile_size' );
        control.active.set( 'large' === setting.get() );
        setting.bind( function( value ) {
            control.active.set( 'large' === value );
        } );
    } );
} );

Make sure that this script gets enqueued into the Customizer pane and not the Customizer preview. In other words, enqueue the JS at the customize_controls_enqueue_scripts action.

Post a comment

comment list (0)

  1. No comments so far