filter関数によりリアルタイム検索 + JSON
2019/02/09
更新日:2020/05/04
デモページへ
仕様書
リアルタイムに検索するをページに反映する希望を叶える検索ページです。
検索のフィルターはカテゴリーと特徴に分けて、それぞれに合致するアイテムを表示していきます。
合致しているものがない場合はカテゴリーや特徴などで選べないようにしていくという機能も備えています。
配送日もデータ属性を使い動的に操作できるようにしています。
5ページ以上はもっと見るボタンを設置を動的に出力できるようにしています。
また、表示できる合計数に関してもリアルタイムで動的出力していきます。
オプションによりカスタムな値段オプションに対応。
データの管理はJSONにで行います。
先ずは情報元になるjsonをみていきます。
抜粋したものになりますが、このような形になります。
"data":[
{
"bookUrl": "dammy_01",
"name": "カテゴリー1",
"label": ["特徴1"],
"class": "cat1",
"title": "タイトル1",
"text": "テキスト1テキスト1テキスト1テキスト1テキスト1テキスト1テキスト1テキスト1テキスト1テキスト1テキスト1",
"price": "1404",
"category": ["cat1","cat6"],
"linkCommon": "https://air-planning.com/",
"icon": ["fas fa-cart-arrow-down", "fas fa-comment-dollar"]
},
{
"bookUrl": "dammy_02",
"name": "カテゴリー2",
"label": ["特徴2"],
"class": "cat2",
"title": "タイトル2タイトル2タイトル2タイトル2タイトル2",
"text": "テキスト2テキスト2テキスト2テキスト2テキスト2テキスト2テキスト2テキスト2テキスト2テキスト2テキスト2",
"price": "1188",
"category": ["cat2","cat7"],
"linkCommon": "https://air-planning.com/news/",
"icon": ["fas fa-cart-arrow-down", "fas fa-bullhorn"]
},
次に検索部分を設計していきます。
XMLHttpRequest
という方法で非同期通信していきます。
input checkboxの入力を発火として、関数を動かします。またinputのvalueにcat1などのカテゴリーのパラメーターを付与します。
それはjsonのパラメーターで言うところのcategoryに該当する部分になります。その部分をfilterしていくことになります。
$(function() {
var blockInput = $('.input-block input');
var area = $('.input-block input')
.map(function() {
return $(this).val();
})
.get();
var areaAll = $('.input-block input')
.map(function() {
return $(this).val();
})
.get();
$reset = $('.reset');
$reset.on('click', function() {
var area = $('.input-block input')
.map(function() {
return $(this).val();
})
.get();
areaReset = $('.input-block input')
.map(function() {
return $(this).val();
})
.get();
blockInput.removeAttr('disabled');
blockInput.prop('checked', false);
getJSON(area);
});
blockInput.change(function() {
var area = $('.input-block input:checked')
.map(function() {
return $(this).val();
})
.get();
getJSON(area);
//disalble Input
var blockInput = $('.input-block input');
blockInput.change(function() {
var area = $('.input-block input:checked')
.map(function() {
return $(this).val();
})
.get();
});
});
getJSON(area);
function getJSON(area) {
var req = new XMLHttpRequest(); // XMLHttpRequest オブジェクトを生成する
req.onreadystatechange = function() {
// XMLHttpRequest オブジェクトの状態が変化した際に呼び出されるイベントハンドラ
if (req.readyState == 4 && req.status == 200) {
// サーバーからのレスポンスが完了し、かつ、通信が正常に終了した場合
var data = req.responseText;
var obj = JSON.parse(data);
var list = obj.data;
dataPicker = list.filter(function(item, index) {
if (area.length == areaAll.length || area.length == 0) {
return true;
} else if (area.length > 1) {
var categoryArray = item.category.filter(function(e) {
return area.indexOf(e) >= 0;
});
if (categoryArray.toString() === area.toString())
return true;
} else {
if (item.category.includes(area.toString()))
return true;
}
});
$('.list-block__wrap').remove(); //全体を削除
var categoryList = [];
//DOMの生成
for (var i in dataPicker) {
categoryList = categoryList.concat(dataPicker[i].category);
var h =
'<div class=list-block__wrap>' +
'<li class="list-block__item">' +
'<div class="list-block__head ' +
dataPicker[i].class +
'">' +
'<p class="list-block__head-title">' +
dataPicker[i].name +
'</p>' +
'<div class="list-block__head-title-label list-block__head-title-label-' +
[i] +
'">' +
'</div>' +
'</div>' +
'<div class="list-block__body">' +
'<div class="list-block__item-image">' +
'<img src="img/' +
dataPicker[i].bookUrl +
'.png" alt="' +
dataPicker[i].title +
'">' +
'</div>' +
'<div class="list-block__item-detail">' +
'<div class="list-block__item-upper">' +
'<div class="list-block__item-upper-description">' +
'<h3 class="list-block__item-detail-title">' +
dataPicker[i].title +
'</h3>' +
'<p class="list-block__item-detail-text">' +
dataPicker[i].text +
'</p>' +
'</div>' +
'</div>' +
' <div class="list-block__item-lowwer">' +
'<div class="list-block__item-info">' +
'<div class="list-block__item-info-left">' +
' <p class="list-block__price">価格:<span>' +
dataPicker[i].price +
'</span>円(税込)</p>' +
'</div>' +
'<div class="list-block__item-info-right list-block__item-info-right-' +
[i] +
'">' +
'</div>' +
'</div>' +
'<div class="list-block__item-link">' +
' <a target="_blank" href="' +
dataPicker[i].linkCommon +
'" class="list-block__item-link-detail">詳しくはこちら</a>' +
'</div>' +
'</div>' +
'</div>' +
'</li>';
$('.list-block').append(h);
var icon = dataPicker[i].icon;
for (key in icon) {
var value1 = icon[key];
var text = '<i class="' + value1 + '">';
$('.list-block__item-info-right-' + [i]).append(text);
}
var label = dataPicker[i].label;
for (key in label) {
var value2 = label[key];
var text2 = '<p><span>' + value2 + '</span></p>';
$('.list-block__head-title-label-' + [i]).append(text2);
}
}
var textLabel = $('.list-block__head-title-label p');
textLabel.each(function() {
$this = $(this);
var thistext = $this.text();
if (thistext === '') {
$this.hide();
}
});
var categoryList = categoryList.filter(function(x, i, self) {
return self.indexOf(x) === i;
});
blockInput.each(function() {
thisVal = $(this).val();
// $(this).attr('disabled', 'disabled');
$(this).prop('disabled', true);
$(this)
.parent('label')
.addClass('disabled');
for (var cat in categoryList) {
if (thisVal == categoryList[cat]) {
$(this).removeAttr('disabled');
$(this)
.parent('label')
.removeClass('disabled');
}
}
});
var size = dataPicker.length;
$('.js-count').text(size);
setItems();
}
};
req.open('GET', 'json/search.json', false); // HTTPメソッドとアクセスするサーバーの URL を指定
req.send(null); // 実際にサーバーへリクエストを送信
}
});