まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

Swagger APIはインタラクティブに動く REST API のドキュメントを比較的簡単に作ることができて便利です。自分も実際に業務やプライベートアプリに使っています。

この機能を使う場合、YAML と言われるフォーマットをベースにした記述方法で API の仕様を記述するだけで動く API ドキュメントページを作ることができます。

で、この YAML で仕様を記述する際に「コメント」を記述したくなることがあります。実質的にプログラミングする必要なく API テストページを作れるのは便利で、プログラミング時と同様にコメントを残したくなることもあると思います。 が、YAML でコメントを書いたことがなかったので、改めて明示的にコメントを残そうとした際の手法がわからず、調べてみました。

答えとしては「# から行末までがコメント」となるようです。つまり一行単位でコメントが生成されます。「ここからここまで」という範囲コメントは存在していないようです。
info:
  description: 普通の行
#  description: コメント行
  titie: タイトル   # ここはコメント  

なお、コメント扱いにしたくない # を含めたい場合は \# のようにバックスラッシュでエスケープすることで実現できます。




 

Bootstrap を使うとモーダルダイアログを簡単に作ることができます。


モーダルダイアログは親画面の中で表示されるダイアログボックス画面のことで、「このダイアログボックスを閉じるまで親画面や他の画面に移動することができない」という特徴を持っています。利用者に質問を促して「はい」か「いいえ」のボタンを押させる、といった時の、どちらかを押すまで他の処理ができなくなる(どちらかを押す前に他の処理をされては困る)場合などに使われます。

具体的にはこんな感じで実装できます:
<html>
<head>
<meta charset="utf8"/>
<title>Bootstrap モーダルから別のモーダルへ</title>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.0.3.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
</head>
<body>
  
  <nav class="navbar">
    <a href="#" class="navbar-brand">Bootstrap モーダルから別のモーダルへ</a>
  </nav>

  <!-- Button trigger modal -->
  <div class="container">
    <a href="#" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal1">モーダル1</a><br/>
    <a href="#" class="btn btn-success" data-toggle="modal" data-target="#exampleModal2">モーダル2</a>
  </div>

  <!-- Modal1 -->
  <div class="modal fade" id="exampleModal1" tabindex="-1" role="dialog" aria-labelledby="exampleModal1Label" aria-hidden="true">
    <div class="modal-dialog" role="document">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title" id="exampleModal1Label">モーダル1</h5>
          <button type="button" class="close" data-dismiss="modal" aria-label="Close">
            <span aria-hidden="true">×</span>
          </button>
        </div>
        <div class="modal-body">
          <p>1番目のモーダル</p>
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
        </div>
      </div>
    </div>
  </div>

  <!-- Modal2 -->
  <div class="modal fade" id="exampleModal2" tabindex="-1" role="dialog" aria-labelledby="exampleModal2Label" aria-hidden="true">
    <div class="modal-dialog" role="document">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title" id="exampleModal2Label">モーダル2</h5>
          <button type="button" class="close" data-dismiss="modal" aria-label="Close">
            <span aria-hidden="true">×</span>
          </button>
        </div>
        <div class="modal-body">
          <p>2番目のモーダル</p>
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
        </div>
      </div>
    </div>
  </div>
</body>
</html>

画面内には2つのモーダルダイアログ(便宜上、「モーダル1」と「モーダル2」と呼ぶことにします)が定義されていて、最初はどちらも非表示状態になっています。初期画面では2つのボタンがあり、それぞれモーダル1、モーダル2を表示するためのボタンになっています。モーダル1を表示している間、元の親画面は薄暗くグレーアウトされ、モーダル1を閉じるまではこの画面上に戻って処理を行うことはできません。モーダル2も同様です。HTML を見ていただくとわかるのですが、特別に JavaScript などを定義することもなく、Bootstrap の標準機能の一部として定義されているので、CSS の指定だけで実現できることがわかります。またモーダルダイアログ内を HTML で簡単&自由度高くカスタマイズできる点も便利です:



では「モーダル1を表示し、モーダル1を消すと同時にモーダル2を呼び出す」ということはできるでしょうか? 結論としてはできるのですが、少し JavaScript を使う必要があります。

