JS

ネイティブネタ帳

UI

モーダル

タブ

ドロワー

スライダー

スクロール

アコーディオン

目次

ローディングアニメーション

ツールチップ

ヘッダー

フォーム

フォーム

文字

文字の装飾

文字の操作

文字のカウント

数字の操作

ウィンドウ

ウィンドウ操作

タイトルの操作

ページ遷移時の動き

class

classの操作

要素

要素の操作

要素の追加

API

WP REST API

Google Books APIs

楽天市場API

画像・動画

画像の操作

YouTube

リンク

Google Analytics

cookie

検索

検索

お気に入り登録

JavaScriptのdocument.cookieで記事一覧レイアウトの設定をページリロードしても生かして表示

お気に入り登録をすると、お気に入り記事一覧に登録することができます。

document.cookie

JavaScriptのdocument.cookieで記事一覧レイアウトの設定をページリロードしても生かして表示

JavaScriptのdocument.cookieで記事一覧レイアウトの設定をページリロードしても生かして表示

JavaScriptではcookieの取得・保存・削除を行うことができます。

そんなcookieを使って、ユーザーが選択した「記事一覧レイアウト」の設定を、ページ離脱後も生かすJavaScriptのスニペットについて解説していきます。

document.cookie

JavaScriptの document.cookie は、Webブラウザ上に保存された情報のcookieを読み書きすることができます。

cookieを追加する時

JavaScriptでcookieを追加する時、以下のような記述をします。

document.cookie = 'value=クッキー名; max-age=9999';

max-age はそのcookieの寿命で表され、上記のような9999だと大体3時間弱です。

かかかず
かかかず

value のところは任意の名称でOKです。

cookieを削除する時

追加したcookieを削除する場合、max-ageの値を0に設定して、Cookieを有効期限切れにすることで削除の扱いにします。

document.cookie = "value=cookie名;max-age=0;";

記事一覧のサンプル

ここで選択したレイアウトは、ページ遷移や更新をしても生きる形です。ので、試してみる場合は「カード」のレイアウトを選択してから、そのままページ更新をしてみてください。

かかかず
かかかず

cookieを使っているので、ブラウザを閉じてから開いても選択した設定が生きます。

cookieを使ったサンプルのコード

コードは、HTML・JavaScript・CSSの3種です。順に解説していきます。

HTML

HTMLは大きく分けて、「レイアウトを変更するボタン」の要素と、「記事一覧」の2つでできています。

コード量は記事一覧に関するものがほとんどで、各記事のコンポーネントは li のリストタグで作っています。

<!-- レイアウト変更のボタンここから -->
<ul class="cookieSwitch">
	<li><p id="styleList" class="activeOn"><i class="fas fa-th-list"></i>リスト</p></li>
	<li><p id="styleCard"><i class="fas fa-th-large"></i>カード</p></li>
</ul>
<!-- レイアウト変更のボタンここまで -->
<!-- 記事一覧のレイアウト -->
<section class="SwitchBlock">
<div class="changeCard">
	<ul>
		<li class="changeItem defaultList">
			<a href="https://dubdesign.net/javascript/addeventlistener-scroll/">
				<p class="itemCat dfont">JavaScript ネタ帳</p>
				<img src="https://dubdesign.net/wp-content/uploads/2021/12/java003.jpg" alt="JavaScriptの.addEventListenerのスクロールでclassの追加と削除">
				<div class="changeItemTxt">
					<time class="pubdate sng-link-time dfont" itemprop="datePublished" datetime="2021年12月15日">2021年12月15日</time>
					<p class="itemTitle">JavaScriptの.addEventListenerのスクロールでclassの追加と削除</p>
					<ul class="itemTag">
<li>JavaScript</li><li>コピペ</li><li>スクロール</li></ul>
				</div>
			</a>
		</li>
		<li class="changeItem defaultList">
			<a href="https://dubdesign.net/download/html-css/javascript-yubinbango/">
				<p class="itemCat dfont">HTML・CSS</p>
				<img src="https://dubdesign.net/wp-content/uploads/2021/08/yuubinnbangou_eyecatch.jpg" alt="JavaScriptのコピペでできる郵便番号を入力すると住所を自動で表示してくれるプラグインYubinBango">
				<div class="changeItemTxt">
					<time class="pubdate sng-link-time dfont" itemprop="datePublished" datetime="2021年8月4日">2021年8月4日</time>
					<p class="itemTitle">JavaScriptのコピペでできる郵便番号を入力すると住所を自動で表示してくれるプラグインYubinBango</p>
					<ul class="itemTag">
