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


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

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

Задача:

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

Demo @ JSFiddle

6 17

6 ответов:

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

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

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

$(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>

Вот плагин, который я только что написал для этого вопроса, который динамически создает и уничтожает макет 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>

Обновлено, чтобы включить предложения по размеру от Garywoo & Эрик Варнке

Попробуйте следующий простой 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/

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

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

// 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;
}

Затем просто используйте его в своей форме select element:

$(this).getSelectWidth();

Вот еще одно простое решение 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);
    }
});

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

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