简体   繁体   English

根据所选选项的宽度调整选择元素的宽度

[英]Adjust width of select element according to selected option's width

I want the select element to have the default option value's width which is shorter.我希望 select 元素具有更短的默认选项值的宽度。 When the user selects another option, the select element should resize itself so the whole text is always visible in the element.当用户选择另一个选项时,select 元素应调整自身大小,以便整个文本始终在元素中可见。

I have found a solution in the question Auto resizing the SELECT element according to selected OPTION's width , but it doesn't work with bootstrap, and I don't know why.我在Auto resizing the SELECT element under selected OPTION's width问题中找到了解决方案,但它不适用于 bootstrap,我不知道为什么。

Here's my attempt:这是我的尝试:

 $(document).ready(function() { $('select').change(function(){ $("#width_tmp").html($('select option:selected').text()); // 30 : the size of the down arrow of the select box $(this).width($("#width_tmp").width()+30); }); });
 .btn-select { color: #333; background-color: #f5f5f5; border-color: #ccc; padding:7px; } select { width: 60px; } #width_tmp{ display : none; }
 <link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/css/bootstrap.css" rel="stylesheet"/> <link href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.css" rel="stylesheet"/> <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/js/bootstrap.js"></script> <div class="form-group"> <div class="input-group"> <span class="input-group-btn"> <select class="btn btn-select align-left"> <option>All</option> <option>Longer</option> <option>A very very long string...</option> </select> <span id="width_tmp"></span> </span> <input type="text" class="form-control" placeholder="Search by..."> <span class="input-group-btn"> <button class="btn btn-default" type="button"> <i class="fa fa-search"></i> </button> </span> </div> </div>

This issue occurs because the #width_tmp is nested under .input-group-btn so it inherits the font-size: 0;出现此问题是因为#width_tmp嵌套在.input-group-btn因此它继承了font-size: 0; property from bootstrap.来自引导程序的属性。 Therefore, the calculated width of the element is always zero:因此,元素的计算宽度始终为零:

截屏

To fix this, just move the <span id="width_tmp"></span> so it's not inside the input group.要解决此问题,只需移动<span id="width_tmp"></span>使其不在输入组内。


Pure JS Solution纯JS解决方案

// resize on initial load
document.querySelectorAll("select").forEach(resizeSelect)

// delegated listener on change
document.body.addEventListener("change", (e) => {
    if (e.target.matches("select")) {
        resizeSelect(e.target)
    }
})

function resizeSelect(sel) {
  let tempOption = document.createElement('option');
  tempOption.textContent = sel.selectedOptions[0].textContent;

  let tempSelect = document.createElement('select');
  tempSelect.style.visibility = "hidden";
  tempSelect.style.position = "fixed"
  tempSelect.appendChild(tempOption);
  
  sel.after(tempSelect);
  sel.style.width = `${+tempSelect.clientWidth + 4}px`;
  tempSelect.remove();
}

Demo in jsFiddle and Stack Snippets jsFiddle和 Stack Snippets 中的演示

 // resize on initial load document.querySelectorAll("select").forEach(resizeSelect) // delegated listener on change document.body.addEventListener("change", (e) => { if (e.target.matches("select")) { resizeSelect(e.target) } }) function resizeSelect(sel) { let tempOption = document.createElement('option'); tempOption.textContent = sel.selectedOptions[0].textContent; let tempSelect = document.createElement('select'); tempSelect.style.visibility = "hidden"; tempSelect.style.position = "fixed" tempSelect.appendChild(tempOption); sel.after(tempSelect); sel.style.width = `${+tempSelect.clientWidth + 4}px`; tempSelect.remove(); }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <select> <option value="2">Some longer option</option> <option value="1">Short option</option> <option value="3">An very long option with a lot of text</option> </select> <select> <option>Short option 2</option> <option>Some longer option 2</option> <option selected>An very long option with a lot of text 2</option> </select>


jQuery Plugin Solution jQuery 插件解决方案

Another alternative would be to use a plugin to handle the whole operation start to finish.另一种选择是使用插件来处理从头到尾的整个操作。 Here's one I just whipped up.这是我刚刚提出的一个。

The plugin dynamically creates and destroys the span so it doesn't clutter up your html.该插件会动态创建和销毁span因此它不会弄乱您的 html。 This helps separate concerns and lets you delegate that functionality to another file and easily re-use with multiple elements across multiple pages.这有助于分离关注点,并让您将该功能委托给另一个文件,并轻松地跨多个页面重复使用多个元素。

(function($, window){
  $(function() {
    let arrowWidth = 30;

    $.fn.resizeselect = function(settings) {  
      return this.each(function() { 

        $(this).change(function(){
          let $this = $(this);

          // get font-weight, font-size, and font-family
          let style = window.getComputedStyle(this)
          let { fontWeight, fontSize, fontFamily } = style

          // create test element
          let text = $this.find("option:selected").text();
          let $test = $("<span>").html(text).css({
            "font-size": fontSize, 
            "font-weight": fontWeight, 
            "font-family": fontFamily,
            "visibility": "hidden" // prevents FOUC
          });

          // add to body, get width, and get out
          $test.appendTo($this.parent());
          let width = $test.width();
          $test.remove();

          // set select width
          $this.width(width + arrowWidth);

          // run on start
        }).change();

      });
    };

    // run by default
    $("select.resizeselect").resizeselect();                       
  })
})(jQuery, window);

You can initialize the plugin in one of two ways:您可以通过以下两种方式之一初始化插件:

  1. HTML - Add the class .resizeselect to any select element: HTML - 将类.resizeselect添加到任何选择元素:

     <select class="btn btn-select resizeselect "> <option>All</option> <option>Longer</option> <option>A very very long string...</option> </select>
  2. JavaScript - Call .resizeselect() on any jQuery object: JavaScript - 在任何 jQuery 对象上调用.resizeselect()

     $("select"). resizeselect ()

Demo in jsFiddle and StackSnippets: jsFiddle和 StackSnippets 中的演示:

 (function($, window){ $(function() { let arrowWidth = 30; $.fn.resizeselect = function(settings) { return this.each(function() { $(this).change(function(){ let $this = $(this); // get font-weight, font-size, and font-family let style = window.getComputedStyle(this) let { fontWeight, fontSize, fontFamily } = style // create test element let text = $this.find("option:selected").text(); let $test = $("<span>").html(text).css({ "font-size": fontSize, "font-weight": fontWeight, "font-family": fontFamily, "visibility": "hidden" // prevents FOUC }); // add to body, get width, and get out $test.appendTo($this.parent()); let width = $test.width(); $test.remove(); // set select width $this.width(width + arrowWidth); // run on start }).change(); }); }; // run by default $("select.resizeselect").resizeselect(); }) })(jQuery, window);
 .btn-select { color: #333; background-color: #f5f5f5; border-color: #ccc; padding:7px; }
 <link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/css/bootstrap.css" rel="stylesheet"/> <link href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.css" rel="stylesheet"/> <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/js/bootstrap.js"></script> <div class="form-group"> <div class="input-group"> <span class="input-group-btn"> <select class="btn btn-select resizeselect"> <option>All</option> <option>Longer</option> <option>A very very long string...</option> </select> </span> <input type="text" class="form-control" placeholder="Search by..."> <span class="input-group-btn"> <button class="btn btn-default" type="button"> <i class="fa fa-search"></i> </button> </span> </div> </div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM