Index

HOME > プログラムTOP > JavaScript



簡易データベース

 JavaScript の実用的なTips集です。ここでは、簡易データベースを考えてみます。JavaScript では本格的なデータベースは無理ですが、簡単なデータの読み込みや表示、検索等は可能です。
[INDEX] データファイルデータファイルの様々なつくり方IE4/NN4
データの表示データファイルを読み込んでテーブルに表示IE4/NN4
データの並べ替えデータを列ごとに並べ替えて表示する方法IE5/NN6
データの検索検索語句と対象列を指定する検索の方法IE5/NN6

sasaraan programming

Exposition

■データファイル

 データファイルは、拡張子を ".js" とする必要があります。そして、通常と同じように、HTML では、head タグ内でファイルを取り込みます。
 一方、データファイルでは、データを取り出しやすいように、あらかじめ Array オブジェクトを生成しています。データは、単純に順番どおりに添え字をつけていくことになります。したがって、データの区切りをつけるのは取り込んでからのさ行となります。なお、後からのデータの挿入や削除のことを考えて、データの添え字には変数 "n++" を指定しています。
 あるいはまた、単に文字列を定義しておくだけでもかまいません。この場合、区切り記号を決めておき、取り出す時には、aData = sMovie.split(",") というように、split メソッドを利用して配列化することになります。
<!-- HTML -->
<head>
    ...
    <script type="text/javascript" src="moviedata.js"></script>
    ...
</head>
// MovieData.js
var aMovie = new Array();                  // データの配列
var n = 0;                                        // インデックス(添え字)

aMovie[n++] = "男と女";                    // タイトル
aMovie[n++] = "1967";                     // 製作年
aMovie[n++] = "フランス";                  // 製作国
aMovie[n++] = "otokotoonna.html";    // リンク先

aMovie[n++] = "おしゃれ泥棒";
aMovie[n++] = "1966";
aMovie[n++] = "アメリカ";
aMovie[n++] = "osyaredoroboh.html";

 ... (中略) ...

aMovie[n++] = "レナードの朝";
aMovie[n++] = "1990";
aMovie[n++] = "アメリカ";
aMovie[n++] = "renahdonoasa.html";
// " , " で区切る例 1
// 配列化 : aData = dbMovie[index].split(",");
var dbMovie = new Array()
var m = 0;
dbMovie[m++] = "男と女, 1967, フランス, otokotoonna.html";
dbMovie[m++] = "おしゃれ泥棒, 1966, アメリカ, osyaredoroboh.html";
                    ... (中略) ...
dbMovie[m++] = "レナードの朝, 1990, アメリカ, renahdonoasa.html";
// " , " で区切る例 2
// 配列化 : aData = sMovie.split(",");
var sMovie = "男と女, 1967, フランス, otokotoonna.html,
                    おしゃれ泥棒, 1966, アメリカ, osyaredoroboh.html,
                    ... (中略) ...
                    レナードの朝, 1990, アメリカ, renahdonoasa.html";	

■データの表示

 データの表示は、一つのレコードの項目数である列数を取得してからの作業となります。今回の例では、タイトル、製作年、製作国、リンク先の四つとなります。下記の例では、これらのデータをテーブルを作成して表示を振り分けています。
// データの読み込み
function ReadData() 
{
    var col = 4;                               // 列数
    var dir = "../../movie/yohga/";    // リンク先のディレクトリ
    var i;
    document.write("<table>");
    document.write("<tr><th>タイトル<th>製作年<th>製作国<th>表示</tr>");
    for (i=0; i<aMovie.length; i++) {
        if (i % col == 0) {                    /* 一列目 */
            document.write("<tr>");
        } 
        if (i % col != col - 1) {             /* 四列目 */
            document.write("<td>", aMovie[i], "</td>");
        } else {                                 /* 四列目以外 */
            var s = dir + aMovie[i];
            document.write("<td><a target='_blanc' href=", s, ">開く</a></td>");
        }
        if (i == aMovie.length - 1 || i % col == col - 1) {    /* 四列目か配列の終端 */
            document.write("</tr>");
        }
    }
    document.write("</table>");
} 

■データの並べ替え

 通常の配列のソートは、Arrayオブジェクトの sort あるいは reverse メソッドで行われますが、今回は複数の項目を同時にソートする必要があります。さらに、すべての列をソートできるように別関数にしたいと思います。
 文字はコード順に並びますので、漢字が混じると思うような結果は出ません。通常はソート用にアルファベットかかなだけの項目を用意します。そして、二つの文字列を比較すればどちらが先に来るかを割り出すことができます。今回は、単純に上から一つ一つ比較して入れ替えていく方法を取っています。
