定制器活动回调实时切换控件

时间:2016-12-19 作者:dingo_d

因此,我启用了在一个控件未激活时不显示控件的选项,但问题是,这仅在刷新自定义程序页面时有效。

在我的示例中,我有一个boxed控件,它是一个复选框(虽然我使用自定义控件来设置样式,但您可以找到代码here). 如果禁用,则会隐藏可更改框体边框宽度、颜色、背景颜色等的关联控件。如果启用装箱正文,则需要刷新页面以查看这些控件,这是UX灾难。代码为:

一零

add_action( \'customize_register\', \'mytheme_customize_register\' );
/**
 * Register customizer settings
 *
 * @see add_action(\'customize_register\',$func)
 * @param  \\WP_Customize_Manager $wp_customize WP Customize object.
 * @since 1.0.0
 */
function mytheme_customize_register( WP_Customize_Manager $wp_customize ) {

    /**
    Boxed Body
    */
    $wp_customize->add_setting( \'boxed_body\', array(
        \'default\'           => false,
        \'transport\'         => \'postMessage\',
        \'sanitize_callback\' => \'mytheme_checkbox_sanitization\',
    ) );
    $wp_customize->add_control(new Toggle_Checkbox_Custom_Control( $wp_customize, \'boxed_body\', array(
        \'label\'       => esc_html__( \'Boxed Body\', \'mytheme\' ),
        \'description\' => esc_html__( \'Check this to enable boxed body layout\', \'mytheme\' ),
        \'type\'        => \'checkbox\',
        \'section\'     => \'section_general\',
    ) ) );

    /**
     * Callback function for boxed body choice
     *
     * @param  object $control Control object.
     * @return boolean
     */
    function boxed_body_choice( $control ) {
        if ( 1 === $control->manager->get_setting( \'boxed_body\' )->value() ) {
            return true;
        } else {
            return false;
        }
    }

    /**
    Boxed Body Border Color
    */
    $wp_customize->add_setting( \'boxed_body_border_color\', array(
        \'default\'           => \'\',
        \'transport\'         => \'postMessage\',
        \'sanitize_callback\' => \'sanitize_hex_color\',
    ) );
    $wp_customize->add_control(new WP_Customize_Color_Control( $wp_customize, \'boxed_body_border_color\', array(
        \'label\'    => esc_html__( \'Boxed Body Border Color\', \'mytheme\' ),
        \'settings\' => \'boxed_body_border_color\',
        \'section\'  => \'section_general\',
        \'active_callback\' => \'boxed_body_choice\',
    ) ) );

}

