From 63d8ef1e8aab4d03f27734afd2001208ee7aebd0 Mon Sep 17 00:00:00 2001 From: ouidade Date: Fri, 6 Jun 2025 11:41:05 +0200 Subject: [PATCH] carroussel thumbnial vertical manque changement visuel fleche thumbnail --- web/themes/custom/eql/dist/assets/bundle.js | 2 +- .../custom/eql/dist/assets/css/bundle.css | 92 ++++++----- web/themes/custom/eql/scripts/main.js | 6 +- .../scss/pages/_ressource-type-en-images.scss | 152 +++++++++--------- ...entity-field--node--field-images.html.twig | 19 ++- 5 files changed, 144 insertions(+), 127 deletions(-) diff --git a/web/themes/custom/eql/dist/assets/bundle.js b/web/themes/custom/eql/dist/assets/bundle.js index 2530221..00836b5 100644 --- a/web/themes/custom/eql/dist/assets/bundle.js +++ b/web/themes/custom/eql/dist/assets/bundle.js @@ -36,7 +36,7 @@ eval("/**\n * @file\n * External links js file.\n */\n\n (function ($, Drupal, d \*************************/ /***/ (function() { -eval("jQuery(function ($) {\n console.log('salut');\n\n // MENU BURGER\n const burger = document.getElementById(\"block-burger\");\n const burgertitle = document.getElementById(\"block-burger-menu\");\n if (burger && burgertitle) {\n burgertitle.addEventListener(\"click\", function () {\n burger.classList.toggle('opened');\n });\n }\n\n // FAQ — réponses\n const answers = document.getElementsByClassName(\"field--name-field-reponse\");\n const fichiers = document.getElementsByClassName(\"field--name-field-fichiers\");\n const liens = document.getElementsByClassName(\"field--name-field-liens\");\n const ressources = document.getElementsByClassName(\"field--name-field-ress\");\n const questions = document.getElementsByClassName(\"field--name-field-question\");\n\n for (let i = 0; i < questions.length; i++) {\n const q = questions[i];\n q.addEventListener(\"click\", function () {\n // Réponses\n Array.from(answers).forEach(a => a.classList.remove(\"opened\"));\n const r = this.parentNode.querySelector(\".field--name-field-reponse\");\n if (r) r.classList.add(\"opened\");\n\n // Fichiers\n Array.from(fichiers).forEach(f => f.classList.remove(\"opened\"));\n const f = this.parentNode.querySelector(\".field--name-field-fichiers\");\n if (f) f.classList.add(\"opened\");\n\n // Liens\n Array.from(liens).forEach(l => l.classList.remove(\"opened\"));\n const l = this.parentNode.querySelector(\".field--name-field-liens\");\n if (l) l.classList.add(\"opened\");\n\n // Ressources\n Array.from(ressources).forEach(r => r.classList.remove(\"opened\"));\n const res = this.parentNode.querySelector(\".field--name-field-ress\");\n if (res) res.classList.add(\"opened\");\n });\n }\n\n // SLIDESHOW INIT\n $('.path-frontpage .view-actus-blocks-pages .view-content .view-type-slide .views-row-wrapper').slick({\n slidesToShow: 1,\n dots: true,\n arrows: true,\n centerMode: true,\n responsive: [{\n breakpoint: 810,\n settings: {\n slidesToShow: 1,\n adaptiveHeight: true,\n arrows: false,\n draggable: true,\n centerMode: true,\n }\n }]\n });\n\n $('.page-node-type-actualite .block-entity-fieldnodefield-images .field--type-image').slick({\n dots: true,\n arrows: true,\n adaptiveHeight: true,\n responsive: [{\n breakpoint: 800,\n settings: { adaptiveHeight: true }\n }]\n });\n\n $('.page-node-type-projet .block-entity-fieldnodefield-photo .field--type-image').slick({\n slidesToShow: 1,\n dots: true,\n arrows: false,\n draggable: true,\n adaptiveHeight: true,\n responsive: [{\n breakpoint: 800,\n settings: { adaptiveHeight: true }\n }]\n });\n \n\n\n \n \n ///// fusion views-type-slide de class identique ////////////\n\n const seen = new Set();\n \n $('.view-type-slide').each(function () {\n const $slide = $(this);\n const classes = $slide.attr('class').split(/\\s+/);\n const typeClass = classes.find(cls => cls.startsWith('type-'));\n \n if (typeClass) {\n if (seen.has(typeClass)) {\n // Trouver le premier slide avec cette classe\n const $target = $('.view-type-slide.' + typeClass).first();\n \n // Déplacer les rows de la slide actuelle vers la première\n $slide.find('.views-row').appendTo($target.find('.views-row-wrapper'));\n \n // Supprimer la slide en double\n $slide.remove();\n } else {\n seen.add(typeClass);\n }\n }\n });\n if (!$('.view-content').hasClass('filtered')) {\n $('.path-ressources .view:not(.view-partenaires) .view-content .view-type-slide .views-row-wrapper').slick({\n slidesToShow: 3,\n dots: false,\n arrows: true,\n infinite: false,\n centerMode: false,\n draggable: true,\n \n responsive: [{\n breakpoint: 810,\n settings: {\n slidesToShow: 3,\n arrows: true,\n draggable: true,\n centerMode: false,\n }\n }]\n });\n }\n\n\n // Classes media → .wrapper-ressource\n $(\".wrapper-ressource\").each(function () {\n const media = $(this).find(\".field--name-field-type-de-media\").text().trim();\n const className = media\n .toLowerCase()\n .normalize(\"NFD\").replace(/[\\u0300-\\u036f]/g, \"\")\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/(^-|-$)/g, '');\n $(this).addClass('type-media-' + className);\n });\n console.log(\"classses media\");\n\n // MASQUER TYPE DE RESSOURCE DOUBLON\n if (document.body.classList.contains(\"path-ressources\")) {\n $(\".view-type-slide\").each(function () {\n const h3Content = $(this).find(\"h3\").text().trim();\n console.log(h3Content);\n $(this).find(\".field--name-field-type-de-ressource .field__item a\").each(function () {\n if ($(this).text().trim() === h3Content) {\n $(this).hide();\n }\n });\n });\n\n }\n\n // Ouvrir les liens externes dans un nouvel onglet\n document.querySelectorAll('a[href^=\"http\"]').forEach(link => {\n if (!link.href.includes(location.hostname)) {\n link.setAttribute('target', '_blank');\n link.setAttribute('rel', 'noopener noreferrer');\n }\n });\n\n // Scroll automatique au filtre\n if (document.body.classList.contains(\"path-projets\")) {\n const form = document.querySelector(\".views-exposed-form\");\n if (form) form.setAttribute(\"action\", form.action.split(\"#\")[0] + \"#filtres\");\n\n if (window.location.hash === \"#filtres\") {\n const target = document.getElementById(\"filtres\");\n if (target) {\n const offset = 300;\n const top = target.getBoundingClientRect().top + window.pageYOffset - offset;\n window.scrollTo({ top: top, behavior: \"smooth\" });\n }\n }\n\n\n }\n});\n/////////////////start diaporama ressource //////////\ndocument.addEventListener('DOMContentLoaded', function () {\n // Vérifie que le body a la classe souhaitée\n if (!document.body.classList.contains('type-media-images---photos')) return;\n // Attendre que les éléments HTML soient bien présents\n const interval = setInterval(() => {\n const mainImage = document.getElementById('mainImage');\n const prevArrow = document.getElementById('prevArrow');\n const nextArrow = document.getElementById('nextArrow');\n const caption = document.getElementById('caption');\n const thumbsContainer = document.getElementById('thumbnails');\n const imagesInDom = document.querySelectorAll('.carousel-items .carousel-item img');\n\n if (mainImage && prevArrow && nextArrow && caption && thumbsContainer && imagesInDom) {\n clearInterval(interval); // Tous les éléments sont là, on lance le carrousel\n initCarousel({ mainImage, prevArrow, nextArrow, caption, thumbsContainer });\n }\n }, 100); // vérifie toutes les 100ms\n});\nfunction initCarousel({ mainImage, prevArrow, nextArrow, caption, thumbsContainer }) {\n const images = [];\n document.querySelectorAll('.carousel-items .carousel-item img').forEach((img) => {\n images.push({\n src: img.getAttribute('src'),\n caption: img.getAttribute('alt') || 'Image sans légende'\n });\n });\n console.log('Images chargées pour le carrousel :', images);\n\n if (!images.length) return;\n\n let currentIndex = 0;\n\n function showImage(index) {\n mainImage.src = images[index].src;\n caption.textContent = images[index].caption;\n\n const thumbnails = document.querySelectorAll('.thumbnails img');\n thumbnails.forEach(img => img.classList.remove('active'));\n if (thumbnails[index]) {\n thumbnails[index].classList.add('active');\n }\n }\n\n prevArrow.addEventListener('click', () => {\n currentIndex = (currentIndex - 1 + images.length) % images.length;\n showImage(currentIndex);\n });\n\n nextArrow.addEventListener('click', () => {\n currentIndex = (currentIndex + 1) % images.length;\n showImage(currentIndex);\n });\n\n images.forEach((img, index) => {\n const thumb = document.createElement('img');\n thumb.src = img.src;\n thumb.alt = img.caption;\n thumb.onclick = () => {\n currentIndex = index;\n showImage(index);\n };\n thumbsContainer.appendChild(thumb);\n });\n\n showImage(currentIndex);\n const thumbPrev = document.getElementById('thumbPrev');\n const thumbNext = document.getElementById('thumbNext');\n\n thumbPrev.addEventListener('click', () => {\n thumbsContainer.scrollBy({ left: -150, behavior: 'smooth' });\n });\n\n thumbNext.addEventListener('click', () => {\n thumbsContainer.scrollBy({ left: 150, behavior: 'smooth' });\n });\n\n}\n/////////////////end diaporama ressource //////////\n\n\n//////////////////////////start classe en JS si des filtres sont présents///////////\ndocument.addEventListener('DOMContentLoaded', () => {\n if (window.location.search.length > 0) {\n document.querySelector('.view-content')?.classList.add('filtered');\n document.querySelectorAll('.tout-voir').forEach(btn => btn.remove());\n\n }\n});\n//////////////////////////end classe en JS si des filtres sont présents///////////\n\n// ////////////////// start tronquage sous titre //////////////////\n document.addEventListener(\"DOMContentLoaded\", function () {\n const maxLength = 80;\n\n document.querySelectorAll('.view-base-de-donnees .wrapper-ressource .field--name-field-sous-titre a').forEach(function (element) {\n const fullText = element.textContent.trim();\n\n if (fullText.length > maxLength) {\n const truncated = fullText.slice(0, maxLength).trim() + '...';\n element.textContent = truncated;\n }\n });\n });\n // //////////////////end tronquage sous titre //////////////////\n\n////////////////// start boutons media ////////////////\n\ndocument.addEventListener(\"DOMContentLoaded\", function () {\n const mediaButtons = document.querySelectorAll('.buttons-filtres-ressources a');\n\n mediaButtons.forEach(button => {\n button.addEventListener('click', function (e) {\n e.preventDefault();\n\n // Récupérer l’ID media depuis l’URL du bouton\n const url = new URL(button.href);\n const mediaID = url.searchParams.get('field_type_de_media_target_id');\n\n // Appliquer la valeur dans le \n const select = document.getElementById('edit-field-type-de-media-target-id');\n if (select) {\n select.value = mediaID;\n // Simuler le clic sur le bouton \"Appliquer\"\n const submit = document.querySelector('input#edit-submit-base-de-donnees');\n if (submit) {\n submit.click();\n }\n }\n });\n });\n});\n////////////////// end boutons media ////////////////\n\n\n\n////////////// start croix clear input recherche ////////////\ndocument.addEventListener(\"DOMContentLoaded\", function () {\n const input = document.getElementById(\"edit-combine\");\n const clearBtn = document.querySelector('.form-item-combine .clear-input');\n const form = document.querySelector(\"form.views-exposed-form\");\n\n if (input && clearBtn && form) {\n // Affiche la croix si contenu présent\n input.addEventListener('input', () => {\n clearBtn.style.display = input.value ? 'block' : 'none';\n });\n\n // Efface et soumet le formulaire\n clearBtn.addEventListener('click', () => {\n input.value = '';\n clearBtn.style.display = 'none';\n input.focus();\n form.submit(); // déclenche la recherche sans rechargement manuel\n });\n\n // Affiche la croix au chargement si une valeur est déjà présente\n if (input.value) {\n clearBtn.style.display = 'block';\n }\n }\n});\n\n\n////////////// end croix clear input recherche ////////////\n\n\n//# sourceURL=webpack://dev.eql.fr/./scripts/main.js?"); /***/ }) diff --git a/web/themes/custom/eql/dist/assets/css/bundle.css b/web/themes/custom/eql/dist/assets/css/bundle.css index 39ad22d..152e215 100644 --- a/web/themes/custom/eql/dist/assets/css/bundle.css +++ b/web/themes/custom/eql/dist/assets/css/bundle.css @@ -5841,64 +5841,90 @@ svg.ext { width: 80%; } .page-node-type-ressource .type-les-projets-en-images.layout__region--top .block-region-top .block-entity-fieldnodefield-images .carousel { - display: flex; + display: grid; + grid-template-columns: 1fr 10fr; + gap: 1.5rem; + justify-content: center; margin: auto; - text-align: center; +} +.page-node-type-ressource .type-les-projets-en-images.layout__region--top .block-region-top .block-entity-fieldnodefield-images .carousel .main-image-block { + display: flex; + align-items: center; + position: relative; + width: 100%; + margin: 0 auto; } .page-node-type-ressource .type-les-projets-en-images.layout__region--top .block-region-top .block-entity-fieldnodefield-images .carousel .main-image-container { - position: relative; flex: 1; - max-width: 600px; - overflow: hidden; - width: 100%; - object-fit: contain; + text-align: center; } .page-node-type-ressource .type-les-projets-en-images.layout__region--top .block-region-top .block-entity-fieldnodefield-images .carousel .main-image-container img { width: 100%; - height: 100%; + height: auto; object-fit: contain; - transition: transform 0.3s ease-in-out; - border: none; } -.page-node-type-ressource .type-les-projets-en-images.layout__region--top .block-region-top .block-entity-fieldnodefield-images .carousel .main-image-container img.animate { - transform: scale(1.02); +.page-node-type-ressource .type-les-projets-en-images.layout__region--top .block-region-top .block-entity-fieldnodefield-images .carousel .main-image-container .caption { + margin-top: 1rem; + font-family: sans-serif; + text-align: center; + font-size: 1rem; + color: #444; } -.page-node-type-ressource .type-les-projets-en-images.layout__region--top .block-region-top .block-entity-fieldnodefield-images .carousel .main-image-container .arrow { - position: absolute; - top: 50%; - transform: translateY(-50%); +.page-node-type-ressource .type-les-projets-en-images.layout__region--top .block-region-top .block-entity-fieldnodefield-images .carousel .arrow { + display: none; + font-size: 2rem; + color: #333; background: none; border-radius: 50%; - padding: 5px 10px; - color: black; + width: 40px; + height: 40px; + line-height: 40px; + text-align: center; cursor: pointer; + user-select: none; + transition: background 0.3s ease; } -content .page-node-type-ressource .type-les-projets-en-images.layout__region--top .block-region-top .block-entity-fieldnodefield-images .carousel .main-image-container .arrow.left { - left: 10px; +.page-node-type-ressource .type-les-projets-en-images.layout__region--top .block-region-top .block-entity-fieldnodefield-images .carousel .arrow:hover { + background: #bbb; } -.page-node-type-ressource .type-les-projets-en-images.layout__region--top .block-region-top .block-entity-fieldnodefield-images .carousel .main-image-container .arrow.right { - right: 10px; +.page-node-type-ressource .type-les-projets-en-images.layout__region--top .block-region-top .block-entity-fieldnodefield-images .carousel .arrow.left { + margin-right: 10px; +} +.page-node-type-ressource .type-les-projets-en-images.layout__region--top .block-region-top .block-entity-fieldnodefield-images .carousel .arrow.right { + margin-left: 10px; } .page-node-type-ressource .type-les-projets-en-images.layout__region--top .block-region-top .block-entity-fieldnodefield-images .carousel .caption { margin-top: 10px; font-family: sans-serif; + grid-column: 2; + grid-row: 2; } .page-node-type-ressource .type-les-projets-en-images.layout__region--top .block-region-top .block-entity-fieldnodefield-images .carousel .thumbnails-wrapper { + grid-column: 1; display: flex; flex-direction: column; align-items: center; - max-height: 500px; - overflow: hidden; + max-height: 70vh; + grid-row: 1/span 2; + top: -30px; + position: relative; +} +.page-node-type-ressource .type-les-projets-en-images.layout__region--top .block-region-top .block-entity-fieldnodefield-images .carousel .thumbnails-wrapper .thumb-arrow { + cursor: pointer; + padding: 5px 10px; + background: #00aaff; + color: white; + border-radius: 50%; + user-select: none; + z-index: 2; } .page-node-type-ressource .type-les-projets-en-images.layout__region--top .block-region-top .block-entity-fieldnodefield-images .carousel .thumbnails-wrapper .thumbnails { display: flex; flex-direction: column; gap: 10px; overflow-y: auto; - overflow-x: hidden; + max-height: 100%; scroll-behavior: smooth; - max-height: 400px; - padding: 10px 0; } .page-node-type-ressource .type-les-projets-en-images.layout__region--top .block-region-top .block-entity-fieldnodefield-images .carousel .thumbnails-wrapper .thumbnails::-webkit-scrollbar { display: none; @@ -5913,18 +5939,6 @@ content .page-node-type-ressource .type-les-projets-en-images.layout__region--to .page-node-type-ressource .type-les-projets-en-images.layout__region--top .block-region-top .block-entity-fieldnodefield-images .carousel .thumbnails-wrapper .thumbnails img.active { border-color: #00aaff; } -.page-node-type-ressource .type-les-projets-en-images.layout__region--top .block-region-top .block-entity-fieldnodefield-images .carousel .thumbnails-wrapper .thumb-arrow { - cursor: pointer; - padding: 5px; - background: #00aaff; - color: white; - border-radius: 50%; - user-select: none; - margin: 5px 0; -} -.page-node-type-ressource .type-les-projets-en-images.layout__region--top .block-region-top .block-entity-fieldnodefield-images .carousel .thumbnails-wrapper .thumb-arrow.left, .page-node-type-ressource .type-les-projets-en-images.layout__region--top .block-region-top .block-entity-fieldnodefield-images .carousel .thumbnails-wrapper .thumb-arrow.right { - margin: 0; -} .page-node-type-ressource .type-les-projets-en-images.layout__region--top .block-region-top .block-entity-fieldnodefield-images .field__items { display: none; } diff --git a/web/themes/custom/eql/scripts/main.js b/web/themes/custom/eql/scripts/main.js index a90b8e7..6f95184 100644 --- a/web/themes/custom/eql/scripts/main.js +++ b/web/themes/custom/eql/scripts/main.js @@ -253,11 +253,11 @@ function initCarousel({ mainImage, prevArrow, nextArrow, caption, thumbsContaine const thumbNext = document.getElementById('thumbNext'); thumbPrev.addEventListener('click', () => { - thumbsContainer.scrollBy({ left: -150, behavior: 'smooth' }); + thumbsContainer.scrollBy({ top: -150, behavior: 'smooth' }); }); - + thumbNext.addEventListener('click', () => { - thumbsContainer.scrollBy({ left: 150, behavior: 'smooth' }); + thumbsContainer.scrollBy({ top: 150, behavior: 'smooth' }); }); } diff --git a/web/themes/custom/eql/scss/pages/_ressource-type-en-images.scss b/web/themes/custom/eql/scss/pages/_ressource-type-en-images.scss index 5c31ac9..933279e 100644 --- a/web/themes/custom/eql/scss/pages/_ressource-type-en-images.scss +++ b/web/themes/custom/eql/scss/pages/_ressource-type-en-images.scss @@ -17,89 +17,101 @@ order: 7; width: 80%; .carousel { + display: grid; + // flex-direction: row; + grid-template-columns: 1fr 10fr; + gap: 1.5rem; + // align-items: flex-start; + justify-content: center; + margin: auto; + .main-image-block { display: flex; - // max-width: 60vw; - margin: auto; + align-items: center; + position: relative; + width: 100%; + margin: 0 auto; + } + + .main-image-container { + flex: 1; text-align: center; - - .main-image-container { - position: relative; - // background: #e0f5ff; - // height: 500px; - // max-height: 500px; - flex: 1; // prend l’espace restant - max-width: 600px; - overflow: hidden; + + img { width: 100%; + height: auto; object-fit: contain; - - img { - width: 100%; - height: 100%; - object-fit: contain; - transition: transform 0.3s ease-in-out; - border: none ; - // transition: opacity 0.4s ease-in-out; // à réactiver si fade souhaité - &.animate { - transform: scale(1.02); // léger effet smooth sur changement - } - } - - .arrow { - position: absolute; - top: 50%; - transform: translateY(-50%); - background:none; - border-radius: 50%; - padding: 5px 10px; - color: black; - cursor: pointer; - content - - &.left { - left: 10px; - } - - &.right { - right: 10px; - } - } - // #prevArrow{ - // &::before{ - // content:url("../images/pictos/fleche-droite-dans-rond.png"); - // display: block; - // transform: scaleX(-1); - // width: 50px; - // } - // } - // #nextArrow{ - // &::before{ - // content:url("../images/pictos/fleche-droite-dans-rond.png"); - // display: block; - // } - // } } + + .caption { + margin-top: 1rem; + font-family: sans-serif; + text-align: center; + font-size: 1rem; + color: #444; + } + } + + .arrow { + display: none; + font-size: 2rem; + color: #333; + background: none; + border-radius: 50%; + width: 40px; + height: 40px; + line-height: 40px; + text-align: center; + cursor: pointer; + user-select: none; + transition: background 0.3s ease; + + &:hover { + background: #bbb; + } + + &.left { + margin-right: 10px; + } + + &.right { + margin-left: 10px; + } + } + .caption { margin-top: 10px; font-family: sans-serif; + grid-column: 2; + grid-row: 2; } .thumbnails-wrapper { + grid-column: 1; display: flex; flex-direction: column; align-items: center; - max-height: 500px; - overflow: hidden; + max-height: 70vh; + grid-row: 1 /span 2; + top: -30px; + position: relative; + .thumb-arrow { + cursor: pointer; + padding: 5px 10px; + background: #00aaff; + color: white; + border-radius: 50%; + user-select: none; + z-index: 2; + // font-weight: bold; + } .thumbnails { display: flex; flex-direction: column; gap: 10px; overflow-y: auto; - overflow-x: hidden; + max-height: 100%; scroll-behavior: smooth; - max-height: 400px; - padding: 10px 0; &::-webkit-scrollbar { display: none; @@ -117,22 +129,8 @@ } } } - - .thumb-arrow { - cursor: pointer; - padding: 5px; - background: #00aaff; - color: white; - border-radius: 50%; - user-select: none; - margin: 5px 0; - - &.left, &.right { - // on ne les utilise plus horizontalement - margin: 0; - } - } } + // .thumbnails-wrapper { // position: relative; diff --git a/web/themes/custom/eql/templates/block--entity-field--node--field-images.html.twig b/web/themes/custom/eql/templates/block--entity-field--node--field-images.html.twig index e968d37..c9f9bda 100644 --- a/web/themes/custom/eql/templates/block--entity-field--node--field-images.html.twig +++ b/web/themes/custom/eql/templates/block--entity-field--node--field-images.html.twig @@ -47,16 +47,21 @@ {% if is_ressource_page %} {# Affichage du carrousel uniquement sur les pages de type ressource #} {% endif %}