【Javascript】キーワード検索&リアルタイム結果表示機能の実装方法 -作って学ぶWeb制作-

JavaScript実践練習コース

はじめに

こんにちは!!作って学ぶWeb制作をご覧いただきありがとうございます。今回はペキーワード検索&リアルタイム結果表示機能を実装していきます
検索ボックスに入力されたキーワードを元に絞り込み検索をしてみます。今回は検索ボックスの値をリアルタイムに取得して、結果をすぐに表示していきます。
オンラインショップで商品を探しているときなどに見かける機能ですね!

検索機能とあわせてひらがな・カタカナ」「大文字・小文字」の変換であいまい検索も学んでいくのでぜひ一緒に作っていただけたら嬉しいです。

では今回作るもののデモと仕様を確認していきます。

デモ

キーワードを入力して検索してみてください。以下が仕様が分かりやすい例です!
・「牛」で検索すると3件ヒット
・全角数字「6」、半角数字「6」のどちらでも食パンがヒット
・ひらがな「り」、カタカナ「リ」のどちらでも3件ヒット
・大文字、小文字、全角半角関係なく「B、b、B、b」どれでも2件ヒット

仕様

以下の仕様をもとに実装を進めていきます。

検索ボックスに入力された値をリアルタイムに取得し、検索結果を表示する

「ひらがな・カタカナ」「大文字・小文字」「全角・半角」どちらでもヒットするあいまい検索に対応

検索対象のアイテムの名前と画像は配列の要素を取得してHTMLに出力する

css、jsファイルは外部ファイルとしてhtmlで読み込みます。

 【実践】検索&リアルタイム結果表示を実装する

HTMLを準備する

まずはHTMLを記載していきます。検索対象のアイテムは配列から取得してリスト表示するので、出力先となる枠組みを準備しておくイメージです。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ワード検索&リアルタイム結果表示機能</title>
    <link rel="stylesheet" href="style.css">
</head>

<body>
    <header>
        <h1>作って学ぶWeb制作 中級 ワード検索&リアルタイム結果表示</h1>
    </header>
    <!-- start main contents -->
    <main>
        <div class="contents">
            <form method="get" action="#" class="search-form">
                <input type="text" id="search-box" placeholder="キーワードを入力">
            </form>
            <ul id="search-list" class="search-list">
            </ul>
        </div>
    </main>
    <!-- end main contents-->

    <script type="text/javascript" src="script.js"></script>
</body>
</html>

ソースコード ポイント解説

search-listが配列から取得した各要素の出力先になります。

    <ul id="search-list" class="search-list">
    </ul>

CSSでスタイルを追加する

    body {
        font-family: "Arial", sans-serif;
    }

    .contents {
        width: 94vw;
        margin: 0 auto;
    }

    #search-box {
        width: 250px;
        padding: 5px;
        height: 30px;
        font-size: 20px;
        font-weight: bold;
        border: 3px solid #51639e;
        outline: none;
    }

    #search-list {
        display: flex;
        justify-content: flex-start;
        flex-wrap: wrap;
        padding: 0;
    }

    .search-item {
        list-style: none;
        font-weight: bold;
        font-size: 18px;
        border: 2px solid #ddd;
        text-align: center;
        width: 23%;
        margin: 0.5% ;
    }

    .search-item img{
        max-width: 100px;
    }

    @media (max-width: 767px) {
        /* 画面サイズが768px未満の場合の設定 */
        .search-item {
            list-style: none;
            width: 48%;
        }
    }
    .hidden {
        display: none;
    }

ソースコード ポイント解説

検索対象のアイテムを横並びにするために#search-listにdisplay:flexを指定しています。画面サイズに応じて各アイテムの横並び数を変えたいため、メディアクエリにて設定しています。

    @media (max-width: 767px) {
        /* 画面サイズが768px未満の場合の設定 */
        .search-item {
            list-style: none;
            width: 48%;
        }
    }

また、検索でヒットしたアイテム以外を非表示にするためのクラス”hidden”を用意しています。

    .hidden {
        display: none;
    }
まだこの時点ではアイテムの表示も空っぽなので、javascriptを書いて画面表示と機能を実装していきましょう!

Javascriptであいまい検索と絞り込みを実現

