連動するプルダウンで選択するカートボタンを作成しました【javascript】

JavaScript

アパレル系のショッピングサイトで見かける、色やサイズを別々に選択するタイプのカートボタンを作成しました。
カラーとサイズを選択したらカートボタンをクリックできる仕様です。
最終的にformでデータを送信することを想定して、パラメーターも設定できるようにしたのでメモ。

作成のポイントは次の通りです。

  • 1ページに複数のカートボタンの設置が可能。
  • カートボタンをクリック後、プルダウンメニューの項目をリセット。
  • 欠品がある場合にも対応。(欠品の場合、メニューに「売り切れ」を表示)
  • 最終的に、formで送信するパラメーターが複数の場合も対応。

完成したカートボタンを確認する

こちらが完成した動作です。最初、サイズは選択できませんが、カラーを選んだら選択できるようになります。

動作デモ

実際の動作はこちらでご確認ください!(別ウィンドウが開きます)

連動するプルダウンメニューのサンプル | えむ家のメモ帳

ソースコードを確認

カラーを選択したら、サイズのオプションが連動して切り替わります。動作は全てjavascriptで実装しました。
作成手順のポイントをメモしておきます。

ページの構造をHTMLで作る

<div class="form_wrap">
    <form name="form_select_1" class="form_layout form_select">
        <div class="select_wrap">
            <span class="select_label">カラー:</span>
            <span class="select_box">
                <select name="sku_color" class="sku_color">
                    <option value="">--カラーを選択してください--</option>
                    <option value="0">レッド</option>
                    <option value="1">グリーン</option>
                    <option value="2">イエロー</option>
                    <option value="3">パープル</option>
                </select>
            </span>
        </div>
        <div class="select_wrap">
            <span class="select_label">サイズ:</span>
            <span class="select_box">
                <select name="sku_size" class="sku_size">
                    <option value="">--サイズを選択してください--</option>
                </select>
            </span>
        </div>
        <p class="shopping-btn">
            <!--デザイン-->
            <a onclick="form_sku_select(document.form_select_1);return false;" href="">
                お買い物かごに入れる<i class="fas fa-shopping-cart"></i>
            </a>
        </p>

    </form>
</div><!-- /form_wrap -->

form名は固有の名前にします。ここでは「form_select_1」です。
このformは、お買い物かごをクリックした時に実行される関数「form_sku_select」に引数として渡します。

複数のカートボタンを設置する事を想定して、共通のクラス名「form_layout」を設定します。
サイズのオプションに関しては、選択されたカラーによって動的に切り替わるのでHTMLには記述しません。

そして「お買い物かご」をクリックしたら、カラー・サイズのオプション選択の判定及び、プルダウンメニューのリセットを実行します。

読み込み時、カラー・サイズのオプションを初期化する

ここからはjavascriptで実装していきます。

ページ読み込み時、全てのカラー・サイズのオプションを初期化します。
複数のカートボタンがあることを想定して、「form_select」のクラス名があるformに対して同じ処理を実行します。

// 読み込み時の「色・サイズ」を選択なしに設定
let setSizeDefault = (function() {
    var form_select = document.querySelectorAll(".form_select");
    for(var i = 0; i < form_select.length; ++i){
        setDefaultOption(form_select[i]);
    };
})();

// オプション初期化
function setDefaultOption(targetForm) {
    // 初期化
    targetForm.sku_color.options[0].selected = true;
    targetForm.sku_size.textContent = null;

    // option生成
    let op = document.createElement("option");
    op.value = "";
    op.text = "--サイズを選択してください--";
    op.hidden = true;
    targetForm.sku_size.style.backgroundColor = "#999";
    targetForm.sku_size.appendChild(op);
}

関数setDefaultOptionでは、カラーの選択を初期値「–カラーを選択してください–」に変更します。
そして、サイズのオプションの中身を一旦全て削除し、改めて初期値だけのオプションを生成します。
その際、サイズメニューが選択できないようにします。
また、選択できないことを分かりやすくするため、背景の色をグレーにします。

この関数は、カラーの選択を初期値「–カラーを選択してください–」にした場合、都度実行されます。

カラー変更時にサイズのオプションが連動して切り替わるようにする

カラーを変更したらサイズのオプションが切り替わるようにしますが、生成されるサイズのタグは次のようになります。

カラー「赤」を選択した時に生成されるサイズのオプション

<select name="sku_size" class="sku_size">
    <option value="">--サイズを選択してください--</option>
    <option value="レッド(22.5cm),CLS11">22.5cm</option>
    <option value="レッド(23.0cm),CLS12">23.0cm</option>
    <option value="レッド(23.5cm),CLS13">23.5cm</option>
    <option value="レッド(24.0cm),CLS14">24.0cm</option>
    <option value="レッド(24.5cm),CLS15">24.5cm</option>
</select>

optionタグのvalue値に、送信したいパラメーターを「,」で区切って記載します。
ここでは、色とサイズ(例:レッド(22.5cm))、そして商品コード(例:CLS11)をパラメーターとして渡すと仮定します。

サイズ、商品コードを配列に格納する

サイズの属性に設定する値は、次のように配列に格納しておきます。

let SizeRed = [
    {label:"--サイズを選択してください--",skuCode:""},
    {label:"22.5cm",skuCode:"レッド(22.5cm),CLS11"},
    {label:"23.0cm",skuCode:"レッド(23.0cm),CLS12"},
    {label:"23.5cm",skuCode:"レッド(23.5cm),CLS13"},
    {label:"24.0cm",skuCode:"レッド(24.0cm),CLS14"},
    {label:"24.5cm",skuCode:"レッド(24.5cm),CLS15"}
];

