我试图在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按钮知道需要保存更改的触发事件时,它工作正常,但无法保存设置。
任何帮助都将不胜感激!谢谢
最合适的回答,由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 )
);
},
)
);
}
);