<li>CSS</li><li>HTML</li><li>JavaScript</li></ul>
				</div>
			</a>
		</li>
		<li class="changeItem defaultList">
			<a href="https://dubdesign.net/javascript/hover-tooltip/">
				<p class="itemCat dfont">JavaScript ネタ帳</p>
				<img src="https://dubdesign.net/wp-content/uploads/2022/02/javatooltip.jpg" alt="JavaScriptの.addEventListener()でhoverした時ツールチップを表示">
				<div class="changeItemTxt">
					<time class="pubdate sng-link-time dfont" itemprop="datePublished" datetime="2022年2月23日">2022年2月23日</time>
					<p class="itemTitle">JavaScriptの.addEventListener()でhoverした時ツールチップを表示</p>
					<ul class="itemTag">
<li>JavaScript</li><li>コピペ</li><li>ツールチップ</li></ul>
				</div>
			</a>
		</li>
		<li class="changeItem defaultList">
			<a href="https://dubdesign.net/admiration/tail-grafic/">
				<p class="itemCat dfont">見て学ぶデザイン</p>
				<img src="https://dubdesign.net/wp-content/uploads/2020/05/0503_tairu_eyecatch.jpg" alt="イラストや写真をタイルのように隙間無く敷き詰めたデザイン">
				<div class="changeItemTxt">
					<time class="pubdate sng-link-time dfont" itemprop="datePublished" datetime="2020年5月3日">2020年5月3日</time>
					<p class="itemTitle">イラストや写真をタイルのように隙間無く敷き詰めたデザイン</p>
					<ul class="itemTag">
<li>広告</li></ul>
				</div>
			</a>
		</li>
	</ul>
</div>
</section>
<!-- 記事一覧のレイアウトここまで -->
かかかず
かかかず

ボタン内のアイコンはFontawesomeを使っています。

JavaScript

JavaScriptは、「ページロード時のcookieチェック」と「ボタンクリック時の処理」の2つで、これらを .addEventListener の「DOMContentLoaded=HTMLの配置が完了次第」と、「click=クリック」のイベントでそれぞれ分けて作っています。

/* ロード時のcookie有無チェック */
window.addEventListener('DOMContentLoaded', (event) => {
/* cookieを取得 */
   function getCookieArray(){
      var arr = new Array();
      if(document.cookie != ''){
         var tmp = document.cookie.split('; ');
         for(var i=0;i<tmp.length;i++){
            var data = tmp[i].split('=');
            arr[data[0]] = decodeURIComponent(data[1]);
         }
      }
      return arr;
   }
   var arr = getCookieArray();
   var result = arr["value"];
/* valueのcookieがない時 */
   if(result == null){
      console.log("no cookie");
   } else {
      var theme = result;
      if(theme == 'cardCookie'){
/* valueの値でcardCookieがある時 */
         var elements = document.getElementsByClassName("changeItem");
         var i;
           for (i = 0; i < elements.length; i++) {
             elements[i].classList.remove('defaultList');
             elements[i].classList.add('gridCard');
         }
         document.getElementById("styleCard").classList.add('activeOn');
         document.getElementById("styleList").classList.remove('activeOn');
         console.log('CardStyle');
      } else {
/* valueの値でcardCookieがない時 */
         var elements = document.getElementsByClassName("changeItem");
         var i;
           for (i = 0; i < elements.length; i++) {
             elements[i].classList.remove('gridCard');
             elements[i].classList.add('defaultList');
         }
         document.getElementById("styleList").classList.add('activeOn');
         document.getElementById("styleCard").classList.remove('activeOn');
         console.log('notCardStyle');
      }
   }
});

/* リストへ変更 */
document.querySelector('#styleList').addEventListener('click', () => {
var elements = document.getElementsByClassName("changeItem");
var i;
  for (i = 0; i < elements.length; i++) {
    elements[i].classList.remove('gridCard');
    elements[i].classList.add('defaultList');
}
document.getElementById("styleList").classList.add('activeOn');
document.getElementById("styleCard").classList.remove('activeOn');
document.cookie = "value=cardCookie;max-age=0;";
console.log('cookieDelete');
});

/* カードへ変更 */
document.querySelector('#styleCard').addEventListener('click', () => {
var elements = document.getElementsByClassName("changeItem");
var i;
  for (i = 0; i < elements.length; i++) {
    elements[i].classList.remove('defaultList');
    elements[i].classList.add('gridCard');
}
document.getElementById("styleCard").classList.add('activeOn');
document.getElementById("styleList").classList.remove('activeOn');
document.cookie = 'value=cardCookie; max-age=9999';
console.log('cookieGet');
});

特に冒頭の「ページロード時のcookieチェック」は、ifの条件分岐で処理を分けているので、一緒に記述してあるコメントアウトと共にご覧ください。

ページロード時の処理

このスニペットでは、HTMLの配置が終わったタイミングでcookieチェックを行い、JavaScriptがclassの追加・削除をおこないます。その為、ロード時の処理が重めなので、PHPなどのバック側でcookieの条件分岐で処理を行った方がいいかもしれません。