上記を少し改良しました。モーダル1を閉じる際に「普通に閉じる」ボタンと「閉じてモーダル2を呼び出す」ボタンを用意しています。そして後者がクリックされた時に以下の JavaScript が呼び出されるように定義しました:
<html>
<head>
<meta charset="utf8"/>
<title>Bootstrap モーダルから別のモーダルへ</title>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.0.3.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<script>
function changeModal(){
  $('body').removeClass( 'modal-open' );
  $('.modal-backdrop').remove();
  $('#exampleModal1').modal( 'hide' );
  
  $('#exampleModal2').modal();
}
</script>
</head>
<body>
  
  <nav class="navbar">
    <a href="#" class="navbar-brand">Bootstrap モーダルから別のモーダルへ</a>
  </nav>

  <!-- Button trigger modal -->
  <div class="container">
    <a href="#" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal1">モーダル1</a><br/>
    <a href="#" class="btn btn-success" data-toggle="modal" data-target="#exampleModal2">モーダル2</a>
  </div>

  <!-- Modal1 -->
  <div class="modal fade" id="exampleModal1" tabindex="-1" role="dialog" aria-labelledby="exampleModal1Label" aria-hidden="true">
    <div class="modal-dialog" role="document">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title" id="exampleModal1Label">モーダル1</h5>
          <button type="button" class="close" data-dismiss="modal" aria-label="Close">
            <span aria-hidden="true">×</span>
          </button>
        </div>
        <div class="modal-body">
          <p>1番目のモーダル</p>
          <a href="#" class="btn btn-success" onClick="changeModal()">モーダル2へ</a>
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
        </div>
      </div>
    </div>
  </div>

  <!-- Modal2 -->
  <div class="modal fade" id="exampleModal2" tabindex="-1" role="dialog" aria-labelledby="exampleModal2Label" aria-hidden="true">
    <div class="modal-dialog" role="document">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title" id="exampleModal2Label">モーダル2</h5>
          <button type="button" class="close" data-dismiss="modal" aria-label="Close">
            <span aria-hidden="true">×</span>
          </button>
        </div>
        <div class="modal-body">
          <p>2番目のモーダル</p>
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
        </div>
      </div>
    </div>
  </div>
</body>
</html>

こうすることでモーダル1を閉じて、後始末の処理も行い、その上でモーダル2を表示する、という一連の処理をすべて JavaScript で行うようにしています。これでモーダルダイアログから別のモーダルダイアログを表示することができるようになります。



HTML (特に jQueryBootstrap を併用する HTML)で表を扱う場合に便利&有名な DataTables という jQuery プラグインがあります:
2019031901


元の HTML にほんの数行追加するだけで、簡単に各列でソートできるようにしたり、ページネーションを追加したり、検索フィルタを追加することができるようになる、というスグレモノです:
2019031902


ほんの数行で簡単にできてしまう点はいいのですが、簡単に実現できるせいか、その見た目をカスタマイズしようとすると、ちとややこしめです。色々調べてみた限りでのカスタマイズ(特に検索フィルタ部分のカスタマイズ)を紹介します。


【基本 HTML】
今回カスタマイズする表は以下のような内容とします:
<table id="mytable" class="table table-bordered">
  <thead>
    <tr><th>#</th><th>name</th><th>age</th></tr>
  </thead>
  <tbody>
    <tr><td>1</td><td>鈴木</td><td>30</td></tr>
    <tr><td>2</td><td>山本</td><td>31</td></tr>
    <tr><td>3</td><td>佐藤</td><td>33</td></tr>
    <tr><td>4</td><td>木村</td><td>28</td></tr>
    <tr><td>5</td><td>井上</td><td>22</td></tr>
    <tr><td>6</td><td>船橋</td><td>20</td></tr>
    <tr><td>7</td><td>近藤</td><td>30</td></tr>
    <tr><td>8</td><td>藤原</td><td>31</td></tr>
    <tr><td>9</td><td>吉田</td><td>40</td></tr>
    <tr><td>10</td><td>鈴木</td><td>35</td></tr>
    <tr><td>11</td><td>山木</td><td>31</td></tr>
    <tr><td>12</td><td>島田</td><td>33</td></tr>
    <tr><td>13</td><td>上原</td><td>19</td></tr>
    <tr><td>14</td><td>野島</td><td>20</td></tr>
    <tr><td>15</td><td>野崎</td><td>41</td></tr>
    <tr><td>16</td><td>奥村</td><td>39</td></tr>
    <tr><td>17</td><td>佐原</td><td>32</td></tr>
    <tr><td>18</td><td>千葉</td><td>22</td></tr>
    <tr><td>19</td><td>池上</td><td>25</td></tr>
    <tr><td>20</td><td>水森</td><td>29</td></tr>
  </tbody>
