もっと見るボタン
JSでもっと見るボタンを実装する
もっと見るボタンの話があり、調べた時の話。発見があったので、メモ。初めてのもっと見るボタンの実装。実際はjQueryでという指示だったので、下記を参考にしました。なかなかいい感じで、これだけ短いコードで実装できるのはjQueryの魅力ですよね。一方で、脱jQueryという流れもあり、普通のJSで書けるか、ちょっとやってみた方が良いなと思い、やってみました。結果的にはなんとか動きました。
index.html、reset.cssとstyle.css、そして、main.jsが構成要素です。HTMLは雛形HTMLに、要素を並べるdivともっと見るのbuttonを追加しただけ。reset.cssの掲載はありませんが、好みが分かれると思うので、お好みで。
<!DOCTYPE html>
<html lang="ja" xml:lang="ja" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="keywords" content="" />
<meta name="description" content="" />
<title>タイトル</title>
<link rel="stylesheet" href="reset.css" />
<link rel="stylesheet" href="style.css" />
<style></style>
</head>
<body>
<main>
<article>
<h1>List</h1>
<div class="json__list">
</div>
<button class="btn__more">
もっと見る
</button>
</article>
</main>
<script src="main.js"></script>
<script></script>
</body>
</html>
style.cssも結構適当です。短くするため、横に並べました。最後の行で、要素が無い場合、クラスを付与し、ボタンがフェードして消える形を踏襲しています。
body { padding: 2em; }
img { width: 100%; height: 100%; }
h1 { margin-bottom: 1em; font-size: 2em; text-align: center; }
.json__list { display: flex; flex-wrap: wrap; }
.list__box { display: flex; width: calc(100% / 4); margin-right: 2em; margin-bottom: 2em; }
.list__wrap { display: flex; width: 100%; margin-right: 1em; }
.listImg__wrap { width: 100px; height: auto; margin-right: 1em; }
.listTxt__ttl { margin-bottom: 0.5em; font-size: 1.4em; font-weight: bold; }
.btn__more { padding: 0.5em; background: #000; color: #fff; transition: all 1s; }
.btn__more.is__out { opacity: 0; visibility: hidden; }
jsが長いので、編集の都合により、分割します。本来は下記すべて、main.jsに記載されています。前半は要素を納めるdivとボタンといった必要な要素の取得、要素を納める配列の用意。そして、表示する数を設定しています。ローカルではダミーのapiからデータをとってきたので、その流れでfetchしている形です。後半にはデータの読み込み(getData())と表示する仕組み(displayList())の関数があります。ボタンをクリックすると指定の数だけ表示され、表示する数より残りの配列が少なければ、ボタンにクラスが付与され、消えます。
const listArea = document.querySelector(".json__list");
const btnMore = document.querySelector(".btn__more");
let list = new Array();
const displayNum = 10;
getData()
.then((list) => {
displayList(list, displayNum);
btnMore.addEventListener("click", () => {
if (list.length > displayNum) {
displayList(list, displayNum);
} else if (list.length < displayNum) {
btnMore.classList.add("is__out");
displayList(list, list.length);
}
});
})
.catch((err) => {
console.log(err);
});
getData()はfetchでデータを読み込みます。urlはダミーです。データをとって来る時に、同期・非同期の関係でデータがわちゃわちゃになり、苦労しましたが、なんとか順番通り表示することができました。displayList()ではデータと数を引数にして、引数の数だけデータを抽出し、その分だけ、データを先頭から削除しています。その後、抽出したデータの数だけ、mapでHTML化し、要素が並ぶdivに挿入。このやり方で大丈夫かって問題はありますが、正直わかりません。気になった点と言えば、innerHTMLと外部apiを使っていたので、エスケープした方がよかったんでしょうね。まあ、参考ということで。
async function getData() {
const data = await fetch(
"https://url"
);
return await data.json();
}
async function displayList(list, num) {
const currentList = list.slice(0, num);
list.splice(0, num);
const box = await currentList
.map((list) => {
return `
<section class="list__box">
<figure class="opacityTargets" class="listImg__wrap">
<img src="${list.image}" alt="${list.title}" class="listImg__img" />
</figure class="opacityTargets">
<div class="listTxt__wrap">
<h2 class="listTxt__ttl">${list.title}</h2>
<p class="listTxt__txt">${list.text}</p>
</div>
</section>
`;
})
.join("");
listArea.innerHTML += box;
}