怒Mは思いつきでモノを言う

やったことメモなどなど

Handsontableを入力フォームとして使って、JSONファイルを検索して結果を表示する

オリジナル

Handsontableを入力フォームとして使って、JSONファイルを検索して結果を表示する - Qiita

はじめに

前回は、JSONファイルを読み込んだ結果をHandsontableで表示させた。今回は、Handsontableを入力フォームとして使って、JSONファイル内を検索して、結果を表示させてみた。 HTMLだけでやっているので、モックアップを作るときには便利そうなのでメモ。

やってること

(1) JSONファイルを読み込む (2) JSONファイル内のテーブル一覧をコンボボックスに表示 (3) コンボボックスを変更した場合、そのテーブルに該当するカラム名を入力フォームに展開 (4) searchボタンを押すと、コンボボックスで選択されたテーブルを検索 (5) clearボタンを押すと、画面の初期状態に戻す (6) csvボタンを押すと、csvをダウンロードする(前回と同じ機能)

環境

Windows 8.1(64bit) Internet Explorer 11

用意したもの

jQuery * jquery-1.11.3.min.js

Handsontable * handsontable.full.js * handsontable.full.css

juantascon * jquery.handsontable.csv.js

JSONファイル(自前)

{
    "tableA":[
        {"Year": "2009", "Maserati": "0", "Mazda": "2941", "Mercedes": "4303", "Mini": "354", "Mitsubishi": "5814" },
        {"Year": "2010", "Maserati": "3", "Mazda": "2905", "Mercedes": "2867", "Mini": "412", "Mitsubishi": "5284" },
        {"Year": "2011", "Maserati": "4", "Mazda": "2517", "Mercedes": "4822", "Mini": "552", "Mitsubishi": "6127" },
        {"Year": "2012", "Maserati": "2", "Mazda": "2422", "Mercedes": "5399", "Mini": "776", "Mitsubishi": "4151" }
    ],  
    "tableB":[
        {"Name": "Maserati", "Since": "1914"},
        {"Name": "Mazda", "Since": "1920"},
        {"Name": "Mercedes", "Since": "1926"},
        {"Name": "Mini", "Since": "1952"},
        {"Name": "Mitsubishi", "Since": "1970"}
    ]
}

内容

(1) JSONファイルを読み込む

(2) JSONファイル内のテーブル一覧をコンボボックスに表示

   $.getJSON("json/table.json", function(table) {
        jsondata = table;
        
        // コンボボックスに表示するテーブル名を取得
        tableName = new Array();
        var count = 0;
        for(key in jsondata){
            tableName[count] = key;
            count++;
        }
        
        // コンボボックスにOPTIONを追加
        for(var i = 0 ; i < tableName.length ; i++){
            $('#selectTable').append($('<option>').html(tableName[i]).val(tableName[i]));
        }
        
        // csvボタンを非活性にする
        $('#csvDownLoad').attr("disabled", "disabled");
        
    });

(3) コンボボックスを変更した場合、そのテーブルに該当するカラム名を入力フォームに展開

// コンボボックスの値を変更した場合に動く
    $('#selectTable').change(function(){
        
        // コンボボックスの値が、"NA"でなければ、テーブルを展開
        // コンボボックスの値が、"NA"の場合は、テーブルを削除
        if( $('#selectTable').val() != "NA") {
            
            // コンボボックスの値をキーにして、テーブルを取得
            var obj = jsondata[$('#selectTable').val()];
            
            // テーブルが持っている、カラム名を取得
            // データ持っている、ありき。
            var searchHeader = new Array();
            var count = 0;
            
            for(key in obj[0]){
                searchHeader[count] = key;
                count++;
            }
            
            // Handsontableに展開する配列を作成
            // 中身は空文字にする。
            var inputCell = new Array();
            for(var i = 0; i < searchHeader.length; i++){
                inputCell[i] = "";
            }
            
            var data = [inputCell]; 
                
            // 表の定義
            hot = $('#searchGrid').handsontable({  //以下はデータ指定と表示オプション
                data: data,                      //さっき作ったdataを指定
                minSpareRows: 0,                 //表の一番下にいくつ空行を表示するか
                colHeaders: searchHeader,        //カラムの名前を表示するかどうか colheader: true/false
                                                 //カラムの名前を任意の名前にする colheader: 配列
                contextMenu: true
            });
        } else {
            $('#searchGrid').handsontable("destroy");
        }
    });

(4) searchボタンを押すと、コンボボックスで選択されたテーブルを検索

