【JavaScript】JavaScriptでテーブルを動的に操作する

以前にも書いた、ワタクシはJavaScriptが苦手だと言うこと。
土日の暇な時間を使ってJavaScriptの勉強がてら遊ぶことにした。
まぁ、天気が悪かっただけなんだが。

業界に詳しくない方は、タイトルを呼んでも何のこっちゃ?ですね。
IT関係の業界では、静的と動的という言葉をよく使うのだが、簡単に説明。

もくじ

動的?静的?

静的って?

固定された情報のこと。
たとえば、「この本は、2018年12月2日に発売されました」
この「2018年12月2日」の部分。

動的って?

そのときの状況によって変動する情報のこと。 たとえば、「この本が発売されてから、2年3ヶ月と12日経ちました」
この「2年3ヶ月と12日」の部分。

…違いわかりますか?
「この本が発売されてから、2年3ヶ月と12日経ちました」を文章として埋め込んでしまうと、公開した翌日からはウソが書いてあることになりますね。
そんなのはキモいんで、プログラムで常に最新の情報を表示するんです。
最初に作成するときに時間をかけるんです。いかに保守作業に時間がかからないように作成するか。後で保守作業をする人にとっても作業しやすいほうがいいですよね。

で、今回やってみるのはそのテーブル版。
ただし、今回はプログラムで配列を作成しているが、本来はデータベース等から表示する内容を取得するパターンが多いと思う。

事前準備

では、サクサク行ってみよう。
まずはスタイル定義。

<style>
    .baseDiv
    {
        width:300px;
        height:auto;
        background:#f0f8ff;
    }
    .tableStyle
    {
        border: solid 1px #d3d3d3;
        border-collapse: collapse;
        width:100%;
    }
    .tableStyle td
    {
        border:solid 1px #000000;
    }
    .tableStyle th
    {
        border:solid 1px #000000;
        background:#ffc0cb;
    }
    .category_width
    {
        width:100px;
    }
    .button_width
    {
        width:100px;
    }
    .select_width
    {
        width:200px;
    }
</style>

そしてhtml。

<body>
    <input type="button" value="テーブル作成" class="button_width" onClick="createTable();">
    <select id="category" class="select_width" onChange="changeCategory();">
        <option value="0">ぜんぶ</option>
        <option value="1">ロッド</option>
        <option value="2">ライン</option>
        <option value="3">ルアー</option>
    </select>
</body>

完成形

そしていきなり完成形w

全ソースコード

