Вопрос по jquery, dom-manipulation, select, autoresize, resize – Автоматическое изменение размера элемента SELECT в соответствии с шириной выбранного параметра

18

У меня есть это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.

Демо @ JSFiddle

@RoryMcCrossan Я тоже об этом думал, но не получу разных результатов при разных настройках разрешения экрана браузера? Я также нашел это возможное решение:jsfiddle.net/zERB7/3 Th3Alchemist
Не существует надежного способа получить ширинуoption элемент. Вы могли бы вместо этого получить длинуtext свойства и угадать ширину, необходимую на основе этого. Rory McCrossan

Ваш Ответ

6   ответов
39

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

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

Я добавил скрытый выбор#width_tmp_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>

Ваша скриптовая ссылка такая же, как и у ОП. Rory McCrossan
хороший подход, но вы должны убедиться, что<option> текст имеет тот же шрифт / размер, что и<span>, Если вы удалите#width_tmp{display : none;}, вы найдете это<span> больше. Это приведет к большему<select> чем это должно быть. Чем длиннее текст, тем больше пустое пространство в<select>. Sami Al-Subhi
Вот чистая попытка javascript версии этого:jsfiddle.net/FSsG8/635 Вы также можете получить некоторую тягу, пытаясь сопоставить шрифт между двумя вариантами выбора, что-то похожее:stackoverflow.com/questions/6385533/... rogerdpack
-3

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

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

)

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

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

1

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

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

$(this).getSelectWidth();
14

этот вопрос который динамически создает и уничтожает макет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);

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

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

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

JavaScript - Вызов.resizeselect() на любом объекте jQuery:

$("select").<b>resizeselect</b>()
ВотДемо в 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 & Эрик Варнке
@EricWarnke, отличное предложение, обновлено KyleMit
к сожалению это не работает на планшетах Ipad / Android, есть идеи, почему? Я думал, что это может быть, что размер шрифта параметра отличается в этих устройствах, но если я установил статический размер шрифта, это не решает его lopezi
Я бы предложил изменить строкуvar $test = $("<span>").html(text); вvar $test = $("<span style=\"font-size:"+$this.css("font-size")+"\">").html(text); чтобы убедиться, что размер шрифта создаваемого временного промежутка совпадает с размером элемента select. Если размер шрифта диапазона меньше или больше, динамическое изменение размера будет компенсировано разницей в размере. Garywoo
Работает в основном! Мой CSS по умолчанию с использованием Bootstrap всегда устанавливал ширину элемента select на 100%, что возвращало неправильную ширину. Я изменил приложение отbody в#myForm а также$("<span>") в$('<span style="visibility:hidden">') только для моего спокойствия. Eric Warnke
@Garywoo - отличное предложение, обновлено KyleMit

Похожие вопросы