ページ表示時は全てのカテゴリーの中から最新5件のコンテンツを、タブ切り替え時はカテゴリーごとにソートして、該当カテゴリーの最新5件のコンテンツをフェードインで表示します。
コンテンツはajaxを利用してxmlファイル内のデータを読み込みます。
- すべて
- お知らせ
- イベント
- 採用
htmlのコードは下記になります。
カテゴリーのソートはfilter編同様、カスタムデータ属性を利用します。
hasClass編、filter編と異なるのはコンテンツをhtmlで記述していない点です。ajaxを利用してxmlファイル内からデータを読み込み、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>
xmlのコードは下記になります。
itemデータ1件がコンテンツ1件になります。itemデータ内に必要な情報をまとめています。
<?xml version="1.0" encoding="utf-8"?>
<news>
<item>
<cat>イベント</cat>
<time>2019/07/24</time>
<link>https://www.yahoo.co.jp/</link>
<linkTarget>true</linkTarget>
<article>イベント情報01:ダミーテキストダミーテキスト</article>
</item>
<item>
<cat>採用ニュース</cat>
<time>2019/07/11</time>
<link>#</link>
<linkTarget>false</linkTarget>
<article>採用情報01:ダミーテキストダミーテキスト</article>
</item>
<item>
<cat>お知らせ</cat>
<time>2019/07/02</time>
<link>#</link>
<linkTarget>false</linkTarget>
<article>お知らせ01:ダミーテキストダミーテキスト</article>
</item>
</news>
続いて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ファイル読み込み部分、読み込み成功時の処理、読み込み失敗時の処理となっています。
xmlファイル読み込み部分ではcacheをfalseにセットして、キャッシュを無効化しています。
xmlファイル読み込み成功時の処理はdone以下に記述します。
まずxmlファイル内のデータを表示させたいhtmlに加工します。出来上がったコンテンツは全て変数insertContentsに格納します。そして変数limitの数だけコンテンツを上から順番にフェードインで表示します。
hasClass編、filter編と異なるのは、元々html内に記述しているコンテンツがないため、コンテンツを一度全て非表示にする処理がない点です。またコンテンツの表示は、appendToでコンテンツを追加し、hideで非表示にしてからfadeInで表示させています。
タブ切り替え時の処理は途中まではfilter編と同じです。異なるのはコンテンツの削除にremove、コンテンツの追加にappendToを利用している点です。hasClass編、filter編のようにコンテンツをcssのdisplay:noneで非表示にすると、タブを切り替える度にdisplay:noneのデータが残って増えていってしまいます。removeでコンテンツを全て削除してからappendToで追加するのがポイントです。
xmlファイル読み込み失敗時の処理はfail以下に記述します。
failの引数でステータスコードとステータスを表示させています。
$(function() {
$.ajax({
url: 'xml/news.xml',
dataType: 'xml',
cache: false,
}).done(function(data) {
var insertContents = '';
$('item', data).each(function() {
var thisItem = $(this);
insertContents += '<div class="news-content" data-category="';
if(thisItem.children('cat').text() == 'お知らせ'){
insertContents += 'catInfo">';
}else if(thisItem.children('cat').text() == "イベント"){
insertContents += 'catEvent">';
}else if(thisItem.children('cat').text() == "採用ニュース"){
insertContents += 'catRecruit">';
}
insertContents += '<p class="news-date">';
insertContents += thisItem.children('time').text();
insertContents += '</p>';
insertContents += '<p class="tags">';
insertContents += thisItem.children('cat').text();
insertContents += '</p>';
insertContents += '<p class="news-r">';
if(thisItem.children('link').text() == ''){
insertContents += thisItem.children('article').text();
}else{
insertContents += '<a href="' + thisItem.children('link').text() + '"';
insertContents += ((thisItem.children('linkTarget').text() == "true") ? ' target="_blank"' : '') + '>';
insertContents += thisItem.children('article').text();
insertContents += '</a>';
}
insertContents += '</p>';
insertContents += '</div>';
});
var newsLink = $(".news_link li");
var limit = 5;
for(var i = 0 ; i < limit ; i++) {
var limitNews = $(insertContents)[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 = $(insertContents)[i];
$(limitNews).appendTo('.news-content-all').hide().fadeIn();
}
} else {
$(".news-content").remove();
for(i = 0 ; i < limit ; i++) {
limitNews = $(insertContents).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');
});
});