Menu

CODE

スライダー(Slick.js)の多重構造と自動計算フォームとプリント

2019/02/08 更新日:2020/05/04
デモページへ
仕様書

多順のスライダーで色々な商品を閲覧させたいという希望を叶えるスライダーです。
大カテゴリーで選別して、また子カテゴリーでもスライダーさせます。
今回使用しているプラグインはスライダーで使用しているslick

また下の価格表のテーブルも連動して該当の場所にカーレントンが当たるようになっています。
配送日もデータ属性を使い動的に操作できるようにしています。

フォームに関しては100個以上から3000以下のバリデーションの追加。
オプションによりカスタムな値段オプションに対応。

最後は計算結果をプリントに出力、もしくはPDF出力、そのままメールにお問い合わせを頂けるような運営を想定しています。

スライダーの実装

2つのスライダーの祖であるjs-slider-forjs-slider-tabを初期化していきます。

$(function() {
    $('.js-slider-for').slick({
        slidesToShow: 1,
        slidesToScroll: 1,
        arrows: false,
        fade: true,
        asNavFor: '.js-slider-tab',
        swipe: false,
        infinite: false
    });
    $('.js-slider-tab').slick({
        slidesToShow: 6,
        slidesToScroll: 1,
        asNavFor: '.js-slider-for',
        arrows: false,
        centerMode: true,
        swipe: false,
        focusOnSelect: true,
        infinite: false
    });
})

下のスライダーに対しての処理を追加

下のスライダーはスライダーの中でまたタブ繊維を行い、その中でcuurentのクラス付けclass="js-bgChange"をつくようにします。

$(function() {
    var $slider = $('.slider-lower');
    $slider.each(function() {
        var $sliderItem = $(this).find('.js-slider-lower');
        var $typeItem = $(this)
            .find('.js-slider-lower-page')
            .children('.js-slider-lower-page-item');
        var activeClass = 'js-type-active';
        $typeItem.each(function() {
            var index = $typeItem.index(this);
            $(this).attr('data-index', index);
        });
        $sliderItem.on('init', function(slick) {
            var index = $(this)
                .find('.slick-slide.slick-current')
                .attr('data-slick-index');
            $(this)
                .closest($slider)
                .find(
                    '.js-slider-lower-page-item' +
                        '[data-index="' +
                        index +
                        '"]'
                )
                .addClass(activeClass);
            $(this)
                .closest($slider)
                .find('.table__price:nth-of-type(' + index + 1 + ')')
                .addClass('js-bgChange');
        });
    if ($(this).hasClass('js-slide-circle')) {
            var showNum = 3;
        } else if ($(this).hasClass('js-slide-square')) {
            var showNum = 1;
        } else {
            var showNum = 0;
        }
      $sliderItem.slick({
            arrows: true,
            fade: true,
            initialSlide: showNum,
            infinite: false
        });
        $typeItem.on('click', function() {
            var index = $(this).attr('data-index');
            $sliderItem.slick('slickGoTo', index, false);
            $(this)
                .closest('.slider-lower')
                .find('.table__price')
                .removeClass('js-bgChange');
            var $dataTr = $(this)
                .closest('.slider-lower')
                .find('tr');
            $dataTr.each(function() {
                $(this)
                    .find('.table__price')
                    .eq(index)
                    .addClass('js-bgChange')
                    .siblings()
                    .removeClass('js-bgChange');
            });
        });
     $sliderItem.on('beforeChange', function(
            event,
            slick,
            currentSlide,
            nextSlide
        ) {
            $typeItem.each(function() {
                $(this).removeClass(activeClass);
            });
            $(this)
                .closest($slider)
                .find(
                    '.js-slider-lower-page-item' +
                        '[data-index="' +
                        nextSlide +
                        '"]'
                )
                .addClass(activeClass);
            var $dataTr = $(this)
                .closest('.slider-lower')
                .find('tr');
            $dataTr.each(function() {
                $(this)
                    .find('.table__price')
                    .eq(nextSlide)
                    .addClass('js-bgChange')
                    .siblings()
                    .removeClass('js-bgChange');
            });
        });
    });
});

次にフォームを設定していきます。

個数によって価格を変動させたいので、個数により元値を変えていきます。またオプションの追加により金額調整も行っていきます。
注文のロットが100以下の場合はエラーで入力の停止、また3001以上のロットは選択不可とする条件も追加しましょう。

