Подтвердить что ты не робот

Автоматическое изменение размера элемента SELECT в соответствии с выбранной шириной OPTION

У меня есть этот элемент select с разными option в нем. Обычно элемент select получает свою ширину от самого большого элемента option, но я хочу, чтобы элемент select имел ширину значения по умолчанию option, которая короче. Когда пользователь выбирает другой option, элемент select должен изменить размер, чтобы весь текст всегда был видимым в элементе.

$(document).ready(function() {
    $('select').change(function(){
        $(this).width($('select option:selected').width());
    });
});

Проблема:

  • В Chrome (Canary) он всегда получает ширину, равную 0.
  • В Firefox ширина добавляется и не изменяется при выборе более короткой опции.
  • Safari: тот же результат, что и Chrome.

Демо @JSFiddle

4b9b3361

Ответ 1

Вы правы, что нет простого или встроенного способа получить размер определенной опции выбора. Вот JsFiddle, который делает то, что вы хотите.

Это нормально с последними версиями Chrome, Firefox, IE, Opera and Safari.

Я добавил скрытый выбор select #width_tmp_select чтобы вычислить ширину видимого select select #resizing_select, для которого мы хотим выполнить автоматическое изменение размера. Мы устанавливаем скрытый выбор, чтобы иметь один параметр, текст которого является текстом выбранного в данный момент параметра видимого выбора. Затем мы используем ширину скрытого выбора как ширину видимого выбора. Обратите внимание, что использование скрытого диапазона вместо скрытого выбора работает довольно хорошо, но ширина будет немного не такой, как указал sami-al-subhi в комментарии ниже.

$(document).ready(function() {
  $('#resizing_select').change(function(){
    $("#width_tmp_option").html($('#resizing_select option:selected').text()); 
    $(this).width($("#width_tmp_select").width());  
  });
});
#resizing_select {
  width: 50px;
} 
 
#width_tmp_select{
  display : none;
} 
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>

<select id="resizing_select">
  <option>All</option>
  <option>Longer</option>
  <option>A very very long string...</option>
</select>

<select id="width_tmp_select">
  <option id="width_tmp_option"></option>
</select>

Ответ 2

Вот плагин, который я только что написал для этого вопроса, который динамически создает и уничтожает фиктивный span чтобы он не загромождал ваш HTML. Это помогает разделить проблемы, позволяет делегировать эту функциональность и позволяет легко повторно использовать несколько элементов.

Включить этот JS в любом месте:

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

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

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

        // create test element
        var text = $this.find("option:selected").text();
        var $test = $("<span>").html(text).css({
            "font-size": $this.css("font-size"), // ensures same size text
            "visibility": "hidden"               // prevents FOUC
        });


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

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

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

    });
  };

  // run by default
  $("select.resizeselect").resizeselect();                       

})(jQuery, window);

Вы можете инициализировать плагин одним из двух способов:

  1. HTML - Добавьте класс .resizeselect к любому элементу select:

    <select class="btn btn-select resizeselect">
      <option>All</option>
      <option>Longer</option>
      <option>A very very long string...</option>
    </select>
    
  2. JavaScript - вызов .resizeselect() для любого объекта jQuery:

    $("select").resizeselect()
    

Вот демо в jsFiddle

Вот демо-версия в стеке фрагментов:

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

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

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

        // create test element
        var text = $this.find("option:selected").text();
        var $test = $("<span>").html(text).css({
        	"font-size": $this.css("font-size"), // ensures same size text
            "visibility": "hidden"               // prevents FOUC
        });
        
        // add to parent, get width, and get out
        $test.appendTo($this.parent());
        var width = $test.width();
        $test.remove();

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

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

    });
  };

  // run by default
  $("select.resizeselect").resizeselect();                       

})(jQuery, window);
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>

<select class="resizeselect">
  <option>All</option>
  <option>Longer</option>
  <option>A very very long string...</option>
</select>

Ответ 3

Попробуйте использовать следующий простой JavaScript и преобразовать его в jQuery:)

<html><head><title>Auto size select</title>

<script>
var resized = false;

function resizeSelect(selected) {
  if (resized) return;
  var sel = document.getElementById('select');
  for (var i=0; i<sel.options.length; i++) {
    sel.options[i].title=sel.options[i].innerHTML;
    if (i!=sel.options.selectedIndex) sel.options[i].innerHTML='';
  }
  resized = true;
  sel.blur();
}

function restoreSelect() {
  if (!resized) return;
  var sel = document.getElementById('select');
  for (var i=0; i<sel.options.length; i++) {
    sel.options[i].innerHTML=sel.options[i].title;
  }  
  resized = false;
}
</script>

</head>
<body onload="resizeSelect(this.selectedItem)">
<select id="select" 
  onchange="resizeSelect(this.selectedItem)"
  onblur="resizeSelect(this.selectedItem)"
  onfocus="restoreSelect()">
<option>text text</option>
<option>text text text text text</option>
<option>text text text </option>
<option>text text text text </option>
<option>text</option>
<option>text text text text text text text text text</option>
<option>text text</option>
</select>
</body></html>

Вот для него jsfiddle: https://jsfiddle.net/sm4dnwuf/1/

В основном, это то, что он временно удаляет невыбранные элементы, когда он не находится в фокусе (вызывая его размер только размером выбранного).

Ответ 4

Вы можете использовать простую функцию:

// Function that helps to get the select element width.
$.fn.getSelectWidth = function() {
  var width = Math.round($(this).wrap('<span></span>').width());
  $(this).unwrap();
  return width;
}

Затем просто используйте его в элементе выбора формы:

$(this).getSelectWidth();

Ответ 5

Здесь еще одно простое решение jQuery:

$('#mySelect').change(function(){
    var $selectList = $(this);

    var $selectedOption = $selectList.children('[value="' + this.value + '"]')
        .attr('selected', true);
    var selectedIndex = $selectedOption.index();

    var $nonSelectedOptions = $selectList.children().not($selectedOption)
        .remove()
        .attr('selected', false);

    // Reset and calculate new fixed width having only selected option as a child
    $selectList.width('auto').width($selectList.width());

    // Add options back and put selected option in the right place on the list
    $selectedOption.remove();
    $selectList.append($nonSelectedOptions);
    if (selectedIndex >= $nonSelectedOptions.length) {
         $selectList.append($selectedOption);
    } else {
         $selectList.children().eq(selectedIndex).before($selectedOption);
    }
});

Ответ 6

Это рабочее решение использует здесь временный вспомогательный select в который клонируется выбранный вариант из основного выбора, так что можно оценить истинную ширину, которую должен иметь основной select.

Приятно то, что вы просто добавляете этот код, и он применим к каждому выбору, поэтому нет необходимости в ids и дополнительных именах.

$('select').change(function(){
  var text = $(this).find('option:selected').text()
  var $aux = $('<select/>').append($('<option/>').text(text))
  $(this).after($aux)
  $(this).width($aux.width())
  $aux.remove()
}).change()
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select>
  <option>REALLY LONG TEXT, REALLY LONG TEXT, REALLY LONG TEXT</option>
  <option>ABCDEFGHIJKL</option>
  <option>ABC</option>
</select>

Ответ 7

Вы также можете попробовать это.

select option{width:0; }
select option:hover{width:auto;}