作ったもの
fruitsという配列群の中からインクリメンタルサーチをするJavaScript。
仕様
- 1文字打つごとに検索
- スペースで分けて検索
- フォームに何もないときちんと結果が全部消える
- 当てはまる検索結果が無いときにはそれを表示
JavaScriptのコード (jQuery)
var fruits = ['apple', 'apricot', 'avocado', 'blueberry', 'cherry', 'coconut', 'cranberry', 'dragonfruit', 'durian', 'grape', 'grapefruit', 'guava', 'kiwi fruit', 'lemon', 'lime', 'lychee', 'mango', 'melon', 'watermelon', 'miracle fruit', 'orange', 'bloodorange','clementine','mandarine','tangerine','papaya','passionfruit','peach','pear','persimmon','physalis','plum/prune','pineapple','pomegranate','raspberry','rambutan','star fruit','strawberry'];
$(function() {
var list = $("#list");
// id="list"を持つ変数を定義
var preWord;
// 入力結果と比較するための変数preWordを設定
function appendList(word) {
var item = $('<li class="list">').append(word);
// class="list"で削除という命令のため、全てのアイテムにclass="list"を追加
list.append(item);
// var list = $("#list")のlistの中に、class="list"を持ったitemを追加
}
function editElement(element) {
var result = "^" + element;
// mapで回ってきた配列の各要素の前に^を付け加える
return result;
}
$("#keyword").on("keyup", function() {
// id="keyword"のキーが押されて上がった時に発火する。
var input = $("#keyword").val();
// 変数inputを設定し、id="keyword"のバリューを中に入れる
var inputs = input.split(" ").filter(function(e) { return e; });
// splitを使い空白で切り新しい配列を形成。aスペース3つbの場合、["a", "", "", "b"]となる。 ※ 1 分け方の解説
// filterでfunction(e)のeに配列がそれぞれ入り、true or falseでtrueのもののみ返す。""はfalseになるため消える。 ※ 2 filterについての解説
var newInputs = inputs.map(editElement);
// 後の正規化表現のために、配列の各要素に^を付け加える。(ex)^ap 文字の先頭がapのときマッチ
var word = newInputs.join("|");
// 後の正規化表現のために、配列の各要素を|を使って連結。(ex) a|b aまたはbにマッチ
// この時点で、最初の入力が a b なら、^a|^b のように加工されており、先頭aもしくは先頭bにマッチ、となる。
var reg = RegExp(word);
// 加工されたwordからパターンマッチの正規化オブジェクトを生成して変数regに入れる。
if (input.length === 0) {
$(".list").remove();
// フォームに値がないときに、listを全て削除する。
}
if (word != preWord && input.length !== 0) {
// word != preWordで値が変わっていることを確認(shiftとか押された時対策)
// input.length !== 0で何か値が入っていることを確認
$(".list").remove();
// class = "list"を全て削除し、リストを空にする
$.each(fruits, function(i, fruit) {
if (fruit.match(reg)) {
// 配列fruitsがreg(正規化オブジェクト)とマッチしていたらappendListする
appendList(fruit);
}
});
if ($(".list").length === 0) {
// $(".list").length === 0は当てはまるものがないということなので、その処理。
appendList("一致する果物はありませんでした");
}
}
preWord = word;
// preWordにwordを入れてpreWordを更新する
});
});
※ 1 splitの分け方の解説
split
メソッドは引数に与えられた文字列で分けた配列を返します。
だいたい以下の通りです。
※ 2 filterの解説
filterが使われているのは以下の部分です。
var inputs = input.split(" ").filter(function(e) { return e; });
※1の解説を例にして、input.split(" ")の値が[a,"","",b]
だったとします。
filterでは、function(e)のeの部分に、eachのように配列の要素を1つずつ入れて判断します。
そして値がtrueだった場合のみ、取り出し、falseの場合は破棄し、新たな配列を形成します。
javascriptでは""
はfalseとなるので(他の言語では違ったりします、、、)
a => true
"" => false
"" => false
b => true
となり、trueのみを集めた配列["a", "b"]
が返されます。
おまけ
htmlとcssのコードも置いておきます。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="main.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="form-group">
<input type='text' id="keyword" class="form-control" placeholder="好きなフルーツを入力してください">
<button type="button" id="submit" class="btn">検索</button>
</div>
<ul id = "list" ></ul>
</body>
</html>
#keyword {
display: inline-block;
width: 50%;
}
#submit {
display: inline-block;
background-color: #6495ed;
color: #fff;
padding: 5.5px 20px;
vertical-align: top;
}
#list {
padding: 0;
margin: 0 auto;
width: 50%;
list-style: none;
}
li {
border-radius: 5px;
box-shadow: 0.5px 0.5px 1px 1px rgba(0,0,0,0.1) inset;
background-color: #eee;
margin: 10px;
padding: 10px;
}
.form-group {
width: 75%;
margin: 20px auto;
text-align: center;
}
##番外編;最近買った、面白いもの
・ハンターハンター34巻(6/29)
クロロ VS ヒソカとか、どうやっても面白くなるとしか
・カーテン自動開閉ロボット
カーテンレールに付ける4000円のロボット。
これを付けてから目覚ましなしで起きられる率が上がった。
・衛藤美彩 写真集
「綺麗なお姉さん」が好きな人、ちょっと眺めてるだけで幸せになれますよ。
間違い、指摘、リファクタリングなどお願いいたします。
フォームに値が入っていない場合にclass="list"を空にする設定をもう少しうまく書けるのではと考えています。。。