{#
///////////////////////////////////////////////////////////////////////
This template is part of EC-CUBE Design template.
Copyright(c) JAPAN ELECTRONIC INDUSTRIAL ARTS CO.LTD.
http://www.jeia.co.jp/
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
本テンプレートの著作権は、「株式会社日本電子工藝社」に帰属いたします。
※本テンプレートを譲渡・再頒布・転用・第三者へ開示することは禁止いたします。
ただし、事業者によるショップ運営者への設置代行を禁止するものではございません。
※本テンプレートを申請されたご利用サイトへの設置以外の目的で複製することは禁止いたします。
※本テンプレートデータ内のライセンス条項、および著作権に関する記述を削除することはできません。
※ご利用サイトを変更することはできません。申請と異なるサイトにてご利用になる場合は、
別途、ご利用費用をお支払いただく必要がございます。
※本テンプレートの改変にあたり、一切のサポートはいたしかねます。
※本テンプレートは、すべての設置環境で動作する事は保証しておりません。
///////////////////////////////////////////////////////////////////////
#}
{#
drift
https://github.com/imgix/drift
Copyright (c) 2015-2018, Zebrafish Labs All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1.Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2.Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
luminous
https://github.com/imgix/luminous
Copyright (c) 2015-2018, Zebrafish Labs All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1.Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2.Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#}
{#
商品詳細ページ
ビジュアル画像にはルーペ型とポップアップ型の拡大表示機能を実装しています。
もし機能が不要な場合は下記のTwig変数「visual_options」を設定してください。
* loupe: ルーペ拡大機能(0=無効、1=有効)
* popup: ポップアップ拡大機能(0=無効、1=有効)
常駐カートイン機能をON/OFF切り替えできます。
* clone_cartin (0,false=無効、1,true=有効)
#}
{# ----------▼ 商品詳細機能設定 ▼---------- #}
{# ビジュアル画像拡大機能のON/OFF設定 #}
{% set visual_options =
{
loupe: 0,
popup: 1
}
%}
{# 常駐カートインのON/OFF設定 #}
{% set clone_cartin = true %}
{# ----------▲ 商品詳細機能設定 ▲---------- #}
{% extends 'default_frame.twig' %}
{% set body_class = 'product_page' %}
{# カテゴリーがスーパーカーか #}
{% set category_id = 0 %}
{% if Product.ProductCategories is not empty %}
{% for ProductCategory in Product.ProductCategories %}
{% for Category in ProductCategory.Category.path %}
{% set category_id = Category.id %}
{% endfor %}
{% endfor %}
{% endif %}
{% block stylesheet %}
<link rel="stylesheet" href="//unpkg.com/flatpickr/dist/flatpickr.min.css">
<!-- カスタムテーマ -->
<link rel="stylesheet" href="//unpkg.com/flatpick/dist/themes/airbnb.css">
<link rel="stylesheet" href="{{ asset('assets/css/rental_detail.css') }}?{{ env('CSS_PARAM') }}">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/modaal@0.4.4/dist/css/modaal.min.css">
{% endblock %}
{% block javascript %}
<script>
eccube.classCategories = {{ class_categories_as_json(Product)|raw }};
// 規格2に選択肢を割り当てる。
function fnSetClassCategories(form, classcat_id2_selected) {
var $form = $(form);
var product_id = $form.find('input[name=product_id]').val();
var $sele1 = $form.find('select[name=classcategory_id1]');
var $sele2 = $form.find('select[name=classcategory_id2]');
eccube.setClassCategories($form, product_id, $sele1, $sele2, classcat_id2_selected);
}
{% if form.classcategory_id2 is defined %}
fnSetClassCategories(
$('#form1'), {{ form.classcategory_id2.vars.value|json_encode|raw }}
);
{% elseif form.classcategory_id1 is defined %}
eccube.checkStock($('#form1'), {{ Product.id }}, {{ form.classcategory_id1.vars.value|json_encode|raw }}, null);
{% endif %}
</script>
<script>
$(function() {
// bfcache無効化
$(window).bind('pageshow', function(event) {
if (event.originalEvent.persisted) {
location.reload(true);
}
});
});
</script>
<script>
$(function() {
$('.add-cart').on('click', function(event) {
{% if form.classcategory_id1 is defined %}
// 規格1フォームの必須チェック
if ($('#classcategory_id1').val() == '__unselected' || $('#classcategory_id1').val() == '') {
$('#classcategory_id1')[0].setCustomValidity('{{ '項目が選択されていません'|trans }}');
return true;
} else {
$('#classcategory_id1')[0].setCustomValidity('');
}
{% endif %}
{% if form.classcategory_id2 is defined %}
// 規格2フォームの必須チェック
if ($('#classcategory_id2').val() == '__unselected' || $('#classcategory_id2').val() == '') {
$('#classcategory_id2')[0].setCustomValidity('{{ '項目が選択されていません'|trans }}');
return true;
} else {
$('#classcategory_id2')[0].setCustomValidity('');
}
{% endif %}
// 個数フォームのチェック
if ($('#quantity').val() < 1) {
$('#quantity')[0].setCustomValidity('{{ '1以上で入力してください。'|trans }}');
return true;
} else {
$('#quantity')[0].setCustomValidity('');
}
event.preventDefault();
$form = $('#form1');
$.ajax({
url: $form.attr('action'),
type: $form.attr('method'),
data: $form.serialize(),
dataType: 'json',
beforeSend: function(xhr, settings) {
// Buttonを無効にする
$('.add-cart').prop('disabled', true);
}
}).done(function(data) {
// レスポンス内のメッセージをalertで表示
$.each(data.messages, function() {
$('#ec-modal-header').text(this);
});
$('.ec-modal').show()
// カートブロックを更新する
$.ajax({
url: "{{ url('block_cart') }}",
type: 'GET',
dataType: 'html'
}).done(function(html) {
//$('.ec-headerRole__cart').html(html);
$('.ec-cartNavi__detail').html(html);
});
}).fail(function(data) {
alert('{{ 'カートへの追加に失敗しました。'|trans }}');
}).always(function(data) {
// Buttonを有効にする
$('.add-cart').prop('disabled', false);
});
});
});
$('.ec-modal-wrap').on('click', function(e) {
// モーダル内の処理は外側にバブリングさせない
e.stopPropagation();
});
$('.ec-modal-overlay, .ec-modal, .ec-modal-close, .ec-inlineBtn--cancel').on('click', function() {
$('.ec-modal').hide()
});
</script>
<script type="application/ld+json">
{
"@context": "https://schema.org/",
"@type": "Product",
"name": "{{ Product.name }}",
"image": [
{% for img in Product.ProductImage %}
"{{ app.request.schemeAndHttpHost }}{{ asset(img, 'save_image') }}"{% if not loop.last %},{% endif %}
{% else %}
"{{ app.request.schemeAndHttpHost }}{{ asset(''|no_image_product, 'save_image') }}"
{% endfor %}
],
"description": "{{ Product.description_list | default(Product.description_detail) | replace({'\n': '', '\r': ''}) | slice(0,300) }}",
{% if Product.code_min %}
"sku": "{{ Product.code_min }}",
{% endif %}
"offers": {
"@type": "Offer",
"url": "{{ url('product_detail', {'id': Product.id}) }}",
"priceCurrency": "{{ eccube_config.currency }}",
"price": {{ Product.getPrice02IncTaxMin ? Product.getPrice02IncTaxMin : 0}},
"availability": "{{ Product.stock_find ? "InStock" : "OutOfStock" }}"
}
}
</script>
{# JEIA #}
{# Drift(画像ルーペ拡大表示ライブラリ) Drift用CSSは「_14.4.product_zoom.scss」に含めています #}
<script src="{{ asset('assets/js/drift/Drift.min.js') }}"></script>
{# Luminous(画像ポップアップ拡大表示ライブラリ) Luminous用CSSは「_14.4.product_zoom.scss」に含めています #}
<script src="{{ asset('assets/js/luminous/Luminous.min.js') }}"></script>
<script>
//------------------------------
// 商品ビジュアル(slick使用)
//------------------------------
// slick適用コンテナ
var $ecSlickContainer = $( '.ec-productVisualMain .ec-slickContainer' );
// キャプションの準備
/** 商品詳細ページのslickアイテムは動的に出力されますのでキャプションを入れられませんが、
* フリーエリア内にてキャプション要素を記述しておき、javascirptで各キャプションを各画像アイテム内に挿入させます。
* ※EC-CUBE4.2.0ではフリーエリアに記述したHTMLがサニタイズ(data属性が削除)されてしまい、この機能が動作しませんのでコメントアウトします。
*/
/*
var $visualCaption = $( '.visual_caption' );// キャプション要素ラッパー
$visualCaption.find( '.caption' ).each(function(){
var $this = $(this);
// index 1つ目の画像用キャプションは「data-caption="1"」としていますので、-1してindex値にします
var _index = parseInt( $this.data('caption'),10 ) - 1;
// 該当slickアイテム
var $slideItem = $ecSlickContainer.find( '.slide-item' ).eq( _index );
if ( $slideItem.length ) {
// 該当slickアイテムにキャプションを挿入
$slideItem.append($this);
} else {
// 該当slickアイテムが存在しない場合はキャプションを破棄します
$this.remove();
}
});
*/
// slick準備完了時の処理
$ecSlickContainer.on('init', function(){
setTimeout(function(){
//
}, 0);
});
// slick適用
$ecSlickContainer.slick({
fade: true,
speed: 600,
dots: false,
arrows: true,
prevArrow: '<div class="slick-prev"><i class="jeiafont jeia-arrow-left"></i></div>',
nextArrow: '<div class="slick-next"><i class="jeiafont jeia-arrow"></i></div>',
asNavFor: '.ec-productVisualNav.desktop',
responsive: [
{
breakpoint: 768,//768px未満(スマホ時)
settings: {
fade: false,
infinit: true
}
}
]
});
// ビジュアルナビ(デスクトップ・タブレット用:縦スライド)
var $visualNavDesktop = $( '.ec-productVisualNav.desktop' );
$visualNavDesktop.slick({
asNavFor: '.ec-productVisualMain .ec-slickContainer',
vertical: true,
verticalSwiping: true,
slidesToShow: 5,
slidesToScroll: 1,
//swipeToSlide: true,// ※verticalでは効かない様子
focusOnSelect: true,
speed: 600,
arrows: true,
prevArrow: '<div class="slick-prev"><i class="jeiafont jeia-arrow"></i></div>',
nextArrow: '<div class="slick-next"><i class="jeiafont jeia-arrow"></i></div>'
});
// ビジュアルナビの高さをメインビジュアルの高さと揃えます(デスクトップ・タブレット時)
// これは見た目の調整と、ナビ送りのnextボタンの配置を正しくする目的もあります
if ( window.innerWidth >= 768 ) {
// slick生成が完了してから実行します。イベント「slick_all_readiness」はjeia_function.jsによってslick生成完了後に発火されます。
$(window).on('slick_all_readiness jeia_resize', function(){
var _height = $ecSlickContainer.height();
// ビジュアルナビの高さを適用
$visualNavDesktop.height( _height );
// ブラウザのリサイズ時に.slick-listの高さが追随しない事があるのでこちらも高さを揃えます
$visualNavDesktop.find( '.slick-list' ).height( _height );
});
}
// ビジュアルナビ(スマホ用)
var $productRoleVisual = $( '.ec-productRole__visual' );// ※ビジュアル画像拡大機能でもこの取得要素を使います
var $visualNavSphone = $( '.ec-productVisualNav.sphone' );// ビジュアルナビ(スマホ用)
var $sideInNavToggleBtn = $( '.sideInNavToggleBtn' );// ビジュアルナビ開閉ボタン
// ビジュアルナビ(スマホ)開閉ボタン
$sideInNavToggleBtn.on('click', function(){
// 開状態となるclassをON/OFF
$productRoleVisual.toggleClass( 'is-navOpen' );
});
// ビジュアルナビ(スマホ)サムネイルタップでメインビジュアル画像を切替え
$visualNavSphone.on('click', '.slideThumb', function() {
var index = $(this).attr( 'data-index' );
$ecSlickContainer.slick( 'slickGoTo', index, false );// slickGoTo: indexで指定したスライドへ移動
// ページ上部にスクロールする処理を入れておきます(ページトップボタンのイベントを発火)
$( '.ec-blockTopBtn' ).trigger( 'click' );
// ナビをCLOSE
$productRoleVisual.removeClass( 'is-navOpen' );
});
// サムネイル以外をタップした場合はナビをCLOSE
$visualNavSphone.on('click', function() {
// ナビをCLOSE
$productRoleVisual.removeClass( 'is-navOpen' );
});
// スライド切り替え完了後のイベント(開閉ボタンのカレント値を更新)
$ecSlickContainer.on('afterChange', function(e, slick, currentSlide){
$sideInNavToggleBtn.find( '.currentNum' ).text( currentSlide + 1 );
});
//------------------------------
// ビジュアル画像 ルーペ拡大表示(Drift)&ポップアップ拡大表示(Luminous)
//------------------------------
// ・Drift
// ルーペ拡大表示には「Drift」を使用しています(Drift was made by imgix.)
// https://github.com/imgix/drift
//------------------------------
// ・Luminous
// ポップアップ拡大表示には「Luminous」を使用しています(Luminous was made by imgix.)
// https://github.com/imgix/luminous
//------------------------------
// 商品ビジュアルの拡大機能ON/OFF
var visual_loupe = Boolean( {{ visual_options.loupe }} );// ルーペ拡大
var visual_popup = Boolean( {{ visual_options.popup }} );// ポップアップ拡大
// slick生成が完了してから実行します。イベント「slick_all_readiness」はjeia_function.jsによってslick生成完了後に発火されます。
$(window).on('slick_all_readiness', function(){
// ルーペ拡大表示
// 画像ズームはデスクトップ・タブレット時のみとします(スマホではあまり実用的ではないと思われますので)
if ( visual_loupe && window.innerWidth >= 768 ) {
// 拡大表示パネルの大きさを決めます(リサイズ時も算出し直します)
$(window).on('on_pane_size jeia_resize', function(){
// パネル表示の基点(サムネイル枠の左端)
var pane_origin = $(' .ec-productVisualNav' ).offset().left;
// パネル幅 →ブラウザ幅から表示基点を引いて(スクロールバー分の幅も調整)、パネル領域を広く設定
var pane_w = window.innerWidth - pane_origin - 50;
// パネル高さ →ビジュアル上位置からブラウザ下まで、少しだけ余白を差し引き
var pane_h = $(window).height() - $productRoleVisual.offset().top - 50;
$( '.drift-pane' ).css({
'width': pane_w,
'height': pane_h,
'left': $( '.ec-productVisualMain' ).width() + 1// メインビジュアルの右端 + 余白
});
}).trigger('on_pane_size');
// メインビジュアル ルーペ拡大表示(ライブラリ「Drift」)
var pane = document.querySelector( '.drift-pane' );
$( '.drift-img' ).each(function(){
new Drift(this, {
paneContainer: pane,
inlinePane: 1279,//1280px以上でパネル表示、それ未満はルーペ表示
containInline: false,// ルーペを画像の端からはみ出させない場合はtrue
inlineOffsetY: -85,
touchDelay: 300
});
})
}
// ポップアップ拡大表示
// 画像ポップアップはデスクトップ・タブレット時のみとします(スマホではあまり実用的ではないと思われますので)
if ( visual_popup && window.innerWidth >= 768 ) {
new LuminousGallery(document.querySelectorAll( '.luminous-gallery' ));
} else {
// ポップアップ拡大を使用しない →画像がクリックされてもa要素が動作しないようにイベントを組んでおきます
$productRoleVisual.find( '.luminous-gallery' ).on('click', function(){
return false;
});
}
});
// どちらの拡大機能も使用しない場合はカーソルを矢印に戻しておきます(通常はCSS側でzoom-inにしています)
if ( !visual_loupe && !visual_popup ) {
$productRoleVisual.find( '.slide-item > a' ).css( 'cursor', 'default' );
}
//------------------------------
// お気に入り処理
//------------------------------
/* 当テンプレートではお気に入りボタンをカートボタンの横に配置するデザインとなっておりますが、
* このエリアはカートインのform要素領域の中に入っていますので、お気に入り追加用formとボタンとを分離させ、
* ボタンをカート横に配置し、ボタンクリック時に当スクリプトお気に入りフォーム送信を発生させています。
*/
$( '#favorite' ).on('click', function(e){
e.preventDefault();
$( '#form_favorite' ).submit();
});
//------------------------------
// シェアボタン(サブウィンドウ表示)
//------------------------------
$( '.shareBtn' ).on('click', function(){
// ウィンドウを開かないタイプはスルー
if ( $(this).hasClass( 'no-window' ) ) {
return true;
}
var this_url = $(this).attr( 'href' ) + location.href;
window.open( this_url, 'sns_win', 'width=650, height=470, personalbar=0, toolbar=0, scrollbars=1, sizable=1' );
return false;
});
//------------------------------
// フリーエリア:タブ切り替えコンテンツ
//------------------------------
/* フリーエリア内にコードを記述することでタブ切り替えコンテンツを実装します。
* タブ切り替えが不要な場合は当スクリプトを削除してください。
* ※EC-CUBE4.2.0ではフリーエリアに記述したHTMLがサニタイズ(data属性が削除)されてしまい、この機能が動作しませんのでコメントアウトします。
*/
/*
var $ecProductDetailTab = $( '.ec-productDetailTab' );
var $ecProductDetailTabNav = $ecProductDetailTab.find( '.ec-productDetailTab__nav' )
var $ecProductDetailTabContent = $ecProductDetailTab.find( '.ec-productDetailTab__content' );
$ecProductDetailTabNav.on('click', 'li', function(){
var $this = $(this);
var _index = '.tab-' + $this.data('tab');
// コンテンツのアクティブ化
$ecProductDetailTabContent.filter(_index).addClass('is-active').siblings().removeClass('is-active');
// タブのアクティブ化
$this.addClass('is-active').siblings().removeClass('is-active');
});
// 初回は1番目のタブコンテンツを表示
$ecProductDetailTabNav.find('li:eq(0)').trigger('click');
*/
</script>
{# 常駐カートイン #}
{% if clone_cartin %}
<script src="{{ asset('assets/js/clone_cartin.js') }}"></script>
{% endif %}
<script src="//unpkg.com/flatpickr"></script>
<!-- 日本語の言語ファイル -->
<script src="//unpkg.com/flatpickr/dist/l10n/ja.js"></script>
<script>
// 日付をフォーマットする関数
function formatDateTmp(date) {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0'); // 月は0始まり
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
//Googleカレンダー予約状況
reservedInfo={{ events|raw }};
{% if Product.id==26 or Product.id==23 or Product.id==22 %}
// 今日の日付を取得
const tmp_today = new Date();
// 100日分の日付を作成
for (let i = 0; i < 100; i++) {
const newDate = new Date(tmp_today);
newDate.setDate(tmp_today.getDate() + i);
tmpdate=formatDateTmp(newDate)
reservedInfo[tmpdate] = tmpdate;
}
console.log(reservedInfo);
{% endif %}
/*
for (let key in reservedInfo) {
console.log('key:' + key);
console.log(reservedInfo[key].length);
}
*/
calendar_start_date="{{ calendar_start_date }}";
</script>
<script src="{{ asset('assets/js/hotelinfo].js') }}?{{ env('JS_PARAM') }}"></script>
<script src="{{ asset('assets/js/rental_common.js') }}?{{ env('JS_PARAM') }}"></script>
<script src="https://cdn.jsdelivr.net/npm/modaal@0.4.4/dist/js/modaal.min.js"></script>
{% endblock %}
{% block main %}
{% set carflg = false %}
{% set supercarflg = false %}
{% for ProductCategory in Product.ProductCategories %}
{% if 7== ProductCategory.Category.id %}
{% set carflg = true %}
{% endif %}
{% if 8== ProductCategory.Category.id %}
{% set supercarflg = true %}
{% endif %}
{% if 10== ProductCategory.Category.id %}
{% set supercarflg = true %}
{% endif %}
{% endfor %}
<div class="ec-productRole">
<div class="ec-productRole__grid">
<div class="ec-productRole__gridCell cellLeft">
{# 商品ビジュアル表示 #}
<div class="ec-productRole__visual">
{# メインビジュアル格納枠 #}
<div class="ec-productVisualMain">
{# slick適用要素 #}
<div class="ec-slickContainer">
{% for ProductImage in Product.ProductImage %}
<div class="slide-item">
<a class="luminous-gallery" data-iteration="<!--{$num}-->" href="{{ asset(ProductImage, 'save_image') }}" target="_blank">
<img class="drift-img" src="{{ asset(ProductImage, 'save_image') }}" data-zoom="{{ asset(ProductImage, 'save_image') }}" alt="{{ loop.first ? Product.name : '' }} {{ loop.first ? Product.search_word : '' }}" {% if loop.index > 1 %} loading="lazy"{% endif %}>
</a>
</div>
{% else %}
<div class="slide-item"><img src="{{ asset(''|no_image_product, 'save_image') }}" alt="{{ loop.first ? Product.name : '' }} {{ loop.first ? Product.search_word : '' }}"></div>
{% endfor %}
</div>
</div>
{#
----------------------------------------------------------------------------------
デスクトップ・タブレット時はビジュアルナビをメインビジュアルの横に配置して縦スライド機能をつけています。
スマホ時はスライド機能は使わずに展開ボタンにより一覧ビューがサイドインする動作になります。
レスポンシブにおいて、スライド機能のON/OFFやレイアウト変更はロジックが煩雑になるかと思いましたので、
ビジュアルナビは、あらかじめデスクトップ用のナビと、モバイル用のナビをそれぞれ組み込んでおきレスポンシブで表示を切り替えています。
----------------------------------------------------------------------------------
#}
{# ビジュアルナビ(デスクトップ・タブレット用) #}
<div class="ec-productVisualNav desktop">
{% for ProductImage in Product.ProductImage %}
{# 当テンプレートの構造上、loading="lazy"は入れないほうがいいかも?
<div class="slideThumb" data-index="{{ loop.index0 }}"><img src="{{ asset(ProductImage, 'save_image') }}" alt="" loading="lazy"></div>
#}
<div class="slideThumb" data-index="{{ loop.index0 }}"><img src="{{ asset(ProductImage, 'save_image') }}" alt=""></div>
{% endfor %}
</div>
{# ビジュアルナビ(スマホ用) #}
<div class="ec-productVisualNav sphone">
<div class="sideInNavShelf">
{% for ProductImage in Product.ProductImage %}
<div class="slideThumb" data-index="{{ loop.index0 }}"><img src="{{ asset(ProductImage, 'save_image') }}" alt="" loading="lazy"></div>
{% endfor %}
</div>
</div>
{# ビジュアルナビ(スマホ用)開閉ボタン #}
<div class="sideInNavToggleBtn">
<i class="jeiafont jeia-grid"></i>
<span class="currentNum">1</span>
<span class="ceparate">/</span>
<span class="totalNum">{{ Product.ProductImage|length }}</span>
</div>
</div>
{# 商品画像ルーペ拡大表示用パネル(デスクトップ時のみ) #}
<div class="drift-pane"></div>
{% if Product.id==16 %}
<video poster="/awd/html/upload/save_image/poster_aquariva34.webp" controls="" muted="" width="100%" src="/awd/html/upload/save_image/IMG_5774.mp4" style="margin-top: 10px;"></video>
{% endif %}
{#
{% if Product.id==62 or Product.id==2 or Product.id==12 %}
<div class="container-offer">
<div class="offer-title">
<p>Limited Offer</p>
</div>
<div class="item">
<p>
1Hour 33,000 JPY ~<br>
<a href="/awd/plan/542" style="text-decoration: underline; color: initial;">Details click here</a>
</p>
</div>
</div>
{% endif %}
#}
<div class="ec-productRole__description pcOnly">
{{ Product.description_detail|raw|nl2br }}
</div>
</div>
<div class="ec-productRole__gridCell cellRight">
{# 商品プロフィール #}
<div class="ec-productRole__profile">
{# 商品タイトル #}
<div class="ec-productRole__title">
<h1>{{ Product.name }}</h1>
{#
{% if Product.id==64 or Product.id==66 or Product.id==68 or Product.id==69 %}
<span style="color: #FF0058;font-weight: bold;font-size: 120%;">Snow tire available! New!</span>
{% endif %}
#}
</div>
{# 販売価格 #}
<div class="ec-productRole__price">
<div class="ec-price">
{% if carflg %}
{% else %}
<span class="ec-price__price">Price ASK</span>
{% endif %}
</div>
</div>
{# 詳細コメント #}
<div class="ec-productRole__description spOnly">
{{ Product.description_detail|raw|nl2br }}
</div>
{% if carflg %}
<div class="ec-productRole__description">
<details class="accordion-006 spec" open>
<summary><h3>Car Rental Plan</h3></summary>
<div class="ec-productRole__price">
<div class="ec-price">
{% if Product.id not in env('AskCar') %}
<span class="ec-price__price">Price ¥{{ (Product.item18+(Product.item17*6)+(Product.item16*40)) |number_format }} (6Hour inc 40Km) 〜</span>
{% else %}
<span class="ec-price__price">Price ASK</span>
{% endif %}
</div>
</div>
{% if Product.id not in env('AskCar') %}
<ul class="spec__item">
<li class="spec__row">
<span>Cost per Km</span>¥{{ Product.item16|number_format }}</li>
<li class="spec__row">
<span>Cost per Hour</span>¥{{ Product.item17|number_format }}</li>
</ul>
{% endif %}
</details>
<details class="accordion-006" open>
<summary><h3>Benefits</h3></summary>
<ul class="container-flex">
<li class="item">
<img src="{{ asset('assets/img/rental/Requirements05.webp') }}" alt="Insurance included" >
<p>Insurance included</p>
</li>
<li class="item">
<img src="{{ asset('assets/img/rental/Requirements06.webp') }}" alt="No need to return<br>with a full tank" >
<p>No need to return<br>with a full tank</p>
</li>
<li class="item">
<img src="{{ asset('assets/img/rental/Requirements07.webp') }}" alt="Highway Free" >
<p>Highway Free</p>
</li>
<li class="item">
<img src="{{ asset('assets/img/rental/Requirements08.webp') }}" alt="Free delivery to your hotel" >
<p>Free delivery to your hotel</p>
</li>
<li class="item">
<img src="{{ asset('assets/img/rental/Requirements09.webp') }}" alt="Driving instruction" >
<p>Driving instruction</p>
</li>
</ul>
</details>
<details class="accordion-006">
<summary><h3>SPEC</h3></summary>
<ul class="spec__item">
<li class="spec__row">
<span>Year </span>{{ Product.item1|trans }}</li>
<li class="spec__row">
<span>HP </span>{{ Product.item21|trans }}</li>
<li class="spec__row">
<span>Steering Wheel </span>{{ Product.item2|trans }}</li>
<li class="spec__row">
<span>Seater </span>{{ Product.item3|trans }}</li>
<li class="spec__row">
<span>Doors </span>{{ Product.item4|trans }}</li>
<li class="spec__row">
<span>Mission </span>{{ Product.item5|trans }}</li>
<li class="spec__row">
<span>Fuel </span>{{ Product.item6|trans }}</li>
<li class="spec__row">
<span>Drive type </span>{{ Product.item7|trans }}</li>
<li class="spec__row">
<span>Displacement </span>{{ Product.item8|number_format }}cc </li>
<li class="spec__row">
<span>Equipment </span>{{ Product.item9|trans }}</li>
</ul>
</details>
</div>
{% endif %}
<form name="reserveForm" action="{{ url('rental_comfirm') }}" method="post" class="reserveForm">
<input type="hidden" name="calendarId" id="calendarId" value="{{ Product.item13|trans }}">
<input type="hidden" name="carurl" value="{{ app.request.getUri }}">
<input type="hidden" name="id" value="{{ Product.id }}">
<input type="hidden" name="carname" value="{{ Product.name }}">
<input type="hidden" name="carimg" value="{{ asset(Product.ProductImage[0], 'save_image') }}">
<input type="hidden" id="rental_fee" name="rental_fee" value="">
<input type="hidden" id="destination_name" name="destination_name" value="">
<input type="hidden" id="extra_day" name="extra_day" value="0">
<input type="hidden" id="estimate" name="estimate" value="0">
<input type="hidden" id="supercarflg" name="supercarflg" value="0">
<input type="hidden" id="basekm" name="basekm" value="">
<input type="hidden" id="rental_term" name="rental_term" value="">
<input type="hidden" id="price_km" name="price_km" value="{{Product.item16}}">
<input type="hidden" id="price_hour" name="price_hour" value="{{Product.item17}}">
<input type="hidden" id="price_setup" name="price_setup" value="{{Product.item18}}">
<input type="hidden" id="price_extra_km" name="price_extra_km" value="{{Product.item10}}">
<input type="hidden" id="price_extra_hour" name="price_extra_hour" value="{{Product.item19}}">
<input type="hidden" id="price_extrakm" name="price_extrakm" value="">
<input type="hidden" id="extra_km" name="extra_km" value="">
<input type="hidden" id="inc_km" name="inc_km" value="">
<p class="ec-para-normal">
Select a rental date and destination to calculate the estimated cost.
</p>
<p class="reserevedError" style="display:none;">Reservation information is not set correctly</p>
{% set spot01 = 'Tokyo City Drive : 30km~' %}
{% set spot02 = 'Daikoku PA Tour : 70km~' %}
{% set spot03 = 'Yokohama Road Trip : 80km~' %}
{% set spot04 = 'Kamakura Round Trip : 100km~' %}
{% set spot05 = 'ATAMI Round Trip : 200km~' %}
{% set spot06 = 'HAKONE Round Trip : 220km~' %}
{% set spot07 = 'FUJI Round Trip : 200km~' %}
{% set spot08 = 'KAWAGUCHIKO Round Trip : 220km~' %}
{% set spot09 = 'NIKKO Round Trip : 320km~' %}
{% set spot10 = 'KARUIZAWA Round Trip : 350km~' %}
<div class="Form-Item name">
<p class="Form-Item-Label">Start Date/Time</p>
<input name="startdate" type="text" class="Form-Item-Input flatpickr flatpickr-input startdate" placeholder="2024-01-01" id="rentalCal" value="">
<select name="starttime" class="Form-Item-Input starttime">
<option value="08:00">08:00</option>
<option value="08:30">08:30</option>
<option value="09:00">09:00</option>
<option value="09:30">09:30</option>
<option value="10:00" selected>10:00</option>
<option value="10:30">10:30</option>
<option value="11:00">11:00</option>
<option value="11:30">11:30</option>
<option value="12:00">12:00</option>
<option value="12:30">12:30</option>
<option value="13:00">13:00</option>
<option value="13:30">13:30</option>
<option value="14:00">14:00</option>
<option value="14:30">14:30</option>
<option value="15:00">15:00</option>
<option value="15:30">15:30</option>
<option value="16:00">16:00</option>
<option value="16:30">16:30</option>
<option value="17:00">17:00</option>
<option value="17:30">17:30</option>
<option value="18:00">18:00</option>
<option value="18:30">18:30</option>
<option value="19:00">19:00</option>
<option value="19:30">19:30</option>
<option value="20:00">20:00</option>
</select>
<span class="Form-Item-Error startdate" style="">*Please Select</span>
</div>
<div class="Form-Item name">
<p class="Form-Item-Label enddate">End Date/Time</p>
<input name="enddate" type="text" class="Form-Item-Input flatpickr flatpickr-input enddate" placeholder="2024-01-01" id="rentalCal" value="">
<select name="endtime" class="Form-Item-Input endtime">
<option value="08:00">08:00</option>
<option value="08:30">08:30</option>
<option value="09:00">09:00</option>
<option value="09:30">09:30</option>
<option value="10:00">10:00</option>
<option value="10:30">10:30</option>
<option value="11:00">11:00</option>
<option value="11:30">11:30</option>
<option value="12:00">12:00</option>
<option value="12:30">12:30</option>
<option value="13:00">13:00</option>
<option value="13:30">13:30</option>
<option value="14:00">14:00</option>
<option value="14:30">14:30</option>
<option value="15:00">15:00</option>
<option value="15:30">15:30</option>
<option value="16:00">16:00</option>
<option value="16:30">16:30</option>
<option value="17:00">17:00</option>
<option value="17:30">17:30</option>
<option value="18:00" selected>18:00</option>
<option value="18:30">18:30</option>
<option value="19:00">19:00</option>
<option value="19:30">19:30</option>
<option value="20:00">20:00</option>
</select>
<span class="Form-Item-Error enddate" style="">*Please Select</span>
</div>
<div class="Form-Item">
<p class="Form-Item-Label block-line">Drive Destination</p>
<div class="w100">
<select name="destination" class="Form-Item-Input destination">
<option value="30" selected>{{ spot01 }}</option>
<option value="70">{{ spot02 }}</option>
<option value="80">{{ spot03 }}</option>
<option value="100">{{ spot04 }}</option>
<option value="200">{{ spot05 }}</option>
<option value="220">{{ spot06 }}</option>
<option value="200">{{ spot07 }}</option>
<option value="220">{{ spot08 }}</option>
<option value="320">{{ spot09 }}</option>
<option value="350">{{ spot10 }}</option>
<option value="other">Other Destination Select your mileage (km)</option>
</select>
</div>
<div class="w100 destination-note" style="display: none;">
<select name="otherkm" class="Form-Item-Input otherkm">
<option value="40" selected>40km</option>
<option value="50">50km</option>
<option value="60">60km</option>
<option value="70">70km</option>
<option value="80">80km</option>
<option value="90">90km</option>
<option value="100">100km</option>
<option value="110">110km</option>
<option value="120">120km</option>
<option value="130">130km</option>
<option value="140">140km</option>
<option value="150">150km</option>
<option value="160">160km</option>
<option value="170">170km</option>
<option value="180">180km</option>
<option value="190">190km</option>
<option value="200">200km</option>
<option value="210">210km</option>
<option value="220">220km</option>
<option value="230">230km</option>
<option value="240">240km</option>
<option value="250">250km</option>
<option value="260">260km</option>
<option value="270">270km</option>
<option value="280">280km</option>
<option value="290">290km</option>
<option value="300">300km</option>
<option value="350">350km</option>
<option value="400">400km</option>
<option value="450">450km</option>
<option value="500">500km</option>
<option value="550">550km</option>
<option value="600">600km</option>
<option value="650">650km</option>
<option value="700">700km</option>
<option value="750">750km</option>
<option value="800">800km</option>
<option value="850">850km</option>
<option value="900">900km</option>
<option value="950">950km</option>
<option value="1000">1,000km</option>
<option value="1500">1,500km</option>
<option value="2000">2,000km</option>
<option value="2500">2,500km</option>
<option value="3000">3,000km</option>
<option value="3500">3,500km</option>
<option value="4000">4,000km</option>
<option value="4500">4,500km</option>
<option value="5000">5,000km</option>
</select>
</div>
{% if Product.id not in env('AskCar') %}
<div>
※Upon return, in the event of exceeded KM/Hours beyond the agreed budget: <br>
per KM ¥{{ Product.item10|number_format }} <br>
per Hour ¥{{ Product.item19|number_format }}
</div>
{% endif %}
</div>
{% if Product.id not in env('AskCar') %}
<div class="estimate-area">
<h4>Rental Price (inc Tax)</h4>
<ul class="detail_item container">
<li class="title w80">
Rental Fee (<span class="inc_hour">0</span>Hours inc <span class="inc_km"></span>Km)
</li>
<li class="w20">
¥ <span class="rental_fee">0</span>
</li>
<li class="title w80">
Extra/Km ( ¥{{ Product.item16|number_format }}/Km, <span class="viewkm">No Extra</span>)
</li>
<li class="w20">
¥ <span class="extra_km">0</span>
</li>
</ul>
<ul class="detail_item container reserved_total">
<li class="title w50">
Total Charge</span>
</li>
<li class="w50">
¥ <span class="totalcharge">0</span>
</li>
</ul>
</div>
{% endif %}
<a class="ec-shopCollectionBtn submit" href="javascript:void(0)">Next</a>
</form>
{# シェアボタン #}
<div class="ec-productRole__share">
<p class="shareLabel">SHARE</p>
<ul class="shareBtnList">
{% spaceless %}
{# Twitter #}
<li>
<a class="shareBtn x-twitter" href="https://twitter.com/share?url=">
<i class="jeiafont jeia-x-twitter"></i><span>Twitter</span>
</a>
</li>
{# Facebook #}
<li>
<a class="shareBtn facebook" href="https://www.facebook.com/sharer/sharer.php?u=">
<i class="jeiafont jeia-facebook"></i><span>Facebook シェア</span>
</a>
</li>
{# LINE #}
<li>
<a class="shareBtn line" href="https://social-plugins.line.me/lineit/share?url=">
<i class="jeiafont jeia-line2"></i><span>LINE</span>
</a>
</li>
{# Pocket #}
<li>
<a class="shareBtn pocket" href="http://getpocket.com/edit?url=">
<i class="jeiafont jeia-get-pocket"></i><span>Pocket</span>
</a>
</li>
{# はてなブックマーク #}
<li>
<a class="shareBtn hatena" href="http://b.hatena.ne.jp/add?mode=confirm&url=">
<i class="jeiafont jeia-hatenabookmark"></i><span>はてなブックマーク</span>
</a>
</li>
{# Pinterest #}
<li>
<a class="shareBtn no-window pinterest" data-pin-do="buttonBookmark" data-pin-custom="true" data-pin-lang="ja" data-pin-save="false" href="//jp.pinterest.com/pin/create/button/">
<i class="jeiafont jeia-pinterest"></i><span>Pinterest</span>
</a>
<script async defer src="//assets.pinterest.com/js/pinit.js"></script>
</li>
{% endspaceless %}
</ul>
</div>
</div>{# end of .ec-productRole__profile #}
</div>{# end of .ec-productRole__gridCell #}
</div>{# end of .ec-productRole__grid #}
{% if Product.freearea %}
<div class="ec-productRole__freearea">
{{ include(template_from_string(Product.freearea)) }}
</div>
{% endif %}
<!-- modaal start-->
<div id="leadcar" style="display:none;" class="white-popup-block">
<h2>Lead Car Option</h2>
<p>
In case you are unfamiliar with Japan's traffic rules, the lead car will provide guidance and support to ensure a safe drive.<br>
To enjoy your drive with peace of mind, the lead car accompanies you, offering a sense of reassurance and confidence to the driver.
</p>
<img src="{{ asset('assets/img/rental/leadcar2.png') }}" alt="" loading="lazy">
<a class="ec-shopCollectionBtn" href="javascript:void(0);" onclick="$('.leadcar').modaal('close');">close</a>
</div>
<!-- modaal end-->
</div>{# end of .ec-productRole #}
<script src="{{ asset('assets/js/rental_detail.js') }}?{{ env('JS_PARAM') }}"></script>
{% endblock %}