我正在尝试重新设计 woocommerce 单个产品页面,而不是显示变体选项的下拉列表,我希望它们被放置在单独的 div 中并并排显示在 flex 框中。我不明白是什么部分使数据采用“下拉列表”形式?
说明我想要实现的目标:
这是 html 部分(取自包含文件夹内的 wc-template-functions.php),我需要将每个变体插入单独的 div 中,而不是选择和选项标签。我真的需要这个。有什么帮助吗?
这是我在 woocommerce -> includes -> wc-template-functions.php 中的尝试,在 function wc_dropdown_variation_attribute_options 中。它显示了变体,但它们不可点击,并且无法在添加到购物车/立即购买事件时提取数据以进行选择和转发:
function wc_dropdown_variation_attribute_options( $args = array() ) {
$args = wp_parse_args(
apply_filters( 'woocommerce_dropdown_variation_attribute_options_args', $args ),
array(
'options' => false,
'attribute' => false,
'product' => false,
'selected' => false,
'name' => '',
'id' => '',
'class' => '',
)
);
// Get selected value.
if ( false === $args['selected'] && $args['attribute'] && $args['product'] instanceof WC_Product ) {
$selected_key = 'attribute_' . sanitize_title( $args['attribute'] );
// phpcs:disable WordPress.Security.NonceVerification.Recommended
$args['selected'] = isset( $_REQUEST[ $selected_key ] ) ? wc_clean( wp_unslash( $_REQUEST[ $selected_key ] ) ) : $args['product']->get_variation_default_attribute( $args['attribute'] );
// phpcs:enable WordPress.Security.NonceVerification.Recommended
}
$options = $args['options'];
$product = $args['product'];
$attribute = $args['attribute'];
$name = $args['name'] ? $args['name'] : 'attribute_' . sanitize_title( $attribute );
$id = $args['id'] ? $args['id'] : sanitize_title( $attribute );
$class = $args['class'];
if ( empty( $options ) && ! empty( $product ) && ! empty( $attribute ) ) {
$attributes = $product->get_variation_attributes();
$options = $attributes[ $attribute ];
}
if ( ! empty( $options ) ) {
if ( $product && taxonomy_exists( $attribute ) ) {
// Get terms if this is a taxonomy - ordered. We need the names too.
$terms = wc_get_product_terms(
$product->get_id(),
$attribute,
array(
'fields' => 'all',
)
);
foreach ( $terms as $term ) {
if ( in_array( $term->slug, $options, true ) ) {
$html .= '<div value="' . esc_attr( $term->slug ) . '" ' . selected( sanitize_title( $args['selected'] ), $term->slug, false ) . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $term->name, $term, $attribute, $product ) ) . '</div>';
}
}
} else {
foreach ( $options as $option ) {
// This handles < 2.4.0 bw compatibility where text attributes were not sanitized.
$selected = sanitize_title( $args['selected'] ) === $args['selected'] ? selected( $args['selected'], sanitize_title( $option ), false ) : selected( $args['selected'], $option, false );
$html .= '<div value="' . esc_attr( $option ) . '" ' . $selected . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $option, null, $attribute, $product ) ) . '</div>';
}
}
}
$html .= '</div>';
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo apply_filters( 'woocommerce_dropdown_variation_attribute_options_html', $html, $args );
}
答案 0 :(得分:1)
我想过不使用任何钩子将属性选择选项转换为单独的 div。我宁愿使用 jQuery。
<块引用>原因很简单。 WooCommerce 使用几个基于 选择选项元素,并用 div 替换选项可以 产生意外冲突。
想法是这样的:创建选择选项产品属性的副本 (对用户隐藏) 并替换 div 中的所有选择选项通过 jQuery unwrap()
函数。我的灵感来自这个答案:Is it possible to convert a select menu to buttons?
每个产品属性的所有select选项都会转成div(甚至不止一个)。
之前的代码不允许自动隐藏与任何产品变体不对应的属性选项 (div)。代码现已更新,允许用户:
该代码适用于产品页面上的任意数量的属性。
JQUERY
add_action( 'wp_footer', 'converts_product_attributes_from_select_options_to_div' );
function converts_product_attributes_from_select_options_to_div() {
?>
<script type="text/javascript">
jQuery(function($){
// clones select options for each product attribute
var clone = $(".single-product div.product table.variations select").clone(true,true);
// adds a "data-parent-id" attribute to each select option
$(".single-product div.product table.variations select option").each(function(){
$(this).attr('data-parent-id',$(this).parent().attr('id'));
});
// converts select options to div
$(".single-product div.product table.variations select option").unwrap().each(function(){
if ( $(this).val() == '' ) {
$(this).remove();
return true;
}
var option = $('<div class="custom_option is-visible" data-parent-id="'+$(this).data('parent-id')+'" data-value="'+$(this).val()+'">'+$(this).text()+'</div>');
$(this).replaceWith(option);
});
// reinsert the clone of the select options of the attributes in the page that were removed by "unwrap()"
$(clone).insertBefore('.single-product div.product table.variations .reset_variations').hide();
// when a user clicks on a div it adds the "selected" attribute to the respective select option
$(document).on('click', '.custom_option', function(){
var parentID = $(this).data('parent-id');
if ( $(this).hasClass('on') ) {
$(this).removeClass('on');
$(".single-product div.product table.variations select#"+parentID).val('').trigger("change");
} else {
$('.custom_option[data-parent-id='+parentID+']').removeClass('on');
$(this).addClass('on');
$(".single-product div.product table.variations select#"+parentID).val($(this).data("value")).trigger("change");
}
});
// if a select option is already selected, it adds the "on" attribute to the respective div
$(".single-product div.product table.variations select").each(function(){
if ( $(this).find("option:selected").val() ) {
var id = $(this).attr('id');
$('.custom_option[data-parent-id='+id+']').removeClass('on');
var value = $(this).find("option:selected").val();
$('.custom_option[data-parent-id='+id+'][data-value='+value+']').addClass('on');
}
});
// when the select options change based on the ones selected, it shows or hides the respective divs
$('body').on('check_variations', function(){
$('div.custom_option').removeClass('is-visible');
$('.single-product div.product table.variations select').each(function(){
var attrID = $(this).attr("id");
$(this).find('option').each(function(){
if ( $(this).val() == '' ) {
return;
}
$('div[data-parent-id="'+attrID+'"][data-value="'+$(this).val()+'"]').addClass('is-visible');
});
});
});
});
</script>
<?php
}
代码已经过测试并且可以工作。将它添加到您的活动主题的functions.php。
CSS
/* adds style to divs */
/* by default all divs are hidden */
div.custom_option {
display: none;
border: 2px solid #ccc;
margin-right: 5px;
padding: 2px 5px;
cursor: pointer;
}
/* show only divs with class "is-visible" */
div.custom_option.is-visible {
display:inline-block;
}
/* adds the style to the selected div */
div.custom_option.on {
background-color: #777;
color: white;
}
在活动主题的样式表中添加 CSS。
之前
之后