各カラーごとにサイズと商品コードを変数に格納します。今回はレッド、グリーン、イエロー、パープルの4色分の変数を設定しています。

ついでに欠品した商品も配列に格納しておきます。格納するのは商品コードのみで、欠品商品がなければ配列は空の状態にしておきます。今回は3つの商品が欠品になっているとします。

// 欠品-商品番号
let soldOut = ["CLS21","CLS19","CLS30"];

カラー変更時のイベントをセットする

カラーのプルダウンメニューが変更されたらイベントが発火するようにセットします。
複数のカートボタンがあることを想定して、「sku_color」のクラス名があるプルダウンメニューすべてにイベントをセットします。

// 「カラー」変更時のイベントセット
let sku_color = document.querySelectorAll(".sku_color");
for(let i = 0; i < sku_color.length; ++i) {
    sku_color[i].addEventListener('change', changeSize);
};

先ほどセットしたイベントで実行される関数はこんな感じです。

// カラーの選択肢が変更された際の処理
function changeSize() {
    let changeForm = this.form;
    let changedColorValue = this.value;

    if (changedColorValue == "0") {
        setSize(SizeRed,changeForm);
    } else if (changedColorValue == "1") {
        setSize(SizeGreen,changeForm);
    } else if (changedColorValue == "2") {
        setSize(SizeYellow,changeForm);
    } else if (changedColorValue == "3") {
        setSize(Sizepurple,changeForm);
    } else {
        setDefaultOption(changeForm)
    }
}

カラーのプルダウンメニューを変更した時、設定されているvalueの値を取得します。
設定されている値は次の通りです。

初期値→値無し、レッド→0、グリーン→1、イエロー→2、パープル→3

value値によって、関数「setSize」に引数で渡す「商品のサイズ、商品コード」を変更します。

// カラーの選択肢が変更された際の処理
function changeSize() {
    let changeForm = this.form;
    let changedColorValue = this.value;

    if (changedColorValue == "0") {
        setSize(SizeRed,changeForm);
    } else if (changedColorValue == "1") {
        setSize(SizeGreen,changeForm);
    } else if (changedColorValue == "2") {
        setSize(SizeYellow,changeForm);
    } else if (changedColorValue == "3") {
        setSize(Sizepurple,changeForm);
    } else {
        setDefaultOption(changeForm)
    }
}

setSize関数でサイズオプションの切り替えをします。
実行の際、選択された「カラーのサイズ、商品コード」と「カラーを変更したform自身」が引き渡されています。

// オプションセット
function setSize(sizeColor,targetForm) {
    // 初期化
    targetForm.sku_size.textContent = null;
    targetForm.sku_size.style.backgroundColor = "#fff";
    
    sizeColor.forEach(function(value) {
        let op = document.createElement("option");
        op.value = value.skuCode;
        op.text = value.label;
        //欠品対応
        for (let i=0; i<soldOut.length;i++){
            if(op.value.match(soldOut[i])) {
                op.disabled = true;
                op.text += " " + "売り切れ"
            }
        }
        targetForm.sku_size.appendChild(op);
    });
}

最初にサイズオプションを初期化した後、配列で渡された「カラーのサイズ、商品コード」を元にオプションを生成します。

その際、売り切れの商品があったら選択できないようにして「売り切れ」の文言を追加します。

参考サイト

JavaScriptで複数のプルダウンメニューを連動させる方法を現役エンジニアが解説【初心者向け】 | TechAcademyマガジン
初心者向けにJavaScriptで複数のプルダウンメニューを連動させる方法について解説しています。プルダウンメニューの基本の作成方法、項目を選んだときに更に選択肢を表示させる場合の書き方についてサンプルコードで見ていきましょう。

「お買い物かごに入れる」ボタンをクリックした時の処理

最後に、購入ボタンをクリックした時の処理を記述します。

// カートボタンをクリックした時の処理
function form_sku_select(form_sku_select){
    if(!form_sku_select.sku_size.value){
        alert("色・サイズを選択してください。");
        return;
    }
    let cartParam= form_sku_select.sku_size.value.split(",");
    alert('選択した商品は' + cartParam[0] + "、SKUコードは" + cartParam[1]  + "です");

    //セレクトボックスを初期値に戻す
    let form_select = document.querySelectorAll(".form_select");
    for(let i = 0; i < form_select.length; ++i){
        form_select[i].sku_color.options[0].selected = true;
        form_select[i].sku_size.options[0].selected = true;
    }
}

まず、サイズのvalue値があるかでカラーとサイズが選択されているかをチェックします。
選択していなかったら、アラートを表示して処理を中止します。


カラーとサイズが選択されていたら、サイズのvalue値を取得します。値は次のような文字列となっています。

レッド(22.5cm),CLS11

この文字列を「,」(カンマ)で分割して、配列にします。
今回は分割したパラメーターをアラートで表示しましたが、必要に応じて別のformに値をセットします。

パラメーターの値に関しての処理が終わったら、プルダウンメニューの選択を初期化します。
「form_select」のクラス名があるformに対して初期化する処理を実行します。

メニューを初期化する理由ですが、ページが遷移した後、ブラウザの「戻る」などで元のページに戻ると、ブラウザによっては、選択したメニューの値が残っています。

選択したメニューの値が残っていると、動的に生成したサイズのオプションが表示されなくなるので、対応処置として初期化します。。

まとめ

今回のカートのプルダウンメニューで難しかったのは、色々な動作で常にサイズオプションのリセット(初期化)が必要なところです。
あと、イベント実行のタイミングでエラーが表示されることも多かったです。。

一応動くサンプルが作れたので、メモしておきます!

コメント