// searchボタンが押されたら、検索して結果を表示
    $('#search').click( function() {
        
        // コンボボックスでテーブルを選択していること。
        if( $('#selectTable').val() != "NA") {
            
            // 現在のコンボボックスの選択内容から、テーブルを取得する
            // コンボボックスの値をキーにして、テーブルを取得
            var obj = jsondata[$('#selectTable').val()];

            // searchGridから入力されているデータを取得する(配列)
            var row = $('#searchGrid').handsontable('getDataAtRow',0);
            
            // カラムを取得する
            var searchData = new Array();
            var count = 0;
            
            for(key in obj[0]){
                searchData[count] = key;
                count++;
            }
            
            // 取得したデータを元に、テーブルを検索
            var resultData = obj.filter(function(record) {
                var flag = false;
                
                for( var j = 0; j < row.length; j++ ){
                    if( row[j] != "" ) {
                        flag = true;
                        break;
                    }
                }
                
                // 検索条件が入力されていたら、JSONを検索
                // 検索条件が未入力であれば、全てを表示する
                if( flag ){
                    for( var colCn = 0; colCn < searchData.length; colCn++){
                        
                        if( record[searchData[colCn]] === row[colCn] ){
                            return true;
                        }
                    }
                } else {
                    return true;
                }
            });
            
            // resultに展開する
            if( resultData.length > 0 ){
                if(hot2 != undefined){
                    try{
                        hot2.destroy();
                    } catch(e) {
                    }
                }
                resultData = resultData,
                    container2 = document.getElementById('result'),  //後ほど表を展開する要素を指定
                    hot2;
                hot2 = new Handsontable(container2, {  //以下はデータ指定と表示オプション
                    data: resultData,                        //さっき作ったdataを指定
                    minSpareRows: 0,                 //表の一番下にいくつ空行を表示するか
                    colHeaders: searchData,          //カラムの名前を表示するかどうか colheader: true/false
                                                     //カラムの名前を任意の名前にする colheader: 配列
                    rowHeaders: true,
                    contextMenu: true,              //セルを右クリックしたときのメニューをすべて表示
                    columnSorting: true                 //カラムのヘッダーをクリックした際に昇順、再クリックで降順にソート
                });
                
                // csvボタンを活性にする
                $('#csvDownLoad').removeAttr("disabled");
            } else {
                if(hot2 != undefined){
                    hot2.destroy();
                    hot2 = undefined;
                }
                // csvボタンを非活性にする
                $('#csvDownLoad').attr("disabled", "disabled");
                alert("検索結果がありません");
            }
        } else {
            alert("テーブルを選択してください");
        }
    });

(5) clearボタンを押すと、画面の初期状態に戻す

   // clearボタンが初期状態に戻す
    $('#clear').click(function(){
        if(hot2 != undefined){
            hot2.destroy();
            hot2 = undefined;
        }
        $('#selectTable').val("NA");
        $('#searchGrid').handsontable("destroy");
        
        // csvボタンを非活性にする
        $('#csvDownLoad').attr("disabled", "disabled");
    });

全文

<!DOCTYPE html>
<html>
 
<head>
    <meta charset="Shift_JIS">
    <title>handsontable_test</title>
    <link rel="stylesheet" type="text/css" href='css/handsontable.full.css'>

    <script src='js/jquery-1.11.3.min.js'></script>   
    <script src='js/handsontable.full.js'></script>
    <script src='js/jquery.handsontable.csv.js'></script>
    <script>
