スクロールできるダイアログでbootstrap-selectを使ったらリストが画面からはみ出して選択できなくなった時の対応方法

![Screen Shot 2017-09-21 at 23.25.37.png](https://qiita-image-store.s3.amazonaws.com/0/159761/ba992e14-0900-b47b-eb1d-345354e15f61.png)
[bootstrap-select](https://silviomoreto.github.io/bootstrap-select/)

- 環境
    - OS : macOS Sierra Version 10.12.6
    - ブラウザ : Chrome
    - jquery : v1.11.1
    - jquery-ui : v1.10.4
    - bootstrap : v3.3.0
    - bootstrap-select : v1.6.3

### 事象
画面にあるbootstrap-select製プルダウンでは問題ないのですが
スクロールできるダイアログではリストが画面からはみ出して選択できなくなることがあります。
![manage.gif](https://qiita-image-store.s3.amazonaws.com/0/159761/1a6f63a0-ab59-3780-76c5-d6d6acd6e96c.gif)

## 原因 : CSSで`overflow-y: scroll`を指定しているから
ダイアログでスクロールできるように`overflow-y: scroll`を指定していると
リストの上部は存在しているのですが見えなくなるのです。
![manage.gif](https://qiita-image-store.s3.amazonaws.com/0/159761/3b00303f-7444-d9e4-7fc8-4bf04760bc70.gif)

```html:html
<!DOCTYPE html>
<html>
<head>
    <title>bootstrap-sassで作るプルダウン</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.6.3/css/bootstrap-select.min.css">
    <link rel="stylesheet" href="css/myBootstrapSelect.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="https://code.jquery.com/ui/1.10.4/jquery-ui.min.js"></script>
    <script type="text/javascript" src="js/myBootstrapSelect.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.6.3/js/bootstrap-select.min.js"></script>
</head>
<body>
    <button type="button" id="modalButton" class="btn btn-primary btn-lg">ダイアログ</button>
    <select class="selectpicker"></select>
    <div id="modalDialog" class="ui-widget-content">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" id="closeButton">閉じる</button>
                </div>
                <div class="modal-body">
                    <select class="selectpicker"></select>
                </div>
            </div>
        </div>
    </div>
</body>
</html>
```
```js:myBootstrapSelect.js
$(window).on('load', function() {
    createSelectOption();
});

$(function() {
    $('#modalDialog').fadeOut(0);
    $('#closeButton').click(onClickCloseButton);
    $('#modalButton').click(openDialog);
});

/**
 * ドロップダウンの中身を作る.
 */
function createSelectOption() {
    var selectObj = $('.selectpicker');

    for (var i = 0; i < 50; i++) {
        var option = $('<option>');
        option.html(i);
        selectObj.append(option);
    }
}

/**
 * ダイアログを開く.
 */
function openDialog() {
    $('#modalDialog').fadeIn(0);
    $('#modalDialog').draggable();
}

/**
 * ダイアログを閉じる.
 */
function onClickCloseButton() {
    $('#modalDialog').fadeOut(0);
}
```
```css:myBootstrapSelect.css
/**
 * ウィンドウ全体のスタイル.
 */
body {
    display: flex;
    flex-direction: column;
}

/**
 * [ダイアログ]ボタンのスタイル.
 */
#modalButton {
    margin: 30px;
    width: 200px;
}

/**
 * プルダウンのスタイル.
 * bootstrap-selectスタイルに負けないように具体的にセレクタを記載.
 */
select + .btn-group.bootstrap-select:not(.input-group-btn) {
    margin: 30px;
}

/**
 * ダイアログのスタイル.
 */
.modal-content {
    width: 300px;
    height: 120px;
    overflow-y: scroll;
}
```


## 対応方法1 : ダイアログを広げてスクロールを諦める
超簡単:mushroom:
![Screen Shot 2017-09-28 at 23.46.43.png](https://qiita-image-store.s3.amazonaws.com/0/159761/d363be82-c509-29e6-b989-429f47435946.png)

１. ダイアログのスタイルに設定された`height`と`overflow-y: scroll` を削除かコメントアウトする

```css:myBootstrapSelect.css
<他は変更ないので省略>
/**
 * ダイアログのスタイル.
 */
.modal-content {
    width: 300px;
/*    height: 120px;
    overflow-y: scroll;*/
}
```

### 対応方法2 : ダイアログからはみ出さないように表示されるリストの行数を決める
![Screen Shot 2017-09-28 at 23.58.48.png](https://qiita-image-store.s3.amazonaws.com/0/159761/4bbe02d4-9d6a-dda2-a71a-3246a93b0995.png)


#### `data-size`版
[bootstrap-selectの`data-size`についてはこちらを参照して下さい。](https://silviomoreto.github.io/bootstrap-select/examples/#customize-menu)
１. ダイアログの`<select class="selectpicker"></select>`に`data-size`をつける

```html:html
<他は変更ないので省略>
                    <select id="dialogSelect" class="selectpicker" data-size="3"></select>
<他は変更ないので省略>
```
#### `options`版
[bootstrap-selectの`options`についてはこちらを参照して下さい。](https://silviomoreto.github.io/bootstrap-select/options/)
１. ダイアログの`<select class="selectpicker"></select>`にidをつける

```html:html
<他は変更ないので省略>
                    <select id="dialogSelect" class="selectpicker"></select>
<他は変更ないので省略>
```

２. プルダウンを作成するメソッドを作ってダイアログを開く時に呼ぶ

```js:myBootstrapSelect.js
<他は変更ないので省略>
/**
 * ダイアログを開く.
 */
function openDialog() {
    $('#modalDialog').fadeIn(0);
    $('#modalDialog').draggable();
    createDropdown();
}

/**
 * ドロップダウンを作る.
 */
function createDropdown() {
    $('#dialogSelect').selectpicker();
}
<他は変更ないので省略>
```

３. `selectpicker()`に`size`を指定した`options`を渡す

```js:myBootstrapSelect.js
<他は変更ないので省略>
/**
 * ドロップダウンを作る.
 */
function createDropdown() {
    var options = {
        size: 3
    };
    $('#dialogSelect').selectpicker(options);
}
<他は変更ないので省略>
```
### 参考にしたソース
```js:bootstrap-select/1.6.3/js/bootstrap-select.js
<省略>
    setSize: function () {
<省略>
      } else if (this.options.size && this.options.size != 'auto' && menu.find('li' + notDisabled).length > this.options.size) {
        var optIndex = this.$lis.not('.divider' + notDisabled).find(' > *').slice(0, this.options.size).last().parent().index();
        var divLength = this.$lis.slice(0, optIndex + 1).filter('.divider').length;
        menuHeight = liHeight * this.options.size + divLength * divHeight + menuPadding;
        if (that.options.dropupAuto) {
          //noinspection JSUnusedAssignment
          this.$newElement.toggleClass('dropup', (selectOffsetTop > selectOffsetBot) && (menuHeight < menu.height()));
        }
        menu.css({'max-height': menuHeight + headerHeight + searchHeight + actionsHeight + 'px', 'overflow': 'hidden'});
        menuInner.css({'max-height': menuHeight - menuPadding + 'px', 'overflow-y': 'auto'});
      }
<省略>
```
### 他の理由でリストが見切れたら・・・
- [bootstrap-select でドロップダウンリストが上向き表示時にリスト領域がfixedボックス位置で途切れた！containerオプションで対策 | サイト構築日記](http://memories.zal.jp/WP/blog/20160422_2728.html)