・初期状態  1:ろば 2:ぞう 3:くま 4:うし
・1と2を比較 1:ぞう 2:ろば 3:くま 4:うし
・1と3を比較 1:くま 2:ろば 3:ぞう 4:うし
・1と4を比較 1:うし 2:ろば 3:ぞう 4:くま ("うし-?-?-?"が確定)
・2と3を比較 1:うし 2:ぞう 3:ろば 4:くま
・2と4を比較 1:うし 2:くま 3:ろば 4:ぞう ("うし-くま-?-?"が確定)
・3と4を比較 1:うし 2:くま 3:ぞう 4:ろば ("うし-くま-ぞう-ろば"が確定)
 上の例は昇順で並べ替える過程を表したものです。降順は比較の方法が逆になります。これは、下記のサンプルコードの SortAscend, SortDescend の両関数にあたります。なお、この方法は、IE5以上/NN6以上のDOMが使用できる環境で有効です。
var aNode = new Array();     // 表示用の TextNodeオブジェクトの配列
var aOrder = new Array();    // 現在昇順か降順かの情報を列ごとに格納
var nCol = 4;                     // データの列数(項目数)

// ソート関数(引数colindex : 列インデックス 0〜nCol-1)
function SortEx(colindex) 
{
    // 並べ替え
    if (aOrder[colindex]) {        /* 現在降順(true)なら昇順に並べ替え */
        SortAscend(colindex);
    } else {                            /* 現在昇順(false)なら降順に並べ替え*/
        SortDescend(colindex);
    }

    // 表示(=TextNodeの値)を更新
    for (i=0; i<aNode.length; i++) {  
        aNode[i].nodeValue = aMovieEx[i];
    }

    // 順番の情報を更新
    aOrder[colindex] = !aOrder[colindex];
}

// 昇順ソート(引数colindex : 列インデックス)
function SortAscend(colindex) 
{
    var i, j, k;

    // 配列の先頭から順に比較
    for (i=colindex; i<aMovieEx.length-nCol; i+=nCol) {
        var aTemp = new Array(nCol);    // データの一時格納用

        for (j=i+nCol; j<aMovieEx.length; j+=nCol) {
            if (aMovieEx[i] > aMovieEx[j]) {
                
                for (k=0; k<nCol; k++) {     /* データの入れ替え */
                    aTemp[k] = aMovieEx[i-colindex+k];
                    aMovieEx[i-colindex+k] = aMovieEx[j-colindex+k];
                    aMovieEx[j-colindex+k] = aTemp[k];
                }
            }
        }
    }
}

// 降順ソート(引数colindex : 列インデックス)
function SortDescend(colindex) 
{
    var i, j, k;

    // 配列の先頭から順に比較
    for (i=colindex; i<aMovieEx.length-nCol; i+=nCol) {
        var aTemp = new Array(nCol);    // データの一時格納用

        for (j=i+nCol; j<aMovieEx.length; j+=nCol) {
            if (aMovieEx[i] < aMovieEx[j]) {

                for (k=0; k<nCol; k++) {     /* データの入れ替え */
                    aTemp[k] = aMovieEx[i-colindex+k];
                    aMovieEx[i-colindex+k] = aMovieEx[j-colindex+k];
                    aMovieEx[j-colindex+k] = aTemp[k];
                }
            }
        }
    }
}

// テーブルの作成と表示
function InitTable() 
{
    if (!document.getElementById) return     // バージョンチェック
    var id_cell = "cell";                               // ID 名
    var i;

    // テーブルの作成
    document.write("<table><tr>");
    document.write("<th><a href='javascript:SortEx(0)'>タイトル</a>");
    document.write("<th><a href='javascript:SortEx(1)'>製作年</a>");
    document.write("<th><a href='javascript:SortEx(2)'>製作国</a>");
    document.write("<th><a href='javascript:SortEx(3)'>よみがな</a>");
    document.write("</tr>");
    for (i=0; i<aMovieEx.length; i++) {
        var id = id_cell + i;
        if (i % nCol == 0) {
            document.write("<tr>");
        } 
        document.write("<td id='", id, "'></td>");
        if (i == aMovieEx.length - 1 || i % nCol == nCol - 1) {
            document.write("</tr>");
        }
    }
    document.write("</table>");

    // 文字列(ノード)の追加
    for (i=0; i<aMovieEx.length; i++) {
        var oTD = document.getElementById(id_cell+i);
        aNode[i] = document.createTextNode(aMovieEx[i]);
        oTD.appendChild(aNode[i]);
    }

    // 昇順・降順の初期化(初期値は降順=true)
    for (i=0; i<nCol; i++) {
        aOrder[i] = true;
    }
} 

■データの検索

 検索には、通常、Stringオブジェクトの indexOfメソッドを利用します。このメソッドは、対象文字列に検索文字列が含まれれば、先頭文字のインデックスを返してきます。見つからない時は -1 を返してきます。下記のサンプルでは、検索語句と検索対象の列を指定できるようにしています。