$(document).ready(function () {

    var jsondata;   //JSON
    var tableName;  //テーブル一覧
    var hot2;       //resultの表定義
    
    // 画面読み込み時、table.jsonの内容を取得する
    $.getJSON("json/table.json", function(table) {
        jsondata = table;
        
        // コンボボックスに表示するテーブル名を取得
        tableName = new Array();
        var count = 0;
        for(key in jsondata){
            tableName[count] = key;
            count++;
        }
        
        // コンボボックスにOPTIONを追加
        for(var i = 0 ; i < tableName.length ; i++){
            $('#selectTable').append($('<option>').html(tableName[i]).val(tableName[i]));
        }
        
        // csvボタンを非活性にする
        $('#csvDownLoad').attr("disabled", "disabled");
        
    });
    
    // コンボボックスの値を変更した場合に動く
    $('#selectTable').change(function(){
        
        // コンボボックスの値が、"NA"でなければ、テーブルを展開
        // コンボボックスの値が、"NA"の場合は、テーブルを削除
        if( $('#selectTable').val() != "NA") {
            
            // コンボボックスの値をキーにして、テーブルを取得
            var obj = jsondata[$('#selectTable').val()];
            
            // テーブルが持っている、カラム名を取得
            // データ持っている、ありき。
            var searchHeader = new Array();
            var count = 0;
            
            for(key in obj[0]){
                searchHeader[count] = key;
                count++;
            }
            
            // Handsontableに展開する配列を作成
            // 中身は空文字にする。
            var inputCell = new Array();
            for(var i = 0; i < searchHeader.length; i++){
                inputCell[i] = "";
            }
            
            var data = [inputCell]; 
                
            // 表の定義
            hot = $('#searchGrid').handsontable({  //以下はデータ指定と表示オプション
                data: data,                      //さっき作ったdataを指定
                minSpareRows: 0,                 //表の一番下にいくつ空行を表示するか
                colHeaders: searchHeader,        //カラムの名前を表示するかどうか colheader: true/false
                                                 //カラムの名前を任意の名前にする colheader: 配列
                contextMenu: true
            });
        } else {
            $('#searchGrid').handsontable("destroy");
        }
    });
    
    // searchボタンが押されたら、検索して結果を表示
    $('#search').click( function() {
        
        // コンボボックスでテーブルを選択していること。
        if( $('#selectTable').val() != "NA") {
            
            // 現在のコンボボックスの選択内容から、テーブルを取得する
            // コンボボックスの値をキーにして、テーブルを取得
            var obj = jsondata[$('#selectTable').val()];

            // searchGridから入力されているデータを取得する(配列)
            var row = $('#searchGrid').handsontable('getDataAtRow',0);
            
            // カラムを取得する
            var searchData = new Array();
            var count = 0;
            
            for(key in obj[0]){
                searchData[count] = key;
                count++;
            }
            
            // 取得したデータを元に、テーブルを検索
            var resultData = obj.filter(function(record) {
                var flag = false;
                
                for( var j = 0; j < row.length; j++ ){
                    if( row[j] != "" ) {
                        flag = true;
                        break;
                    }
                }
                
                // 検索条件が入力されていたら、JSONを検索
                // 検索条件が未入力であれば、全てを表示する
                if( flag ){
                    for( var colCn = 0; colCn < searchData.length; colCn++){
                        
                        if( record[searchData[colCn]] === row[colCn] ){
                            return true;
                        }
                    }
                } else {
                    return true;
                }
            });
            
            // resultに展開する
            if( resultData.length > 0 ){
                if(hot2 != undefined){
                    try{
                        hot2.destroy();
                    } catch(e) {
                    }
                }
                resultData = resultData,
                    container2 = document.getElementById('result'),  //後ほど表を展開する要素を指定
                    hot2;
                hot2 = new Handsontable(container2, {  //以下はデータ指定と表示オプション
                    data: resultData,                        //さっき作ったdataを指定
                    minSpareRows: 0,                 //表の一番下にいくつ空行を表示するか
                    colHeaders: searchData,          //カラムの名前を表示するかどうか colheader: true/false
                                                     //カラムの名前を任意の名前にする colheader: 配列
                    rowHeaders: true,
                    contextMenu: true,               //セルを右クリックしたときのメニューをすべて表示
                    columnSorting: true              //カラムのヘッダーをクリックした際に昇順、再クリックで降順にソート
                });
                
                // csvボタンを活性にする
                $('#csvDownLoad').removeAttr("disabled");
            } else {
                if(hot2 != undefined){
                    hot2.destroy();
                    hot2 = undefined;
                }
                // csvボタンを非活性にする
                $('#csvDownLoad').attr("disabled", "disabled");
                alert("検索結果がありません");
            }
        } else {
            alert("テーブルを選択してください");
        }
    });
    
    // csvボタンがクリックされたら表の内容をCSV出力する
    $('#csvDownLoad').click(function(){
        
        var csv_string = handsontable2csv.string(hot2);
    
        var bom = new Uint8Array([0xEF, 0xBB, 0xBF]);
        var blob = new Blob([bom, csv_string], { type: 'text/csv'});
    
        // IE独自関数
        window.navigator.msSaveBlob(blob, "test.csv");
    });
    
    // clearボタンが初期状態に戻す
    $('#clear').click(function(){
        if(hot2 != undefined){
            hot2.destroy();
            hot2 = undefined;
        }
        $('#selectTable').val("NA");
        $('#searchGrid').handsontable("destroy");
        
        // csvボタンを非活性にする
        $('#csvDownLoad').attr("disabled", "disabled");
    });
    
    // Handsontableのおまじない
    //以下は基本的にいじらない
    function bindDumpButton() {

        Handsontable.Dom.addEvent(document.body, 'click', function (e) {

            var element = e.target || e.srcElement;

            if (element.nodeName == "BUTTON" && element.name == 'dump') {
                var name = element.getAttribute('data-dump');
                var instance = element.getAttribute('data-instance');
                var hot = window[instance];
                console.log('data of ' + name, hot.getData());
            }
        });
    }
    //関数実行
    bindDumpButton();
});
    </script>
</head>

<body>
    <p>テーブル選択</p>
    <select style="width:200px;" id="selectTable">
    <option value="NA"></option>
    </select>
    <div id="searchGrid" class="handsontable"></div><br>
    <input id="search" type="button" value="search"/>
    <input id="clear" type="button" value="clear"/>

    <hr>
    <div id="result" class="handsontable"></div><br>
    <input id="csvDownLoad" type="button" value="csv"/>
</body>
</html>

最後に

わかりにくい点、間違っている点、効率的に書ける箇所などあれば教えていただければ幸いです。