脱プラグイン!スクラッチでJSを書いてみよう【初級・モーダル編】
世の中に配布されているプラグインは工数の短縮のためにとても便利な物ですよね。
例えばアコーディオンやハンバーガーメニュー、スライダー、モーダルなどはどこのサイトでも高い確率で使われており、これらは決まったプラグインを使い回す方も多いのではないでしょうか。
ですが、プラグインでのカスタマイズ可能範疇を超えた要件の時に自前でスクラッチで書いたものを用意しておき、それを使いこなせる技術力はあって損はないものです。
今回は、出現頻度が高い&様々な仕様が想定されるモーダルについて簡単に使い回せるようなものを用意してみましたのでぜひ参考にしてください!
※jQuery 3.6.0/Chromeで動作確認
上記のCodepenにあるHTML、JSについて掘り下げて説明します。
■HTML
<div class="btn__wrap">
<a class="btn js-modal-btn" href="javascript:void(0)">モーダルを開く</a>
</div>
<div class="modal js-modal">
<div class="modal__inner">
<p class="modal__close">×</p>
<div class="modal__box js-modal-box">
モーダルの内容です。モーダルの内容です。
</div>
</div>
</div>
大きく分けて2つの要素を今回は設置しています。
①モーダルを開く用のボタン
<div class="btn__wrap">
<a class="btn js-modal-btn" href="javascript:void(0)">モーダルを開く</a>
</div>
②モーダルの枠組み
<div class="modal js-modal">
<div class="modal__inner">
<p class="modal__close">×</p>
<div class="modal__box js-modal-box">
モーダルの内容です。モーダルの内容です。
</div>
</div>
</div>
■JS
上から順にご説明します。
変数定義
const $modal = $('.js-modal');
const $modalBtn = $('.js-modal-btn');
const $modalBox = $('.js-modal-box');
let modalShowFlg = false
let animationSpeed = 300
const $modal = $('.js-modal');
const $modalBtn = $('.js-modal-btn');
const $modalBox = $('.js-modal-box');
各要素を参照しています。
let modalShowFlg = false
modalを表示させた状態かそうでないかを定義しています。
初期値はfalse(非表示)です。
let animationSpeed = 300
CSSのtransitionと数値を合わせるため最初に定義しています。
モーダルを表示する動き
$modalBtn.on('click', (() => {
$modal.addClass('is-show');
setTimeout(() => { modalShowFlg = true }, animationSpeed);
}));
$modal.addClass('is-show');
「モーダルを開く」ボタンを押すと、モーダルに「is-show」クラスが付与されます。
初期状態ではCSSで非表示にしているので、表示させるためのものになります。
setTimeout(() => { modalShowFlg = true }, animationSpeed);
settimeoutメソッドは、指定時間が経過した後に実行させるための処理です。
今回の指定時間は最初に定義した変数「animationSpeed」になります。
※settimeoutについて詳しくはこちら
ですので、内容としては300ミリ秒後に「modalShowFlg」をtrueに変更しているといった感じになります。
settimeoutを使用する意図は、モーダルを開閉させようと連続でクリックしたときに300ミリ秒(0.3秒)かけて開くアニメーションを処理中に、もう一度イベントが走ると表示バグを起こす原因になってしまいます。
なので、「modalShowFlg」がtrueに変更される前=モーダルが表示し終わる前にモーダルを非表示にするイベントは走らないようにしております。(※ここの記述は後述します。)
モーダルを閉じる動き
$(document).on('click', ((el) => {
const $this = $(el.target)
if(modalShowFlg == true) {
if(!$this.closest($modalBox).length) {
$modal.removeClass('is-show');
setTimeout(() => { modalShowFlg = false }, animationSpeed);
}
}
}));
if(modalShowFlg == true) {
先ほどお話しした変数「modalShowFlg」がtrueでないと発火させないよ!という記述になります。
if(!$this.closest($modalBox).length) {
$thisは2行目に定義していますが、画面上のどこをクリックしているかを判別しています。
ここでは『クリックした要素($this)が「$modalBox」の中じゃない場合』に処理をするという記述になります。
ここからは表示時と全く逆の処理を行っています。
$modal.removeClass('is-show');
上記した条件を通過した時、モーダルから「.is-show」クラスを除去します。
setTimeout(() => { modalShowFlg = false }, animationSpeed);
300ミリ秒経過後、「modalShowFlg」をfalseにしています。
意外に処理を読んでみると、自作したことがない方でも簡単だなと感じるのではないでしょうか。
ここから少し、応用したものを記述していきます。
プラグインでカバーしきれない範疇とし、
「クリックする要素によってモーダルの中身のテキストや画像を入れ替えたい」などが挙げられるかなと思います。
モーダルの中身を変えたHTMLをいくつも用意すればクリアできるかもしれませんが、何十個も入れ込みたいデータがある場合はナンセンスな組み方ですよね。
そこで、先ほどのコードを応用して以下のような実装をしてみようと思います。
※jQuery 3.6.0/Chromeで動作確認
■HTML
ボタン部分
<div class="btn__wrap">
<a class="btn is-red js-modal-btn" data-color="red" data-text="赤" href="javascript:void(0)">モーダルを開く:赤</a>
<a class="btn is-blue js-modal-btn" data-color="blue" data-text="青" href="javascript:void(0)">モーダルを開く:青</a>
<a class="btn is-green js-modal-btn" data-color="green" data-text="緑" href="javascript:void(0)">モーダルを開く:緑</a>
</div>
data-color="red" data-text="赤"
data-color="blue" data-text="青"
data-color="green" data-text="緑"
ボタンを3つ複製した上でスタイリング用のクラスと、上記の「data属性」を追加しました。
モーダル部分
<div class="modal js-modal">
<div class="modal__inner">
<p class="modal__close">×</p>
<div class="modal__box js-modal-box">
<div class="modal__color js-modal-color"></div>
<div class="modal__text js-modal-text"></div>
</div>
</div>
</div>
<div class="modal__color js-modal-color"></div>
<div class="modal__text js-modal-text"></div>
四角と文字用のdivを追加しています。
■JS
モーダルを表示するとき
$modalBtn.on('click', ((el) => {
const $this = $(el.target);
const btnColor = $this.data('color');
const btnText = $this.data('text');
$modal.addClass('is-show');
$modalColor.css('background-color', btnColor);
$modalText.text(btnText);
}));
const $this = $(el.target);
const btnColor = $this.data('color');
const btnText = $this.data('text');
1行目の「$this」でクリックした要素を取得しています。
2行目、3行目で「data-color」と「data-text」の属性の値をそれぞれ取得しています。
$modalColor.css('background-color', btnColor);
$modalText.text(btnText);
先ほど定義した「btnColor」をCSSで四角部分の背景色に、
「btnText」を文字部分にテキストとして挿入しています。
このように「data属性」をクリックする要素に追加すると、jQueryで簡単に要素を取得して出力を付け替えることができます。
いかがでしたでしょうか。
JSやjQueryに苦手意識を持ちすぎず、スクラッチで記述していけるように理解を深める一歩となれれば幸いです!