<script>
    /*
        baseDivにテーブル情報を追加する処理
    */
    function createTable()
    {

        // 基本Div
        var baseDiv = document.getElementById("baseDiv");

        // テーブル作成
        var tableElement = document.createElement("table");
        tableElement.id = "table";

        // テーブルにスタイル属性を追加
        tableElement.classList.add('tableStyle');

        // テーブル行作成
        var tableRow = tableElement.insertRow(-1);

        baseDiv.appendChild(tableElement);

        // ヘッダ行作成
        addHeader();

        // リンク配列作成
        var targetArray = createLinkArray();

        // 作成したリンク配列分繰り返し処理
        for ( arrCount = 0 ; arrCount < targetArray.length; arrCount ++ ){
            // 行追加処理
            addRow(targetArray[arrCount]);
        }
    }

    /*
        テーブルにヘッダ情報を追加する処理
    */
    function addHeader()
    {
        // テーブル取得
        var tableElement = document.getElementById("table");

        // 明細行
        tableRow = tableElement.insertRow(-1);

        // ヘッダ行作成
        var th = null;
        th = document.createElement("th");
        th.innerHTML = "カテゴリ";
        th.classList.add('category_width');
        tableRow.appendChild(th);

        th = document.createElement("th");
        th.innerHTML = "メーカー名";
        tableRow.appendChild(th);

    }

    /*
        テーブルに行情報を追加する処理
    */
    function addRow(targetItem)
    {

        // テーブル取得
        var tableElement = document.getElementById("table");

        // 現在の最大行数を取得
        var maxRowNumber = tableElement.rows.length;

        // ヘッダ行分を減算
        var addRowNumber = maxRowNumber - 1;

        // 明細行
        tableRow = tableElement.insertRow(-1);

        cell = tableRow.insertCell( -1 );
        cell.innerHTML = targetItem["category_name"];

        // リンクセル
        // メーカー名+リンク+別タブとした
        cell = tableRow.insertCell( -1 );
        cell.innerHTML = "<a href=\"" + targetItem["link"] + "\" target=\"_blank\" >" + targetItem["name_japan"] + "</a>";

        // カテゴリ属性を追加
        tableRow.setAttribute('category_num', targetItem["category_num"]);

    }

    /*
        カテゴリ変更時のフィルタ処理
    */
    function changeCategory()
    {

        // カテゴリ選択値を取得
        var SelectedCategoryValue = Number(document.getElementById("category").value);

        // テーブル取得
        var tableElement = document.getElementById("table");
        var tableRows = tableElement.rows;

        // 行数分ループ
        for (var rowCount = 2, len=tableRows.length; rowCount < len; rowCount ++) {

            // 表示状態に初期化
            tableRows[rowCount].style.display = "";

            // カテゴリ指示がない場合は次行へ
            if ( SelectedCategoryValue === 0 ) 
            {
                continue;
            }

            // カテゴリ番号を取得
            var categoryNumber = Number(tableRows[rowCount].getAttribute("category_num"));

            // カテゴリが一致しない場合は非表示にする
            if ( SelectedCategoryValue !== categoryNumber )
            {
                tableRows[rowCount].style.display = "none";
            }

        }

    }

    /*
        一覧の配列作成処理。
    */
    function createLinkArray()
    {

      // 連想配列作成用
      var linkArray = new Array();

      linkArray = [
                    { "category_name" : "ロッド" , "category_num" : 1 , "name_roman" : "OLYMPIC" , "name_japan" : "オリムピック" , "link" : "http://www.olympic-co-ltd.jp/" } ,
                    { "category_name" : "ロッド" , "category_num" : 1 , "name_roman" : "SAKURA" , "name_japan" : "櫻井釣漁具" , "link" : "http://www.sakura-rod.co.jp/" } ,
                    { "category_name" : "ロッド" , "category_num" : 1 , "name_roman" : "TENRYU" , "name_japan" : "天龍" , "link" : "http://fishing.tenryu-magna.com/" } ,
                    { "category_name" : "ロッド" , "category_num" : 1 , "name_roman" : "MajorCraft" , "name_japan" : "メジャークラフト" , "link" : "http://www.majorcraft.co.jp/" } ,
                    { "category_name" : "ロッド" , "category_num" : 1 , "name_roman" : "NISSIN" , "name_japan" : "宇崎日新" , "link" : "http://www.u-nissin.co.jp/" } ,
                    { "category_name" : "ロッド" , "category_num" : 1 , "name_roman" : "Daikoh" , "name_japan" : "ダイコー" , "link" : "http://www.f-daiko.com/" } ,
                    { "category_name" : "ロッド" , "category_num" : 1 , "name_roman" : "ZENAQ" , "name_japan" : "ゼナック" , "link" : "http://www.zenaq.com/" } ,
                    { "category_name" : "ロッド" , "category_num" : 1 , "name_roman" : "PALMS" , "name_japan" : "パームス" , "link" : "http://www.palms.co.jp/" } ,
                    { "category_name" : "ロッド" , "category_num" : 1 , "name_roman" : "YAMAGABLANKS" , "name_japan" : "ヤマガブランクス" , "link" : "http://yamaga-blanks.com/" } ,
                    { "category_name" : "ライン" , "category_num" : 2 , "name_roman" : "SUNLINE" , "name_japan" : "サンライン" , "link" : "http://www.sunline.co.jp/" } ,
                    { "category_name" : "ライン" , "category_num" : 2 , "name_roman" : "モーリス" , "name_japan" : "VARIVAS" , "link" : "http://www.varivas.co.jp/" } ,
                    { "category_name" : "ライン" , "category_num" : 2 , "name_roman" : "TORAY" , "name_japan" : "東レ" , "link" : "http://www.torayfishing.net/" } ,
                    { "category_name" : "ライン" , "category_num" : 2 , "name_roman" : "UNITIKA" , "name_japan" : "ユニチカ" , "link" : "http://www.unitika.co.jp/" } ,
                    { "category_name" : "ライン" , "category_num" : 2 , "name_roman" : "APPLAUD" , "name_japan" : "サンヨーナイロン" , "link" : "http://www.sanyo-nylon.co.jp/" } ,
                    { "category_name" : "ライン" , "category_num" : 2 , "name_roman" : "KUREHA" , "name_japan" : "クレハ" , "link" : "http://www.kureha.co.jp/" } ,
                    { "category_name" : "ライン" , "category_num" : 2 , "name_roman" : "GOSEN" , "name_japan" : "ゴーセン" , "link" : "http://www.gosen.jp/" } ,
                    { "category_name" : "ライン" , "category_num" : 2 , "name_roman" : "YAMATOYO" , "name_japan" : "山豊テグス" , "link" : "http://www.yamatoyo.com/" } ,
                    { "category_name" : "ライン" , "category_num" : 2 , "name_roman" : "Fujino" , "name_japan" : "フジノナイロン" , "link" : "http://www.fujinoline.co.jp/" } ,
                    { "category_name" : "ライン" , "category_num" : 2 , "name_roman" : "YGK" , "name_japan" : "YGKよつあみ" , "link" : "http://www.yoz-ami.jp/index.html" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "GaryYAMAMOTO" , "name_japan" : "ゲーリーヤマモト" , "link" : "http://www.gary-yamamoto.com/index.shtml" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "EverGreen" , "name_japan" : "エバーグリーン" , "link" : "http://www.evergreen-fishing.com/" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "SAURUS" , "name_japan" : "ザウルス" , "link" : "http://www.saurus50.jp/" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "Rapala" , "name_japan" : "ラパラジャパン" , "link" : "http://www.rapala.co.jp/" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "Berkley" , "name_japan" : "バークレイ/ピュアフィッシングジャパン" , "link" : "http://www.purefishing.jp/berkley/" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "Megabass" , "name_japan" : "メガバス" , "link" : "http://www.megabass.co.jp/site/" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "SMITH" , "name_japan" : "スミス" , "link" : "http://www.smith.co.jp/" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "OFT" , "name_japan" : "オフト" , "link" : "http://www.oft-fishing.com/" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "TACKLEHOUSE" , "name_japan" : "タックルハウス" , "link" : "http://www.tacklehouse.co.jp/" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "MariaJAPAN" , "name_japan" : "YAMASHITA" , "link" : "http://www.yamaria.co.jp/" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "Valleyhill" , "name_japan" : "バレーヒル" , "link" : "http://valleyhill.taniyamashoji.co.jp/" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "BREADEN" , "name_japan" : "ブリーデン" , "link" : "http://breaden.net/" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "JACKALL" , "name_japan" : "ジャッカル" , "link" : "http://www.jackall.co.jp/" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "ECOGEAR" , "name_japan" : "エコギア" , "link" : "http://www.ecogear.jp/game_fishing/" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "Jackson" , "name_japan" : "ジャクソン" , "link" : "http://www.jackson.jp/" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "Bassday" , "name_japan" : "バスディ" , "link" : "http://www.bassday.co.jp/" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "TIEMCO" , "name_japan" : "ティムコ" , "link" : "http://www.tiemco.co.jp/" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "DUO" , "name_japan" : "デュオ" , "link" : "http://www.duo-inc.co.jp/" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "NORTHCRAFT" , "name_japan" : "ノースクラフト" , "link" : "http://www.northcraft.jp/" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "LUCKYCRAFT" , "name_japan" : "ラッキークラフト" , "link" : "http://www.luckycraft.co.jp/" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "ima" , "name_japan" : "アムズデザイン" , "link" : "http://www.ima-ams.co.jp/" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "Tsunekichi" , "name_japan" : "常吉" , "link" : "http://www.tsunekichi.co.jp/" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "AIMS" , "name_japan" : "アイムス" , "link" : "http://www.b-fin.com/" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "ZIPBaits" , "name_japan" : "ジップベイツ" , "link" : "http://www.zipbaits.com/" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "SKAGITDESIGNS" , "name_japan" : "スカジットデザイン" , "link" : "http://skagit.co.jp/" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "DOWLUCK" , "name_japan" : "道楽" , "link" : "http://www.dowluck.com/" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "TICT" , "name_japan" : "ティクト" , "link" : "http://tict-net.com/" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "DAMIKIJAPAN" , "name_japan" : "DAMIKI" , "link" : "http://damiki-japan.com/" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "Tailwalk" , "name_japan" : "テイルウォーク" , "link" : "http://www.tailwalk.jp/" } ,
                    { "category_name" : "ルアー" , "category_num" : 3 , "name_roman" : "APIA" , "name_japan" : "アピア" , "link" : "http://www.spartas.jp/" } 
                  ];

      return linkArray;

    }

    function removeRow(rowNumber)
    {
        // テーブル取得
        var tableElement = document.getElementById("table");

        // 最終行を取得
        var maxRowNumber = tableElement.rows.length;

        // 行削除
        if ( rowNumber === 0 )
        {
        tableElement.deleteRow( maxRowNumber -1 );
        } else {
        tableElement.deleteRow( rowNumber + 1 );
        }

    }
</script>

まとめ

時間がなくてこの辺までしかできなかった。

テーブル処理についてはサーバサイドの処理とクライアントサイドの処理を分けて考える必要があるだろう。
いちいちサーバサイドの処理を移してられないしね。レスポンス的にも。
ただ、メンテナンスしにくくなるのは避けたい。

今後はノートにも転記してまとめておきます。

参考:MDN web docs

前の記事 次の記事