$(function() {
    var $item = $('.js-autocalc');
    var $error = $('.js-error');
    var $option = $('.js-autocalc-option').find('input[type="checkbox"]');
    var $option1 = $('.js-autocalc-option1');
    var $option2 = $('.js-autocalc-option2');
    var $option3 = $('.js-autocalc-option3');
    $item.each(function() {
        var $input = $(this).find('.js-autocalc-input');
        var $output = $(this).find('.js-autocalc-conf');
        var $thisError = $(this).find($error);
        $input.on('change', function() {
            // 半角変換
            var halfVal = $(this)
                .val()
                .replace(/[!-~]/g, function(tmpStr) {
                    // 文字コードをシフト
                    return String.fromCharCode(tmpStr.charCodeAt(0) - 0xfee0);
                });
            // 数字以外の不要な文字を削除
            var val = $(this)
                .val(halfVal.replace(/[^0-9]/g, ''))
                .val();
            //ロット数で条件分岐
            if (val < 1) {
                var price = null;
            } else if (1 <= val && val < 100) {
                var price = 0;
            } else if (100 <= val && val < 300) {
                var price = $(this)
                    .closest($item)
                    .find('.js-autocalc-price1')
                    .val();
            } else if (300 <= val && val < 500) {
                var price = $(this)
                    .closest($item)
                    .find('.js-autocalc-price2')
                    .val();
            } else if (500 <= val && val < 1000) {
                var price = $(this)
                    .closest($item)
                    .find('.js-autocalc-price3')
                    .val();
            } else if (1000 <= val && val < 1500) {
                var price = $(this)
                    .closest($item)
                    .find('.js-autocalc-price4')
                    .val();
            } else if (1500 <= val && val < 2000) {
                var price = $(this)
                    .closest($item)
                    .find('.js-autocalc-price5')
                    .val();
            } else if (2000 <= val && val < 2500) {
                var price = $(this)
                    .closest($item)
                    .find('.js-autocalc-price6')
                    .val();
            } else if (2500 <= val && val < 3001) {
                var price = $(this)
                    .closest($item)
                    .find('.js-autocalc-price7')
                    .val();
            } else {
                var price = 'over';
            }
            //オプション1
            if ($option1.prop('checked')) {
                var option1 = 5;
            } else {
                var option1 = 0;
            }
            //オプション2
            if ($option2.prop('checked')) {
                var option2 = -500;
            } else {
                var option2 = 0;
            }
            //オプション3
            if ($option3.prop('checked')) {
                var option3 = 20000;
            } else {
                var option3 = 0;
            }
            if (price === null) {
                $thisError.text('');
                $output.text('0');
            } else if (price === 0) {
                $thisError.text('ご注文は100以上からになります'); //指定個数未満時のアクrション
                $output.text('0');
            } else if (price === 'over') {
                $thisError.text('3001個以上はお問い合わせください'); //指定個数未満時のアクrション
                $output.text('0');
            } else {
                var result = val * price + val * option1 + option2 + option3; //合計
                $output.text(result); //出力
                $thisError.text('');
            }
        });
    });

最後にフォームで設定したものをプリントとして出力します。

フォームで入力されたデータをもとにHTMLをappendしていきます。

$(function() {
    var $item = $('.js-loop'); //連続するの要素
    var $input = $item.find('.js-loop-input'); //値を取得する要素
    var $output = $('.js-print-output'); //出力先の要素
    var $total = $('.js-loop-total'); //出力先の要素
    var $option1 = $('.js-autocalc-option1');
    var $option2 = $('.js-autocalc-option2');
    var $option3 = $('.js-autocalc-option3');
    var total;
    $input.on('change', function() {
        $output.empty(); //出力先の要素を空にする
        $item.each(function(i) {
            //連続するの要素内の値を取得
            var val1 = $(this)
                .find('.js-loop-input1')
                .text();
            var val2 = $(this)
                .find('.js-loop-input2')
                .val();
            var val3 = $(this)
                .find('.js-loop-input3')
                .text();
            //値があったら取得した値を出力
            if (val1 && 99 < val2 && val3 && 3001 > val2) {
                var val3 = Number(val3);
                var val3 = val3.toLocaleString();
                $output.append(
                    '<div class="print__body-container loop-container-' +
                        [i] +
                        '"></div>'
                ); //出力する親要素を連番管理
                $('.loop-container-' + [i]).append(
                    '<div class="print__body-info loop-div-' + [i] + '"></div>'
                ); //出力する親要素を連番管理
                $('.loop-div-' + [i]).append(
                    '<p class="print__body-name">品目: ' + val1 + '</p>'
                );
                $('.loop-div-' + [i]).append(
                    '<p class="print__body-sum">合計金額 ' + val3 + ' 円</p>'
                );
                $('.loop-container-' + [i]).append(
                    '<ul class="print__body-list loop-ul-' + [i] + '"></ul>'
                ); //出力する親要素を連番管理
                $('.loop-ul-' + [i]).append(
                    '<li class="print__body-list-item"><dl class="print__body-lot-definition"><dt class="print__body-lot-definition-title">個数</dt><dd class="print__body-lot-definition-text">' +
                        val2 +
                        '<span>個</span></dd></dl></li>'
                );
                $('.loop-container-' + [i]).append(
                    '<ul class="print__body-list loop-ul-option-' +
                        [i] +
                        '"></ul>'
                ); //出力する親要素を連番管理
                if ($option1.prop('checked')) {
                    $('.loop-ul-option-' + [i]).append(
                        '<li class="print__body-list-item print__body-list-item--option">透明PP袋入れ</li>'
                    );
                }
                if ($option2.prop('checked')) {
                    $('.loop-ul-option-' + [i]).append(
                        '<li class="print__body-list-item print__body-list-item--option">デザイン6種類以上</li>'
                    );
                }
                if ($option3.prop('checked')) {
                    $('.loop-ul-option-' + [i]).append(
                        '<li class="print__body-list-item print__body-list-item--option">色校正</li>'
                    );
                }
            }
        });