フィルターの開発 - paulbarre/RssReader GitHub Wiki

フィルターの入力

ページのレイアウトを準備した際に、フィルターを入力するためtextinputを記述しています。

このinputにキーワードを入力すると、フィルター処理を開始します。

ボタンのクリックと同じように、インプット用のイベントがあるので、このイベントを利用するために、inputタグにidを設定しましょう。

<footer>
    <input id="feed-filter" type="text" placeholder="検索する...">
</footer>

イベントの設定はmain.jsの関数で行います。

$(document).ready(function () {

    ...

    $('#feed-filter').on('input', function () {
        var word = $(this).val();
        console.log('-- フィルター: ' + word);
    });
});

inputというイベントを実装すると、テキストが変更されるタイミングでコールバックが呼ばれます。

コールバックが呼ばれ、入力したキーワードを読み込んでフィルターを実行します。

フィルターのプロセス

feed.jsに新しい関数を実装します。

function filterFeed(word) {

    if (word.length >= 2) {
        // フィルターを実行する
    } else {
        // フィルターをリセットする
    }
}

このフィルターでは、2文字以上入力されたらフィルター処理を行います。

フィルターによって入力したキーワードを一覧から検索し、キーワードに一致しないアイテムは非表示にします。

function filterFeed(word) {

    if (word.length >= 2) {

        $('article').each(function () {
            var title = $(this).find('.article-title').text();
            var description = $(this).find('.article-description').text();
        });
    } else {
    }
}

上記の処理によって各アイテムのタイトルと概要をtitledescriptionという変数にセットします。

titledescriptionがstring型なので、文字列の中に存在する該当のキーワードを検索するために、indexOfという関数を使います。

例:

var hello_world = 'Hello world!';
var index = hello_world.indexOf('world');

上記のソースコードを実行してみると、index6になります。6hellow_worldにあるworldの位置です。H0e1、空白は5w6となります。

var index = hello_world.indexOf('ward');

上記のソースコードではindex-1になります。wardというstringがhello_wordに存在しないので、存在しない場合は-1を返します。

フィードのフィルターについても、タイトルと概要からキーワードを検索する方法と同様のやり方で行います。

function filterFeed(word) {

    if (word.length >= 2) {

        $('article').each(function () {
            var title = $(this).find('.article-title').text();
            var titleHasWord = title.indexOf(word) >= 0;

            var description = $(this).find('.article-description').text();
            var descriptionHasWord = description.indexOf(word) >= 0;
        });
    } else {
    }
}

タイトルにフィルターしたいキーワードがあれば、titleHasWordtrueになり、概要にあればdescriptionHasWordtrueになります。どちらかがtrueであればアイテムが表示され、どちらもfalseであればアイテムを隠します。

function filterFeed(word) {

    if (word.length >= 2) {

        $('article').each(function () {
            var title = $(this).find('.article-title').text().toLowerCase();
            var titleHasWord = title.indexOf(word.toLowerCase()) >= 0;

            var description = $(this).find('.article-description').text().toLowerCase();
            var descriptionHasWord = description.indexOf(word.toLowerCase()) >= 0;

            if (titleHasWord || descriptionHasWord) {
                // 表示します
            } else {
                // 隠します
            }
        });
    } else {
        // 全てのアイテムを普通に表示します
    }
}

アイテムを非表示にする

アイテムを非表示にするためにCSSを使います。cssフォルダーにmain.cssというファイルを作成します。

index.htmlのヘッダーにリンクを設定します。

<head>
    <meta charset="UTF-8">
    <title>Rss Reader</title>
    <link rel="stylesheet" type="text/css" href="css/main.css">
    ...
</head>

main.cssでは下記を追記します:

.hidden {
    display: none;
}

上記のCSSは「hiddenというクラスを使っている項目を非表示にします。

次に隠したいフィードのアイテムにhiddenのクラスを付け、feed.jsにフィルターを実装します。

function filterFeed(word) {

    if (word.length >= 2) {

        $('article').each(function () {
            var title = $(this).find('.article-title').text().toLowerCase();
            var titleHasWord = title.indexOf(word.toLowerCase()) >= 0;

            var description = $(this).find('.article-description').text().toLowerCase();
            var descriptionHasWord = description.indexOf(word.toLowerCase()) >= 0;

            if (titleHasWord || descriptionHasWord) {
                $(this).removeClass('hidden');
            } else {
                $(this).addClass('hidden');
            }
        });
    } else {
        $('article').removeClass('hidden');
    }
}

jQueryではクラスを付けるためにaddClassを使います。削除する場合はremoveClassを使います。

最後にmain.jsに戻り、フィルターを呼び出しましょう。

$(document).ready(function () {

    ...

    $('#feed-filter').on('input', function () {
        var word = $(this).val();
        filterFeed(word);
    });
});

ブラウザーで、ページを更新し、フィードをダウンロードしてからフィルターを試してください。

英語の対応

チュートリアルで使うはてなのRSSフィードを使う限りは気づかないかもしれませんが、英語のフィードを使うとバグが発生します。

確認のため、TechCrunchさんのフィードをつかってみましょう:

http://feeds.feedburner.com/crunchgear

このフィードを登録し、ダウンロードします。大文字と小文字、どちらも使う言葉をフィードの中にピックアップします。例:World

開発したフィルターのインプットにはWorldではなく、worldを入力しましょう。Worldを使っているアイテムまで非表示になってしまいます。

理由はindexOfは大文字と小文字を区別するためです。この対応を行うため、toLowerCaseというメソッドを使用します。このメソッドはstringの全ての文字を小文字にします。

下記のソースコードを実行してみてください。

var hello_world = 'Hello world!';
var index;
// 0
index = hello_world.indexOf('Hello');
// -1
index = hello_world.indexOf('hello');
// 0
index = hello_world.toLowerCase().indexOf('hello');

// 6
index = hello_world.indexOf('world');
// -1
index = hello_world.indexOf('World');
// 6
index = hello_world.indexOf('World'.toLowerCase());

場合によっては、検索するキーワードとターゲットのキーワードの両方にtoLowerCaseを付けます。

index = hello_world.toLowerCase().indexOf('World'.toLowerCase());

フィルターにこの対応を追加します。

function filterFeed(word) {

    if (word.length >= 2) {

        $('article').each(function () {
            var title = $(this).find('.article-title').text().toLowerCase();
            var titleHasWord = title.indexOf(word.toLowerCase()) >= 0;

            var description = $(this).find('.article-description').text().toLowerCase();
            var descriptionHasWord = description.indexOf(word.toLowerCase()) >= 0;

            if (titleHasWord || descriptionHasWord) {
                $(this).removeClass('hidden');
            } else {
                $(this).addClass('hidden');
            }
        });
    } else {
        $('article').removeClass('hidden');
    }
}

もう一度英語のフィードをダウンロードして確認してみてください。

⚠️ **GitHub.com Fallback** ⚠️