JSでjsonを読み込んで更新作業をラクにする
こんにちは、むったん(@6ttan)です。
私が最近制作を担当した複数のサイトでは、今後「HTMLで使用する要素は一緒だけど、画像や文言だけが異なる更新作業」になるだろうな…と想定できるものが多々ありまして。
作業工数の削減と正確性を求めてjsonを読み込ませる事にしました。
とあるサイトでは、指定した日時になったら表示/非表示…というような事もやっていて、とても便利だったのでご紹介します。
Contents close
やりたかったこと
コードサンプルだけ見たいよ!という方は、この項目は飛ばしてコードをご覧ください。
コンテンツのリストをサムネ付きで表示する
これは一定期間ごとにコンテンツが増えていくページで、ページ作成ごとに
- コンテンツリストの増産
- 過去に作成したページに最新リンクを設置
という作業がありました。
過去に作成したページが多ければ多いほど、管理が大変になっていくパターンのものです。
過去に作成したページに最新リンクを設置する作業は、更新箇所の内容やインデントが揃っていれば一括置換で対処できます。
しかし、作業する人が増えると曖昧になってきて一括置換の対象に入らないことも…
正確性を確保するのであれば、リストをまとめたjsonをJSで読み込んで、HTMLに出力してあげたほうがいいでしょう✨
…という事で、やりたかった事その1を図式化するとこんな感じ。
同じ形の複数コンテンツを決められた日付に表示する
先ほどとは逆に、既に存在する同じ形(要素)の複数コンテンツを決められた日付に表示/非表示にするというものです。
これを手作業(JSすら使わずに)でやろうとすると
- 決められた日時の前にコードを編集し、サーバーにアップしなければいけない
という大変地獄な作業が待っているし、かといってJSのみで管理しようとすると
- HTMLコードに非表示にするコードが記載されており、本来隠したい内容がソースから見えてしまう(jsonでも見えてしまいますが、最低でも2クッションは挟めるかな…)
- 中身の再編集をしたいが、コンテンツが多すぎて該当コードに辿り着けない
なんてこともあると思います。
実際、表示を隠すためのコメントアウトだらけコードって編集するの大変ではないですか?
…ということで、JSONに表示したい日付を記載しておき、表示タイミングが定期的であればJSで操作します。
やりたかった事その2を図式化するとこんな感じ。
コード
まずコンテンツををまとめているjsonです。
{
"lists" : [
{
"title": "コンテンツ01",
"img": "/hoge/img/image01.jpg",
"link": "/hoge/content/page01.html"
},
{
"title": "コンテンツ02",
"img": "/hoge/img/image02.jpg",
"link": "/hoge/content/page02.html"
}
]
}
keyとvalueは必要に応じて、それぞれセットしてあげます。
JSONについての詳しい書き方等はこちらが勉強になります✨
次にJSの共通部分になります。
let requestURL = '###.json';
let request = new XMLHttpRequest();
request.open('GET', requestURL);
request.responseType = 'json';
request.send();
request.onload = function() {
let list = request.response;
list = JSON.parse(JSON.stringify(list));
console.log(list)
}
まず1行目で、内容をまとめているjson(上で準備したものなど)をセットします。
2行目で、XMLHttpRequestを生成してrequest変数に入れています。
3行目で、リクエストを初期化してjsonデータを取り込みますよー!としています。
6行目で、サーバーにリクエストを送信します。
8行目ではjsonデータの受信が成功した時に行う処理をまとめています。
この状態で12行目のconsole.logを表示すると、以下の様になります。
ベースはできましたので、次はやりたかったことをベースにコンテンツを表示するためにいじります。
「コンテンツのリストをサムネ付きで表示する」のコード
まずはhtmlです。
~
<div class="js-lists lists__area"></div>
~
このdiv要素の中に、jsonで作成したリストを入れていきます。
次にJSです。
let requestURL = 'test.json';
let request = new XMLHttpRequest();
request.open('GET', requestURL);
request.responseType = 'json';
request.send();
request.onload = function() {
let listJSON = request.response;
listJSON = JSON.parse(JSON.stringify(listJSON));
pageList(listJSON.lists)
}
function pageList(els) {
let section = document.querySelector('.js-lists');
els.forEach(function(el) {
let title = el.title;
let img = el.img;
let link = el.link;
let sampleCode = '<div class="list__content">' +
'<a href="' + link + '">' +
'<div class="img__box">' +
'<img src="' + img + '">' +
'</div>' +
'<p class="title">' + title + '</p>' +
'</a>' +
'</div>';
section.insertAdjacentHTML('beforeend', sampleCode);
});
}
最初の13行は先ほどの共通JSですね。
まずquerySelectorで出力先を読み込んでおきます。
その後、forEachで0番目のデータを取得し、それぞれのvalue(値)を変数に格納していきます。
※その方が私は操作がラクだからやりましたが、問題なければ変数に格納しなくてもOKです
次にsampleCodeという変数に、型となるHTMLと先程のvalueを格納した変数で1つのリスト要素を作成します。
作成したらinsertAdjacentHTMLで該当場所にコードを挿入していきますが、beforeendでelement内部の最後の要素の後に挿入としています。
− element.insertAdjacentHTMLとは
これで0番目のデータの次(HTMLでいうと、下に書いていく)に1番目、2番目…となっていきます。
完成サンプルはこんな感じになりました。
これをベースにif文で条件を付けていってあげれば、例えばページと同じカテゴリに属するコンテンツのリストのみを出力する…などができます👏
ちなみに、各ページに同様のコンテンツリストを掲載したいのであれば…
JSファイルの読み込みと出力先のHTMLコードが記述されていれば、JSONデータを更新していくだけで以降はHTMLにコードの追加をせずラクに更新ができます。
「同じ形の複数コンテンツを決められた日付に表示する」のコード
先程と同様ですが、まずはhtmlです。
~
<div class="js-lists lists__area"></div>
~
このdiv要素の中に、jsonで作成したリストを入れていきます。
次にJSONです。
先ほど紹介したJSONデータに表示したい日付情報を追加します。
{
"lists" : [
{
"title": "コンテンツ01",
"img": "/hoge/img/image01.jpg",
"link": "/hoge/content/page01.html",
"date": "2021-11-22"
},
{
"title": "コンテンツ02",
"img": "/hoge/img/image02.jpg",
"link": "/hoge/content/page02.html",
"date": "2021-11-25"
}
]
}
最後に…JSにJSONの取得、HTMLへ出力、そして非表示にするタイミングを書いていきます。
let requestURL = 'test.json';
let request = new XMLHttpRequest();
request.open('GET', requestURL);
request.responseType = 'json';
request.send();
request.onload = function() {
let listJSON = request.response;
listJSON = JSON.parse(JSON.stringify(listJSON));
pageList(listJSON.lists)
}
function pageList(els) {
let section = document.querySelector('.js-lists');
const currentDay = new Date();
const currentDate = currentDay.getFullYear() + "/" + (currentDay.getMonth() + 1)+ "/"+ currentDay.getDate();
els.forEach(function(el) {
let title = el.title;
let img = el.img;
let link = el.link;
let date = el.date;
let visibleDay = new Date(date);
let visibleDate = visibleDay.getFullYear() + "/" + (visibleDay.getMonth() + 1) + "/"+ visibleDay.getDate();
if(currentDate === visibleDate) {
let sampleCode = '<div class="list__content">' +
'<a href="' + link + '">' +
'<div class="img__box">' +
'<img src="' + img + '">' +
'</div>' +
'<p class="title">' + title + '</p>' +
'</a>' +
'</div>';
section.insertAdjacentHTML('beforeend', sampleCode);
}
});
}
最初の13行は先ほど同じく共通JSですね。
表示 / 非表示タイミングを操作するために、17行目で現在日時でDateオブジェクトを生成します。
18行目で、年月日のみに変換します(時間などの条件を加える場合は、getHours()などもいじってあげてください)
ちなみになぜ18行目のようなことをしてるかというと、答えはconsole.logが教えてくれます。
年月日時分秒まで取得してしまうと、09:00:00の1秒間しか表示しないことになります。
1日中表示する、であれば時分秒は不要なのでこのようなことをしています。
forEachの中では先ほどのコードに加えて、日付設定の内容を変数に格納しています。
ifで現在日とjsonのdate情報が同じであれば…コンテンツのリストに表示する、としています。
変数currentDate, visibleDateをconsole.logで表示するとこんな感じになります。
なので、非表示になるタイミングは日付が異なる時です(今日表示されてれば、明日は非表示…という感じ)
完成サンプルはこんな感じ。
さいごに
用途は様々あると思いますが、要素は同じだけど中身だけ変えたい!
…という時にjsonで管理するのは物凄くラクでした。
内容を理解すれば様々な応用をきかせられるので、同じ様にラクしたーい!という方はぜひ検討してみてください☺️
では👋