スマホ画面でのみタブで表組みの縦列を切り替えるJavaScript

現在一般的なレスポンシブWebデザインでは、 基本的にパソコン画面と同様のHTMLソースをスマホ画面でも表示させます。 其の際、スタイルシートを駆使しますが、 一般的に縦長画面で閲覧されるスマホ画面では工夫が必要になります。

パソコン画面で横に広く表示させていたコンテンツも スマホ画面では縦長にならざるを得ないため、 例えば横に並列して並べていたコンテンツを故意にカラム落ちさせ、 縦表示させるテクニックはごくごく基本的な手法です。

処がコンテンツによっては其の基本的な手法が適切でない場合もあります。 其の様なケースではスマホ画面の場合にはタブ切り替えは屡々採用されるテクニックです。 ネットで検索しても有用な情報が多く見付けられます。 例えばQiitaにも2017年8月6日付けで以下の情報が寄せられています。

jQueryとCSSでシンプルなタブ切り替え

記載されるコードは散見される同様な情報が上手くまとめられたように、 簡便さに加え汎用性も考慮され書かれています。 基本的には切り替えボタン用のタブを構成するタグと、切り替えられるコンテンツを表示させるタグが同数用意され、 初期に表示される以外のコンテンツを含むタグには非表示属性、 display: none; がスタイルシートで付与されており、 クリックされたタブと同じ、先頭から数えた数のコンテンツタグ以外に非表示属性が与えられるように jQuery で処理される、当該機能の定番的な構成が取られています。

レスポンシブWebデザインで扱い難い表組み(tableタグ)データ
レスポンシブWebデザインで扱い難い表組み(tableタグ)データ

処でレスポンシブWebデザインで扱い難いデータに表組み(tableタグ)があります。 一般的にパソコンの広い画面では一覧性に富み、 表組みも全体を表示させられる余裕がありますが…

スポンサーリンク

縦画面で閲覧されることの多いスマホ画面では縦長で特に横に広がり易い表組みは見易いレイアウトで表示するには限界があります。 其処でタブをトリガーとする表示切り替えを採用したい要請があります。 特に縦長のアスペクト比が見込まれるスマホ画面に於いては 縦列の切り替えが望まれるでしょう。 処が表組みを表示するための TABLE タグの仕様上、縦でのグループ化は困難です。 すると上に記したタブボタンとコンテンツが同数で構成される手法では無理が生じてしまいます。

実際に冒頭に記した手法を表組みに適用しようと思うと、 タブをクリックした際に表組みでの縦列をグループ化して考えた場合の 一番上のテーブルセルのみが表示切り替えされるような事態が招かれるでしょう。 従って、此処に本記事に記す処の上記手法を参考にしながらも、 独自の手法でのタブ切り替えの実現を考案したものです。

例えば上の レスポンシブWebデザインで扱い難い表組み(tableタグ)データ で示した表組みのHTMLタグは以下のように記されるでしょう。 タグ中 dn なるクラスが与えられたものはスタイルシートで display: none; 属性を付与して初期に非表示にしたいテーブルセルです。 延いてはタブ切り替えの表示、非表示のために使いたい目論見もあります。

<ul class="tab-switch">
  <li>TAB 0</li>
  <li>TAB 1</li>
  <li>TAB 2</li>
</ul>

<table class="tab-switch">
  <tr>
    <th>TH 0</th>
    <td>​TD 0​</td>​
    <td class=​"dn">​TD 1​</td>​
    <td class=​"dn">TD 2​</td>​
  </tr>
  <tr>
    <th>TH 1</th>
    <td>​TD 3​</td>​
    <td class=​"dn">TD 4​</td>​
    <td class=​"dn">​TD ​5</td>​
  </tr>
  <tr>
    <th>TH 2</th>
    <td class>TD 6</td>​
    <td class=​"dn">​TD ​7</td>​
    <td class=​"dn">​TD ​8</td>​
  </tr>
  <tr>
    <th>TH 3</th>
    <td>​TD ​9</td>​
    <td class=​"dn">TD 10​</td>​
    <td class=​"dn">TD 11​</td>​
  </tr>
  <tr>
    <th>TH 4</th>
    <td colspan=​"3">​TD 12​</td>​
  </tr>
  <tr>
    <th>TH 5</th>
    <td colspan=​"3" class=​"dn">​TD 13​</td>​
  </tr>
  <tr>
    <th>TH 6</th>
    <td>​TD 14​</td>​
    <td class=​"dn">​TD 15</td>​
    <td class=​"dn">​TD 16</td>​
  </tr>
  <tr>
    <th>TH 7</th>
    <td>​TD ​17</td>​
    <td class=​"dn">TD 18​</td>​
    <td class=​"dn">​TD ​19</td>​
  </tr>
  <tr>
    <th>TH 8</th>
    <td>​TD ​20</td>​
    <td class=​"dn">TD 21​</td>​
    <td class=​"dn">​TD ​22</td>​
  </tr>
  <tr>
    <th>TH 9</th>
    <td>​TD ​23</td>​
    <td class=​"dn">​TD 24​</td>​
    <td class=​"dn">​TD 25​</td>​
  </tr>
  <tr>
    <th>TH 10</th>
    <td>​TD 26</td>​
    <td class=​"dn">TD 27​</td>​
    <td class=​"dn">​TD 28​</td>​
  </tr>
  <tr>
    <th>TH 11</th>
    <td>​TD ​29</td>​
    <td class=​"dn">​TD ​30</td>​
    <td class=​"dn">TD ​31</td>​
  </tr>
