Jump to content
thirty bees forum

Recommended Posts

Posted

I've been playing around with this idea for 2 days.

Up until now I've always used dropdowns for my size selections but I would like to make them buttons. Of course thirty bees does not offer such thing currently.

I tried editing the radio button case in product.tpl to display bootstrap buttons and hide the circle. Some js, some css and it works for Niara:

Product.tpl changes:

{elseif ($group.group_type == 'radio')}
  <div id="product-options" class="btn-group" data-toggle="buttons">
    {foreach from=$group.attributes key=id_attribute item=group_attribute}
      <label class="btn btn-outline-primary {if ($group.default == $id_attribute)} active{/if}" for="group_{$id_attribute}">
        <input type="radio" id="group_{$id_attribute}" class="d-none" name="{$groupName|escape:'html':'UTF-8'}" value="{$id_attribute}" {if ($group.default == $id_attribute)} checked="checked"{/if} autocomplete="off">
        {$group_attribute|escape:'html':'UTF-8'}
      </label>
    {/foreach}
  </div>
{/if}

Additional css in my example to make them 'table-like' (when I have mutliple sizes): 

/* Ensure buttons behave like inline blocks and center content */
#product-options .btn {
  display: inline-block; /* Inline block to align buttons horizontally */
  padding-left: 10px !important;
  padding-right: 10px !important;/* Adjust padding as needed */
  text-align: center; /* Center text horizontally */
  border: 1px solid #ccc; /* Border style */
  background-color: white; /* Background color */
  color: #333; /* Text color */
  border-radius: 3px; /* Rounded corners */
  margin: 3px; /* Space between buttons */
  min-width: 65px; /* Ensure minimum button width */
  white-space: nowrap; /* Prevent text wrapping */
  transition: background-color 0.3s ease; /* Smooth background transitions */
  outline: none; /* Remove focus outline */
  box-shadow: none !important; /* Remove any shadow */
}

/* Style for the selected state (checked radio button) */
#product-options .btn.active {
  background-color: #43b775; /* Green background for active buttons */
  color: white; /* White text for active buttons */
  border-color: #ccc; /* Keep the border color unchanged */
  box-shadow: none !important; /* Remove any box-shadow on active buttons */
}

/* Hover effect for inactive buttons */
#product-options .btn:hover {
  background-color: #d3d3d3; /* Light grey background on hover */
  color: #333; /* Keep the original text color on hover */
  border-color: #ccc; /* Keep the same border color as unselected buttons */
  box-shadow: none !important; /* Remove any box-shadow on hover */
}

/* Remove the black frame (focus outline) */
#product-options .btn:focus, #product-options .btn:active {
  outline: none; /* Remove the black focus/active border */
  box-shadow: none !important; /* Remove any shadow effect */
}

/* Style the radio button (which is hidden) */
#product-options input[type="radio"] {
  position: absolute;
  opacity: 0;
}

/* Ensure uniform text size */
#product-options .btn .label-text {
  font-weight: bold; /* Bold text */
  display: inline-block;
  width: 100%;
  text-align: center;
}

Additinal js to assign the selected button to the radio buttons and sort the buttons alphabetically (as they appear in the order they are created in BO, unlike with dropdown where it sorts them):

 

document.addEventListener('DOMContentLoaded', function() {
    const productOptionsContainer = document.querySelector('#product-options');
    
    if (productOptionsContainer) {
        const buttons = productOptionsContainer.querySelectorAll('.btn');
        
        buttons.forEach(function(button) {
            button.addEventListener('click', function() {
                buttons.forEach(function(btn) {
                    btn.classList.remove('active');
                });
                
                button.classList.add('active');
                
                const radioInput = button.querySelector('input[type="radio"]');
                if (radioInput) {
                    radioInput.checked = true;
                    
                    // Manually trigger the combination update in Thirty Bees
                    if (typeof findCombination === "function") {
                        findCombination();
                    }
                }
            });
        });
    }
});


document.addEventListener('DOMContentLoaded', function() {
    const productOptionsContainer = document.querySelector('#product-options');

    if (productOptionsContainer) {
        const buttons = Array.from(productOptionsContainer.querySelectorAll('.btn')); // Get all buttons
        
        // Extract the text values and sort them numerically or alphabetically
        buttons.sort((a, b) => {
            let valueA = a.textContent.trim();
            let valueB = b.textContent.trim();
            
            // Convert to numbers if possible, else compare as strings
            if (!isNaN(valueA) && !isNaN(valueB)) {
                return parseFloat(valueA) - parseFloat(valueB);
            } else {
                return valueA.localeCompare(valueB);
            }
        });

        // Clear the container and re-append sorted buttons
        productOptionsContainer.innerHTML = '';
        buttons.forEach(button => productOptionsContainer.appendChild(button));
    }
});

The issue is that this change does not work with Warehouse theme, I'm unable to make the button change the active combination, also the sorting does not work.

My questions are:
1. Which functions were changed for detecting the combinations in this section? Currently Warehouse's implementation only adds to the cart the default combination so the js I have here does not work.

2. Can we move the sorting in the core for radio buttons? Currently it's done with a js during the output.

3. Is somebody else interested in such development and migration of the community themes? Are there people that use radio buttons in their pages in 2024? If we implement something similar for FO, the BO should still refer to them as 'radio buttons' as this is interwoven in many many parts of the system.