add_action( \'customize_preview_init\', \'mytheme_customizer_live_preview\' );
/**
 * Live preview script enqueue
 *
 * @since 1.0.0
 */
function mytheme_customizer_live_preview() {
    wp_enqueue_script( \'mytheme-themecustomizer\', get_template_directory_uri() . \'/inc/customizer/js/customizer.js?v=\' . rand(), array( \'jquery\', \'customize-preview\' ), \'\', true );
}
 我试着效仿韦斯顿·鲁特(WestonRuter)在上下文控制方面的例子heregist, 但运气不好。我在customizer.js

(function($) {

    // Add callback for when the boxed_body setting is toggled.
    wp.customize( \'boxed_body\', function(setting) {
        var isBoxedBodyToggled, linkSettingValueToControlActiveState;

        /**
         * Determine whether the boxed body associated options should be displayed.
         *
         * @returns {boolean} Is toggled?
         */
        isBoxedBodyToggled = function() {
            return \'\' !== setting.get();
        };

        /**
         * Update a control\'s active state according to the boxed_body setting\'s value.
         *
         * @param {wp.customize.Control} control Boxed body control.
         */
        linkSettingValueToControlActiveState = function( control ) {
            var setActiveState = function() {
                control.active.set( isBoxedBodyToggled() );
            };

            // FYI: With the following we can eliminate all of our PHP active_callback code.
            control.active.validate = isBoxedBodyToggled;

            // Set initial active state.
            setActiveState();

            /*
             * Update activate state whenever the setting is changed.
             * Even when the setting does have a refresh transport where the
             * server-side active callback will manage the active state upon
             * refresh, having this JS management of the active state will
             * ensure that controls will have their visibility toggled
             * immediately instead of waiting for the preview to load.
             * This is especially important if the setting has a postMessage
             * transport where changing the setting wouldn\'t normally cause
             * the preview to refresh and thus the server-side active_callbacks
             * would not get invoked.
             */
            setting.bind( setActiveState );
        };

        // Call linkSettingValueToControlActiveState on the site title and tagline controls when they exist.
        wp.customize.control( \'boxed_body_border_width\', linkSettingValueToControlActiveState );
        wp.customize.control( \'boxed_body_border_color\', linkSettingValueToControlActiveState );
        wp.customize.control( \'boxed_body_border_style\', linkSettingValueToControlActiveState );
        wp.customize.control( \'boxed_body_bg_image\', linkSettingValueToControlActiveState );
        wp.customize.control( \'boxed_body_bg_image_repeat\', linkSettingValueToControlActiveState );
        wp.customize.control( \'boxed_body_bg_image_size\', linkSettingValueToControlActiveState );
        wp.customize.control( \'boxed_body_bg_image_position\', linkSettingValueToControlActiveState );
        wp.customize.control( \'boxed_body_bg_image_attachment\', linkSettingValueToControlActiveState );

    });

})(jQuery);
但在自定义刷新时

未捕获类型错误:wp。定制控件不是函数(…)

wp.customize.control( \'boxed_body_border_width\', linkSettingValueToControlActiveState );
切换不会隐藏或显示控件。我已经做了一些更改以适应自定义切换控件,因此我不检查\'blank\' 而是\'\'isBoxedBodyToggled 作用

当我在DevTools中拉小提琴时,我可以看到wp.customize 是函数,而不是对象。在这个例子中,这应该是一个对象(我猜)。

任何帮助都将不胜感激。

NEW CODE

所以我注意到,自从我添加了

add_theme_support( \'custom-background\' );
这给了我身体背景的内置控制,所以我把它做成这样:

add_action( \'customize_register\', \'mytheme_customize_register\' );
/**
 * Register customizer settings
 *
 * @see add_action(\'customize_register\',$func)
 * @param  \\WP_Customize_Manager $wp_customize WP Customize object.
 * @since 1.0.0
 */
function mytheme_customize_register( WP_Customize_Manager $wp_customize ) {

    /**
    ------------------------------------------------------------
    SECTION: Body Settings
    ------------------------------------------------------------
    */
    $wp_customize->add_section( \'background_image\', array(
        \'title\'    => esc_html__( \'Body Settings\', \'mytheme\' ),
        \'priority\' => 0,
    ) );

    /**
    Boxed Body
    */
    $wp_customize->add_setting( \'boxed_body\', array(
        \'default\'           => false,
        \'transport\'         => \'postMessage\',
        \'sanitize_callback\' => \'mytheme_checkbox_sanitization\',
    ) );
    $wp_customize->add_control(new Toggle_Checkbox_Custom_Control( $wp_customize, \'boxed_body\', array(
        \'label\'       => esc_html__( \'Boxed Body\', \'mytheme\' ),
        \'description\' => esc_html__( \'Check this to enable boxed body layout\', \'mytheme\' ),
        \'type\'        => \'checkbox\',
        \'section\'     => \'background_image\',
        \'priority\'    => 0,
    ) ) );

    /**
     * Callback function for boxed body choice
     *
     * @param  object $control Control object.
     * @return boolean
     */
    function boxed_body_choice( $control ) {
        if ( 1 === $control->manager->get_setting( \'boxed_body\' )->value() ) {
            return true;
        } else {
            return false;
        }
    }

    /**
    Boxed Body Border Color
    */
    $wp_customize->add_setting( \'boxed_body_border_color\', array(
        \'default\'           => \'\',
        \'transport\'         => \'postMessage\',
        \'sanitize_callback\' => \'sanitize_hex_color\',
    ) );
    $wp_customize->add_control(new WP_Customize_Color_Control( $wp_customize, \'boxed_body_border_color\', array(
        \'label\'           => esc_html__( \'Boxed Body Border Color\', \'mytheme\' ),
        \'settings\'        => \'boxed_body_border_color\',
        \'section\'         => \'background_image\',
        \'active_callback\' => \'boxed_body_choice\',
        \'priority\'        => 0,
    ) ) );

}

add_action( \'customize_preview_init\', \'mytheme_customizer_live_preview\' );
/**
 * Live preview script enqueue
 *
 * @since 1.0.0
 */
function mytheme_customizer_live_preview() {
    wp_enqueue_script( \'mytheme-themecustomizer\', get_template_directory_uri() . \'/inc/customizer/js/customizer.js?v=\' . rand(), array( \'jquery\', \'customize-preview\' ), \'\', true );
}
以及customizer.js 看起来像这样

(function($, api) {
    \'use strict\';

    //Boxed Body Toggle
    api( \'boxed_body\', function(value) {
        value.bind(function(newval) {
            if (newval) {
                $(\'body\').wrapInner(\'<div class="boxed_body_wrapper" />\');
            } else {
                $(\'.boxed_body_wrapper\').contents().unwrap();
            }
        });
    });

    // Add callback for when the boxed_body setting is toggled.
    api( \'boxed_body\', function(value) {
        value.bind(function(setting){
            var isBoxedBodyToggled, linkSettingValueToControlActiveState;

            /**
             * Determine whether the boxed body associated options should be displayed.
             *
             * @returns {boolean} Is toggled?
             */
            isBoxedBodyToggled = function() {
                return \'\' !== setting.get();
            };

            /**
             * Update a control\'s active state according to the boxed_body setting\'s value.
             *
             * @param {api.Control} control Boxed body control.
             */
            linkSettingValueToControlActiveState = function( control ) {
                var setActiveState = function() {
                    control.active.set( isBoxedBodyToggled() );
                };

                // FYI: With the following we can eliminate all of our PHP active_callback code.
                control.active.validate = isBoxedBodyToggled;
                // Set initial active state.
                setActiveState();

                /*
                 * Update activate state whenever the setting is changed.
                 * Even when the setting does have a refresh transport where the
                 * server-side active callback will manage the active state upon
                 * refresh, having this JS management of the active state will
                 * ensure that controls will have their visibility toggled
                 * immediately instead of waiting for the preview to load.
                 * This is especially important if the setting has a postMessage
                 * transport where changing the setting wouldn\'t normally cause
                 * the preview to refresh and thus the server-side active_callbacks
                 * would not get invoked.
                 */

                setting.bind( setActiveState );
            };

            // Call linkSettingValueToControlActiveState on the site title and tagline controls when they exist.
            api.control( \'boxed_body_border_color\', linkSettingValueToControlActiveState );
        });
    });

})(jQuery, wp.customize);
我还是会

自定义程序。js?v=1256189197(&;版本=4.7:111未捕获类型错误:api。控件不是功能

在i处(jquery.js?ver=1.12.4:2)

at对象。fireWith(jquery.js?ver=1.12.4:2)

at功能。设置(自定义base.min.js?ver=4.7:1)

at功能。d[按设置](jquery.js?ver=1.12.4:2)

在c(自定义预览。min.js?ver=4.7:1)

f.(自定义预览。min.js?ver=4.7:1)

在i处(jquery.js?ver=1.12.4:2)

at对象。fireWith(jquery.js?ver=1.12.4:2)

在f.trigger(自定义base.min.js?ver=4.7:1)

如果我添加\'customize-controls\' 作为依赖项,我得到了错误:

未捕获的TypeError:无法读取未定义的属性“dirty”

at功能。初始化(自定义控件。min.js?ver=4.7:1)

在f.e.Class(自定义base.min.js?ver=4.7:1)

at f[作为构造函数](自定义base.min.js?ver=4.7:1)

新f时(自定义base.min.js?ver=4.7:1)

at功能。创建(自定义base.min.js?ver=4.7:1)

在字符串处。c(自定义预览。min.js?ver=4.7:1)

at功能。每个(jquery.js?ver=1.12.4:2)

f.(自定义预览。min.js?ver=4.7:1)

在i处(jquery.js?ver=1.12.4:2)

at对象。fireWith(jquery.js?ver=1.12.4:2)

仍然不确定我做错了什么:\\

EDIT

排队时我用错了动作钩。我创建了另一个文件,其中添加了:

add_action( \'customize_controls_enqueue_scripts\', \'utter_customizer_control_toggle\' );

/**
 * Custom contextual controls
 *
 * @since 1.0.0
 */
function utter_customizer_control_toggle() {
    wp_enqueue_script( \'utter-contextualcontrols\', UTTER_TEMPPATH . \'/inc/customizer/js/customizer-contextual.js?v=\' . rand(), array( \'customize-controls\' ), false );
}
这将消除所有错误。第一次切换有效,但不是在我切换回时,但我想这与我使用的自定义控件有关,而不是常规复选框。我可能很快就会解决这个问题:D

1 个回复
最合适的回答,由SO网友:dingo_d 整理而成

答案是“解耦”实时预览和上下文控制。如果我把它们放在一起,我就不能使用同一个动作钩-live将不起作用customize_controls_enqueue_scripts 上下文控制不起作用customize_preview_init.

所以答案是:

add_action( \'customize_controls_enqueue_scripts\', \'mytheme_customizer_control_toggle\' );
add_action( \'customize_preview_init\', \'mytheme_customizer_live_preview\' );
/**
 * Live preview script enqueue
 *
 * @since 1.0.0
 */
function mytheme_customizer_live_preview() {
    wp_enqueue_script( \'mytheme-themecustomizer\', get_template_directory_uri() . \'/inc/customizer/js/customizer.js?v=\' . rand(), array( \'jquery\', \'customize-preview\' ), false );
}

/**
 * Custom contextual controls
 *
 * @since 1.0.0
 */
function mytheme_customizer_control_toggle() {
    wp_enqueue_script( \'mytheme-contextualcontrols\', get_template_directory_uri() . \'/inc/customizer/js/customizer-contextual.js?v=\' . rand(), array( \'customize-controls\' ), false );
}
上下文控制代码为

( function( api ) {
    \'use strict\';

    api( \'boxed_body\', function(setting) {
        var isBoxedBodyToggled, linkSettingValueToControlActiveState;

        /**
         * Determine whether the boxed body associated options should be displayed.
         *
         * @returns {boolean} Is toggled?
         */
        isBoxedBodyToggled = function() {
            return \'\' !== setting.get();
        };

        /**
         * Update a control\'s active state according to the boxed_body setting\'s value.
         *
         * @param {api.Control} control Boxed body control.
         */
        linkSettingValueToControlActiveState = function( control ) {
            var setActiveState = function() {
                control.active.set( isBoxedBodyToggled() );
            };

            // FYI: With the following we can eliminate all of our PHP active_callback code.
            control.active.validate = isBoxedBodyToggled;
            // Set initial active state.
            setActiveState();

            /*
             * Update activate state whenever the setting is changed.
             * Even when the setting does have a refresh transport where the
             * server-side active callback will manage the active state upon
             * refresh, having this JS management of the active state will
             * ensure that controls will have their visibility toggled
             * immediately instead of waiting for the preview to load.
             * This is especially important if the setting has a postMessage
             * transport where changing the setting wouldn\'t normally cause
             * the preview to refresh and thus the server-side active_callbacks
             * would not get invoked.
             */

            setting.bind( setActiveState );
        };

        // Call linkSettingValueToControlActiveState on the site title and tagline controls when they exist.
        api.control( \'boxed_body_border_width\', linkSettingValueToControlActiveState );
        api.control( \'boxed_body_border_color\', linkSettingValueToControlActiveState );
        api.control( \'boxed_body_border_style\', linkSettingValueToControlActiveState );
    });

}( wp.customize ) );
我现在的问题是我的自定义控件不能正常工作,但这是一个我可以轻松解决的不同问题。

感谢韦斯顿·鲁特为我指明了正确的方向:)

WORKING EDIT

出于某种原因,上面的代码只切换了一次控件,所以我这样重写了它

( function( api ) {
    \'use strict\';

    api.bind( \'ready\', function() {

        api( \'boxed_body\', function(setting) {
            var linkSettingValueToControlActiveState;

            /**
             * Update a control\'s active state according to the boxed_body setting\'s value.
             *
             * @param {api.Control} control Boxed body control.
             */
            linkSettingValueToControlActiveState = function( control ) {
                var visibility = function() {
                    if ( true === setting.get() || 1 === setting.get() ) {
                        control.container.slideDown( 180 );
                    } else {
                        control.container.slideUp( 180 );
                    }
                };

                // Set initial active state.
                visibility();
                //Update activate state whenever the setting is changed.
                setting.bind( visibility );
            };

            // Call linkSettingValueToControlActiveState on the border controls when they exist.
            api.control( \'boxed_body_border_width\', linkSettingValueToControlActiveState );
            api.control( \'boxed_body_border_color\', linkSettingValueToControlActiveState );
            api.control( \'boxed_body_border_style\', linkSettingValueToControlActiveState );
        });

    });

}( wp.customize ) );
这似乎很有效。我使用了2017作为指导,他们以类似的方式切换自定义配色方案。

相关推荐