</table>

此の表組みをスマホ画面では以下のように表示したくあります。 其々のタブのタップによって表示が切り替えられますので三種類の表示が考えられます。

TAB 0 タップ
TAB 0 タップ
TAB 1 タップ
TAB 1 タップ
TAB 2 タップ
TAB 2 タップ

此処で赤字で表示しているのはPC画面に於いては rowspan でテーブルセルがまとめられたもので、 スマホ画面では縦其々に独立させたいので分割して記しますが、 其の為、テーブルセルは別物になっています。 詰まり、TD12は、TD14、TD15、TD16と、 TD13は、TD17、TD18、TD19と同じ内容が記されています。

先ずjQueryに於いてDOMがどのように認識されているか確認する為に、 タブをタップをトリガーにコンソールに出力させるスクリプトを書けば以下のようになるでしょう。

jQuery("ul.tab-switch li").click(function() {
  var num = jQuery("ul.tab-switch li").index(this);
  jQuery("table.tab-switch td").each(function (index, elm) {
    console.log(num)
    console.log(index);
    console.log(elm);
  });
});

ループ処理はjQueryの each() メソッドを利用しています。 以下リンク先などが当該メソッドの利用法、 each(function(index , elm){…} の理解に役立つでしょう。

上で得られたコンソール出力から 実際に処理したいループの中に於いては 以下の様にjQueryはDOMの順序を認識していると考えられます。

0:<td class>​TD 0​</td>​
1:<td class=​"dn">​TD 1​</td>​
2:<td class=​"dn">TD 2​</td>​
3:<td class>​TD 3​</td>​
4:<td class=​"dn">TD 4​</td>​
5:<td class=​"dn">​TD ​5</td>​
6:<td class>TD 6</td>​
7:<td class=​"dn">​TD ​7</td>​
8:<td class=​"dn">​TD ​8</td>​
9:<td class>​TD ​9</td>​
10:<td class=​"dn">TD 10​</td>​
11:<td class=​"dn">TD 11​</td>​
12:<td colspan=​"3" class>​TD 12​</td>​
13:<td colspan=​"3" class=​"dn">​TD 13​</td>​
14:<td class>​TD 14​</td>​
15:<td class=​"dn">​TD 15</td>​
16:<td class=​"dn">​TD 16</td>​
17:<td class>​TD ​17</td>​
18:<td class=​"dn">TD 18​</td>​
19:<td class=​"dn">​TD ​19</td>​
20:<td class>​TD ​20</td>​
21:<td class=​"dn">TD 21​</td>​
22:<td class=​"dn">​TD ​22</td>​
23:<td class>​TD ​23</td>​
24:<td class=​"dn">​TD 24​</td>​
25:<td class=​"dn">​TD 25​</td>​
26:<td class>​TD 26</td>​
27:<td class=​"dn">TD 27​</td>​
28:<td class=​"dn">​TD 28​</td>​
29:<td class>​TD ​29</td>​
30:<td class=​"dn">​TD ​30</td>​
31:<td class=​"dn">TD ​31</td>​

此処迄来れば後は簡単な話で、 ループ処理で極く基本的な剰余演算子を用いてグループ分けを実行するだけです。 図中の赤字で示されるまとめられたテーブルセルを考慮しなければ 単純に3で割った余りによってグループ分けすれば良いでしょう。 更にはテーブルセルがまとめられている部分が混入していれば、 其れを考慮した場合分けをすれば良いだけです。 図で示した表組みの場合の場合分けを考慮した 表組みのタグ切り替え機能のコードは最終的に以下の様になります。

jQuery(function(){
  var w = jQuery(window).width();
  var x = 768;
  if ( w <= x ) {
    jQuery("ul.tab-switch li").click(function() {
      var num = jQuery("ul.tab-switch li").index(this);
      jQuery("table.tab-switch td").addClass('dn');
      jQuery("table.tab-switch td").each(function (index , elm) {
        var surplus = num;
        if (num == 1 || num == 2) {
          if (index > 12) {
            surplus--;
          }
        } else {
          if (index > 12) {
            surplus += 2;
          }
        }
        if(index%3 == surplus){
          this.classList.remove('dn');
        }
      });
      jQuery("ul.tab-switch li").removeClass("is-active");
      jQuery(this).addClass("is-active")
    });
  }
});

タブにはタップによってどれがタップされたのが明示出来る様にクラスを付与すれば都合が良いでしょう。 スクリプト内では is-active クラスが該当します。 レスポンシブに於けるスマホ想定画面でのみ機能させる為に、 ブラウザ幅の768pxを以て分岐点としています。

なお、最終的なスクリプト内ではeachメソッドで抽出される要素から 逐次クラスを除去するのにjQuery所与のメソッド removeClass() が使えなかった為、剥き出しのJavaScriptのメソッドの .classList.remove() を利用しています。

クラス名(class属性に値)を削除(ShanaBrian Website)

最終的なスクリプトではマジックナンバーは使っていますし、 汎用化のための最適化は全く図られていません。 jQueryを利用しながら剥き出しのJavaScriptのメソッドも利用していたりします。 此れ等の解決にはもう少し時間が必要ですが、 此の機能にニッチながら需要が存ずるのかも知れず、 時間が出来れば汎用化スクリプトを作成してみるのも一興かも知れないとは思っています。 今回、此の様な目的のスクリプトが公開されていなかったので、 機能は限定的ながらも独自で作成してみたものを共有するものです。

スポンサーリンク