WordPress(PHP)でcookieの条件分岐を行わせる場合は、以下の記事も参考にしてみてください。

クッキーの条件分岐 cookieで条件分岐

CSS

レイアウトはFlexboxを使い、JavaScriptでclassを付け替えた時にCSSが紐づき表示を切り替えます。

その為、CSSはレイアウトに関する記述がほとんどになっています。

/* ボタンのレイアウト */
ul.cookieSwitch {
    border: none;
    padding: 0;
    list-style: none;
    display: flex;
    justify-content: flex-end;
    flex-wrap: wrap;
    margin: 0;
    gap: 20px;
}
ul.cookieSwitch li p {
    margin: 0;
    display: inline-block;
    cursor: pointer;
    padding: 5px 20px 3px;
    background: #ddd;
    color: #FFF;
    border-radius: 2px;
    font-size: 0.9rem;
}
ul.cookieSwitch li p.activeOn {
    background: #707070;
}
ul.cookieSwitch li p i {
    margin-right: 5px;
}
/* ボタンここまで */

/* レイアウト共通 */
.changeCard ul {
    padding: 0;
    list-style: none;
    border: none;
    display: flex;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0;
    margin-top: 5px;
}
.changeItemTxt {
    width: 62%;
}
.changeItemTxt p.itemTitle {
    font-size: 1.1rem;
    line-height: 1.56;
    margin: 0;
    font-weight: bold;
    color: #313131;
    margin-bottom: 10px;
}
.changeItemTxt ul.itemTag {
    padding: 0;
    margin: 0;
    display: flex;
    justify-content: flex-start;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
}
.changeItemTxt ul.itemTag li {
    background: #f1f1f1;
    color: #707070;
    font-size: 0.7rem;
    padding: 2px 10px;
    position: relative;
}
.changeItemTxt ul.itemTag li:before {
    padding-right: 3px;
    font-family: "Font Awesome 5 Free";
    font-weight: 900;
    font-size: 1em;
    content: "\f02b";
    vertical-align: baseline;
    color: #aaa;
}
p.itemCat {
    position: absolute;
    left: 22px;
    top: 22px;
    background: #6bb6ff;
    color: #FFF;
    border-radius: 9999px;
    font-size: 0.7rem;
    display: inline-block;
    padding: 1px 12px 0px;
    z-index: 2;
}
/* 共通ここまで */

/* List */
li.changeItem.defaultList {
    width: 100%;
    padding: 0;
}
li.changeItem.defaultList a {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    border-radius: 2px;
    background: #fff;
    cursor: pointer;
    transition: 0.2s ease-in-out;
    padding: 15px;
    position: relative;
    align-items: center;
    text-decoration: none;
    border-top: solid 1px #eee;
    padding-right: 10px;
    cursor: pointer;
}
li.changeItem.defaultList:last-child a {
    border-bottom: solid 1px #EEE;
}
li.changeItem.defaultList a:hover {
    background: #fafafa;
}
li.changeItem.defaultList a img {
    width: 35%;
    margin-right: 3%;
}

@media screen and (max-width: 767px) {
/* (ここにモバイル用スタイルを記述) */
li.changeItem.defaultList a {
    flex-direction: column;
}
li.changeItem.defaultList a img {
    width: 100%;
    margin: 0 0 15px;
}
li.changeItem.defaultList a .changeItemTxt {
    width: 100%;
}
}

/* GridCard変更後 */
li.changeItem.gridCard {
    width: 47.5%;
    margin-bottom: 30px;
}
li.changeItem.gridCard a {
    display: flex;
    flex-direction: column;
    border: none;
    border-radius: 2px;
    background: #fff;
    box-shadow: 0 0 3px 0 rgb(0 0 0 / 12%), 0 2px 3px 0 rgb(0 0 0 / 22%);
    cursor: pointer;
    transition: 0.2s ease-in-out;
    height: 100%;
    padding: 0;
    position: relative;
    text-decoration: none;
}
li.changeItem.gridCard a:hover {
    box-shadow: 0 15px 30px -5px rgb(0 0 0 / 15%), 0 0 5px rgb(0 0 0 / 10%);
    transform: translateY(-4px);
}
li.changeItem.gridCard a p.itemCat {
    top: 10px;
    left: 10px;
}
li.changeItem.gridCard a .changeItemTxt {
    width: 100%;
    padding-left: 18px;
    padding-right: 18px;
    padding-bottom: 10px;
}
li.changeItem.gridCard a img {
    width: 100%;
    margin: 0 0 12px;
}
li.changeItem.gridCard .changeItemTxt ul.itemTag {
    display:none;
}
@media screen and (max-width: 767px) {
/* (ここにモバイル用スタイルを記述) */
li.changeItem.gridCard {
    width: 100%;
    margin-bottom: 20px;
}
}