![見出し画像](https://assets.st-note.com/production/uploads/images/71526583/rectangle_large_type_2_65a1a9590265a82514eba515c300063c.png?width=800)
【Shopify】九十九悪嵐のうぇぶでざいんびぼうろく。~年齢制限をかけてみる編~【解説編】
解説とかどうでもいいからコードだけくれよって人はこちら↓
https://note.com/alarn99/n/n011863a03c98
それでは解説します~!
Sectionsフォルダにあるmain-cart-footer.liquid(HTML部分)では何をやってるの?
コード全体
<div class="page-width{% if cart == empty %} is-empty{% endif %}" id="main-cart-footer" data-id="{{ section.id }}">
<!-- ここから -->
{% for item in cart.items %}
{% if item.product.type == 'お酒' %}
<div id="ageCheck" class="cart-attribute__field">
<div class="cart-birth">
<div class="cart-birth__field">
<label>大切な確認事項</label>
<p class="caution">生年月日を選択してください。</p>
<select required="" class="required birthday" id="birthday-year" name="attributes[年] attr1">
</select>
<span>年</span>
<select required="" class="required birthday" id="birthday-month" name="attributes[月]">
</select>
<span>月</span>
<select required="" class="required birthday" id="birthday-day" name="attributes[日]">
</select>
<span>日</span>
</div>
<div class="consent">
<div class="consent_box">
<input type="hidden" name="attributes[以下の注意事項に同意します(必須)。]" value="No">
<input required="" class="age-check required" type="checkbox" name="attributes[以下の注意事項に同意します(必須)。]" value="Yes" checked="">
<label>以下の注意事項に同意します(必須)。</label>
</div>
<div class="consent_detail">
<ul class="consent_list">
<li class="consent_txt">生年月日が未入力または未成年者の場合、お酒の販売はお断りしております。</li>
<li class="consent_txt">妊娠中や授乳期の飲酒は、胎児・乳児の発育に悪影響を与えるおそれがあります。</li>
</ul>
</div>
</div>
</div>
</div>
{% break %}
{% endif %}
{% endfor %}
<!-- ここまで追記 -->
<div>
<!-- 省略 -->
解説
{% for item in cart.items %}
~~省略~~
{% endfor %}
ここのfor文で、カート(cart)に入っている全ての商品(items)を参照しています。
「お酒」という商品タイプがあるかどうか見極めるためには、まずは商品全部を引っ張ってくる必要があるのです…。
{% if item.product.type == 'お酒' %}
~~省略~~
{% endif %}
ここのif文で、カートに入っている商品に商品タイプ「お酒」がないかチェックしています。
商品タイプ「お酒」の商品が入っていた場合は年齢確認用の文章(「大事な確認事項うんぬん」を出すようにしています。商品タイプ「お酒」の商品がなければこの文章は出ません。
もし他の商品タイプでも年齢確認したいよって人はここの'お酒'の後に年齢確認対象の商品タイプを入れてあげましょう(以下はサンプル)。
{% if item.product.type == 'お酒' or item.product.type == 'アルコール飲料' %}
~~省略~~
{% endif %}
また、以下のようにしてもいいです。
{% if item.product.type contains 'お酒' %}
~~省略~~
{% endif %}
「contains」は「~を含む」という意味を持つ演算子です。
なので、仮に「お酒入りチョコレート」という商品タイプがあったとしたら、「== 'お酒'」だと「or item.product.type == 'お酒入りチョコレート'」にする必要がありますが、「contains 'お酒'」にすると「お酒」という文字列が入っているので、わざわざ「or item.product.type == 'お酒入りチョコレート'」と書かなくて大丈夫です!便利!
~~省略~~
<div id="ageCheck" class="cart-attribute__field">
<div class="cart-birth">
<div class="cart-birth__field">
<label>大切な確認事項</label>
<p class="caution">生年月日を選択してください。</p>
<select required="" class="required birthday" id="birthday-year" name="attributes[年] attr1">
</select>
<span>年</span>
<select required="" class="required birthday" id="birthday-month" name="attributes[月]">
</select>
<span>月</span>
<select required="" class="required birthday" id="birthday-day" name="attributes[日]">
</select>
<span>日</span>
</div>
<div class="consent">
<div class="consent_box">
<input type="hidden" name="attributes[以下の注意事項に同意します(必須)。]" value="No">
<input required="" class="age-check required" type="checkbox" name="attributes[以下の注意事項に同意します(必須)。]" value="Yes" checked="">
<label>以下の注意事項に同意します(必須)。</label>
</div>
<div class="consent_detail">
<ul class="consent_list">
<li class="consent_txt">生年月日が未入力または未成年者の場合、お酒の販売はお断りしております。</li>
<li class="consent_txt">妊娠中や授乳期の飲酒は、胎児・乳児の発育に悪影響を与えるおそれがあります。</li>
</ul>
</div>
</div>
</div>
</div>
~~省略~~
ここは年齢確認用の文章とかなので解説は省略します。
~~省略~~
</div>
{% break %}
~~省略~~
ここの{% break %}…実はとっっっても重要な役目を果たしています…。
{% break %}を忘れてしまうとどうなるか?
カートに入っている商品タイプ「お酒」の数だけ、年齢確認用の文章が増えてしまうのですッ!!
年齢確認用の文章が2、3個でも「なんであるんだろう…?」と不思議に感じますが、これが10個、20個…と増えていくと、不思議を通り越して気持ち悪いを通り越して怖いレベルです。
あと、恐らくJSが効かなくなる可能性があります(これは推測ですが)。
ですので、{% break %}を記述し、これ以上文章が増えないようにしてあげましょう。
Sectionsフォルダにあるmain-cart-footer.liquid(JS部分)では何をやっているの?
コード全体
{% endjavascript %}
<!-- ここから -->
{% for item in cart.items %}
{% if item.product.type == 'お酒' %}
<script>
/**
*
* 変数
*
**/
let i; // 生年月日の数値用
const cartSubmit = $('.cart__footer #checkout'); // 購入手続きボタン
let birthdayYear = document.getElementById("birthday-year"); // 生年月日[年]
let birthdayMonth = document.getElementById("birthday-month"); // 生年月日[月]
let birthdayDay = document.getElementById("birthday-day"); // 生年月日[日]
const ageCheck = $(' .age-check '); // 同意チェックボックス
/**
*
* 初期値
*
**/
ageCheck.prop('checked', false); // 同意チェックボックス(チェックなし)
cartSubmit.prop('disabled', true); // 購入手続きボタン(押下不可)
/* 生年月日[年]の設定 */
function $set_year() {
const selectYear = new Date();
// 「未選択」用
let not_select = document.createElement('option');
not_select.value = '';
not_select.text = '未選択';
not_select.hidden = 'hidden';
birthdayYear.appendChild(not_select);
// 年を生成
for(i = 1900; i < selectYear.getFullYear(); i++){
let op = document.createElement('option');
op.value = i;
op.text = i;
birthdayYear.appendChild(op);
}
}
// 生年月日[月]の設定
function $set_month(){
// 「未選択」用
const not_select = document.createElement('option');
not_select.value = '';
not_select.text = '未選択';
not_select.hidden = 'hidden';
birthdayMonth.appendChild(not_select);
// 月を生成
for(i = 1; i <= 12; i++){
let op = document.createElement('option');
op.value = i;
op.text = i;
birthdayMonth.appendChild(op);
}
}
// 生年月日[日]の設定
function $set_day(){
//日の選択肢を空にする
let children = birthdayDay.children;
while(children.length){
children[0].remove();
}
// 日を生成(動的に変える)
if(birthdayYear.value !== '' && birthdayMonth.value !== ''){
const last_day = new Date(birthdayYear.value,birthdayMonth.value,0).getDate();
for (i = 1; i <= last_day; i++) {
let op = document.createElement('option');
op.value = i;
op.text = i;
birthdayDay.appendChild(op);
}
}else {
// 「未選択」用
let not_select = document.createElement('option');
not_select.value = '';
not_select.text = '未選択';
birthdayDay.appendChild(not_select);
}
}
/**
*
* イベント
*
**/
// 「同意する」チェックボックス押下イベント
ageCheck.on('click', function() {
if( $(this).prop('checked') == true ) { // 「同意する」チェックボックスにチェックが入っている場合
if(birthdayYear.value != '' && birthdayMonth.value != '' && birthdayDay.value != '') { // 生年月日が空白ではない場合
// 年齢確認
let age = getUserAge( birthdayYear.value, birthdayMonth.value, birthdayDay.value );
if( age < 20) { // 年齢が20歳未満の場合
ageCheck.prop('checked', false);
cartSubmit.prop('disabled', true);
}else { // 年齢が20歳以上の場合
cartSubmit.prop('disabled', false);
}
}else { // 生年月日が空白の場合
ageCheck.prop('checked', false);
cartSubmit.prop('disabled', true);
}
}else { // 「同意する」チェックボックスにチェックが入っていない場合
cartSubmit.prop('disabled', true);
}
});
// 「ご購入の手続きへ」ボタン押下イベント
cartSubmit.on('click', function() {
if(ageCheck.prop('checked') == true ) { // 「同意する」チェックボックスにチェックが入っている場合
if(birthdayYear.value != '' && birthdayMonth.value != '' && birthdayDay.value != '') { // 生年月日が空白ではない場合
// 年齢確認
let age = getUserAge( birthdayYear.value, birthdayMonth.value, birthdayDay.value );
if( age < 20) { // 年齢が20歳未満の場合
ageCheck.prop('checked', false);
cartSubmit.prop('disabled', true);
}else { // 年齢が20歳以上の場合
cartSubmit.prop('disabled', false);
}
}else { // 生年月日が空白の場合
ageCheck.prop('checked', false);
cartSubmit.prop('disabled', true);
}
}else { // 「同意する」チェックボックスにチェックが入っていない場合
cartSubmit.prop('disabled', true);
}
});
// load時、年月変更時に実行する
window.onload = function(){
$set_year();
$set_month();
$set_day();
birthdayYear.addEventListener('change',$set_day)
birthdayMonth.addEventListener('change',$set_day)
}
/**
*
* 関数
*
**/
// 年齢確認
function getUserAge( year, month, day ) {
//誕生日を一旦 Date クラスに変換する
const birthdayDate = new Date(year, month - 1, day);
if( year != birthdayDate.getFullYear() || (month - 1) != birthdayDate.getMonth() || day != birthdayDate.getDate() ) { // 不正の値判定
return null;
}
//今日の日付けを取得する
var todayDate = new Date();
//誕生日を計算する
var userAge = todayDate.getFullYear() - birthdayDate.getFullYear();
// 誕生日
var currentYearDate = new Date(todayDate.getFullYear(), birthdayDate.getMonth(), birthdayDate.getDate());
if(currentYearDate > todayDate) { // 今年の誕生日を迎えていない場合
userAge = ( userAge - 1 );
}
return userAge; // 年齢を返す
}
</script>
{% break %}
{% endif %}
{% endfor %}
<!-- ここまで追記 -->
{% schema %}
解説
{% for item in cart.items %}
~~省略~~
{% endfor %}
HTML部分と同じく、ここのfor文で、カート(cart)に入っている全ての商品(items)を参照しています。
{% if item.product.type == 'お酒' %}
~~省略~~
{% endif %}
ここもHTML部分と同じです。ここのif文で、カートに入っている商品に商品タイプ「お酒」がないかチェックしています。
カートに商品タイプ「お酒」があったら<script>~</script>が読み込まれるという仕組みです。
ここのif文はなくても支障はあまりないのですが、商品タイプ「お酒」がない場合のHTML部分は空っぽになるので、コンソール上ではエラーが吐き出されています。いわゆる「ちょっと何言ってるのか分からない」状態です。
<script>
/**
*
* 変数
*
**/
let i; // 生年月日の数値用
const cartSubmit = $('.cart__footer #checkout'); // 購入手続きボタン
let birthdayYear = document.getElementById("birthday-year"); // 生年月日[年]
let birthdayMonth = document.getElementById("birthday-month"); // 生年月日[月]
let birthdayDay = document.getElementById("birthday-day"); // 生年月日[日]
const ageCheck = $(' .age-check '); // 同意チェックボックス
/**
*
* 初期値
*
**/
ageCheck.prop('checked', false); // 同意チェックボックス(チェックなし)
cartSubmit.prop('disabled', true); // 購入手続きボタン(押下不可)
/* 生年月日[年]の設定 */
function $set_year() {
const selectYear = new Date();
// 「未選択」用
let not_select = document.createElement('option');
not_select.value = '';
not_select.text = '未選択';
not_select.hidden = 'hidden';
birthdayYear.appendChild(not_select);
// 年を生成
for(i = 1900; i < selectYear.getFullYear(); i++){
let op = document.createElement('option');
op.value = i;
op.text = i;
birthdayYear.appendChild(op);
}
}
// 生年月日[月]の設定
function $set_month(){
// 「未選択」用
const not_select = document.createElement('option');
not_select.value = '';
not_select.text = '未選択';
not_select.hidden = 'hidden';
birthdayMonth.appendChild(not_select);
// 月を生成
for(i = 1; i <= 12; i++){
let op = document.createElement('option');
op.value = i;
op.text = i;
birthdayMonth.appendChild(op);
}
}
// 生年月日[日]の設定
function $set_day(){
//日の選択肢を空にする
let children = birthdayDay.children;
while(children.length){
children[0].remove();
}
// 日を生成(動的に変える)
if(birthdayYear.value !== '' && birthdayMonth.value !== ''){
const last_day = new Date(birthdayYear.value,birthdayMonth.value,0).getDate();
for (i = 1; i <= last_day; i++) {
let op = document.createElement('option');
op.value = i;
op.text = i;
birthdayDay.appendChild(op);
}
}else {
// 「未選択」用
let not_select = document.createElement('option');
not_select.value = '';
not_select.text = '未選択';
birthdayDay.appendChild(not_select);
}
}
/**
*
* イベント
*
**/
// 「同意する」チェックボックス押下イベント
ageCheck.on('click', function() {
if( $(this).prop('checked') == true ) { // 「同意する」チェックボックスにチェックが入っている場合
if(birthdayYear.value != '' && birthdayMonth.value != '' && birthdayDay.value != '') { // 生年月日が空白ではない場合
// 年齢確認
let age = getUserAge( birthdayYear.value, birthdayMonth.value, birthdayDay.value );
if( age < 20) { // 年齢が20歳未満の場合
ageCheck.prop('checked', false);
cartSubmit.prop('disabled', true);
}else { // 年齢が20歳以上の場合
cartSubmit.prop('disabled', false);
}
}else { // 生年月日が空白の場合
ageCheck.prop('checked', false);
cartSubmit.prop('disabled', true);
}
}else { // 「同意する」チェックボックスにチェックが入っていない場合
cartSubmit.prop('disabled', true);
}
});
// 「ご購入の手続きへ」ボタン押下イベント
cartSubmit.on('click', function() {
if(ageCheck.prop('checked') == true ) { // 「同意する」チェックボックスにチェックが入っている場合
if(birthdayYear.value != '' && birthdayMonth.value != '' && birthdayDay.value != '') { // 生年月日が空白ではない場合
// 年齢確認
let age = getUserAge( birthdayYear.value, birthdayMonth.value, birthdayDay.value );
if( age < 20) { // 年齢が20歳未満の場合
ageCheck.prop('checked', false);
cartSubmit.prop('disabled', true);
}else { // 年齢が20歳以上の場合
cartSubmit.prop('disabled', false);
}
}else { // 生年月日が空白の場合
ageCheck.prop('checked', false);
cartSubmit.prop('disabled', true);
}
}else { // 「同意する」チェックボックスにチェックが入っていない場合
cartSubmit.prop('disabled', true);
}
});
// load時、年月変更時に実行する
window.onload = function(){
$set_year();
$set_month();
$set_day();
birthdayYear.addEventListener('change',$set_day)
birthdayMonth.addEventListener('change',$set_day)
}
/**
*
* 関数
*
**/
// 年齢確認
function getUserAge( year, month, day ) {
//誕生日を一旦 Date クラスに変換する
const birthdayDate = new Date(year, month - 1, day);
if( year != birthdayDate.getFullYear() || (month - 1) != birthdayDate.getMonth() || day != birthdayDate.getDate() ) { // 不正の値判定
return null;
}
//今日の日付けを取得する
var todayDate = new Date();
//誕生日を計算する
var userAge = todayDate.getFullYear() - birthdayDate.getFullYear();
// 誕生日
var currentYearDate = new Date(todayDate.getFullYear(), birthdayDate.getMonth(), birthdayDate.getDate());
if(currentYearDate > todayDate) { // 今年の誕生日を迎えていない場合
userAge = ( userAge - 1 );
}
return userAge; // 年齢を返す
}
</script>
ほぼほぼコメントの通りなので、解説省略したい…!
解説しろよという方はお気軽におっしゃってください…解説します…。
{% break %}
ここもしっかりと書きましょうね~書かないと商品タイプ「お酒」の数だけ記述されちゃって気持ち悪いですからね~。
ここまでお付き合いいただき、ありがとうございました!
お疲れ様でした~。
この記事が気に入ったらサポートをしてみませんか?