web-dev-qa-db-ja.com

選択したOPTIONの幅に応じてSELECT要素のサイズを自動変更

このselect要素には、異なるoptionが含まれています。通常、select要素は最大のoption要素から幅を取得しますが、select要素にはデフォルトのoption値の幅が短くなります。ユーザーが別のoptionを選択すると、select要素のサイズが変更され、テキスト全体が常に要素に表示されるようになります。

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

問題:

  • Chrome(カナリア)では、常に幅0が返されます。
  • Firefoxでは、短いオプションを選択すると幅が追加され、サイズ変更されません。
  • Safari:Chromeと同じ結果。

デモ@ JSFiddle

24
Th3Alchemist

特定の選択オプションのサイズを取得する簡単な方法や組み込みの方法はありません。ここに 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>
41
kmas

ここに この質問 のために書いたプラグインがあります。これは、モック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);
_

次の2つの方法のいずれかでプラグインを初期化できます。

  1. [〜#〜] html [〜#〜]-クラス_.resizeselect_を選択要素に追加します。

    _<select class="btn btn-select resizeselect">
      <option>All</option>
      <option>Longer</option>
      <option>A very very long string...</option>
    </select>
    _
  2. JavaScript-jQueryオブジェクトで.resizeselect()を呼び出します:

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

GarywooEric Warnke からのサイジングの提案を含むように更新されました

15
KyleMit

次の簡単な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/

基本的には、フォーカスされていないときに選択されていない要素を一時的に削除します(選択された要素のサイズに合わせてサイズを変更します)。

3
Divyesh

この作業ソリューションは、メイン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>

簡単な関数を使用できます:

// 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要素でそれを使用します。

$(this).getSelectWidth();
1
Jack

さらにもう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
Antwerp Danish