使定制器部分可排序,但第一次移动项目时未排序的项目

时间:2021-08-14 作者:Divjot Singh

我试图在customizer中创建一个面板,其部分是可排序的,并且部分的顺序决定了它们在前端控制的区域的顺序。我提到了以下问题-possible to make sections in theme customizer sortable and saveable at publish button clicked?

一切似乎都很顺利。但是,当我尝试对元素进行排序时,排序第一次失败,并且项目不会更改其顺序。它在第二次之后正常工作。这是第一次引发问题。

下面是我用来添加节的PHP代码-

function itpg_front_page() {
    $wp_customize->add_panel(
        \'itpg_front_page\', array(
            \'title\'         =>  __(\'Front Page\', \'it-photographer\'),
            \'description\'   =>  __(\'Modules for the Static Front Page.<br/>Will work on Static Front page with Front Page Template set.\', \'it-photographer\'),
            \'priority\'      =>  30
        )
    );
    
    //Sections for te Panel. This is currently in default order but will vary depending on value of \'itpg_front_order\'
    
    $default_sections = array(
        
        \'itpg_hero\' => array(
            \'title\'         =>  __(\'Hero\', \'it-photographer\'),
            \'description\'   =>  \'\',
            \'panel\'         =>  \'itpg_front_page\'
        ),
    
        \'itpg_home_portfolio\' => array(
            \'title\'         =>  __(\'Projects\', \'it-photographer\'),
            \'description\'   =>  __(\'Jetpack needs to be installed and Portfolios need to be activated for this section to work\', \'it-photographer\'),
            \'panel\'         => \'itpg_front_page\'
        ),
    
        \'itpg_home_testimonial\' => array(
            \'title\'         =>  __(\'Testimonials\', \'it-photographer\'),
            \'description\'   =>  __(\'Jetpack needs to be installed and Testimonials need to be activated for this section to work\', \'it-photographer\'),
            \'panel\'         => \'itpg_front_page\'
        ),
    
        \'itpg_front_blog\' => array(
            \'title\'         =>  __(\'From the Blog\', \'it-photographer\'),
            \'description\'   =>  \'\',
            \'panel\'         =>  \'itpg_front_page\'
        ),
    
        \'itpg_cat_tabs\' => array(
            \'title\'         =>  __(\'Category Tabs\', \'it-photographer\'),
            \'description\'   =>  \'\',
            \'panel\'         =>  \'itpg_front_page\'
        ),
    
        \'itpg_counters\' => array(
            \'title\'         =>  __(\'Counters\', \'it-photographer\'),
            \'description\'   =>  \'\',
            \'panel\'         =>  \'itpg_front_page\'
        )
    );
    
    $sortable_sections = get_theme_mod(\'itpg_front_order\');
    
    if( !isset( $sortable_sections ) || empty( $sortable_sections ) ) {
        
        set_theme_mod( \'itpg_hidden_front_order\', implode(\',\', array_keys( $default_sections ) ) );
        $sortable_sections = get_theme_mod(\'itpg_front_order\');
        
    }
    
    $sortable_sections = explode(\',\', $sortable_sections );
    
    foreach( $sortable_sections as $sortable_section ){
        $wp_customize->add_section( $sortable_section, array(
            \'title\'       => $default_sections[$sortable_section][\'title\'],
            \'description\' => $default_sections[$sortable_section][\'description\'],
            \'panel\'       => \'itpg_front_page\'
        ) );
    }
    $wp_customize->add_section(
        \'itpg_hidden_front_order\', array(
        \'title\'     =>  __(\'Front Page Order\', \'it-photographer\'),
        \'panel\'     =>  \'itpg_panel_front_page\'
        )
    );
    $wp_customize->add_setting(
        \'itpg_front_order\', array(
            \'default\'   =>  \'\',
            \'sanitize_callback\' =>  \'sanitize_text_field\'
        )
    );

    $wp_customize->add_control(
        \'itpg_front_order\', array(
             \'type\'     =>  \'hidden\',
            \'section\'   =>  \'itpg_hidden_front_order\'
        )
    );

    ...Added Controls for the respective sections...

}
add_action(\'customize_register\', \'itpg_front_page\');
CSS nad JS文件在customizer中排队,使用customize_controls_enqueue_scripts -

function itpg_customize_control_scripts() {
    wp_enqueue_script( \'jquery-ui-sortable\' );
    wp_enqueue_script("itpg-customize-control-js", esc_url(get_template_directory_uri() . "/assets/js/customize_controls.js"), array(), ITPG_VERSION, true );
}
add_action("customize_controls_enqueue_scripts", "itpg_customize_control_scripts");

function itpg_custom_admin_styles() {
    wp_enqueue_style( \'itpg-admin-css\', esc_url( get_template_directory_uri() . \'/assets/theme-styles/css/admin.css\' ), array(), ITPG_VERSION );
}
add_action( \'admin_enqueue_scripts\', \'itpg_custom_admin_styles\' );
由于要使用可排序的jQuery插件,我从WordPress将其排队。

上述代码中有6个部分需要重新安排。我创建了另一个节,控件在其中存储节的顺序。

我使用CSS隐藏带有隐藏输入的部分。在管理中添加了以下代码。css-

li#accordion-section-itpg_hidden_front_order {
    display: none !important;
}
这是我在customize\\u控件中编写的JS代码。js-

jQuery(document).ready(function() {

 var frontPanel, frontSections, hiddenSection, hiddenAcc, order
    
frontPanel      = jQuery(\'#sub-accordion-panel-itpg_front_page\')
frontSections   = frontPanel.find(\'li[id^="accordion-section-"]\').not(\'#accordion-section-itpg_hidden_front_order\')
hiddenAcc       = jQuery(\'#accordion-section-itpg_hidden_front_order\')
hiddenPanel     = jQuery(\'#\' + hiddenAcc.attr(\'aria-owns\'));

//Added \'itpg_draggable\' class to all the visible sections
frontSections.each(function() {
    jQuery(this).addClass(\'itpg_draggable\') 
})

//Initialised the sortable for all items containing \'itpg_draggable\' class
frontPanel.sortable({
    item: \'li.itpg_draggable\',
    axis: \'y\',
    stop: function( event, ui ) {
        getOrder()
    }
})

//Get ids of all the sections of Front Page and save them in the \'itpg_front_order\' setting
const getOrder = () => {
    
    order = frontPanel.find(\'.itpg_draggable\').map( function() {
        
        var id = jQuery(this).attr(\'id\'),
            id = id.replace(\'accordion-section-\',\'\');
        
        return id;
    }).get().join(\',\');
    
    //Save the value in the hidden input field
    hiddenPanel.find(\'input\').prop(\'value\', order)

    //Make sure to trigger the change event to enable the Publish Button
    hiddenPanel.find(\'input\').trigger(\'change\')
    
}
}
当我注释掉用于让Publish按钮知道需要保存更改的触发事件时,它工作正常,但无法保存设置。

任何帮助都将不胜感激!谢谢

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

我认为您的问题可能是您没有设置priority 在DOM中手动更改其顺序后,这些部分中的一部分将被删除,因此一旦控件UI刷新,手动更改可能会丢失。

您的代码也可以通过不必注册隐藏节或控件来简化。您可以只注册一个包含主题mod的设置,并通过Customizer API直接更新它,而无需触发对输入的更改。

以下是简化的JS代码:

wp.customize.bind( \'ready\', () => {
    const orderSetting = wp.customize( \'itpg_front_order\' );
    const panel = wp.customize.panel( \'itpg_front_page\' );

    panel.contentContainer.sortable({
        item: \'.control-section\',
        axis: \'y\',
        stop: () => {
            // Get the sections in the new order.
            const newlySortedSections = [ ...panel.sections() ].sort( ( a, b ) => {
                return a.container.index() - b.container.index();
            } );

            // Persist the new order as part of the changeset (and trigger preview update).
            orderSetting.set(
                newlySortedSections.map( ( section ) => section.id ).join( \',\' )
            );
        }
    });

    // When the order setting is updated, make sure the sections get the appropriate priorities.
    // By setting the priorities in this way, the setting can be updated programmatically and the UI will
    // update accordingly. This two-way data binding.
    orderSetting.bind( ( newOrder ) => {
        const newlyOrderedSections = newOrder.split( /,/ ).map( ( sectionId ) => wp.customize.section( sectionId ) );
        newlyOrderedSections.forEach( ( section, i ) => {
            section.priority( i );
        } );
    } );
} );
假设JS代码存储在customize-controls.js 插件中的文件:

add_action(
    \'customize_controls_enqueue_scripts\',
    static function() {
        wp_enqueue_script(
            \'itpg-customize-control-js\',
            plugin_dir_url( __FILE__ ) . \'customize-controls.js\',
            array( \'jquery-ui-sortable\', \'customize-controls\' ),
            false,
            true
        );
    }
);
然后,这里是注册自定义程序面板、节和设置的更新逻辑:

add_action(
    \'customize_register\',
    static function ( WP_Customize_Manager $wp_customize ) {
        $panel = $wp_customize->add_panel(
            \'itpg_front_page\',
            array(
                \'title\'       => __( \'Front Page\', \'it-photographer\' ),
                \'description\' => __( \'Modules for the Static Front Page.<br/>Will work on Static Front page with Front Page Template set.\', \'it-photographer\' ),
                \'priority\'    => 30,
            )
        );

        $sections = array(
            \'itpg_hero\' => array(
                \'title\'       => __( \'Hero\', \'it-photographer\' ),
                \'description\' => \'\',
                \'panel\'       => \'itpg_front_page\'
            ),

            \'itpg_home_portfolio\' => array(
                \'title\'       => __( \'Projects\', \'it-photographer\' ),
                \'description\' => __( \'Jetpack needs to be installed and Portfolios need to be activated for this section to work\', \'it-photographer\' ),
                \'panel\'       => \'itpg_front_page\'
            ),

            \'itpg_home_testimonial\' => array(
                \'title\'       => __( \'Testimonials\', \'it-photographer\' ),
                \'description\' => __( \'Jetpack needs to be installed and Testimonials need to be activated for this section to work\', \'it-photographer\' ),
                \'panel\'       => \'itpg_front_page\'
            ),

            \'itpg_front_blog\' => array(
                \'title\'       => __( \'From the Blog\', \'it-photographer\' ),
                \'description\' => \'\',
                \'panel\'       => \'itpg_front_page\'
            ),

            \'itpg_cat_tabs\' => array(
                \'title\'       => __( \'Category Tabs\', \'it-photographer\' ),
                \'description\' => \'\',
                \'panel\'       => \'itpg_front_page\'
            ),

            \'itpg_counters\' => array(
                \'title\'       => __( \'Counters\', \'it-photographer\' ),
                \'description\' => \'\',
                \'panel\'       => \'itpg_front_page\'
            )
        );

        $theme_mod_id  = \'itpg_front_order\';
        $section_order = get_theme_mod( $theme_mod_id, array_keys( $sections ) );

        foreach ( $sections as $section_id => $section ) {
            $section = $wp_customize->add_section(
                $section_id,
                array(
                    \'title\'       => $section[\'title\'],
                    \'description\' => $section[\'description\'],
                    \'panel\'       => $panel->id,

                    // Note the order here will change based on what was saved in the theme mod.
                    \'priority\'    => (int) array_search( $section_id, $section_order, true ),
                )
            );

            // Add control to each section just so that it is not hidden.
            // Actual controls would be registered here instead.
            $wp_customize->add_control(
                "{$section->id}-placeholder",
                [
                    \'label\'       => \'Placeholder\',
                    \'description\' => \'This control is registered purely to make the section not be hidden.\',
                    \'type\'        => \'text\',
                    \'section\'     => $section->id,
                    \'settings\'    => [],
                ]
            );
        }

        // Register a setting for the theme mod which contains the section order.
        $wp_customize->add_setting(
            $theme_mod_id,
            array(
                \'type\'              => \'theme_mod\',
                \'default\'           => $section_order,
                \'sanitize_callback\' => function ( $value) use ( $sections ) {
                    return array_intersect(
                        explode( \',\', $value ),
                        array_keys( $sections )
                    );
                },
            )
        );
    }
);

相关推荐