Skip to content

Instantly share code, notes, and snippets.

@emilushi
Created May 2, 2019 11:29
Show Gist options
  • Select an option

  • Save emilushi/7e1acc2417371a640c543324ff2465a1 to your computer and use it in GitHub Desktop.

Select an option

Save emilushi/7e1acc2417371a640c543324ff2465a1 to your computer and use it in GitHub Desktop.
Convert WooCommerce variations to custom radio input.
<?php
/**
* Output radio buttons on WooCommerce variations.
*/
add_filter('woocommerce_dropdown_variation_attribute_options_html', static function ($html, $args) {
/** @var array $args */
$args = wp_parse_args(apply_filters('woocommerce_dropdown_variation_attribute_options_args', $args), [
'options' => false,
'attribute' => false,
'product' => false,
'selected' => false,
'name' => '',
'id' => '',
'class' => '',
'show_option_none' => __('Choose an option', 'woocommerce'),
]);
/** @var WC_Product_Variable $product */
$options = $args['options'];
$product = $args['product'];
$attribute = $args['attribute'];
$name = $args['name'] ?: 'attribute_'.sanitize_title($attribute);
$id = $args['id'] ?: sanitize_title($attribute);
$class = $args['class'];
$show_option_none = (bool)$args['show_option_none'];
// We'll do our best to hide the placeholder, but we'll need to show something when resetting options.
$show_option_none_text = $args['show_option_none'] ?: __('Choose an option', 'woocommerce');
// Get selected value.
if ($attribute && $product instanceof WC_Product && $args['selected'] === false) {
$selected_key = 'attribute_'.sanitize_title($attribute);
$args['selected'] = isset($_REQUEST[$selected_key]) ? wc_clean(wp_unslash($_REQUEST[$selected_key]))
: $product->get_variation_default_attribute($attribute); // WPCS: input var ok, CSRF ok, sanitization ok.
}
if (empty($options) && ! empty($product) && ! empty($attribute)) {
$attributes = $product->get_variation_attributes();
$options = $attributes[$attribute];
}
$radios = '<div class="custom-wc-variations">';
if ( ! empty($options)) {
if ($product && taxonomy_exists($attribute)) {
$terms = wc_get_product_terms($product->get_id(), $attribute, ['fields' => 'all']);
foreach ($terms as $term) {
if (in_array($term->slug, $options, true)) {
$radios .= '<input type="radio" name="custom_'.esc_attr($name).'" data-value="'.esc_attr($term->slug).'" id="'
.esc_attr($name).'_'.esc_attr($term->slug).'" data-variation-name="'.esc_attr($name).'" '
.checked(sanitize_title($args['selected']), $term->slug, false).'>';
$radios .= '<label for="'.esc_attr($name).'_'.esc_attr($term->slug).'">';
$radios .= esc_html(apply_filters('woocommerce_variation_option_name', $term->name));
$radios .= '</label>';
}
}
} else {
foreach ($options as $option) {
$checked = sanitize_title($args['selected']) === $args['selected'] ? checked($args['selected'],
sanitize_title($option), false) : checked($args['selected'], $option, false);
$radios .= '<input type="radio" name="custom_'.esc_attr($name).'" data-value="'.esc_attr($option).'" id="'
.esc_attr($name).'_'.esc_attr($option).'" data-variation-name="'.esc_attr($name).'" '.$checked.'>';
$radios .= '<label for="'.esc_attr($name).'_'.esc_attr($option).'">';
$radios .= esc_html(apply_filters('woocommerce_variation_option_name', $option));
$radios .= '</label>';
}
}
}
$radios .= '</div>';
return $html.$radios;
}, 20, 2);
(function ($) {
$(document).ready(function () {
const customVariations = document.getElementsByClassName('custom-wc-variations');
if (customVariations.length > 0) {
Array.from(customVariations).forEach(function (variation) {
const radios = variation.querySelectorAll('input[type=radio]');
radios.forEach(function (radio) {
radio.addEventListener('change', function () {
const variationName = radio.getAttribute('data-variation-name');
const selectBox = document.querySelector('select[name=' + variationName + ']');
selectBox.value = radio.getAttribute('data-value');
$(selectBox).trigger('change');
});
});
});
}
});
})(jQuery);
@javadfathy
Copy link

hi emilushi
tanks for this code

why not change price when change attribute in shop page?

@NosyEnthusiast
Copy link

This works! Thank you very much.

I just have a suggestion. It would be nice if the display only showed the available variations. For instance, if I have a black T-shirt in Small, Medium, and Large, and a white T-shirt in Small and Large, the Medium label for the white T-shirt is still showing.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment