app/template/default/Product/option_js.twig line 1

Open in your IDE?
  1. {#
  2. * Plugin Name : ProductOption
  3. *
  4. * Copyright (C) BraTech Co., Ltd. All Rights Reserved.
  5. * http://www.bratech.co.jp/
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. #}
  10. {% block css %}
  11.     <style type="text/css">
  12.         .datepicker-days th.dow:first-child,
  13.         .datepicker-days td:first-child {
  14.             color: #f00;
  15.         }
  16.         .datepicker-days th.dow:last-child,
  17.         .datepicker-days td:last-child {
  18.             color: #00f;
  19.         }
  20.     </style>
  21. {% endblock %}
  22. {% block javascript %}
  23. <script src="{{ asset('../../plugin/ProductOption42/assets/js/jquery.plainmodal.min.js') }}"></script>
  24. <script>
  25. $(function() {
  26.     //デフォルトのデイトタイムピッカーが存在しない場合
  27.     if ($('[type="date"]').prop('type') !== 'date') {
  28.         $.getScript("{{ asset('assets/js/vendor/moment.min.js', 'admin') }}").done(function() {
  29.             $.getScript("{{ asset('assets/js/vendor/moment-with-locales.min.js', 'admin') }}").done(function() {
  30.                 $.getScript("{{ asset('assets/js/vendor/tempusdominus-bootstrap-4.min.js', 'admin') }}").done(function() {
  31.                     $('input[type=date]').datetimepicker({
  32.                         locale: '{{ eccube_config.locale }}',
  33.                         format: 'YYYY-MM-DD',
  34.                         useCurrent: false,
  35.                         buttons: {
  36.                             showToday: true,
  37.                             showClose: true
  38.                         }
  39.                     });
  40.                 });
  41.             });
  42.         });
  43.     }
  44. });
  45. var product_id;
  46. $(function() {
  47.     {% set prev_condition = '' %}
  48.     {% set count = 0 %}
  49.     {% set index = 0 %}
  50.     {% for ProductOption in Product.ProductOptions %}
  51.         {% set current_condition = '' %}
  52.         {% set Option = ProductOption.Option %}
  53.         {% set Product = ProductOption.Product %}
  54.         {% if '張地' in ProductOption.Option.backend_name %}
  55.             {% set current_condition = '張地' %}
  56.         {% elseif 'サイズ選択' in ProductOption.Option.backend_name %}
  57.             {% set current_condition = 'サイズ' %}
  58.         {% else %}
  59.             {# 他の条件を追加する場合は、ここに追加してください。 #}
  60.         {% endif %}
  61.         {% if prev_condition != current_condition %}
  62.             {# 最後のカウントの処理 ============================= #}
  63.             {% if prev_condition != '' %}
  64.                 {# 最後の処理 #}
  65.             {% endif %}
  66.             {# 最初のカウントの処理 ============================= #}
  67.             {% set count = 0 %}
  68.             {% if (count == 0 and current_condition == '張地') or (count == 0 and current_condition == 'サイズ') %}
  69.                 {# 最初はオプション全体のモーダルを出力する #}
  70.                 modal{{ current_condition }} = $('#option_description_{{ current_condition }}').plainModal();
  71.                 $('#option_description_link_{{ current_condition }}').click(function() {
  72.                     modal{{ current_condition }}.plainModal('open');
  73.                     product_id = $(this).attr('data');
  74.                     return false;
  75.                 });
  76.             {% endif %}
  77.         {% endif %}
  78.         {# 最初と最後以外の通常処理 ============================= #}
  79.         {% if current_condition == '張地' or current_condition == 'サイズ' %}
  80.             {# 張地/サイズの場合 #}
  81.             {% if Option.description_flg == constant('Plugin\\ProductOption42\\Entity\\OptionCategory::ON') %}
  82.                 modal{{ Product.id }}_{{ Option.id }} = $('#option_description_{{ Product.id }}_{{ Option.id }}').plainModal();
  83.                 $(document).on('click', '#option_description_link_{{ Product.id }}_{{ Option.id }}', function(e) {
  84.                     e.preventDefault();
  85.                     $('#option_description_{{ current_condition }}').plainModal('close');
  86.                     // plainModalの 'close' イベントが発生した後に新しいモーダルを開く
  87.                     $('#option_description_{{ current_condition }}').one('plainmodalclose', function() {
  88.                         modal{{ Product.id }}_{{ Option.id }}.plainModal('open');
  89.                         product_id = $('#option_description_link_{{ Product.id }}_{{ Option.id }}').attr('data');
  90.                     });
  91.                 });
  92.             {% endif %}
  93.             {# 戻るボタンで戻る #}
  94.             modal{{ current_condition }} = $('#option_description_{{ current_condition }}').plainModal();
  95.             $(document).on('click', '#option_back_link_{{ current_condition }}', function(e) {
  96.                 e.preventDefault();
  97.                 $('#option_description_{{ Product.id }}_{{ Option.id }}').plainModal('close');
  98.                 $('#option_description_{{ Product.id }}_{{ Option.id }}').one('plainmodalclose', function() {
  99.                     modal{{ current_condition }}.plainModal('open');
  100.                     return false;
  101.                 });
  102.             });
  103.         {% else %}
  104.             {# 張地/以外の画像オプション #}
  105.             {% if Option.description_flg == constant('Plugin\\ProductOption42\\Entity\\OptionCategory::ON') %}
  106.                 modal{{ Product.id }}_{{ Option.id }} = $('#option_description_{{ Product.id }}_{{ Option.id }}').plainModal();
  107.                 $(document).on('click', '#option_description_link_{{ Product.id }}_{{ Option.id }}', function(e) {
  108.                     e.preventDefault();
  109.                     modal{{ Product.id }}_{{ Option.id }}.plainModal('open');
  110.                     product_id = $('#option_description_link_{{ Product.id }}_{{ Option.id }}').attr('data');
  111.                 });
  112.             {% endif %}
  113.         {% endif %}
  114.         {% set prev_condition = current_condition %}
  115.         {% set count = count + 1 %}
  116.         {% set index = index + 1 %}
  117.     {% endfor %}
  118. });
  119. //初期値で全てのセレクトボックスを必須
  120. $(document).ready(function() {
  121.    $("select.form-select").attr("required", true);
  122. });
  123. //オプション選択ボタンクリックイベント
  124. $(function() {
  125.     $("[id^=desc_btn_]").click(function(){
  126.         /*optionが選択されたら選択項目を表示する 後で関数にする*/
  127.         //データを取得
  128.         var select_data = $(this).data('type');
  129.         var select_title = $(this).siblings('h3').text();
  130.         var select_img_src = $(this).siblings('img').attr('src');
  131.         var select_img_txt = $(this).siblings('p').text();
  132.         //表示する前に一度オプションを全て解除する
  133.         var targetElementSelect = $('[data-select-type="' + select_data + '"]');
  134.         targetElementSelect.children('select').prop("selectedIndex", 0);
  135.         //表示するエリアに選択した情報を表示
  136.         var targetElement = $('[data-type="' + select_data + '"]');
  137.         targetElement.fadeIn();
  138.         if(select_img_src){
  139.             targetElement.find('img').attr('src', select_img_src);
  140.         }else{
  141.             targetElement.find('img').hide();
  142.         }
  143.         targetElement.find('h3').text(select_title);
  144.         targetElement.find('p').text(select_img_txt);
  145.         //表示エリアの選択状態をtrueにする
  146.         $('.choice_display_area[data-type="' + select_data + '"]').attr('data-select-result', true);
  147.         //「リストから選択」ボタンを非表示
  148.         targetElement.siblings('.choice_display_area__top').children('a.option_description_link_brn').addClass('display_disable');
  149.         var form_id;
  150.         var id = $(this).attr('id').replace(/^desc_btn_/ig, '');
  151.         var ids = id.split('_');
  152.         if (eccube.hasOwnProperty('productsClassCategories')) {
  153.             form_id = product_id;
  154.         }else{
  155.             form_id = 1;
  156.         }
  157.         var $form = $("form[name=form"+form_id+"]");
  158.         func_submit($form,ids[0],ids[1]);
  159.         onOptionChange($form)
  160.     });
  161.     $("[name^=productoption]").change(function(){
  162.         $form = $(this).parents('form');
  163.         onOptionChange($form);
  164.     });
  165. });
  166. //選択クリアボタンイベント
  167. $(function() {
  168.     $("a.option_delete_link_btn").click(function(){
  169.         var data_type = $(this).data('type');
  170.         //非表示にする前に一度オプションを全てリセット
  171.         var targetElementSelect = $('[data-select-type="' + data_type + '"]');
  172.         targetElementSelect.children('select').prop("selectedIndex", 0);
  173.         //表示エリアを非表示
  174.         if($(this).parent('.choice_display_area').data('type') == data_type){
  175.             $(this).parent('.choice_display_area').hide();
  176.         }
  177.         //選択状態をfalseにする
  178.          $('.choice_display_area[data-type="' + data_type + '"]').attr('data-select-result', false);
  179.         //モーダルボタンを表示
  180.         $('[data-btn-type="' + data_type + '"]').removeClass('display_disable');
  181.         //表示金額をリセット
  182.         $form = $(this).parents('form');
  183.         onOptionChange($form);
  184.     });
  185. });
  186. function func_submit($form,optionId, setValue) {
  187.     var $sele_option = $form.find("[name=productoption" + optionId + "]");
  188.     if($sele_option && $sele_option.length){
  189.         var kind = $sele_option.attr("type");
  190.         if(kind == 'radio'){
  191.             $sele_option.val([setValue]);
  192.         }else{
  193.             $sele_option.val(setValue);
  194.         }
  195.     }else{
  196.         var $sele_option = $form.find('[name="productoption' + optionId + '[]"]');
  197.         if($sele_option && $sele_option.length){
  198.             $sele_option.each(function(){
  199.                 if($(this).val() == setValue){
  200.                     $(this).prop('checked',true);
  201.                 }
  202.             });
  203.         }
  204.     }
  205.     $('#option_description_' + product_id + '_' + optionId).plainModal('close');
  206. }
  207. var optionPrice = {{ optionPrices|json_encode|raw }};
  208. var optionPoint = {{ optionPoints|json_encode|raw }};
  209. var optionMultiple = {{ optionMultiples|json_encode|raw }};
  210. var taxRules = {{ taxRules|json_encode|raw }};
  211. var default_class_id = {{ default_class_id|json_encode|raw }};
  212. function onOptionChange($form){
  213.     if(!$form.length){
  214.         return;
  215.     }
  216.     var optionPriceTotal = 0;
  217.     var optionPointTotal = 0;
  218.     var tax_rate = null;
  219.     var tax_rule = null;
  220.     var product_id = $form.find('input[name="product_id"]').val();
  221.     var $sele1 = $form.find('select[name=classcategory_id1]');
  222.     var $sele2 = $form.find('select[name=classcategory_id2]');
  223.     var classcat_id1 = $sele1.val() ? $sele1.val() : '__unselected';
  224.     var classcat_id2 = $sele2.val() ? $sele2.val() : '';
  225.     if (eccube.hasOwnProperty('productsClassCategories')) {
  226.         // 商品一覧時
  227.         classcat2 = eccube.productsClassCategories[product_id][classcat_id1]['#' + classcat_id2];
  228.     } else {
  229.         // 詳細表示時
  230.         classcat2 = eccube.classCategories[classcat_id1]['#' + classcat_id2];
  231.     }
  232.     $form.find("[id^=productoption]").each(function(){
  233.         var id = $(this).prop("id");
  234.         var name = $(this).attr("name");
  235.         var option_id = null;
  236.         if(name === undefined){
  237.             name = $(this).find("input").prop("id");
  238.         }
  239.         if(name === undefined)return;
  240.         option_id = name.replace(/productoption/ig,'');
  241.         option_id = option_id.replace(/_\d+/ig,'');
  242.         option_id = option_id.replace(/\[\]/ig,'');
  243.         if(id.match(/^productoption\d+$/)){
  244.             var kind = $(this).prop('tagName');
  245.             var type = $(this).attr('type');
  246.             var value = null;
  247.             var multi = 1;
  248.             switch(kind){
  249.                 case 'SELECT':
  250.                     value = $(this).val();
  251.                     break;
  252.                 case 'TEXTAREA':
  253.                 case 'INPUT':
  254.                     var text = $(this).val();
  255.                     if(text.length > 0){
  256.                         value = 0;
  257.                     }
  258.                     if(type == 'number'){
  259.                         if(optionMultiple[product_id][option_id]){
  260.                             multi = $(this).val();
  261.                             if(multi.length == 0)multi = 0;
  262.                         }
  263.                     }
  264.                     break;
  265.                 default:
  266.                     if($(this).find('input[type="checkbox"]').length > 0){
  267.                         value = [];
  268.                         $(this).find('input[type="checkbox"]:checked').each(function(){
  269.                             value.push($(this).val());
  270.                         });
  271.                     }else{
  272.                         value = $form.find("input[name='productoption" + option_id + "']:checked").val();
  273.                     }
  274.                     break;
  275.             }
  276.             if(value != null){
  277.                 if(Array.isArray(value)){
  278.                     for(var key in value){
  279.                         optionPriceTotal += parseFloat(optionPrice[product_id][option_id][value[key]]);
  280.                         optionPointTotal += parseFloat(optionPoint[product_id][option_id][value[key]]);
  281.                     }
  282.                 }else{
  283.                     optionPriceTotal += parseFloat(optionPrice[product_id][option_id][value]*multi);
  284.                     optionPointTotal += parseFloat(optionPoint[product_id][option_id][value]*multi);
  285.                 }
  286.             }
  287.         }
  288.     });
  289.     if(classcat2){
  290.         var product_class_id = classcat2.product_class_id;
  291.     }else{
  292.         var product_class_id = default_class_id[product_id];
  293.     }
  294.     var tax_rate = taxRules[product_class_id]['tax_rate'];
  295.     var tax_rule = taxRules[product_class_id]['tax_rule'];
  296.     var $option_price = $form.parent().find('#option_price_default').first();
  297.     $option_price.text(number_format(optionPriceTotal));
  298.     var $option_point = $form.parent().find('#option_price_inctax_default').first();
  299.     $option_point.text(number_format(optionPriceTotal + sfTax(optionPriceTotal, tax_rate, tax_rule)));
  300.     //オプション金額を加算した表示金額を表示
  301.     var result_price =  default_price() + (optionPriceTotal + sfTax(optionPriceTotal, tax_rate, tax_rule));
  302.     $('.ec-price__price').text('¥' + result_price.toLocaleString());
  303. }
  304. //商品のデフォルト金額を取得
  305. function default_price() {
  306.     var jsonData = JSON.parse(document.querySelector('script[type="application/ld+json"]').innerHTML);
  307.     var productPrice = jsonData.offers.price;
  308.     return productPrice;
  309. }
  310. function number_format(num) {
  311.     return num.toString().replace(/([0-9]+?)(?=(?:[0-9]{3})+$)/g , '$1,');
  312. }
  313. function sfTax(price, tax_rate, tax_rule) {
  314.     real_tax = tax_rate / 100;
  315.     ret = price * real_tax;
  316.     tax_rule = parseInt(tax_rule);
  317.     switch (tax_rule) {
  318.         // 四捨五入
  319.         case {{ constant('Eccube\\Entity\\Master\\RoundingType::ROUND') }}:
  320.             $ret = Math.round(ret);
  321.             break;
  322.         // 切り捨て
  323.         case {{ constant('Eccube\\Entity\\Master\\RoundingType::FLOOR') }}:
  324.             $ret = Math.floor(ret);
  325.             break;
  326.         // 切り上げ
  327.         case {{ constant('Eccube\\Entity\\Master\\RoundingType::CEIL') }}:
  328.             $ret = Math.ceil(ret);
  329.             break;
  330.         // デフォルト:切り上げ
  331.         default:
  332.             $ret = Math.round(ret);
  333.             break;
  334.     }
  335.     return $ret;
  336. }
  337. </script>
  338. {% endblock %}