wpdreams / ajax-search-pro-development

Issues and dev tracking repository for Ajax Search Pro for WordPress plugin
0 stars 0 forks source link

Make Frontend Search Settings Options Dropdown Also an Option Label #112

Open seranca opened 1 month ago

seranca commented 1 month ago

Is your feature request related to a problem? Please describe.

Currently, we can only configure the Frontend Search Settings as a dropdown button. This limitation makes it challenging to create a more user-friendly and aesthetically pleasing search bar where the settings are represented as an option label.

image

Attempting to convert the dropdown into an option label involves the following steps:

  1. Deactivating the search settings switch on the front end.
  2. Setting the search settings to be visible by default.
  3. Configuring the search settings position to "Block" or "Custom".

image

However, the result is not visually appealing or easily customizable:

image

While it is possible to modify the CSS on the front end, these changes often get overwritten, making it difficult to achieve the desired appearance.

Describe the solution you'd like

I would like to have a search bar where the front-end settings are presented as an option label, similar to the Amazon search bar. This approach allows the overall width to remain the same, with only the text of the option label changing dynamically.

Here is an example of the desired design:

image

In this design, the width of the search bar stays consistent, and only the text from the option label increases:

image image

Describe alternatives you've considered

  1. Providing the ability to highly customize the CSS and ensuring these customizations persist.
  2. Integrating with Elementor to allow for more customization options during site development.
  3. Creating a theme builder as the current Theme & Styling Options lack many necessary features.

Additional context

Please use the Amazon search bar as a reference for the desired functionality and design.

seranca commented 1 month ago

When trying to implement this feature by myself, I came across additional problems: the variable boxheight, which controls the height of the search box and other features, is hardcoded in pixels. This is causing issues with aligning the search options and the search box.

Ideally, we would want it to have a height of 100% of the parent container. This way, we can control the height of both the search options (asp_dropdown_filter_box) and the search input (probox).

seranca commented 1 month ago

This is the code sample which may allow a regular option label to have a dinamic width (TEST IT ) :

<!DOCTYPE html>
<html lang="en">
<body>
<select id="dynamic-width-select">
    <option value="short">Short Text</option>
    <option value="medium">Medium Length Text</option>
    <option value="long">Longer Text Example</option>
</select>
<script>
document.addEventListener('DOMContentLoaded', function() {
    const selectElement = document.getElementById('dynamic-width-select');
    const measureSpan = document.createElement('span');

    // Apply styles to mimic select option text styling
    measureSpan.style.visibility = 'hidden';
    measureSpan.style.position = 'absolute';
    measureSpan.style.whiteSpace = 'nowrap';
    document.body.appendChild(measureSpan);

    function updateSelectWidth() {
        const selectedOption = selectElement.options[selectElement.selectedIndex].text;
        measureSpan.textContent = selectedOption;
        selectElement.style.width = `${measureSpan.offsetWidth + 20}px`; // Add extra pixels for padding
    }

    // Initial width update
    updateSelectWidth();

    // Update width on option change
    selectElement.addEventListener('change', updateSelectWidth);
});
</script>
</body>
</html>

I found it was quite problematic to implement since the plugin is adding the option label (dropdow options) via AJAX

I ended up with the following working script:

document.addEventListener('DOMContentLoaded', function() {
    function updateSelectWidth(selectElement) {
        const measureSpan = document.createElement('span');
        measureSpan.style.visibility = 'hidden';
        measureSpan.style.position = 'absolute';
        measureSpan.style.whiteSpace = 'nowrap';
        document.body.appendChild(measureSpan);

        const selectedOption = selectElement.options[selectElement.selectedIndex].text;
        measureSpan.textContent = selectedOption;
        const newWidth = measureSpan.offsetWidth + 40; // Extra padding for aesthetic spacing
        selectElement.style.width = `${newWidth}px`;
        selectElement.style.height = '100%'; // Set height to 100%

        // Traverse up and update all parent elements including the specified container
        let currentElement = selectElement.parentElement;
        while (currentElement && !currentElement.matches('body')) { // Now stops at the <body>, encompassing all elements
            currentElement.style.width = `${newWidth}px`;
            currentElement.style.height = '100%'; // Set height to 100% for each parent element
            if (currentElement.classList.contains('elementor-element')) {
                break; // Stop after updating the specific target element
            }
            currentElement = currentElement.parentElement;
        }

        document.body.removeChild(measureSpan); // Clean up
    }

    const observer = new MutationObserver((mutations) => {
        mutations.forEach((mutation) => {
            if (mutation.addedNodes) { // Checks for new elements added to the DOM
                mutation.addedNodes.forEach((node) => {
                    if (node.nodeType === 1 && node.matches('.asp_nochosen.asp_noselect2')) { // Element type node and matches the select class
                        updateSelectWidth(node);
                    } else if (node.nodeType === 1 && node.querySelectorAll) {
                        const selects = node.querySelectorAll('.asp_nochosen.asp_noselect2');
                        selects.forEach(select => updateSelectWidth(select));
                    }
                });
            }
        });
    });

    const config = { childList: true, subtree: true };
    const targetNode = document.body; // Watch the entire body for changes
    observer.observe(targetNode, config);

    document.body.addEventListener('change', function(event) {
        if (event.target.matches('.asp_nochosen.asp_noselect2')) {
            updateSelectWidth(event.target);
        }
    });
});

Of course, this could be a lot easier to implent via the plugin back end, but I didn't found any documentation that could help

ernestmarcinko commented 1 month ago

Hi,

Thank you for the suggestion. The closest similar example to this is probably the staff search demo

Unfortunately it's not integrated into the box itself. The main issue with all of this is, that creating multiple filters need to be handled as well. In case of Amazon it's only a simple search with a single drop-down, but here you can create multiple variations.

A possible solution could be to have a position for a drop-down at that location, and a single filter could be applied to it, so it's definitely doable.

I think we can make this happen, however probably not in the nearest future. There need to be changes made on the back-end so the filter creation is more intuitive.

I will however keep this issue open, I see potential in it, and once a back-end rework is made, this should be a piece of cake to implement.

All the best, Ernest