4. Can this be pulled into a module that replaces this part of the theme so this module could be theme-agnostic? Something similar to https://addons.prestashop.com/it/combinazioni-personalizzazione/49820-product-combination-images-swatch-attributes.html but for the buttons.

5. Shopify has a nice functionality - Swatch King - if we can implement something similar it will be nice - https://apps.shopify.com/variant-swatch-king

The PS module and this also implement color swatches for combinations. The color swatches per combination is also a nice feature to have.
image.thumb.png.6447fdfa5f2b30545c3461bc6f2ca925.png
image.thumb.png.0f46092a009269ed504b63614c1ab7a5.png

  • Like 2
Posted (edited)

I did something a little different, but similar within the warehouse theme. It's not perfect, but works pretty well still. It's a construct of CSS and JS primarily on the radios. It was with @wakabayashi's help. You can see the result here https://twighockeycompany.com/hockey-sticks/senior-sticks/rogue-c-hockey-stick-senior

document.querySelector('#buy_block').addEventListener("click", function(event) {
    updateLabelsSelectedClass();
});

updateLabelsSelectedClass();

function updateLabelsSelectedClass() {

    var attributes_options = document.querySelectorAll('#attributes input');

    if (attributes_options) {
        attributes_options.forEach(function (element) {
            var label = element.closest('li').querySelector('label');
            if (label) {
                (element.checked) ? label.classList.add('labelSelected') : label.classList.remove('labelSelected');
            }
        })
    }
}

 

 

Edited by x97wehner
  • Like 2
Posted

Something that I think is working, of course not perfect as some things are done in js and not at backend but...

Warehouse's product.tpl

{elseif ($group.group_type == 'radio')}
	<div id="product-options">
		{foreach from=$group.attributes key=id_attribute item=group_attribute}
			<input type="radio" id="attribute_{$id_attribute}" class="attribute_radio" name="{$groupName|escape:'html':'UTF-8'}" value="{$id_attribute}" {if ($group.default == $id_attribute)} checked="checked"{/if} hidden />
			<label for="attribute_{$id_attribute}" class="btn {if $group.default == $id_attribute}active{/if}">
				<span class="label-text">{$group_attribute|escape:'html':'UTF-8'}</span>
			</label>
		{/foreach}
	</div>
{/if}

css:
 

/* Warehouse buttons css START */

/* Ensure buttons behave like inline blocks and center content */
#product-options .btn {
  display: inline-block; 
  padding-left: 10px !important;
  padding-right: 10px !important;
  text-align: center;
  border: 1px solid #ccc;
  border-color: #ccc;
  background-color: white;
  color: #333;
  font-weight: normal;
  margin: 3px;
  min-width: 65px;
  white-space: nowrap;
  transition: background-color 0.3s ease;
  outline: none;
  box-shadow: none !important;
}

/* Style for the selected state (checked radio button) */
#product-options .btn.active {
  background-color: #55c65e;
  color: white;
}

/* Hover effect for inactive buttons */
#product-options .btn:hover {
  background-color: #d3d3d3;
}

/* Style the radio button (which is hidden) */
#product-options input[type="radio"] {
  position: absolute;
  opacity: 0;
}

/* Ensure uniform text size */
#product-options .btn .label-text {
  display: inline-block;
  width: 100%;
  text-align: center;
}

/* Warehouse buttons css END */

js:
 

$(document).ready(function () {

    // Handling click events for selecting attributes
    $('#product-options .btn').on('click', function () {
        $(this).siblings('.btn').removeClass('active');
        $(this).addClass('active');
        $(this).prev('input[type="radio"]').prop('checked', true).trigger('change');

        // Trigger PrestaShop's findCombination to update the combination details
        findCombination();
    });

});

I would like to move the sorting to BO but for now it is what it is.

EDIT: Corrected code as there was no need to reorder using js.

image.thumb.png.de90f6680fc2d950c7951eb5b8108f84.png

Posted

did you try to set the desire position of each attribute in the back office?

based on the code it should works fine.

ORDER BY ag.`position` ASC, a.`position` ASC, agl.`name` ASC';

unless you have an override for ProductController "assignAttributesGroups" or Product class "getAttributesGroups"

Posted

Thanks for your reply!

It does not sort them. They are displayed in the order I have added them to the product:

image.png.571b2fc694700154a337cf9c7c6de22d.png
image.png.02727435aaa4b0e38db20914e3ef4867.png

I was under the impression that the drop-down is also sorted but no, when I add them assorted in BO, they appear assorted in FO.

image.png.ce2edc01949ade9de35cdd352a866e44.png
 

image.png

Posted
16 minutes ago, the.rampage.rado said:

It does not sort them. They are displayed in the order I have added them to the product

I checked on TB 1.6 and sorting attribute values in BO by “Position” also works correctly on the front end on the product page.

  • Like 1
Posted
1 hour ago, Yabber said:

I checked on TB 1.6 and sorting attribute values in BO by “Position” also works correctly on the front end on the product page.

Just a quick question - if you add your attributes in random order in BO so they look like this in Product->Attributes:

image.png.59496f9014c1eaa19424d422746a7aed.png

You see them in FO ordered, right?

EDIT: just tested a brand new install - yes, they are ordering in FO.

Posted

@the.rampage.rado The order of attribute combinations in the product configuration has no meaning. If I change the “Position” in the attribute values then the order on the store front changes identically.

  • Like 1

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...