検索対象のアイテムの宣言、キーワードの正規表現と文字の相互変換、入力値と検索対象の文字列との比較が主なポイントです。

    var foodlist = [
        {
            name: '食パン(6枚切り)',
            img: '1.png',
        }, {
            name: '牛肉',
            img: '2.png',
        }, {
            name: '豚肉',
            img: '3.png',
        }, {
            name: 'ブロッコリー',
            img: '4.png',
        }, {
            name: 'りんご',
            img: '5.png',
        }, {
            name: 'バター',
            img: '6.png',
        }, {
            name: 'abc牛乳',
            img: '7.png',
        }, {
            name: ' Bitterコーヒー牛乳',
            img: '8.png',
        },
    ];


    ul = document.getElementById('search-list');
    var addLists = function (items) {
        const path = "image/"
        var html = '';
        for (i = 0; i < items.length; i++) {
            html += '<li class="search-item"><p>' + items[i].name + '</p>' +
                '<img src="' + path + items[i].img + '" alt="">';
        }
        // HTMLに出力
        ul.insertAdjacentHTML('afterbegin', html);
    }
    addLists(foodlist);


    const searchBox = document.getElementById('search-box');
    const listItems = document.querySelectorAll('.search-item');


    // 全角ひらがなに変換
    function convertString(str) {
        return str
            .replace(/[\u30a1-\u30f6]/g, match =>
                // 全角カタカナをひらがなに変換
                String.fromCharCode(match.charCodeAt(0) - 0x60))
            // 全角文字を半角に変換
            .normalize('NFKC')
            // 英数字を小文字に変換
            .toLowerCase();
    }


    // 検索ボックスの入力イベントで実行
    searchBox.addEventListener('input', function () {
        const query = convertString(searchBox.value);
        const inputwords = query.split(/[\s\u3000]+/).filter(inputword => inputword);


        if (query.trim() === '') {
            for (i = 0; i < listItems.length; i++) {
                listItems[i].classList.remove('hidden');
            }
        } else {
            // 検索ワードの値がある場合、配列各要素に対して処理を行う
            for (i = 0; i < listItems.length; i++) {
                const itemname = convertString(listItems[i].textContent);
                const hit = inputwords.some(inputword => itemname.includes(inputword));
                if (hit) {
                    listItems[i].classList.remove('hidden');
                } else {
                    // ヒット0の場合hiddenクラスを追加で非表示
                    listItems[i].classList.add('hidden');
                }
            }
        }
    });

ソースコード ポイント解説

2~31行目foodlistが今回の検索対象アイテムの配列です。オブジェクト内のnameがアイテムの名前、imgが画像のパスになります。
以下の繰り返し処理の中でHTMLを動的に作成し、insertAdjacentHTMLメソッドで追加しています。

    ul = document.getElementById('search-list');
    var addLists = function (items) {
        const path = "image/"
        var html = '';
        for (i = 0; i < items.length; i++) {
            html += '<li class="search-item"><p>' + items[i].name + '</p>' +
                '<img src="' + path + items[i].img + '" alt="">';
        }
        // HTMLに出力
        ul.insertAdjacentHTML('afterbegin', html);
    }
    addLists(foodlist);

次に、あいまい検索を実現するにあたって文字を変換している部分を見てみましょう。

    // 全角ひらがなに変換
    function convertString(str) {
        return str
            .replace(/[\u30a1-\u30f6]/g, match =>
                // 全角カタカナをひらがなに変換
                String.fromCharCode(match.charCodeAt(0) - 0x60))
            // 半角文字を全角に変換
            .normalize('NFKC')
            // 英数字を小文字に変換
            .toLowerCase();
    }

全角カタカナは全角ひらがなに変換、半角文字は全角文字へ変換、大文字の英数字は小文字に変換しています。

最後に文字の比較を行っている80行目以降を見てみましょう。

    for (i = 0; i < listItems.length; i++) {
        const itemname = convertString(listItems[i].textContent);
        const hit = inputwords.some(inputword => itemname.includes(inputword));
        if (hit) {
            listItems[i].classList.remove('hidden');
        } else {
            // ヒット0の場合hiddenクラスを追加で非表示
            listItems[i].classList.add('hidden');
        }
    }

listItemsが検索対象のアイテム全てなので、その要素の長さ分for分で回します。その繰り返しの中で検索ボックスに入力された値 inputwordsの文字と各アイテムの名前を比較しています。

.includes()…特定の要素が配列に存在するかどうかを調べる
.some()…配列内に特定の条件を満たす要素が1つでも存在するかを調べる
以上であいまい検索、入力値と検索対象の文字列との比較、結果の表示まで実装できました!

まとめ

今回はキーワード検索&リアルタイム結果表示機能を実装してみました!検索ができると欲しい情報があるかどうか探せるので便利なWebページになりますね。

作って学ぶWeb制作も中級編になり、使うイベントやメソッドの種類も増えてきました。イベントなどの書き方や使い方は覚えておくと便利ですね。


使えるイベントが増えてくるとできる機能の幅も広がりますね~

最後までお読みいただきありがとうございました。

タイトルとURLをコピーしました