</table>


Bootstrap を併用して、table & table-bordered クラスを適用しています(<table> の id は "mytable" としています)。ちなみにこのままだと見た目は以下のようになります:
#nameage
1鈴木30
2山本31
3佐藤33
4木村28
5井上22
6船橋20
7近藤30
8藤原31
9吉田40
10鈴木35
11山木31
12島田33
13上原19
14野島20
15野崎41
16奥村39
17佐原32
18千葉22
19池上25
20水森29

ではこの表を DataTables プラグインを使ってカスタマイズしていきます。


【普通に適用】
特別なカスタマイズなしに DataTables を適用します。まずは DataTables の JavaScript と CSS を CDN からロードします(この中に Bootstrap も含まれているようです):
<link rel="stylesheet" href="https://cdn.datatables.net/t/bs-3.3.6/jqc-1.12.0,dt-1.10.11/datatables.min.css"/>
<script src="https://cdn.datatables.net/t/bs-3.3.6/jqc-1.12.0,dtー1.10.11/datatables.min.js"></script>

次に表の id(="mytable")を指定して、DataTable を適用します。この時点では特にオプションは指定していません:
<script>
$(function(){
  $('#mytable').DataTable({});
});
</script>

すると上記の表は以下のようになります:
#nameage
1鈴木30
2山本31
3佐藤33
4木村28
5井上22
6船橋20
7近藤30
8藤原31
9吉田40
10鈴木35
11山木31
12島田33
13上原19
14野島20
15野崎41
16奥村39
17佐原32
18千葉22
19池上25
20水森29



特別に何を指定したわけでもないのですが、これだけで指定した表の各列の見出し部分をクリックすることでその列値によるソートが可能になります。またデフォルトで 10 件ずつのページネーションが行われ、次のページや前のページを少しずつ表示することができるようになります。更に表の右上でリアルタイム検索フィルタリングが有効になり、ここに入力した文字を含むレコードだけがフィルタリングされて表示されるようになります。ここまでが実質一行の追加でできてしまいました。

【日本語化】
上記例ではページネーションや検索フィルタリングが追加されましたが、よく見ると英語になっています。これを日本語化する方法はないでしょうか? 実はこれも簡単で、単に日本語化するだけであれば公開されているリソースファイルを使って以下の赤字部分を追加するだけです:
<script>
$(function(){
  $.extend( $.fn.dataTable.defaults, {
    language: {
      url: 'https://cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/Japanese.json'
    }
  });
  $('#mytable').DataTable({});
});
</script>

すると上記の表は以下のようになります:
#nameage
1鈴木30
2山本31
3佐藤33
4木村28
5井上22
6船橋20
7近藤30
8藤原31
9吉田40
10鈴木35
11山木31
12島田33
13上原19
14野島20
15野崎41
16奥村39
17佐原32
18千葉22
19池上25
20水森29



指定したファイル(Japanese.json)をダウンロードして、この中身を別の日本語で書き換え、そのファイルを指定することで日本語訳を変更したり、リッチテキストにしたり、文字列ではなく画像を使ったりすることも可能です。


【ソート列の指定】
DataTables をオプション無しで適用すると表内のすべての列がソート対応になります。ここを明示的に変更することも可能です。例えば上記例で0列目(#)と2列目(age)ではソート可能にしたいが、1列目(name)ではソートできないようにしたい、という場合は以下のように(1列目のソート機能を無効に)します:
<script>
$(function(){
  $.extend( $.fn.dataTable.defaults, {
    language: {
      url: 'https://cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/Japanese.json'
    }
  });
  $('#mytable').DataTable({
    columnDefs: [{
      targets: [ 1 ],
      orderable: false
    }]
  });
});
</script>

すると上記の表は以下のようになります:
#nameage
1鈴木30
2山本31
3佐藤33
4木村28
5井上22
6船橋20
7近藤30
8藤原31
9吉田40
10鈴木35
11山木31
12島田33
13上原19
14野島20
15野崎41
16奥村39
17佐原32
18千葉22
19池上25
20水森29



本当はもっと別の(パーツの位置変更とか)もできないわけじゃないけど、長くなりそうなので別の機会に。


 

このページのトップヘ