1

I have a piece of JS code that I use show/hide customizer control groups depending on a select item value.

The code was working fine until recent wp update (not sure which version first broke this).

Here is the code for enqueuing the js file.

add_action('customize_controls_print_scripts', 'ppl_customize_controls_scripts');
function ppl_customize_controls_scripts(){
    wp_register_script( 'ppl-customize-control', get_template_directory_uri().'/js/customizer-control.js', array('jquery'), 1, true);
    wp_enqueue_script( 'ppl-customize-control' );
}

The JS file

jQuery(document).ready(function($){
    var skin_select = $('#customize-control-ppl-ninja-theme-options-skin').find('select');

    //alert(skin_select.attr('class'));
    var selected_val = skin_select.children('option:selected').val();
    var custom_group = [
        '#accordion-section-custom_header_styles',
        '#accordion-section-custom_slider_styles',
        '#accordion-section-custom_footer_styles',
        '#accordion-section-custom_general_colors'
    ];

    if(selected_val != 4){
        hide_custom_controls(custom_group);
    }

    skin_select.change(function(){
       var val = $(this).val();

        if(val != 4){
            hide_custom_controls(custom_group);
        }else{
            show_custom_controls(custom_group);
        }

    });

    function hide_custom_controls(custom_group){
        var selector = custom_group.join(',');
        $(selector).hide();
    }

    function show_custom_controls(custom_group){
        var selector = custom_group.join(',');
        $(selector).show();
    }

});

The problem is, JS loads and hides the customizer control section just fine with inline css display:none. Then the cusomizer js script revises it and update the inline css to display:list-item which makes them visible. So, I need to run the JS code later after the customizer loads fully.

I looked into customizer script in wp-includes directory but haven't find anything that I can use. Perhaps I missed something.

Further Information

  1. The code that revising the css can be found in /wp-admin/js/customize-controls.js.

  2. The script is using the ready event to add class and revise visibility of panels, sections and controls. But I am unable to add listener to that event.

  3. The property activePanels, activeSections, activeControls are set from PHP from the file /wp-admin/customize.php I have found no way to overwrite that variable as you can see it is printed just before the body tag ends.

So, the possible solution is perhaps finding a way to hook into the ready event.

2

So, far the problem was with the initial loading of the JS file. As i couldn't find any solution using the JS. The problem was not about the script loading rather then the execution timing.

Anyways, The theme customizer looks into the global variable for which Panel/Section/Control it will show as active when it loads.

How to Make Sections/Controls/Panels Active/Deactive on initial loading

After spending hours into the core files I have found solution.

  1. For Panels use customize_panel_active filter. Passes two parameter $active boolean and $panel object.
  2. For Sections use customize_section_active filter. Passes two parameter $active boolean and $section object.
  3. For Controls use customize_control_active filter. Passes two parameter $active boolean and $control object.

Example: If I assume I have a panel and its id is my_panel. And I want to hide it if certain theme option is not set.

add_filter('customize_panel_active', 'maybe_panel_active', 10, 2);

function maybe_panel_active($active, $panel){

    if($panel->id == 'my_panel' && !theme_option('certain_theme_option') ){
        $active = false;
    }

    return $active;
}

That's about it! Pretty straight forward :)

Note: The solution is purely php. If anyone able to make it work by listening to the customizers JS events. I would be very interested on it as the question was initially intended for a JS solutions.

0

Seems like a timing problem to me, maybe/probably I'm oversimplifying this, but what about making use of the $debs parameter wp_register_script and wp_enqueue_script are offering to control load order, where one of those - in the order they are added at script-loader.php - customize-base, customize-loader, customize-preview, customize-models, customize-views, customize-controls, customize-widgets or customize-preview-widgets should be a dependency.

0

Sounds like a dependency problem. You're only checking for jQuery, so your script could be getting preempted. You can ensure your script loads after all the other customizer scripts with 'customize-preview-widgets'. Try this…

add_action('customize_preview_init', 'ppl_customize_controls_scripts');
function ppl_customize_controls_scripts(){
    wp_enqueue_script(
          'ppl-customize-control',
          get_template_directory_uri().'/js/customizer-control.js',
          array( 'jquery','customize-preview-widgets' ),
          '',
          true
    );
}
  • Can't use customize_preview_init as I need the script to run in the parent window. Not in the iframe. The customizer finishes loading with bit delay, adding dependencies doen't seem to work. – Sisir Jul 24 '15 at 11:17
0

Rather than trying to divine the mysteries of the customizer javascript initialization, which as you say is far from clear, you could use a custom control to inject your javascript, by overriding the render_content(), eg

add_action( 'customize_register', function ( $wp_customize ) {
    // Custom control.
    class PPL_Ninja_Skin_Select_Customize_Control extends WP_Customize_Control {
        public $type = 'select';

        // Override to inject our javascript.
        public function render_content() {
            parent::render_content();
            ?>
<script type="text/javascript">
(function () {
    var skin_select = $('#customize-control-ppl-ninja-theme-options-skin').find('select');
    var custom_group = [
        '#accordion-section-custom_header_styles',
        '#accordion-section-custom_slider_styles',
        '#accordion-section-custom_footer_styles',
        '#accordion-section-custom_general_colors'
    ];

    skin_select.change(function () {
        if ($(this).val() == 4) {
            $(custom_group.join(',')).hide();
        } else {
            $(custom_group.join(',')).show();
        }
    });
    skin_select.change();
}());
</script>
            <?php
        }
    }

    $wp_customize->add_setting( 'ppl-ninja-theme-options-skin' );
    $wp_customize->add_section( 'ppl-ninja-theme-options', array(
        'title' => __( 'Ninja Options', 'ppl' ),
    ) );

    // Add custom control.
    $wp_customize->add_control( new PPL_Ninja_Skin_Select_Customize_Control(
        $wp_customize, 'ppl-ninja-theme-options-skin', array(
            'label' => __( 'Skin', 'ppl' ),
            'section' => 'ppl-ninja-theme-options',
            'choices' => array(
                '' => __( 'Select', 'ppl' ),
                1 => __( 'One', 'ppl' ),
                2 => __( 'Two', 'ppl' ),
                3 => __( 'Three', 'ppl' ),
                4 => __( 'Four', 'ppl' ),
            ),
        )
    ) );

    // Test data.
    foreach ( array( 'header_styles', 'slider_styles', 'footer_styles', 'general_colors' ) as $setting ) {
        $wp_customize->add_setting( 'custom_' . $setting . '-setting' );
        $wp_customize->add_section( 'custom_' . $setting, array(
            'title' => sprintf( __( 'Ninja %s', 'ppl' ), $setting ),
        ) );
        $wp_customize->add_control( 'custom_' . $setting . '-setting', array (
            'label' => __( 'Setting', 'td' ),
            'section' => 'custom_' . $setting,
        ) );
    }
} );

(also don't bother with any CSS).

0

Although not a pretty solution, maybe you can sample it using window.setInterval() and once visible stop the interval and do whatever you want to do.

  • 1
    Yes, it was the backup solution ;) – Sisir Jul 26 '15 at 11:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.