skip to Main Content

I need to create a website that contains multiple dropdowns that have dynamic width functionality. The dropdowns are nested within large bodies of text, so it is essential that they are able to change width based on the currently selected item.

This is the script I have been working with.

<style>
  :root {
  --dynamic-size: 20px;
  --arrow-size: 20px;
  --select-size: calc(var(--dynamic-size) + var(--arrow-size));
}

.resizing-select {
  width: var(--select-size);
}

.helper-element {
  position: absolute;
  top: 0;
  left: -9999px;
}

</style>
<html>
  <select id="resizing-select">
    <option>All</option>
    <option>books</option>
    <option>audiobooks</option>
    <option>Living and more</option>
  </select>
  <span class="helper-element" aria-hidden="true"></span>

<!-- Malfunctioning Dropdown -->
  <select id="resizing-select2">
    <option>All</option>
    <option>books</option>
    <option>audiobooks</option>
    <option>Living and more</option>
  </select>
  <span class="helper-element" aria-hidden="true"></span>
<!--  -->

</html>

<script>
const resizingSelect = document.querySelector(".resizing-select");
const helperElement = document.querySelector(".helper-element");
resizingSelect.addEventListener("change", initResize);

function initResize(event) {
  helperElement.innerHTML = event.target.querySelector(
    "option:checked"
  ).innerText;
  resize(helperElement.offsetWidth);
}

function resize(width) {
  const root = document.documentElement;
  root.style.setProperty("--dynamic-size", `${width}px`);
}
</script>

This what I have attempted to solve but cannot seem to figure out:

<script>
const resizingSelect = document.querySelector(".resizing-select");

const helperElement = document.querySelector(".helper-element");

resizingSelect.addEventListener("change", initResize);

function initResize(event) {
  helperElement.innerHTML = event.target.querySelector(
    "option:checked"
  ).innerText;
  resize(helperElement.offsetWidth);
}

function resize(width) {
  const root = document.documentElement;
  root.style.setProperty("--dynamic-size", `${width}px`);
}
</script>

References:

http://jsfiddle.net/o64pfvnL/

https://codepen.io/jfaehrmann/pen/ExjpVEE

The major issue I have is that the dropdowns don’t have unique ID’s to assign individual widths. I am not confident enough in jQuery to achieve the functionality I had in mind. I have a feeling that I’m close, but I am very lost in what to do.

2

Answers


  1. So, to make things more understandable I need to go over couple of things.

    — If you do not have unique ID’s for each dropdown, you can simply use another element (Which is helper in your code) to distinguish the dropdowns.

    — Once you add helpers, you can assign class (.dropdown in this case) into your select elements to trigger change method.

    — The method itself simply gets the content of selected option and assigns it to its helper (the span next to it)

    — Then finally, the method gets the width of span and assigns it to select box.

    I hope that helps. 🙂

    /*----- Define 'on change' function -----*/
        $(".dropdown").change(function () {
    
          /*----- Assign selected value to its helper -----*/
            $(this).next('.helper-element').html($(this).children('option:selected').val());
    
          /*----- Get width of helper and assign it to select box ------*/
            var caretWidth = 20;
            $(this).css('width', ($(this).next('.helper-element').width() + caretWidth) + 'px');
    
        });
        
    /*----- On document load, do it for all selects ------*/
    $(document).ready(function(){
        /*------ Get all dropdowns into a variable on page load -----*/
        var dropdowns = $('.dropdown');
      
      /*----- If there is one or more dropdown(s), loop over them */
        if(dropdowns.length > 0){
        $.each(dropdowns, function(i, item){
           
           /*----- Do the same trick in here ------*/
           $(item).next('.helper-element').html($(item).children('option:selected').val());
           var caretWidth = 20;
           $(item).css('width', ($(item).next('.helper-element').width() + caretWidth) + 'px');
           
        });
      }  
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <select id="resizing_select" class='dropdown'>
       <option>Longer</option>
       <option>All</option>
       
       <option>A very very long string...</option>
    </select>
    <span class="helper-element" aria-hidden="true" style='display:none;'></span>
    
    <select id="resizing_select" class='dropdown'>
       <option>All</option>
       <option>Longer</option>
       <option>A very very long string...</option>
    </select>
    <span class="helper-element" aria-hidden="true" style='display:none;'></span>
    Login or Signup to reply.
  2. Here an optimized version of the previous answer

    $(function() {
      var $select = $('.dropdown');
      var $helper = $('.helper-element');
      $select.change(function() {
        $helper.html($(this).children('option:selected').val());
        $(this).css('width', ($helper.width() + 20) + 'px');
      });
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <select id="resizing_select" class='dropdown'>
       <option>All</option>
       <option>Longer</option>
       <option>A very very long string...</option>
    </select>
    <span class="helper-element" aria-hidden="true" style='display:none;'></span>
    
    <select id="resizing_select" class='dropdown'>
       <option>All</option>
       <option>Longer</option>
       <option>A very very long string...</option>
    </select>
    <span class="helper-element" aria-hidden="true" style='display:none;'></span>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search