【タブメニュー】コンテンツをカテゴリーごとにソートして表示【ajax:xml編】

ページ表示時は全てのカテゴリーの中から最新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');
	});
});
タイトルとURLをコピーしました