ページ表示時は全てのカテゴリーの中から最新5件のコンテンツを、タブ切り替え時はカテゴリーごとにソートして、該当カテゴリーの最新5件のコンテンツをフェードインで表示します。
コンテンツはajaxを利用してjsonファイル内のデータを読み込みます。
- すべて
- お知らせ
- イベント
- 採用
htmlのコードは下記になります。
カテゴリーのソートはfilter編同様、カスタムデータ属性を利用します。
ajaxを利用してjsonファイル内からデータを読み込み、class=”news-content-all”を付与した空のdivタグ内にコンテンツを表示させます。
<ul class="news_link">
<li class="active" data-filter="catAll">すべて</li>
<li data-filter="catInfo">お知らせ</li>
<li data-filter="catEvent">イベント</li>
<li data-filter="catRecruit">採用</li>
</ul>
<div class="news-content-all"></div>
jsonのコードは下記になります。
xml編のデータはカテゴリーはバラバラで新しいものから順番に並んでいましたが、jsonのデータはカテゴリーごとに分類され、その該当カテゴリーの中で新しいものから順番に並んでいます。
[
{
"cat": "お知らせ",
"item": [
{
"time": "2019/07/02",
"link": "#",
"linkTarget": "false",
"article": "お知らせ01:ダミーテキストダミーテキスト"
},
{
"time": "2019/06/21",
"link": "#",
"linkTarget": "false",
"article": "お知らせ02:ダミーテキストダミーテキスト"
}
]
},
{
"cat": "イベント",
"item": [
{
"time": "2019/07/24",
"link": "https://www.yahoo.co.jp/",
"linkTarget": "true",
"article": "イベント情報01:ダミーテキストダミーテキスト"
},
{
"time": "2019/07/18",
"link": "https://www.msn.com/ja-jp",
"linkTarget": "false",
"article": "イベント情報02:ダミーテキストダミーテキスト"
}
]
},
{
"cat": "採用ニュース",
"item": [
{
"time": "2019/07/11",
"link": "#",
"linkTarget": "false",
"article": "採用情報01:ダミーテキストダミーテキスト"
},
{
"time": "2019/07/11",
"link": "",
"linkTarget": "",
"article": "採用情報02:ダミーテキストダミーテキスト"
}
]
}
]
続いてCSSのコードです。hasClass編、filter編と全く同じで、変更はありません。
.news_link {
display: flex;
margin: 0 0 35px;
padding: 0;
list-style-type: none;
}
.news_link li {
width: 24.7%;
margin-left: 2px;
background: #78909c;
color: #FFFFFF;
position: relative;
padding: 20px 6px 20px;
cursor: pointer;
text-align: center;
line-height: 1;
}
.news_link li:first-child {
margin-left: 0;
}
.news_link li:after {
content: '';
position: absolute;
width: 0;
height: 0;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 16px solid #c3d4dc;
display: none;
bottom: -16px;
left: 50%;
transform: translateX(-50%);
}
.news_link li.active, .news_link li:hover {
background: #c3d4dc;
color: #010101;
font-weight: bold;
}
.news_link li.active:after, .news_link li:hover:after {
display: block;
}
.news-content {
display: flex;
flex-wrap: nowrap;
align-items: baseline;
margin-bottom: 30px;
}
.news-date {
font-size: 16px;
margin-right: 20px;
}
.tags {
margin-right: 20px;
background: #c3d4dc;
min-width: 110px;
font-size: 14px;
text-align: center;
padding: 0 6px;
height: 35px;
line-height: 35px;
color: #000000;
}
.news-content .news-r a {
color: #000;
transition: color 0.2s ease-in-out;
}
.news-content .news-r a:hover {
color: #8bc73f;
transition: color 0.2s ease-in-out;
}
最後にjQueryのコードです。
xml編同様、jsonファイル読み込み部分、読み込み成功時の処理、読み込み失敗時の処理に分かれています。
xml編と異なるのはjsonファイル読み込み成功時の処理です。jsonのデータはxml編と異なりカテゴリーごとに分類されているので、それに対応したデータの取得方法になっています。xml編がeachでデータを取得していたのに対し、jsonはforのネストでデータを取得しています。jsonはデータへのアクセスが直接可能です。xml編のようにDOMでアクセスする必要はありません。
出来上がったコンテンツはカテゴリーごとに日付順で並んでいます。これをsortを利用して日付順に並べます。ここで日付順に並べ替えなければ「すべて」のタブに対応できません。ソートの処理でreturn 0;を記述しているのは、同じ日付の場合はデータの取得順で並べるためです。
ソートの対象はクラス名news-dateの付与された日付のpタグです。そのため変数sortDataの中身は日付のpタグになっています。コンテンツとしては、クラス名news-contentの付与されたdivタグを含めたhtmlが必要です。これをprop(“outerHTML”)を利用して取得し、変数insertContentsSortに格納します。
そして、変数limitの数だけソート後のコンテンツを上から順番にフェードインで表示します。
$(function() {
$.ajax({
url: 'js/news.json',
dataType: 'json',
cache: false,
}).done(function(data) {
var insertContents = '';
var len1 = data.length;
for(var i = 0 ; i < len1 ; i++) {
var len2 = data[i].item.length;
for(var j = 0 ; j < len2 ; j++) {
insertContents += '<div class="news-content" data-category="';
if(data[i].cat == 'お知らせ'){
insertContents += 'catInfo">';
}else if(data[i].cat == "イベント"){
insertContents += 'catEvent">';
}else if(data[i].cat == "採用ニュース"){
insertContents += 'catRecruit">';
}
insertContents += '<p class="news-date">';
insertContents += data[i].item[j].time;
insertContents += '</p>';
insertContents += '<p class="tags">';
insertContents += data[i].cat;
insertContents += '</p>';
insertContents += '<p class="news-r">';
if(data[i].item[j].link == ''){
insertContents += data[i].item[j].article;
}else{
insertContents += '<a href="' + data[i].item[j].link + '"';
insertContents += ((data[i].item[j].linkTarget == "true") ? ' target="_blank"' : '') + '>';
insertContents += data[i].item[j].article;
insertContents += '</a>';
}
insertContents += '</p>';
insertContents += '</div>';
}
}
var sortData = $('.news-date' , insertContents).sort(function(a,b) {
if($(a).text() < $(b).text()) return 1;
if($(a).text() > $(b).text()) return -1;
return 0;
});
var insertContentsSort = '';
$(sortData).each(function(){
insertContentsSort += $(this).parent().prop("outerHTML");
});
var newsLink = $(".news_link li");
var limit = 5;
for(var i = 0 ; i < limit ; i++) {
var limitNews = $(insertContentsSort)[i];
$(limitNews).appendTo('.news-content-all').hide().fadeIn();
}
$(newsLink).click(function(){
$(newsLink).removeClass("active");
$(this).addClass("active");
var btnFilter = $(this).attr('data-filter');
if (btnFilter == 'catAll') {
$(".news-content").remove();
for(i = 0 ; i < limit ; i++) {
limitNews = $(insertContentsSort)[i];
$(limitNews).appendTo('.news-content-all').hide().fadeIn();
}
} else {
$(".news-content").remove();
for(i = 0 ; i < limit ; i++) {
limitNews = $(insertContentsSort).filter('[data-category = "' + btnFilter + '"]')[i];
$(limitNews).appendTo('.news-content-all').hide().fadeIn();
}
}
});
}).fail(function(jqXHR, textStatus) {
var errorMessage = '';
errorMessage += '<p>データの読み込みに失敗しました。';
errorMessage += 'ステータスコード:' + jqXHR.status + '、';
errorMessage += 'ステータス:' + textStatus + '</p>';
$(errorMessage).appendTo('.news-content-all');
});
});