var nCol = 4;                          // 列数(一レコードの項目数)
var id_table = "table1";            // table オブジェクトのID
var id_text = "text1";              // text オブジェクトの ID
var id_select = "select1";        // select オブジェクトのID

// 検索を実行して結果を表示
function FindData() 
{
    if (!document.getElementById(id_table)) return;         // tableオブジェクトの確認
    var oTable = document.getElementById(id_table);      // tableオブジェクトの取得
    var oTbody;                                                         // tbodyオブジェクト
    var oText = document.getElementById(id_text);        // textオブジェクトの取得
    var oSelect = document.getElementById(id_select);  // selectオブジェクトの取得
    var oWord = oText.value;                                       // 検索語句の取得
    var oRow = null;                                                   // テーブル行(tr)オブジェクト
    var nStep = (oSelect.value == "all")? 1: nCol;          // 何個おきにチェックするか
    var i;

    // tbody オブジェクトの削除
    if (document.getElementById("tbody1")) {
        oTable.removeChild(document.getElementById("tbody1"));
    }

    // tbody オブジェクトの生成
    oTbody = document.createElement("tbody");
    oTbody.id = "tbody1";

    // 開始インデックスの取得(検索する列に依存)
    if (oSelect.value == "all")          i = 0;        // 全データ
    else if (oSelect.value == "title") i = 0;        // タイトルの列
    else if (oSelect.value == "year") i = 1;        // 製作年の列
    else if (oSelect.value == "area") i = 2;        // 製作国の列
    else if (oSelect.value == "kana") i = 3;        // よみがなの列

    // 検索の実行と表示
    if (oWord == "") {            /* 検索語句が空白の場合 */
        oRow = GetRowFrom(-2);
        oTbody.appendChild(oRow);
    } else {                           /* 検索語句が空白でない場合 */
        for (; i<aMovieEx.length; i+=nStep) {
            if (aMovieEx[i].indexOf(oWord) >= 0) {
                oRow = GetRowFrom(i);
                oTbody.appendChild(oRow);
            }
        }
        if (!oRow) {                  /* 検索結果が 0 件の場合 */
            oRow = GetRowFrom(-1);
            oTbody.appendChild(oRow);
        }
    }
    oTable.appendChild(oTbody);    // tbodyオブジェクトを追加
}

// テーブル行オブジェクトの取得
// 引数index : データのインデックス(-2で初期表示、-1で検索結果0)
// 戻り値 : trオブジェクト
function GetRowFrom(index) 
{
    var oTR = document.createElement("tr");    // trオブジェクトの生成
    var oTD;                                                   // tdオブジェクト
    var oNode;                                                // textnodeオブジェクト

    // trオブジェクトに tdオブジェクトを追加
    if (index < 0) {            /* 初期表示(index=-2)または検索結果0(index=-1)の時 */
        oTD = document.createElement("td");     // tdオブジェクト
        oNode = (index == -2)?                          /* 表示文字列 */
                document.createTextNode("--- ここに検索結果が表示されます ---"):
                document.createTextNode("--- 検索結果 : 0 件です ---");
        oTD.colSpan = 4;
        oTD.style.textAlign = "center";
        oTD.appendChild(oNode);
        oTR.appendChild(oTD);
    } else {        /* データのインデックス値の指定があった場合(index>=0) */
        var i, j;
        for (i=index-index%nCol, j=0; j<nCol; i++, j++) {
            oTD = document.createElement("td");
            oNode = document.createTextNode(aMovieEx[i]);
            if (i == index) oTD.style.color = "#cc0000";       // 該当項目は赤い文字で表示
            oTD.appendChild(oNode);
            oTR.appendChild(oTD);
        }
    }
    return oTR;
}

// 検索フォームと結果表示テーブルの作成
function InitFindForm() 
{
    if (!document.getElementById) return;
    with (document) {
        write("<form>");
        write("検索語句 : ");
        write("<input type='text' id='", id_text, "' style='width:8em;'/>");
        write(" 検索対象 : ");
        write("<select id='", id_select, "'>");
        write("<option value='all' selected>全項目");
        write("<option value='title'>タイトル");
        write("<option value='year'>製作年");
        write("<option value='area'>製作国");
        write("<option value='kana'>よみがな");
        write("</select> ");
        write("<input type='button' value='検索開始' onclick='FindData()'/>");
        write("</form>");
        write("<table id='", id_table, "'><thead>");
        write("<tr><th colspan='4'>検索結果</tr>");
        write("<tr><th>タイトル<th>製作年<th>製作国<th>よみがな</tr>");
        write("</thead></table>");
    }
    document.getElementById(id_text).value = "";
    FindData();
} 

www.sasaraan.net

(c) morijoh