javascript - Woocommerce 2 Variable Product Dropdown List, force first one to always show all options

811

I have 2 drop down select fields in my variable WooCommerce product.

1st one is Type of Product (in my case framed or unframed artwork) 2nd one is Size of Artwork.

Thanks to this code:

add_filter( 'woocommerce_dropdown_variation_attribute_options_args', 'dropdown_variation_attribute_options', 10, 1 );
function dropdown_variation_attribute_options( $args ){

    // For attribute "Type"
    if( 'Type' == $args['attribute'] )
        $args['show_option_none'] = __( 'Select Framed or Unframed Artwork', 'woocommerce' );

    // For attribute "Sizes"
    if( 'Size' == $args['attribute'] )
        $args['show_option_none'] = __( 'Select Size of Artwork', 'woocommerce' );

    return $args;
}

I can display the default text when nothing has been selected for each drop down select field individually.

The problem I have now is that I need to force the 1st drop down list to always show all options and when a selection is made, to reset the 2nd one.

Example:

I offer Variation A,B,C,D in the first drop down list. The 2nd Drop down list would have variations 1,2,3,4.

Lets say i choose A, the second drop down select field will now limit the options to 1 and 3 as A is not available with 2 and 4.

Lets say i choose 3 now in the 2nd drop down select field, which will limit the first drop down select field's choices to A and B as C and D are not available in 3.

But i need to see C and D as well in the first one so people can always start from the beginning when they choose a product.

Any help will be appreciated.

985

Answer

Solution:

Please check below code. Hope this would help you.

jQuery(document).ready(function($){
    if (jQuery('form.variations_form').length) {
        let $form              = jQuery('form.variations_form');
        let $first_attr_select = $form.find( '.variations select' ).eq(0);
        let first_attr_val     = $first_attr_select.val() || '';

        $first_attr_select.on('change', function(e){
            if (!e.isTrigger) {
                // store the real value only
                first_attr_val = this.value;
            }
        });

        $form.on('woocommerce_update_variation_values', function(){
            let first_attr_name       = $first_attr_select.data( 'attribute_name' ) || $first_attr_select.attr( 'name' ),
                show_option_none        = $first_attr_select.data( 'show_option_none' ),
                option_gt_filter        = ':gt(0)',
                attached_options_count  = 0,
                new_attr_select         = $( '<select/>' ),
                first_attr_val_valid = true;

            let variations          = $form.data('product_variations');

            new_attr_select.html( $first_attr_select.data( 'attribute_html' ) );

            // Loop through variations.
            for ( let variation of variations ) {
                if ( typeof( variation ) !== 'undefined' && first_attr_name in variation.attributes ) {
                    let attr_val         = variation.attributes[ first_attr_name ],
                        variation_active = variation.variation_is_active ? 'enabled' : '';

                    if ( attr_val ) {
                        // Decode entities.
                        attr_val = $( '<div/>' ).html( attr_val ).text();

                        // Attach to matching options by value. This is done to compare
                        // TEXT values rather than any HTML entities.
                        var $option_elements = new_attr_select.find( 'option' );
                        for (var i = 0, len = $option_elements.length; i < len; i++) {
                            var $option_element = $( $option_elements[i] ),
                                option_value = $option_element.val();

                            if ( attr_val === option_value ) {
                                $option_element.addClass( 'attached ' + variation_active );
                                break;
                            }
                        }
                    } else {
                        // Attach all apart from placeholder.
                        new_attr_select.find( 'option:gt(0)' ).addClass( 'attached ' + variation_active );
                    }
                }
            }

            // Count available options.
            attached_options_count = new_attr_select.find( 'option.attached' ).length;

            // Check if current selection is in attached options.
            if ( first_attr_val ) {
                first_attr_val_valid = false;

                if ( 0 !== attached_options_count ) {
                    new_attr_select.find( 'option.attached.enabled' ).each( function() {
                        var option_value = $( this ).val();

                        if ( first_attr_val === option_value ) {
                            first_attr_val_valid = true;
                            return false; // break.
                        }
                    });
                }
            }

            // Detach the placeholder if:
            // - Valid options exist.
            // - The current selection is non-empty.
            // - The current selection is valid.
            // - Placeholders are not set to be permanently visible.
            if ( attached_options_count > 0 && first_attr_val && first_attr_val_valid && ( 'no' === show_option_none ) ) {
                new_attr_select.find( 'option:first' ).remove();
                option_gt_filter = '';
            }

            // Detach unattached.
            new_attr_select.find( 'option' + option_gt_filter + ':not(.attached)' ).remove();

            // Finally, copy to DOM and set value.
            $first_attr_select.html( new_attr_select.html() );
            $first_attr_select.find( 'option' + option_gt_filter + ':not(.enabled)' ).prop( 'disabled', true );

            // Choose selected value.
            if ( first_attr_val ) {
                // If the previously selected value is no longer available, fall back to the placeholder (it's going to be there).
                if ( first_attr_val_valid ) {
                    $first_attr_select.val( first_attr_val );
                } else {
                    $first_attr_select.val( '' ).change();
                }
            } else {
                $first_attr_select.val( '' ); // No change event to prevent infinite loop.
            }

        });
    }
});

People are also looking for solutions to the problem: php - Mysqli_error() returns a blank page

Source

Didn't find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.

Ask a Question

Write quick answer

Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.

Similar questions

Find the answer in similar questions on our website.