From 09a1e18f16dd8d3873f675484edd9b0266aa0267 Mon Sep 17 00:00:00 2001 From: ouidade Date: Sun, 2 Mar 2025 11:55:32 +0100 Subject: [PATCH 01/22] css live --- .../quartiers_de_demain/dist/assets/bundle.js | 2 +- .../dist/assets/css/bundle.css | 20 +++- .../dist/assets/img/formes-animees-live.svg | 102 ++++++++++++++++++ .../src/assets/js/animated_formes.js | 2 +- .../src/assets/scss/pages/home.scss | 15 +++ .../assets/scss/partials/formes-animees.scss | 58 +++++++--- .../templates/page--front.html.twig | 8 +- 7 files changed, 183 insertions(+), 24 deletions(-) create mode 100644 web/themes/custom/quartiers_de_demain/dist/assets/img/formes-animees-live.svg diff --git a/web/themes/custom/quartiers_de_demain/dist/assets/bundle.js b/web/themes/custom/quartiers_de_demain/dist/assets/bundle.js index 11daa9c..28d9d93 100644 --- a/web/themes/custom/quartiers_de_demain/dist/assets/bundle.js +++ b/web/themes/custom/quartiers_de_demain/dist/assets/bundle.js @@ -26,7 +26,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony default export */ \******************************************/ /***/ (function() { -eval("document.addEventListener('scroll', function() {\n const scrolled = window.pageYOffset;\n const background = document.getElementById('background-animated');\n if (background) {\n // Adjust this value to control the speed of the parallax effect\n const parallaxSpeed = 0.5;\n background.style.transform = 'translateY(' + (scrolled * parallaxSpeed) + 'px)';\n }\n});\n\n\n\n\n //ANimation Pilliers \n// const svg = document.querySelector('#paragraph-id--7 .colone-picto');\n\n// // Configuration de l'observateur d'intersection\n// const observer = new IntersectionObserver(entries => {\n// entries.forEach(entry => {\n// if (entry.isIntersecting) {\n// // Ajoute une classe lorsque l'élément est visible\n// svg.classList.add('visible');\n// } else {\n// // Optionnel : Retirez la classe si nécessaire\n// svg.classList.remove('visible');\n// }\n// });\n// });\n\n// // Observer l'élément SVG\n// observer.observe(svg);\n\n//////////////////////////////////////////////////\n\n//ANimation Pilliers \nconst svg = document.querySelector('#paragraph-id--7 .colone-picto');\n\nif (svg) {\n // Configuration de l'observateur d'intersection\n const observer = new IntersectionObserver(entries => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n // Ajoute une classe lorsque l'élément est visible\n // svg.classList.remove('invisible');\n svg.classList.add('visible');\n } \n // else {\n // // Optionnel : Retirez la classe si nécessaire\n // svg.classList.remove('visible');\n \n // }\n });\n });\n \n // Observer l'élément SVG\n observer.observe(svg);\n \n}\n\n\n//# sourceURL=webpack://quartiers_de_demain/./src/assets/js/animated_formes.js?"); +eval("document.addEventListener('scroll', function() {\n const scrolled = window.pageYOffset;\n const background = document.getElementById('background-animated-live');\n if (background) {\n // Adjust this value to control the speed of the parallax effect\n const parallaxSpeed = 0.5;\n background.style.transform = 'translateY(' + (scrolled * parallaxSpeed) + 'px)';\n }\n});\n\n\n\n\n //ANimation Pilliers \n// const svg = document.querySelector('#paragraph-id--7 .colone-picto');\n\n// // Configuration de l'observateur d'intersection\n// const observer = new IntersectionObserver(entries => {\n// entries.forEach(entry => {\n// if (entry.isIntersecting) {\n// // Ajoute une classe lorsque l'élément est visible\n// svg.classList.add('visible');\n// } else {\n// // Optionnel : Retirez la classe si nécessaire\n// svg.classList.remove('visible');\n// }\n// });\n// });\n\n// // Observer l'élément SVG\n// observer.observe(svg);\n\n//////////////////////////////////////////////////\n\n//ANimation Pilliers \nconst svg = document.querySelector('#paragraph-id--7 .colone-picto');\n\nif (svg) {\n // Configuration de l'observateur d'intersection\n const observer = new IntersectionObserver(entries => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n // Ajoute une classe lorsque l'élément est visible\n // svg.classList.remove('invisible');\n svg.classList.add('visible');\n } \n // else {\n // // Optionnel : Retirez la classe si nécessaire\n // svg.classList.remove('visible');\n \n // }\n });\n });\n \n // Observer l'élément SVG\n observer.observe(svg);\n \n}\n\n\n//# sourceURL=webpack://quartiers_de_demain/./src/assets/js/animated_formes.js?"); /***/ }), diff --git a/web/themes/custom/quartiers_de_demain/dist/assets/css/bundle.css b/web/themes/custom/quartiers_de_demain/dist/assets/css/bundle.css index 46dc0b8..8589402 100644 --- a/web/themes/custom/quartiers_de_demain/dist/assets/css/bundle.css +++ b/web/themes/custom/quartiers_de_demain/dist/assets/css/bundle.css @@ -1693,7 +1693,7 @@ header #block-quartiers-de-demain-logoquartiersdedemain .field_field_logo .qdd-h } } -#home #background-animated { +#home #background-animated-live { position: absolute; top: 1500px; left: 200px; @@ -1702,11 +1702,11 @@ header #block-quartiers-de-demain-logoquartiersdedemain .field_field_logo .qdd-h z-index: 2; /* S'assure que l'élément soit au-dessus */ } @media (max-width: 1400px) { - #home #background-animated { + #home #background-animated-live { display: none; } } -#home #background-animated svg { +#home #background-animated-live svg { max-width: 100%; position: relative; top: -1500px; @@ -2572,6 +2572,20 @@ body { #home .paragraph--type--static-parts:not(#paragraph-id--7) #svg1 { display: none; } +#home #live-youtube { + width: 60%; + margin: auto; + margin-left: 14rem; +} +#home #live-youtube h2 { + text-align: center; + font-size: 1.5rem; + font-family: "gilroy-semibold"; +} +#home #live-youtube .field_field_descritpion { + margin-bottom: 2rem; +} + #consultation { background-color: #f6f7f3; } diff --git a/web/themes/custom/quartiers_de_demain/dist/assets/img/formes-animees-live.svg b/web/themes/custom/quartiers_de_demain/dist/assets/img/formes-animees-live.svg new file mode 100644 index 0000000..a4133a8 --- /dev/null +++ b/web/themes/custom/quartiers_de_demain/dist/assets/img/formes-animees-live.svg @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/web/themes/custom/quartiers_de_demain/src/assets/js/animated_formes.js b/web/themes/custom/quartiers_de_demain/src/assets/js/animated_formes.js index 0ffb76a..6e4da8d 100644 --- a/web/themes/custom/quartiers_de_demain/src/assets/js/animated_formes.js +++ b/web/themes/custom/quartiers_de_demain/src/assets/js/animated_formes.js @@ -1,6 +1,6 @@ document.addEventListener('scroll', function() { const scrolled = window.pageYOffset; - const background = document.getElementById('background-animated'); + const background = document.getElementById('background-animated-live'); if (background) { // Adjust this value to control the speed of the parallax effect const parallaxSpeed = 0.5; diff --git a/web/themes/custom/quartiers_de_demain/src/assets/scss/pages/home.scss b/web/themes/custom/quartiers_de_demain/src/assets/scss/pages/home.scss index 848940c..9383583 100644 --- a/web/themes/custom/quartiers_de_demain/src/assets/scss/pages/home.scss +++ b/web/themes/custom/quartiers_de_demain/src/assets/scss/pages/home.scss @@ -697,6 +697,21 @@ // display: none; } + #live-youtube{ + width: 60%; + margin: auto; + margin-left: 14rem; + h2{ + text-align: center; + font-size: 1.5rem; + font-family: "gilroy-semibold"; + + } + .field_field_descritpion{ + margin-bottom: 2rem; + } + } + } diff --git a/web/themes/custom/quartiers_de_demain/src/assets/scss/partials/formes-animees.scss b/web/themes/custom/quartiers_de_demain/src/assets/scss/partials/formes-animees.scss index d58f00c..22d02b4 100644 --- a/web/themes/custom/quartiers_de_demain/src/assets/scss/partials/formes-animees.scss +++ b/web/themes/custom/quartiers_de_demain/src/assets/scss/partials/formes-animees.scss @@ -1,23 +1,44 @@ #home{ +/////////////////start à remettre après fin live /////////////// + // #background-animated { + // // display: none; + // position: absolute; + // top: 1500px; + // left: 200px; + // width: 90%; + // // height: 100%; + // pointer-events: none; /* Permet de cliquer à travers l'élément */ + // z-index: 2; /* S'assure que l'élément soit au-dessus */ + // @media(max-width: 1400px){ + // display: none; + // } + // svg{ + // max-width: 100%; + // position: relative; + // top: -1500px; + // } + // } - #background-animated { - // display: none; - position: absolute; - top: 1500px; - left: 200px; - width: 90%; - // height: 100%; - pointer-events: none; /* Permet de cliquer à travers l'élément */ - z-index: 2; /* S'assure que l'élément soit au-dessus */ - @media(max-width: 1400px){ - display: none; - } - svg{ - max-width: 100%; - position: relative; - top: -1500px; +////////////////////////// end à remettre après fin live/////////// + #background-animated-live { + // display: none; + position: absolute; + top: 1500px; + left: 200px; + width: 90%; + // height: 100%; + pointer-events: none; /* Permet de cliquer à travers l'élément */ + z-index: 2; /* S'assure que l'élément soit au-dessus */ + @media(max-width: 1400px){ + display: none; } + svg{ + max-width: 100%; + position: relative; + top: -1500px; } + } + // .not-visible{ // @media (max-width:1100px) { // display: none; @@ -32,4 +53,7 @@ .layout-container.home { position: relative; } -} \ No newline at end of file + + + +} diff --git a/web/themes/custom/quartiers_de_demain/templates/page--front.html.twig b/web/themes/custom/quartiers_de_demain/templates/page--front.html.twig index 876f336..606f998 100644 --- a/web/themes/custom/quartiers_de_demain/templates/page--front.html.twig +++ b/web/themes/custom/quartiers_de_demain/templates/page--front.html.twig @@ -82,11 +82,15 @@ {{ page.content }} {# /.layout-content #} -
+ {#
{% include active_theme_path() ~ '/dist/assets/img/formes-animees.svg' %} +
#} +
+ {% include active_theme_path() ~ '/dist/assets/img/formes-animees-live.svg' %} +
- + {% if page.sidebar_first %}
{# /.layout-content #} - {#
+
{% include active_theme_path() ~ '/dist/assets/img/formes-animees.svg' %} -
#} -
- {% include active_theme_path() ~ '/dist/assets/img/formes-animees-live.svg' %} -
- + {% if page.sidebar_first %}
#} {% block content %} + +
{{content.field_type_d_actualite}} {{content.field_date}}
+ + {{ label }} + {{content.body}} {{content.field_liens}} {{content.field_images}} + {{content.field_title}} {% endblock %} From f745ce2f6cc4211e853c9879421b73c44ee43e3a Mon Sep 17 00:00:00 2001 From: ouidade Date: Mon, 3 Mar 2025 17:25:43 +0100 Subject: [PATCH 18/22] fix tamporaire bug actu carroussel --- .../quartiers_de_demain/dist/assets/bundle.js | 2 +- .../dist/assets/css/bundle.css | 77 ++++++++++++++----- .../src/assets/js/quartiers_de_demain.js | 44 +++++------ .../scss/partials/actu-caroussel-home.scss | 43 ++++++++++- .../templates/node--actualite.html.twig | 13 ++-- 5 files changed, 128 insertions(+), 51 deletions(-) diff --git a/web/themes/custom/quartiers_de_demain/dist/assets/bundle.js b/web/themes/custom/quartiers_de_demain/dist/assets/bundle.js index d82cd15..82a34d8 100644 --- a/web/themes/custom/quartiers_de_demain/dist/assets/bundle.js +++ b/web/themes/custom/quartiers_de_demain/dist/assets/bundle.js @@ -36,7 +36,7 @@ eval("document.addEventListener('scroll', function() {\n const scrolled = win \**********************************************/ /***/ (function() { -eval("/**\n * @file\n * quartiers_de_demain behaviors.\n */\n (function (Drupal) {\n\n 'use strict';\n \n Drupal.behaviors.quartiers_de_demain = {\n attach: function (context, settings) {\n console.log('It works!');\n }\n };\n } (Drupal));\n\n\n //////// start header ////////////\n document.addEventListener('DOMContentLoaded', function() {\n\n const header = document.querySelector('header');\n const logo = document.querySelector('#block-quartiers-de-demain-logoquartiersdedemain > div:nth-child(1) > div:nth-child(1) > a:nth-child(1) > svg:nth-child(1)');\n const headerNavContainer = document.querySelector('.header_nav_container');\n const isFirstLoad = !performance.getEntriesByType(\"navigation\")[0].type.includes('back_forward');\n const isTargetPath = window.location.pathname === '/';\n\n // Fonction pour démarrer l'animation du logo SVG\n function startLogoAnimation() {\n logo.classList.add('animated');\n }\n \n // Fonction pour arrêter l'animation du logo SVG\n function stopLogoAnimation() {\n logo.classList.remove('animated');\n }\n \n // Vérifier si le header a la classe header--collapse\n function checkHeaderCollapse() {\n if (header.classList.contains('header--collapsed')) {\n stopLogoAnimation();\n } else if (header.classList.contains('header--collapsed-already')) {\n stopLogoAnimation();\n } else {\n startLogoAnimation();\n }\n\n }\n \n // Appeler la fonction au chargement initial\n checkHeaderCollapse();\n \n // Observer les changements de classe sur le header\n const observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(mutation) {\n if (mutation.attributeName === 'class') {\n checkHeaderCollapse();\n }\n });\n });\n observer.observe(header, { attributes: true });\n \n\n // Si ce n'est pas la première charge ou si le chemin n'est pas le chemin cible, ajouter la classe immédiatement\n if (!isFirstLoad || !isTargetPath) {\n header.classList.add('header--collapsed-already');\n // logo.classList.remove('animated');\n stopLogoAnimation();\n } else {\n // Sinon, appliquer la transition après un délai\n setTimeout(() => {\n header.classList.add('header--collapsed');\n }, 5000);\n }\n\n //////////////////////////////////////\n\n let lastScrollTop = 0;\n let threshold = 100; // Change this value as needed\n let isHidden = false;\n \n function slideOut() {\n headerNavContainer.animate([\n { transform: 'translateX(0)' },\n { transform: 'translateX(-100%)' }\n ], {\n duration: 300,\n fill: 'forwards'\n });\n isHidden = true;\n }\n \n function slideIn() {\n headerNavContainer.animate([\n { transform: 'translateX(-100%)' },\n { transform: 'translateX(0)' }\n ], {\n duration: 300,\n fill: 'forwards'\n });\n isHidden = false;\n }\n \n function slideDown() {\n // headerNavContainer.style.display = 'block';\n headerNavContainer.animate([\n { transform: 'translateY(0%)' },\n { transform: 'translateY(+100%)' }\n ], {\n duration: 300,\n fill: 'forwards'\n });\n isHidden = false;\n }\n \n function slideUp() {\n headerNavContainer.animate([\n { transform: 'translateY(100%)' },\n { transform: 'translateY(0%)' }\n ], {\n duration: 300,\n fill: 'forwards'\n }).onfinish = function() {\n // headerNavContainer.style.display = 'none';\n };\n isHidden = true;\n }\n // Fonction pour ajuster la hauteur du header lors du défilement\n function adjustHeaderHeight() {\n if (window.scrollY > 0) {\n header.classList.add('shrink');\n } else {\n header.classList.remove('shrink');\n }\n }\n\n function handleScroll() {\n let scrollTop = window.pageYOffset || document.documentElement.scrollTop;\n const isMobile = window.innerWidth < 811;\n\n if (scrollTop > threshold && !isHidden) {\n if (isMobile) {\n slideUp();\n } else {\n slideOut();\n }\n } else if (scrollTop <= threshold && isHidden) {\n if (isMobile) {\n slideDown();\n } else {\n slideIn();\n }\n }\n \n \n lastScrollTop = scrollTop <= 0 ? 0 : scrollTop; // For Mobile or negative scrolling\n }\n \n function handleTouchAndMouseEnter() {\n if (isHidden) {\n if (window.innerWidth < 811) {\n slideDown();\n } else {\n slideIn();\n }\n }\n }\n \n function handleTouchAndMouseLeave() {\n if (lastScrollTop > threshold && !isHidden) {\n if (window.innerWidth < 811) {\n slideUp();\n } else {\n slideOut();\n }\n }\n }\n \n window.addEventListener('scroll', handleScroll);\n window.addEventListener('scroll', adjustHeaderHeight);\n \n // Mouse events for desktop\n header.addEventListener('mouseenter', handleTouchAndMouseEnter);\n header.addEventListener('mouseleave', handleTouchAndMouseLeave);\n \n // Touch events for tablets and mobile devices\n header.addEventListener('touchstart', handleTouchAndMouseEnter);\n header.addEventListener('touchend', handleTouchAndMouseLeave);\n \n // Initial check to see if we're at the top of the page\n if (window.pageYOffset <= threshold) {\n if (window.innerWidth < 811) {\n slideDown();\n } else { \n slideIn();\n } \n } else {\n if (window.innerWidth < 811) {\n slideUp();\n } else {\n slideIn();\n }\n }\n \n });\n\n//////// end header ////////////\n \n\n\n//// ancre dans texte au click paragraphe correspondant arrive en dessous du header \n\n\n(function($, window) {\n var adjustAnchor = function() {\n var $anchor = $('.sidebar_first_container'),\n fixedElementHeight = 500;\n if ($anchor.length > 0) {\n $('html, body').stop().animate({scrollTop: $anchor.offset().top - fixedElementHeight }, 0);\n }\n };\n\n $(window).on('hashchange', function() {\n adjustAnchor();\n });\n\n\n //////////////////////// start script smooth apparition des textes /////////////////\n\n function scrollReaveal(){\n\n const nodes = {\n logo : document.querySelectorAll('#logo-animated-container'),\n chapeau : document.querySelectorAll('.field_body'),\n paragraph: document.querySelectorAll('.field_field_textes .paragraph--type--static-parts'),\n enjeux : document.querySelectorAll('.field_field_textes .paragraph--type--static-parts .enjeux'),\n // mapHome : document.querySelectorAll('.field_field_map_block #block-sitesmapblock'),\n // mapSite : document.querySelectorAll('#sites-map-container'),\n lienDoc : document.querySelectorAll('.field_field_documents'),\n lienURL : document.querySelectorAll('.field_field_liens_site'),\n }\n\n const showUp = {\n origin: 'bottom',\n delay: 100,\n duration: 1000,\n distance: '50px',\n easing: 'cubic-bezier(0.5, 0, 0, 1)'\n }\n\n const Show = {\n delay: 100,\n duration: 600,\n easing: 'cubic-bezier(0.5, 0, 0, 1)'\n }\n\n console.log(nodes);\n\n ScrollReveal().reveal(nodes.logo, Show);\n ScrollReveal().reveal(nodes.chapeau, showUp);\n ScrollReveal().reveal(nodes.paragraph, showUp);\n ScrollReveal().reveal(nodes.enjeux, showUp);\n // ScrollReveal().reveal(nodes.mapHome, showUp);\n // ScrollReveal().reveal(nodes.mapSite, showUp);\n ScrollReveal().reveal(nodes.lienDoc, showUp);\n ScrollReveal().reveal(nodes.lienURL, showUp);\n\n }\n\n\n $( document ).ready(function() {\n scrollReaveal();\n });\n\n //////////////////////// end script smooth apparition des textes /////////////////\n\n // //////////////////// start Timeline script ///////////////////////\n\n // Update month field to only show the first 3 letters\n document.querySelectorAll('.paragraph--type--phase-deroulement').forEach(function(paragraph) {\n const monthField = paragraph.querySelector('.field_field_date_de_moi div:nth-of-type(2)');\n if (monthField) {\n const monthText = monthField.textContent.trim();\n if (monthText === \"juillet\") {\n monthField.textContent = monthText.slice(0, 4);\n monthField.classList.add('after');\n } else if (monthText === \"juin\") {\n monthField.textContent = monthText.slice(0, 4);\n } else if (monthText.length > 3) {\n monthField.textContent = monthText.slice(0, 3);\n monthField.classList.add('after');\n }\n }\n });\n \n // Fonction pour ajouter ou retirer la classe .only\n function updateDateClasses() {\n document.querySelectorAll('.paragraph--type--phase-deroulement .date').forEach(function(dateElement) {\n const date2Element = dateElement.querySelector('.date2');\n const yearElement = dateElement.querySelector('.field_field_date_de_annee');\n \n if (date2Element && !date2Element.textContent.trim()) {\n if (yearElement) {\n yearElement.classList.add('only');\n }\n } else {\n if (yearElement) {\n yearElement.classList.remove('only');\n }\n }\n });\n }\n \n // Exécuter la fonction une première fois pour le contenu déjà présent\n updateDateClasses();\n \n // MutationObserver pour surveiller les changements dans le DOM\n const observer = new MutationObserver(function(mutationsList, observer) {\n for(let mutation of mutationsList) {\n if (mutation.type === 'childList') {\n updateDateClasses();\n }\n }\n });\n\n\n // ////////////////////// start calendrier home /////////////////////////////////\n $(document).ready(function(){\n $('.__timeline-content').slick({\n slidesToShow: 3,\n slidesToScroll: 1,\n dots: false,\n arrows: true,\n centerMode: false,\n draggable: true,\n infinite: false,\n responsive: [\n {\n breakpoint: 810,\n settings: {\n slidesToShow: 1,\n adaptiveHeight: false,\n arrows: true,\n draggable: true,\n centerMode: false,\n infinite: false,\n }\n }]\n });\n console.log('salut slick calendrier');\n \n });\n \n //////////////////////// end calendrier home /////////////////////////////////\n \n \n\n //////////////////////// end Timeline script /////////////////////////////////////////////\n\n /////////////////// caracteres body actus/////////////////////////\n\n // document.addEventListener('DOMContentLoaded', function() {\n // // Nombre maximum de caractères à afficher\n // const maxChars = 140; // Ajustez cette valeur selon vos besoins\n\n // document.querySelectorAll('#actus-caroussel .node-type-actualite').forEach(function(node) {\n // let paragraphs = node.querySelectorAll('.field_body p');\n // let fullText = \"\";\n \n // // Concaténer tous les paragraphes\n // paragraphs.forEach(p => fullText += p.textContent.trim() + \" \");\n // fullText = fullText.trim();\n\n // // Vérifier si le texte dépasse la limite\n // if (fullText.length > maxChars) {\n // let truncatedText = fullText.slice(0, maxChars) + '...';\n\n // // Vider tout le contenu et insérer seulement le texte tronqué\n // let firstParagraph = paragraphs[0];\n // firstParagraph.textContent = truncatedText;\n\n // // Masquer les autres paragraphes\n // for (let i = 1; i < paragraphs.length; i++) {\n // paragraphs[i].style.display = \"none\";\n // }\n // }\n // });\n // });\n\n \n\n //////////// start slideshow home ////////////////////////// \n\n\n\n $(document).ready(function(){\n let actuview = $('.content-actus .view ')\n if (actuview) {\n actuview.slick({\n slidesToShow: 3,\n // slidesToScroll: 1,\n dots: false,\n arrows: true,\n // centerMode: true,\n adaptiveHeight: false,\n autoplay: false,\n // autoplaySpeed: 1500,\n // infinite: true,\n // centerPadding: '100px',\n responsive: [\n {\n breakpoint: 810,\n settings: {\n slidesToShow: 1,\n // slidesToScroll: 1,\n adaptiveHeight: false,\n arrows: true,\n draggable: true,\n // centerMode: true,\n // centerPadding: '100px',\n autoplay: false,\n // autoplaySpeed: 2000,\n }\n }]\n });\n console.log('salut slick home');\n \n }\n $('.slick-carousel').slick({\n lazyLoad: 'progressive', // Option 'ondemand' ou 'progressive'\n });\n\n });\n\n\n\n\n $(document).ready(function () {\n let diapohome = $('.config_pages--type--diaporama-home .diaporama');\n\n if (diapohome.length) {\n // Initialisation de Slick\n diapohome.slick({\n slidesToShow: 1,\n dots: false,\n arrows: false,\n // centerMode: true,\n adaptiveHeight: false,\n autoplay: true, // Activer l'autoplay\n autoplaySpeed: 4000, // Changement de slide toutes les 4 secondes\n // infinite: true,\n pauseOnHover: false, // Ne pas arrêter l'autoplay lors du survol\n pauseOnFocus: false,\n responsive: [\n {\n breakpoint: 810,\n settings: {\n slidesToShow: 1,\n adaptiveHeight: false,\n arrows: false,\n draggable: true,\n centerMode: false,\n }\n }]\n });\n\n }\n});\n\n //////////// end slideshow home ////////////////////////// \n\n//////////////// start lightbox galerie image page site////////////////////////\n\n// Sélection des images et de leurs légendes dans la galerie\nlet images = document.querySelectorAll('.paragraph--type--site-diapo .lightbox-trigger');\nlet currentIndex;\n\n// Création de la lightbox et de ses éléments\nconst lightbox = document.createElement('div');\nlightbox.id = 'lightbox';\nlightbox.classList.add('lightbox');\ndocument.body.appendChild(lightbox);\n\nconst img = document.createElement('img');\nlightbox.appendChild(img);\n\n// Élément pour afficher la légende\nconst caption = document.createElement('p');\ncaption.classList.add('caption');\nlightbox.appendChild(caption);\n\nconst closeBtn = document.createElement('span');\ncloseBtn.classList.add('close');\ncloseBtn.innerHTML = '×';\nlightbox.appendChild(closeBtn);\n\nconst prevBtn = document.createElement('a');\nprevBtn.classList.add('prev');\nprevBtn.innerHTML = '❮';\nlightbox.appendChild(prevBtn);\n\nconst nextBtn = document.createElement('a');\nnextBtn.classList.add('next');\nnextBtn.innerHTML = '❯';\nlightbox.appendChild(nextBtn);\n\n// Fonction pour afficher l'image et la légende à l'index donné\nfunction showImage(index) {\n if (index < 0) index = images.length - 1;\n if (index >= images.length) index = 0;\n currentIndex = index;\n\n // Mettre à jour l'image\n img.src = images[currentIndex].getAttribute('src');\n\n // Récupérer la légende associée (le paragraphe dans blockquote suivant l'image)\n const captionText = images[currentIndex]\n .closest('.cadre-img-zoom')\n .nextElementSibling.querySelector('.image-field-caption p')\n .textContent;\n \n caption.textContent = captionText || ''; // Affiche la légende ou une chaîne vide si elle est absente\n lightbox.style.display = 'flex';\n}\n\n// Événements de clic sur chaque image pour ouvrir le lightbox avec la légende\nimages.forEach((image, index) => {\n image.addEventListener('click', () => {\n showImage(index);\n });\n});\n\n// Fermer le lightbox\ncloseBtn.addEventListener('click', () => {\n lightbox.style.display = 'none';\n});\n\n// Navigation pour images précédente et suivante\nprevBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n showImage(currentIndex - 1);\n});\n\nnextBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n showImage(currentIndex + 1);\n});\n\n// Fermer le lightbox en cliquant en dehors de l'image\nlightbox.addEventListener('click', (e) => {\n if (e.target === lightbox) {\n lightbox.style.display = 'none';\n }\n});\n\n// Ajout des contrôles clavier (Échap, flèches gauche/droite)\ndocument.addEventListener('keydown', (e) => {\n if (lightbox.style.display === 'flex') {\n if (e.key === 'Escape') {\n lightbox.style.display = 'none';\n } else if (e.key === 'ArrowLeft') {\n showImage(currentIndex - 1);\n } else if (e.key === 'ArrowRight') {\n showImage(currentIndex + 1);\n }\n }\n});\n\n\n//////////////// end lightbox galerie image page site////////////////////////\n\n \n\n//////////////////// start wrapper views-row lessites /////////////////////////\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n // Sélectionne le conteneur principal avec l'ID 'lessites'\n const container = document.getElementById(\"lessites\");\n\n // Vérifie si le conteneur existe pour éviter toute erreur sur d'autres pages\n if (container) {\n // Sélectionne l'élément 'view' à l'intérieur de '.views-element-container'\n const viewContainer = container.querySelector(\".views-element-container .view\");\n\n // Vérifie si 'viewContainer' existe pour éviter les erreurs\n if (viewContainer) {\n // Crée une div englobante pour tous les éléments 'views-row'\n const wrapperDiv = document.createElement(\"div\");\n wrapperDiv.classList.add(\"views-row-wrapper\"); // ajoute une classe pour faciliter le style CSS\n\n // Déplace tous les éléments 'views-row' dans la nouvelle div\n const viewsRows = viewContainer.querySelectorAll(\".views-row\");\n viewsRows.forEach(row => wrapperDiv.appendChild(row));\n\n // Ajoute la div englobante dans le 'viewContainer'\n viewContainer.appendChild(wrapperDiv);\n }\n }\n});\n\n\n//////////////////// end wrapper views-row lessites /////////////////////////\n\n\n\n//////////////////// start div infos site ////////////////////////\n\n// Vérifie si la page a la classe 'node-type-site' dans le \nif (document.body.classList.contains('node-type-site')) {\n // Sélectionne le conteneur principal\n const blockRegion = document.querySelector('.block-region-second');\n\n // Liste des classes spécifiques à cibler\n const fieldClasses = [\n '.field_field_region',\n '.field_field_nom_du_qpv_nb_d_hab',\n '.field_field_departement_s',\n '.field_field_programme_de_l_etat',\n '.field_field_porteur_s_de_site',\n '.field_field_nom_de_la_commune_nb_d_hab'\n ];\n\n // Sélectionne les div parents de chacun des champs listés\n const elementsToWrap = [];\n fieldClasses.forEach(className => {\n const fieldElement = blockRegion.querySelector(className);\n if (fieldElement) {\n // Ajoute le parent du champ au tableau si trouvé\n elementsToWrap.push(fieldElement.parentElement);\n }\n });\n\n // Vérifie que des éléments ont été trouvés\n if (elementsToWrap.length > 0) {\n // Crée le conteneur avec la classe 'infos'\n const infosContainer = document.createElement('div');\n infosContainer.className = 'infos';\n\n // Insère le conteneur `.infos` avant le premier élément ciblé\n const firstElement = elementsToWrap[0];\n blockRegion.insertBefore(infosContainer, firstElement);\n\n // Déplace chaque élément dans le conteneur `.infos`\n elementsToWrap.forEach(element => infosContainer.appendChild(element));\n }\n}\n//////////////////// end div infos site ////////////////////////\n\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n // Sélectionner les éléments à déplacer\n const documentsField = document.querySelector(\".field_field_documents\");\n const liensSiteField = document.querySelector(\".field_field_liens_site\");\n \n // Sélectionner la destination\n const thirdRegion = document.querySelector(\".block-region-third > div\");\n\n // Créer une nouvelle div pour englober les éléments déplacés\n const wrapperDiv = document.createElement(\"div\");\n wrapperDiv.classList.add(\"documents-liens-wrapper\");\n\n // Déplacer les éléments dans la nouvelle div\n if (documentsField && liensSiteField && thirdRegion) {\n wrapperDiv.appendChild(documentsField);\n wrapperDiv.appendChild(liensSiteField);\n\n // Ajouter la nouvelle div dans la destination\n thirdRegion.appendChild(wrapperDiv);\n }\n});\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n // Sélectionner les éléments pertinents\n const documentsLiensWrapper = document.querySelector(\".documents-liens-wrapper\");\n const blockRegionThird = document.querySelector(\".block-region-third\");\n\n // Vérifier que les éléments existent avant de les manipuler\n if (documentsLiensWrapper && blockRegionThird) {\n // Déplacer .documents-liens-wrapper en dehors du div contenant les boutons prev/next\n blockRegionThird.appendChild(documentsLiensWrapper);\n }\n});\n\n\ndocument.addEventListener(\"DOMContentLoaded\", function () {\n // Fonction pour déplacer le bloc en fonction de la taille de l'écran\n function moveLanguageSwitcher() {\n const languageSwitcher = document.getElementById(\"block-quartiers-de-demain-selecteurdelangue\");\n const navContainer = document.querySelector(\".header_nav_container\");\n\n if (window.innerWidth <= 810) { // Si écran téléphone\n if (languageSwitcher && navContainer && !navContainer.contains(languageSwitcher)) {\n navContainer.appendChild(languageSwitcher); // Déplace le bloc dans header_nav_container\n }\n } else { // Si écran non téléphone\n const headerRightContainer = document.querySelector(\".header_right_container\");\n if (languageSwitcher && headerRightContainer && !headerRightContainer.contains(languageSwitcher)) {\n headerRightContainer.appendChild(languageSwitcher); // Remet le bloc dans sa position initiale\n }\n }\n }\n\n // Déclencher au chargement et au redimensionnement\n moveLanguageSwitcher();\n window.addEventListener(\"resize\", moveLanguageSwitcher);\n});\n\n\n//////////////////////////////////////////\n\n\n/////////// Start script ressources ////////////////////////////////\n\ndocument.addEventListener(\"DOMContentLoaded\", () => {\n const view = document.querySelector(\".view\");\n const elements = Array.from(view.children);\n\n let newView = document.createElement(\"div\");\n newView.classList.add(\"view\");\n\n let group = null;\n let groupContent = null;\n\n elements.forEach((el) => {\n if (el.tagName === \"H3\") {\n if (group) {\n newView.appendChild(group);\n }\n\n group = document.createElement(\"div\");\n group.classList.add(\"group\");\n\n groupContent = document.createElement(\"div\");\n groupContent.classList.add(\"group-content\");\n\n groupContent.appendChild(el);\n group.appendChild(groupContent);\n } else if (el.classList.contains(\"views-row\")) {\n groupContent.appendChild(el);\n }\n });\n\n if (group) {\n newView.appendChild(group);\n }\n\n view.replaceWith(newView);\n\n // Ajouter un bouton \"Voir plus\" dans chaque groupe\n document.querySelectorAll(\".group\").forEach((group) => {\n const rows = group.querySelectorAll(\".views-row\");\n const button = document.createElement(\"button\");\n button.classList.add(\"toggle-btn\");\n button.textContent = \"Voir plus de\";\n\n rows.forEach((row, index) => {\n if (index >= 3) {\n row.classList.add(\"hidden\");\n row.style.maxHeight = \"0\";\n row.style.opacity = \"0\";\n }\n });\n\n button.addEventListener(\"click\", () => {\n const isExpanded = button.textContent === \"Voir moins de\";\n const hiddenRows = group.querySelectorAll(\".views-row.hidden\");\n\n if (isExpanded) {\n // Cacher les lignes avec un délai pour l'effet de transition\n hiddenRows.forEach((row) => {\n row.style.maxHeight = \"0\";\n row.style.opacity = \"0\";\n setTimeout(() => row.classList.add(\"hidden\"), 500); // Délai pour la transition\n });\n } else {\n // Afficher les lignes\n hiddenRows.forEach((row) => {\n row.classList.remove(\"hidden\");\n row.style.maxHeight = row.scrollHeight + \"px\";\n row.style.opacity = \"1\";\n });\n }\n\n button.textContent = isExpanded ? \"Voir plus de\" : \"Voir moins de\";\n });\n\n group.appendChild(button);\n });\n});\n\n\n/////////// end script ressources ////////////////////////////////\n\n})(jQuery, window);\n\n\n\n\n//# sourceURL=webpack://quartiers_de_demain/./src/assets/js/quartiers_de_demain.js?"); +eval("/**\n * @file\n * quartiers_de_demain behaviors.\n */\n (function (Drupal) {\n\n 'use strict';\n \n Drupal.behaviors.quartiers_de_demain = {\n attach: function (context, settings) {\n console.log('It works!');\n }\n };\n } (Drupal));\n\n\n //////// start header ////////////\n document.addEventListener('DOMContentLoaded', function() {\n\n const header = document.querySelector('header');\n const logo = document.querySelector('#block-quartiers-de-demain-logoquartiersdedemain > div:nth-child(1) > div:nth-child(1) > a:nth-child(1) > svg:nth-child(1)');\n const headerNavContainer = document.querySelector('.header_nav_container');\n const isFirstLoad = !performance.getEntriesByType(\"navigation\")[0].type.includes('back_forward');\n const isTargetPath = window.location.pathname === '/';\n\n // Fonction pour démarrer l'animation du logo SVG\n function startLogoAnimation() {\n logo.classList.add('animated');\n }\n \n // Fonction pour arrêter l'animation du logo SVG\n function stopLogoAnimation() {\n logo.classList.remove('animated');\n }\n \n // Vérifier si le header a la classe header--collapse\n function checkHeaderCollapse() {\n if (header.classList.contains('header--collapsed')) {\n stopLogoAnimation();\n } else if (header.classList.contains('header--collapsed-already')) {\n stopLogoAnimation();\n } else {\n startLogoAnimation();\n }\n\n }\n \n // Appeler la fonction au chargement initial\n checkHeaderCollapse();\n \n // Observer les changements de classe sur le header\n const observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(mutation) {\n if (mutation.attributeName === 'class') {\n checkHeaderCollapse();\n }\n });\n });\n observer.observe(header, { attributes: true });\n \n\n // Si ce n'est pas la première charge ou si le chemin n'est pas le chemin cible, ajouter la classe immédiatement\n if (!isFirstLoad || !isTargetPath) {\n header.classList.add('header--collapsed-already');\n // logo.classList.remove('animated');\n stopLogoAnimation();\n } else {\n // Sinon, appliquer la transition après un délai\n setTimeout(() => {\n header.classList.add('header--collapsed');\n }, 5000);\n }\n\n //////////////////////////////////////\n\n let lastScrollTop = 0;\n let threshold = 100; // Change this value as needed\n let isHidden = false;\n \n function slideOut() {\n headerNavContainer.animate([\n { transform: 'translateX(0)' },\n { transform: 'translateX(-100%)' }\n ], {\n duration: 300,\n fill: 'forwards'\n });\n isHidden = true;\n }\n \n function slideIn() {\n headerNavContainer.animate([\n { transform: 'translateX(-100%)' },\n { transform: 'translateX(0)' }\n ], {\n duration: 300,\n fill: 'forwards'\n });\n isHidden = false;\n }\n \n function slideDown() {\n // headerNavContainer.style.display = 'block';\n headerNavContainer.animate([\n { transform: 'translateY(0%)' },\n { transform: 'translateY(+100%)' }\n ], {\n duration: 300,\n fill: 'forwards'\n });\n isHidden = false;\n }\n \n function slideUp() {\n headerNavContainer.animate([\n { transform: 'translateY(100%)' },\n { transform: 'translateY(0%)' }\n ], {\n duration: 300,\n fill: 'forwards'\n }).onfinish = function() {\n // headerNavContainer.style.display = 'none';\n };\n isHidden = true;\n }\n // Fonction pour ajuster la hauteur du header lors du défilement\n function adjustHeaderHeight() {\n if (window.scrollY > 0) {\n header.classList.add('shrink');\n } else {\n header.classList.remove('shrink');\n }\n }\n\n function handleScroll() {\n let scrollTop = window.pageYOffset || document.documentElement.scrollTop;\n const isMobile = window.innerWidth < 811;\n\n if (scrollTop > threshold && !isHidden) {\n if (isMobile) {\n slideUp();\n } else {\n slideOut();\n }\n } else if (scrollTop <= threshold && isHidden) {\n if (isMobile) {\n slideDown();\n } else {\n slideIn();\n }\n }\n \n \n lastScrollTop = scrollTop <= 0 ? 0 : scrollTop; // For Mobile or negative scrolling\n }\n \n function handleTouchAndMouseEnter() {\n if (isHidden) {\n if (window.innerWidth < 811) {\n slideDown();\n } else {\n slideIn();\n }\n }\n }\n \n function handleTouchAndMouseLeave() {\n if (lastScrollTop > threshold && !isHidden) {\n if (window.innerWidth < 811) {\n slideUp();\n } else {\n slideOut();\n }\n }\n }\n \n window.addEventListener('scroll', handleScroll);\n window.addEventListener('scroll', adjustHeaderHeight);\n \n // Mouse events for desktop\n header.addEventListener('mouseenter', handleTouchAndMouseEnter);\n header.addEventListener('mouseleave', handleTouchAndMouseLeave);\n \n // Touch events for tablets and mobile devices\n header.addEventListener('touchstart', handleTouchAndMouseEnter);\n header.addEventListener('touchend', handleTouchAndMouseLeave);\n \n // Initial check to see if we're at the top of the page\n if (window.pageYOffset <= threshold) {\n if (window.innerWidth < 811) {\n slideDown();\n } else { \n slideIn();\n } \n } else {\n if (window.innerWidth < 811) {\n slideUp();\n } else {\n slideIn();\n }\n }\n \n });\n\n//////// end header ////////////\n \n\n\n//// ancre dans texte au click paragraphe correspondant arrive en dessous du header \n\n\n(function($, window) {\n var adjustAnchor = function() {\n var $anchor = $('.sidebar_first_container'),\n fixedElementHeight = 500;\n if ($anchor.length > 0) {\n $('html, body').stop().animate({scrollTop: $anchor.offset().top - fixedElementHeight }, 0);\n }\n };\n\n $(window).on('hashchange', function() {\n adjustAnchor();\n });\n\n\n //////////////////////// start script smooth apparition des textes /////////////////\n\n function scrollReaveal(){\n\n const nodes = {\n logo : document.querySelectorAll('#logo-animated-container'),\n chapeau : document.querySelectorAll('.field_body'),\n paragraph: document.querySelectorAll('.field_field_textes .paragraph--type--static-parts'),\n enjeux : document.querySelectorAll('.field_field_textes .paragraph--type--static-parts .enjeux'),\n // mapHome : document.querySelectorAll('.field_field_map_block #block-sitesmapblock'),\n // mapSite : document.querySelectorAll('#sites-map-container'),\n lienDoc : document.querySelectorAll('.field_field_documents'),\n lienURL : document.querySelectorAll('.field_field_liens_site'),\n }\n\n const showUp = {\n origin: 'bottom',\n delay: 100,\n duration: 1000,\n distance: '50px',\n easing: 'cubic-bezier(0.5, 0, 0, 1)'\n }\n\n const Show = {\n delay: 100,\n duration: 600,\n easing: 'cubic-bezier(0.5, 0, 0, 1)'\n }\n\n console.log(nodes);\n\n ScrollReveal().reveal(nodes.logo, Show);\n ScrollReveal().reveal(nodes.chapeau, showUp);\n ScrollReveal().reveal(nodes.paragraph, showUp);\n ScrollReveal().reveal(nodes.enjeux, showUp);\n // ScrollReveal().reveal(nodes.mapHome, showUp);\n // ScrollReveal().reveal(nodes.mapSite, showUp);\n ScrollReveal().reveal(nodes.lienDoc, showUp);\n ScrollReveal().reveal(nodes.lienURL, showUp);\n\n }\n\n\n $( document ).ready(function() {\n scrollReaveal();\n });\n\n //////////////////////// end script smooth apparition des textes /////////////////\n\n // //////////////////// start Timeline script ///////////////////////\n\n // Update month field to only show the first 3 letters\n document.querySelectorAll('.paragraph--type--phase-deroulement').forEach(function(paragraph) {\n const monthField = paragraph.querySelector('.field_field_date_de_moi div:nth-of-type(2)');\n if (monthField) {\n const monthText = monthField.textContent.trim();\n if (monthText === \"juillet\") {\n monthField.textContent = monthText.slice(0, 4);\n monthField.classList.add('after');\n } else if (monthText === \"juin\") {\n monthField.textContent = monthText.slice(0, 4);\n } else if (monthText.length > 3) {\n monthField.textContent = monthText.slice(0, 3);\n monthField.classList.add('after');\n }\n }\n });\n \n // Fonction pour ajouter ou retirer la classe .only\n function updateDateClasses() {\n document.querySelectorAll('.paragraph--type--phase-deroulement .date').forEach(function(dateElement) {\n const date2Element = dateElement.querySelector('.date2');\n const yearElement = dateElement.querySelector('.field_field_date_de_annee');\n \n if (date2Element && !date2Element.textContent.trim()) {\n if (yearElement) {\n yearElement.classList.add('only');\n }\n } else {\n if (yearElement) {\n yearElement.classList.remove('only');\n }\n }\n });\n }\n \n // Exécuter la fonction une première fois pour le contenu déjà présent\n updateDateClasses();\n \n // MutationObserver pour surveiller les changements dans le DOM\n const observer = new MutationObserver(function(mutationsList, observer) {\n for(let mutation of mutationsList) {\n if (mutation.type === 'childList') {\n updateDateClasses();\n }\n }\n });\n\n\n // ////////////////////// start calendrier home /////////////////////////////////\n $(document).ready(function(){\n $('.__timeline-content').slick({\n slidesToShow: 3,\n slidesToScroll: 1,\n dots: false,\n arrows: true,\n centerMode: false,\n draggable: true,\n infinite: false,\n responsive: [\n {\n breakpoint: 810,\n settings: {\n slidesToShow: 1,\n adaptiveHeight: false,\n arrows: true,\n draggable: true,\n centerMode: false,\n infinite: false,\n }\n }]\n });\n console.log('salut slick calendrier');\n \n });\n \n //////////////////////// end calendrier home /////////////////////////////////\n \n \n\n //////////////////////// end Timeline script /////////////////////////////////////////////\n\n /////////////////// caracteres body actus/////////////////////////\n\n document.addEventListener('DOMContentLoaded', function() {\n // Nombre maximum de caractères à afficher\n const maxChars = 140; // Ajustez cette valeur selon vos besoins\n\n document.querySelectorAll('#actus-caroussel .node-type-actualite').forEach(function(node) {\n let paragraphs = node.querySelectorAll('.field_body p');\n let fullText = \"\";\n \n // Concaténer tous les paragraphes\n paragraphs.forEach(p => fullText += p.textContent.trim() + \" \");\n fullText = fullText.trim();\n\n // Vérifier si le texte dépasse la limite\n if (fullText.length > maxChars) {\n let truncatedText = fullText.slice(0, maxChars) + '...';\n\n // Vider tout le contenu et insérer seulement le texte tronqué\n let firstParagraph = paragraphs[0];\n firstParagraph.textContent = truncatedText;\n\n // Masquer les autres paragraphes\n for (let i = 1; i < paragraphs.length; i++) {\n paragraphs[i].style.display = \"none\";\n }\n }\n });\n });\n\n \n\n //////////// start slideshow home ////////////////////////// \n\n\n\n $(document).ready(function(){\n let actuview = $('.content-actus .view ')\n if (actuview) {\n actuview.slick({\n slidesToShow: 3,\n // slidesToScroll: 1,\n dots: false,\n arrows: true,\n // centerMode: true,\n adaptiveHeight: false,\n autoplay: false,\n // autoplaySpeed: 1500,\n // infinite: true,\n // centerPadding: '100px',\n responsive: [\n {\n breakpoint: 810,\n settings: {\n slidesToShow: 1,\n // slidesToScroll: 1,\n adaptiveHeight: false,\n arrows: true,\n draggable: true,\n // centerMode: true,\n // centerPadding: '100px',\n autoplay: false,\n // autoplaySpeed: 2000,\n }\n }]\n });\n console.log('salut slick home');\n \n }\n $('.slick-carousel').slick({\n lazyLoad: 'progressive', // Option 'ondemand' ou 'progressive'\n });\n\n });\n\n\n\n\n $(document).ready(function () {\n let diapohome = $('.config_pages--type--diaporama-home .diaporama');\n\n if (diapohome.length) {\n // Initialisation de Slick\n diapohome.slick({\n slidesToShow: 1,\n dots: false,\n arrows: false,\n // centerMode: true,\n adaptiveHeight: false,\n autoplay: true, // Activer l'autoplay\n autoplaySpeed: 4000, // Changement de slide toutes les 4 secondes\n // infinite: true,\n pauseOnHover: false, // Ne pas arrêter l'autoplay lors du survol\n pauseOnFocus: false,\n responsive: [\n {\n breakpoint: 810,\n settings: {\n slidesToShow: 1,\n adaptiveHeight: false,\n arrows: false,\n draggable: true,\n centerMode: false,\n }\n }]\n });\n\n }\n});\n\n //////////// end slideshow home ////////////////////////// \n\n//////////////// start lightbox galerie image page site////////////////////////\n\n// Sélection des images et de leurs légendes dans la galerie\nlet images = document.querySelectorAll('.paragraph--type--site-diapo .lightbox-trigger');\nlet currentIndex;\n\n// Création de la lightbox et de ses éléments\nconst lightbox = document.createElement('div');\nlightbox.id = 'lightbox';\nlightbox.classList.add('lightbox');\ndocument.body.appendChild(lightbox);\n\nconst img = document.createElement('img');\nlightbox.appendChild(img);\n\n// Élément pour afficher la légende\nconst caption = document.createElement('p');\ncaption.classList.add('caption');\nlightbox.appendChild(caption);\n\nconst closeBtn = document.createElement('span');\ncloseBtn.classList.add('close');\ncloseBtn.innerHTML = '×';\nlightbox.appendChild(closeBtn);\n\nconst prevBtn = document.createElement('a');\nprevBtn.classList.add('prev');\nprevBtn.innerHTML = '❮';\nlightbox.appendChild(prevBtn);\n\nconst nextBtn = document.createElement('a');\nnextBtn.classList.add('next');\nnextBtn.innerHTML = '❯';\nlightbox.appendChild(nextBtn);\n\n// Fonction pour afficher l'image et la légende à l'index donné\nfunction showImage(index) {\n if (index < 0) index = images.length - 1;\n if (index >= images.length) index = 0;\n currentIndex = index;\n\n // Mettre à jour l'image\n img.src = images[currentIndex].getAttribute('src');\n\n // Récupérer la légende associée (le paragraphe dans blockquote suivant l'image)\n const captionText = images[currentIndex]\n .closest('.cadre-img-zoom')\n .nextElementSibling.querySelector('.image-field-caption p')\n .textContent;\n \n caption.textContent = captionText || ''; // Affiche la légende ou une chaîne vide si elle est absente\n lightbox.style.display = 'flex';\n}\n\n// Événements de clic sur chaque image pour ouvrir le lightbox avec la légende\nimages.forEach((image, index) => {\n image.addEventListener('click', () => {\n showImage(index);\n });\n});\n\n// Fermer le lightbox\ncloseBtn.addEventListener('click', () => {\n lightbox.style.display = 'none';\n});\n\n// Navigation pour images précédente et suivante\nprevBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n showImage(currentIndex - 1);\n});\n\nnextBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n showImage(currentIndex + 1);\n});\n\n// Fermer le lightbox en cliquant en dehors de l'image\nlightbox.addEventListener('click', (e) => {\n if (e.target === lightbox) {\n lightbox.style.display = 'none';\n }\n});\n\n// Ajout des contrôles clavier (Échap, flèches gauche/droite)\ndocument.addEventListener('keydown', (e) => {\n if (lightbox.style.display === 'flex') {\n if (e.key === 'Escape') {\n lightbox.style.display = 'none';\n } else if (e.key === 'ArrowLeft') {\n showImage(currentIndex - 1);\n } else if (e.key === 'ArrowRight') {\n showImage(currentIndex + 1);\n }\n }\n});\n\n\n//////////////// end lightbox galerie image page site////////////////////////\n\n \n\n//////////////////// start wrapper views-row lessites /////////////////////////\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n // Sélectionne le conteneur principal avec l'ID 'lessites'\n const container = document.getElementById(\"lessites\");\n\n // Vérifie si le conteneur existe pour éviter toute erreur sur d'autres pages\n if (container) {\n // Sélectionne l'élément 'view' à l'intérieur de '.views-element-container'\n const viewContainer = container.querySelector(\".views-element-container .view\");\n\n // Vérifie si 'viewContainer' existe pour éviter les erreurs\n if (viewContainer) {\n // Crée une div englobante pour tous les éléments 'views-row'\n const wrapperDiv = document.createElement(\"div\");\n wrapperDiv.classList.add(\"views-row-wrapper\"); // ajoute une classe pour faciliter le style CSS\n\n // Déplace tous les éléments 'views-row' dans la nouvelle div\n const viewsRows = viewContainer.querySelectorAll(\".views-row\");\n viewsRows.forEach(row => wrapperDiv.appendChild(row));\n\n // Ajoute la div englobante dans le 'viewContainer'\n viewContainer.appendChild(wrapperDiv);\n }\n }\n});\n\n\n//////////////////// end wrapper views-row lessites /////////////////////////\n\n\n\n//////////////////// start div infos site ////////////////////////\n\n// Vérifie si la page a la classe 'node-type-site' dans le \nif (document.body.classList.contains('node-type-site')) {\n // Sélectionne le conteneur principal\n const blockRegion = document.querySelector('.block-region-second');\n\n // Liste des classes spécifiques à cibler\n const fieldClasses = [\n '.field_field_region',\n '.field_field_nom_du_qpv_nb_d_hab',\n '.field_field_departement_s',\n '.field_field_programme_de_l_etat',\n '.field_field_porteur_s_de_site',\n '.field_field_nom_de_la_commune_nb_d_hab'\n ];\n\n // Sélectionne les div parents de chacun des champs listés\n const elementsToWrap = [];\n fieldClasses.forEach(className => {\n const fieldElement = blockRegion.querySelector(className);\n if (fieldElement) {\n // Ajoute le parent du champ au tableau si trouvé\n elementsToWrap.push(fieldElement.parentElement);\n }\n });\n\n // Vérifie que des éléments ont été trouvés\n if (elementsToWrap.length > 0) {\n // Crée le conteneur avec la classe 'infos'\n const infosContainer = document.createElement('div');\n infosContainer.className = 'infos';\n\n // Insère le conteneur `.infos` avant le premier élément ciblé\n const firstElement = elementsToWrap[0];\n blockRegion.insertBefore(infosContainer, firstElement);\n\n // Déplace chaque élément dans le conteneur `.infos`\n elementsToWrap.forEach(element => infosContainer.appendChild(element));\n }\n}\n//////////////////// end div infos site ////////////////////////\n\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n // Sélectionner les éléments à déplacer\n const documentsField = document.querySelector(\".field_field_documents\");\n const liensSiteField = document.querySelector(\".field_field_liens_site\");\n \n // Sélectionner la destination\n const thirdRegion = document.querySelector(\".block-region-third > div\");\n\n // Créer une nouvelle div pour englober les éléments déplacés\n const wrapperDiv = document.createElement(\"div\");\n wrapperDiv.classList.add(\"documents-liens-wrapper\");\n\n // Déplacer les éléments dans la nouvelle div\n if (documentsField && liensSiteField && thirdRegion) {\n wrapperDiv.appendChild(documentsField);\n wrapperDiv.appendChild(liensSiteField);\n\n // Ajouter la nouvelle div dans la destination\n thirdRegion.appendChild(wrapperDiv);\n }\n});\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n // Sélectionner les éléments pertinents\n const documentsLiensWrapper = document.querySelector(\".documents-liens-wrapper\");\n const blockRegionThird = document.querySelector(\".block-region-third\");\n\n // Vérifier que les éléments existent avant de les manipuler\n if (documentsLiensWrapper && blockRegionThird) {\n // Déplacer .documents-liens-wrapper en dehors du div contenant les boutons prev/next\n blockRegionThird.appendChild(documentsLiensWrapper);\n }\n});\n\n\ndocument.addEventListener(\"DOMContentLoaded\", function () {\n // Fonction pour déplacer le bloc en fonction de la taille de l'écran\n function moveLanguageSwitcher() {\n const languageSwitcher = document.getElementById(\"block-quartiers-de-demain-selecteurdelangue\");\n const navContainer = document.querySelector(\".header_nav_container\");\n\n if (window.innerWidth <= 810) { // Si écran téléphone\n if (languageSwitcher && navContainer && !navContainer.contains(languageSwitcher)) {\n navContainer.appendChild(languageSwitcher); // Déplace le bloc dans header_nav_container\n }\n } else { // Si écran non téléphone\n const headerRightContainer = document.querySelector(\".header_right_container\");\n if (languageSwitcher && headerRightContainer && !headerRightContainer.contains(languageSwitcher)) {\n headerRightContainer.appendChild(languageSwitcher); // Remet le bloc dans sa position initiale\n }\n }\n }\n\n // Déclencher au chargement et au redimensionnement\n moveLanguageSwitcher();\n window.addEventListener(\"resize\", moveLanguageSwitcher);\n});\n\n\n//////////////////////////////////////////\n\n\n/////////// Start script ressources ////////////////////////////////\n\ndocument.addEventListener(\"DOMContentLoaded\", () => {\n const view = document.querySelector(\".view\");\n const elements = Array.from(view.children);\n\n let newView = document.createElement(\"div\");\n newView.classList.add(\"view\");\n\n let group = null;\n let groupContent = null;\n\n elements.forEach((el) => {\n if (el.tagName === \"H3\") {\n if (group) {\n newView.appendChild(group);\n }\n\n group = document.createElement(\"div\");\n group.classList.add(\"group\");\n\n groupContent = document.createElement(\"div\");\n groupContent.classList.add(\"group-content\");\n\n groupContent.appendChild(el);\n group.appendChild(groupContent);\n } else if (el.classList.contains(\"views-row\")) {\n groupContent.appendChild(el);\n }\n });\n\n if (group) {\n newView.appendChild(group);\n }\n\n view.replaceWith(newView);\n\n // Ajouter un bouton \"Voir plus\" dans chaque groupe\n document.querySelectorAll(\".group\").forEach((group) => {\n const rows = group.querySelectorAll(\".views-row\");\n const button = document.createElement(\"button\");\n button.classList.add(\"toggle-btn\");\n button.textContent = \"Voir plus de\";\n\n rows.forEach((row, index) => {\n if (index >= 3) {\n row.classList.add(\"hidden\");\n row.style.maxHeight = \"0\";\n row.style.opacity = \"0\";\n }\n });\n\n button.addEventListener(\"click\", () => {\n const isExpanded = button.textContent === \"Voir moins de\";\n const hiddenRows = group.querySelectorAll(\".views-row.hidden\");\n\n if (isExpanded) {\n // Cacher les lignes avec un délai pour l'effet de transition\n hiddenRows.forEach((row) => {\n row.style.maxHeight = \"0\";\n row.style.opacity = \"0\";\n setTimeout(() => row.classList.add(\"hidden\"), 500); // Délai pour la transition\n });\n } else {\n // Afficher les lignes\n hiddenRows.forEach((row) => {\n row.classList.remove(\"hidden\");\n row.style.maxHeight = row.scrollHeight + \"px\";\n row.style.opacity = \"1\";\n });\n }\n\n button.textContent = isExpanded ? \"Voir plus de\" : \"Voir moins de\";\n });\n\n group.appendChild(button);\n });\n});\n\n\n/////////// end script ressources ////////////////////////////////\n\n})(jQuery, window);\n\n\n\n\n//# sourceURL=webpack://quartiers_de_demain/./src/assets/js/quartiers_de_demain.js?"); /***/ }) diff --git a/web/themes/custom/quartiers_de_demain/dist/assets/css/bundle.css b/web/themes/custom/quartiers_de_demain/dist/assets/css/bundle.css index d3f4fe3..a66d50b 100644 --- a/web/themes/custom/quartiers_de_demain/dist/assets/css/bundle.css +++ b/web/themes/custom/quartiers_de_demain/dist/assets/css/bundle.css @@ -1498,7 +1498,6 @@ footer { display: flex; flex-direction: column; align-items: center; - padding-bottom: 4rem; } #actus-caroussel h2 { width: fit-content; @@ -1512,6 +1511,9 @@ footer { #actus-caroussel button { top: -2.5rem; } +#actus-caroussel .content-actus .slick-list { + padding-bottom: 4rem; +} #actus-caroussel .content-actus .view { display: flex; flex-direction: row; @@ -1527,11 +1529,14 @@ footer { padding-top: 3rem; } } -#actus-caroussel .content-actus .views-row article.node-type-actualite { +#actus-caroussel .content-actus .views-row article.node-type-actualite a { display: flex; flex-direction: column; } -#actus-caroussel .content-actus .views-row article.node-type-actualite .field_field_images { +#actus-caroussel .content-actus .views-row article.node-type-actualite a h2 { + display: none; +} +#actus-caroussel .content-actus .views-row article.node-type-actualite a .field_field_images { order: 1; background-color: black; -moz-border-radius: 9px; /* pour Mozilla */ @@ -1542,18 +1547,18 @@ footer { margin-bottom: 0.6rem; } @media (max-width: 550px) { - #actus-caroussel .content-actus .views-row article.node-type-actualite .field_field_images { + #actus-caroussel .content-actus .views-row article.node-type-actualite a .field_field_images { height: 170px; } } -#actus-caroussel .content-actus .views-row article.node-type-actualite .field_field_images div { +#actus-caroussel .content-actus .views-row article.node-type-actualite a .field_field_images div { height: 100%; } -#actus-caroussel .content-actus .views-row article.node-type-actualite .field_field_images div div a { +#actus-caroussel .content-actus .views-row article.node-type-actualite a .field_field_images div div a { display: block; height: 100%; } -#actus-caroussel .content-actus .views-row article.node-type-actualite .field_field_images div div a img { +#actus-caroussel .content-actus .views-row article.node-type-actualite a .field_field_images div div a img { width: 100%; height: 100%; object-fit: cover; @@ -1563,11 +1568,11 @@ footer { border-radius: 9px; /* CSS3 */ } @media (max-width: 550px) { - #actus-caroussel .content-actus .views-row article.node-type-actualite .field_field_images div div a img { + #actus-caroussel .content-actus .views-row article.node-type-actualite a .field_field_images div div a img { max-height: 170px; } } -#actus-caroussel .content-actus .views-row article.node-type-actualite .field_field_images img { +#actus-caroussel .content-actus .views-row article.node-type-actualite a .field_field_images img { width: 100%; height: 100%; object-fit: cover; @@ -1577,11 +1582,11 @@ footer { border-radius: 9px; /* CSS3 */ } @media (max-width: 550px) { - #actus-caroussel .content-actus .views-row article.node-type-actualite .field_field_images img { + #actus-caroussel .content-actus .views-row article.node-type-actualite a .field_field_images img { max-height: 170px; } } -#actus-caroussel .content-actus .views-row article.node-type-actualite .field_field_type_d_actualite { +#actus-caroussel .content-actus .views-row article.node-type-actualite a .field_field_type_d_actualite { text-transform: uppercase; color: red; font-size: 0.5rem; @@ -1589,51 +1594,81 @@ footer { display: inline-flex; align-items: center; } -#actus-caroussel .content-actus .views-row article.node-type-actualite .field_field_type_d_actualite::before { +#actus-caroussel .content-actus .views-row article.node-type-actualite a .field_field_type_d_actualite::before { content: url("../img/type-actu.svg"); padding-right: 0.3rem; padding-bottom: 0.2rem; } -#actus-caroussel .content-actus .views-row article.node-type-actualite .infos-actu { +#actus-caroussel .content-actus .views-row article.node-type-actualite a .infos-actu { order: 2; } -#actus-caroussel .content-actus .views-row article.node-type-actualite .field_field_date { +#actus-caroussel .content-actus .views-row article.node-type-actualite a .infos-actu h2 { + font-family: "gilroy-semibold"; +} +#actus-caroussel .content-actus .views-row article.node-type-actualite a .field_field_date { color: red; display: inline-flex; align-items: center; font-size: 0.5rem; font-family: "gilroy-bold"; } -#actus-caroussel .content-actus .views-row article.node-type-actualite .field_field_date::before { +#actus-caroussel .content-actus .views-row article.node-type-actualite a .field_field_date::before { content: url("../img/date-actu.svg"); padding-right: 0.3rem; } -#actus-caroussel .content-actus .views-row article.node-type-actualite .field_title { +#actus-caroussel .content-actus .views-row article.node-type-actualite a .field_title { order: 3; padding-top: 0.2rem; } -#actus-caroussel .content-actus .views-row article.node-type-actualite .field_title h2 { +#actus-caroussel .content-actus .views-row article.node-type-actualite a .field_title h2 { margin: 0; line-height: 0.4; padding-bottom: 0.6rem; } -#actus-caroussel .content-actus .views-row article.node-type-actualite .field_title h2 a { +#actus-caroussel .content-actus .views-row article.node-type-actualite a .field_title h2 a { font-size: 0.8rem; color: rgb(7, 50, 194); } -#actus-caroussel .content-actus .views-row article.node-type-actualite .field_body { +#actus-caroussel .content-actus .views-row article.node-type-actualite a .field_body { order: 4; opacity: 1 !important; transform: none !important; font-family: "gilroy-regular"; } -#actus-caroussel .content-actus .views-row article.node-type-actualite .field_body p { +#actus-caroussel .content-actus .views-row article.node-type-actualite a .field_body p { margin: 0; margin-bottom: 1rem; font-size: 0.7rem; } -#actus-caroussel .content-actus .views-row article.node-type-actualite .field_field_liens { +#actus-caroussel .content-actus .views-row article.node-type-actualite a .field_body a { + color: rgb(7, 50, 194); +} +#actus-caroussel .content-actus .views-row article.node-type-actualite a .field_field_liens { order: 5; + width: fit-content; + padding-left: 0.5rem; + background: black; +} +@media (max-width: 810px) { + #actus-caroussel .content-actus .views-row article.node-type-actualite a .field_field_liens { + margin-left: 0; + } +} +#actus-caroussel .content-actus .views-row article.node-type-actualite a .field_field_liens a { + display: inline-flex; + align-items: center; + color: white; + text-transform: uppercase; + font-size: 0.6rem; +} +#actus-caroussel .content-actus .views-row article.node-type-actualite a .field_field_liens a svg { + display: none; +} +#actus-caroussel .content-actus .views-row article.node-type-actualite a .field_field_liens a::after { + display: inline-flex; + content: url("../img/noun-arrow-to-right.svg"); + padding-right: 0.2rem; + padding-left: 0.2rem; } #actus-caroussel .content-actus .views-row:nth-child(odd) { position: relative; diff --git a/web/themes/custom/quartiers_de_demain/src/assets/js/quartiers_de_demain.js b/web/themes/custom/quartiers_de_demain/src/assets/js/quartiers_de_demain.js index a4dfe95..5b5dff8 100644 --- a/web/themes/custom/quartiers_de_demain/src/assets/js/quartiers_de_demain.js +++ b/web/themes/custom/quartiers_de_demain/src/assets/js/quartiers_de_demain.js @@ -357,33 +357,33 @@ /////////////////// caracteres body actus///////////////////////// - // document.addEventListener('DOMContentLoaded', function() { - // // Nombre maximum de caractères à afficher - // const maxChars = 140; // Ajustez cette valeur selon vos besoins + document.addEventListener('DOMContentLoaded', function() { + // Nombre maximum de caractères à afficher + const maxChars = 140; // Ajustez cette valeur selon vos besoins - // document.querySelectorAll('#actus-caroussel .node-type-actualite').forEach(function(node) { - // let paragraphs = node.querySelectorAll('.field_body p'); - // let fullText = ""; + document.querySelectorAll('#actus-caroussel .node-type-actualite').forEach(function(node) { + let paragraphs = node.querySelectorAll('.field_body p'); + let fullText = ""; - // // Concaténer tous les paragraphes - // paragraphs.forEach(p => fullText += p.textContent.trim() + " "); - // fullText = fullText.trim(); + // Concaténer tous les paragraphes + paragraphs.forEach(p => fullText += p.textContent.trim() + " "); + fullText = fullText.trim(); - // // Vérifier si le texte dépasse la limite - // if (fullText.length > maxChars) { - // let truncatedText = fullText.slice(0, maxChars) + '...'; + // Vérifier si le texte dépasse la limite + if (fullText.length > maxChars) { + let truncatedText = fullText.slice(0, maxChars) + '...'; - // // Vider tout le contenu et insérer seulement le texte tronqué - // let firstParagraph = paragraphs[0]; - // firstParagraph.textContent = truncatedText; + // Vider tout le contenu et insérer seulement le texte tronqué + let firstParagraph = paragraphs[0]; + firstParagraph.textContent = truncatedText; - // // Masquer les autres paragraphes - // for (let i = 1; i < paragraphs.length; i++) { - // paragraphs[i].style.display = "none"; - // } - // } - // }); - // }); + // Masquer les autres paragraphes + for (let i = 1; i < paragraphs.length; i++) { + paragraphs[i].style.display = "none"; + } + } + }); + }); diff --git a/web/themes/custom/quartiers_de_demain/src/assets/scss/partials/actu-caroussel-home.scss b/web/themes/custom/quartiers_de_demain/src/assets/scss/partials/actu-caroussel-home.scss index fd2869c..f8ad2f8 100644 --- a/web/themes/custom/quartiers_de_demain/src/assets/scss/partials/actu-caroussel-home.scss +++ b/web/themes/custom/quartiers_de_demain/src/assets/scss/partials/actu-caroussel-home.scss @@ -2,7 +2,7 @@ display: flex; flex-direction: column; align-items: center; - padding-bottom: 4rem; + // padding-bottom: 4rem; h2{ width: fit-content; @@ -18,6 +18,9 @@ top: -2.5rem; } .content-actus{ + .slick-list{ + padding-bottom: 4rem; + } .view{ display: flex; flex-direction: row; @@ -33,8 +36,12 @@ padding-top: 3rem; } article.node-type-actualite{ + a{ display: flex; flex-direction: column; + h2{ + display: none; + } .field_field_images{ order: 1; background-color: black; @@ -100,6 +107,9 @@ } .infos-actu{ order: 2; + h2{ + font-family: 'gilroy-semibold'; + } } .field_field_date{ @@ -140,11 +150,42 @@ margin-bottom: 1rem; font-size: 0.7rem ; } + a{ + color: $blue_QDD; + } } .field_field_liens{ order: 5; + width: fit-content; + padding-left: 0.5rem; + // padding-bottom: 0.2rem; + // padding-top: 0.2rem; + background: black; + @media (max-width:810px) { + margin-left: 0; + } + + a{ + display: inline-flex; + align-items: center; + color: white; + text-transform: uppercase; + font-size: 0.6rem; + + svg{ + display: none; + } + &::after{ + display: inline-flex; + content: url("../img/noun-arrow-to-right.svg"); + padding-right: 0.2rem; + padding-left: 0.2rem; + // padding-bottom: 0.2rem; + } + } } } + } } .views-row:nth-child(odd){ diff --git a/web/themes/custom/quartiers_de_demain/templates/node--actualite.html.twig b/web/themes/custom/quartiers_de_demain/templates/node--actualite.html.twig index baa414b..7394958 100644 --- a/web/themes/custom/quartiers_de_demain/templates/node--actualite.html.twig +++ b/web/themes/custom/quartiers_de_demain/templates/node--actualite.html.twig @@ -93,19 +93,20 @@ {# #} {% block content %} - +{{ label }} +{{content.field_images}}
{{content.field_type_d_actualite}} {{content.field_date}}
-
{{ label }} + {{content.body}} - {{content.field_liens}} - {{content.field_images}} - {{content.field_title}} - + {{content.field_liens}} + + + {% endblock %} From 5eceec0083e8e03cbb9efc52d8d59842489cb137 Mon Sep 17 00:00:00 2001 From: bach Date: Mon, 3 Mar 2025 18:38:03 +0100 Subject: [PATCH 19/22] alias url --- ...nt_settings.block_content.live_youtube.yml | 11 ++++++++++ config/sync/pathauto.pattern.actus.yml | 22 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 config/sync/language.content_settings.block_content.live_youtube.yml create mode 100644 config/sync/pathauto.pattern.actus.yml diff --git a/config/sync/language.content_settings.block_content.live_youtube.yml b/config/sync/language.content_settings.block_content.live_youtube.yml new file mode 100644 index 0000000..89bb8f0 --- /dev/null +++ b/config/sync/language.content_settings.block_content.live_youtube.yml @@ -0,0 +1,11 @@ +uuid: 0be47de1-35a4-49f3-ae07-99b77c62db51 +langcode: fr +status: true +dependencies: + config: + - block_content.type.live_youtube +id: block_content.live_youtube +target_entity_type_id: block_content +target_bundle: live_youtube +default_langcode: site_default +language_alterable: false diff --git a/config/sync/pathauto.pattern.actus.yml b/config/sync/pathauto.pattern.actus.yml new file mode 100644 index 0000000..9f9b967 --- /dev/null +++ b/config/sync/pathauto.pattern.actus.yml @@ -0,0 +1,22 @@ +uuid: b4825987-4cfe-4342-a7d0-29d190fd71b3 +langcode: fr +status: true +dependencies: + module: + - node +id: actus +label: Actus +type: 'canonical_entities:node' +pattern: '/actualites/[node:title]' +selection_criteria: + ae8c556c-ba96-4e19-87c1-46ee3c9639d4: + id: 'entity_bundle:node' + negate: false + uuid: ae8c556c-ba96-4e19-87c1-46ee3c9639d4 + context_mapping: + node: node + bundles: + actualite: actualite +selection_logic: and +weight: -5 +relationships: { } From 4aaa3f90c5d71b2af09d7f6d1981592d4cd2017e Mon Sep 17 00:00:00 2001 From: ouidade Date: Mon, 3 Mar 2025 22:20:11 +0100 Subject: [PATCH 20/22] fix tamporaire bug actu carroussel =responsive --- .../dist/assets/css/bundle.css | 40 ++++-- ...s-original.svg => formes-animees-live.svg} | 0 .../dist/assets/img/rect4.svg | 129 ++++++++++++++++++ .../src/assets/scss/global/_layout.scss | 2 +- .../src/assets/scss/pages/actualite.scss | 10 ++ .../scss/partials/actu-caroussel-home.scss | 6 + .../src/assets/scss/partials/header.scss | 13 +- .../templates/node--actualite.html.twig | 15 +- 8 files changed, 193 insertions(+), 22 deletions(-) rename web/themes/custom/quartiers_de_demain/dist/assets/img/{formes-animees-original.svg => formes-animees-live.svg} (100%) create mode 100644 web/themes/custom/quartiers_de_demain/dist/assets/img/rect4.svg diff --git a/web/themes/custom/quartiers_de_demain/dist/assets/css/bundle.css b/web/themes/custom/quartiers_de_demain/dist/assets/css/bundle.css index a66d50b..488ee37 100644 --- a/web/themes/custom/quartiers_de_demain/dist/assets/css/bundle.css +++ b/web/themes/custom/quartiers_de_demain/dist/assets/css/bundle.css @@ -202,7 +202,7 @@ h2, h3 { } @media (max-width: 810px) { .layout-container main#home { - padding-top: 380px; + padding-top: 300px; } } @media (max-width: 810px) { @@ -432,17 +432,17 @@ header .header_nav_container { transform: translateX(0); transition: transform 0.3s ease-in-out; z-index: -1; -} -@media (max-width: 1090px) { - header .header_nav_container { - height: fit-content; - } + display: flex; + flex-direction: column; } @media (max-width: 500px) { header .header_nav_container { flex: 0 0 40%; } } +header .header_nav_container #block-quartiers-de-demain-entete { + margin: auto; +} header .header_nav_container #block-quartiers-de-demain-entete h2 { display: none; } @@ -564,7 +564,6 @@ header .header:hover + .header_nav_container { flex: 1 0 100%; position: relative; left: -100%; - top: -45px; } } @@ -607,7 +606,11 @@ header .header:hover + .header_nav_container { flex: 1 0 100%; position: relative; left: -100%; - top: -75px; + } +} +@media (max-width: 550px) { + .header--collapsed-already .header_nav_container { + top: 0px; } } @@ -1511,9 +1514,19 @@ footer { #actus-caroussel button { top: -2.5rem; } +@media (max-width: 810px) { + #actus-caroussel button { + top: -1.5rem; + } +} #actus-caroussel .content-actus .slick-list { padding-bottom: 4rem; } +@media (max-width: 810px) { + #actus-caroussel .content-actus .slick-list { + padding-bottom: 0rem; + } +} #actus-caroussel .content-actus .view { display: flex; flex-direction: row; @@ -3171,8 +3184,11 @@ body { #page-node .content_container .node-type-actualite { width: 100%; padding-bottom: 7rem; + display: flex; + flex-direction: column; } #page-node .content_container .node-type-actualite .infos-actu { + order: 1; display: flex; flex-direction: row; border-top: solid red 1px; @@ -3203,12 +3219,14 @@ body { padding-right: 0.4rem; } #page-node .content_container .node-type-actualite .field_body { + order: 2; padding-bottom: 2rem; } #page-node .content_container .node-type-actualite .field_body p { font-size: 0.8rem; } #page-node .content_container .node-type-actualite .field_field_liens { + order: 3; padding-bottom: 2rem; } #page-node .content_container .node-type-actualite .field_field_liens a { @@ -3229,6 +3247,12 @@ body { padding-right: 0.2rem; padding-left: 0.2rem; } +#page-node .content_container .node-type-actualite .field_field_liens a:not(.ext) { + display: none; +} +#page-node .content_container .node-type-actualite .field_field_images { + order: 5; +} #page-node .content_container .node-type-actualite .field_field_images img { width: 100%; height: auto; diff --git a/web/themes/custom/quartiers_de_demain/dist/assets/img/formes-animees-original.svg b/web/themes/custom/quartiers_de_demain/dist/assets/img/formes-animees-live.svg similarity index 100% rename from web/themes/custom/quartiers_de_demain/dist/assets/img/formes-animees-original.svg rename to web/themes/custom/quartiers_de_demain/dist/assets/img/formes-animees-live.svg diff --git a/web/themes/custom/quartiers_de_demain/dist/assets/img/rect4.svg b/web/themes/custom/quartiers_de_demain/dist/assets/img/rect4.svg new file mode 100644 index 0000000..d0090ab --- /dev/null +++ b/web/themes/custom/quartiers_de_demain/dist/assets/img/rect4.svg @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/web/themes/custom/quartiers_de_demain/src/assets/scss/global/_layout.scss b/web/themes/custom/quartiers_de_demain/src/assets/scss/global/_layout.scss index a97dd0b..8ebe28f 100644 --- a/web/themes/custom/quartiers_de_demain/src/assets/scss/global/_layout.scss +++ b/web/themes/custom/quartiers_de_demain/src/assets/scss/global/_layout.scss @@ -45,7 +45,7 @@ $width-menu-slidedown : 550px; @media(max-width: 810px){ - padding-top: 380px; + padding-top: 300px; } } } diff --git a/web/themes/custom/quartiers_de_demain/src/assets/scss/pages/actualite.scss b/web/themes/custom/quartiers_de_demain/src/assets/scss/pages/actualite.scss index 225cff8..a2ff58f 100644 --- a/web/themes/custom/quartiers_de_demain/src/assets/scss/pages/actualite.scss +++ b/web/themes/custom/quartiers_de_demain/src/assets/scss/pages/actualite.scss @@ -33,7 +33,10 @@ .node-type-actualite{ width: 100%; padding-bottom: 7rem; + display: flex; + flex-direction: column; .infos-actu{ + order: 1; display: flex; flex-direction: row; border-top: solid red 1px; @@ -65,12 +68,14 @@ } .field_body { + order: 2; padding-bottom: 2rem; p{ font-size: 0.8rem; } } .field_field_liens{ + order: 3; padding-bottom: 2rem; a{ padding-left: 0.5rem; @@ -91,9 +96,14 @@ } } + + a:not(.ext){ + display: none; + } } .field_field_images{ + order: 5; img{ width: 100%; height: auto; diff --git a/web/themes/custom/quartiers_de_demain/src/assets/scss/partials/actu-caroussel-home.scss b/web/themes/custom/quartiers_de_demain/src/assets/scss/partials/actu-caroussel-home.scss index f8ad2f8..2661e44 100644 --- a/web/themes/custom/quartiers_de_demain/src/assets/scss/partials/actu-caroussel-home.scss +++ b/web/themes/custom/quartiers_de_demain/src/assets/scss/partials/actu-caroussel-home.scss @@ -16,10 +16,16 @@ } button{ top: -2.5rem; + @media(max-width: 810px){ + top: -1.5rem; + } } .content-actus{ .slick-list{ padding-bottom: 4rem; + @media(max-width: 810px){ + padding-bottom: 0rem; + } } .view{ display: flex; diff --git a/web/themes/custom/quartiers_de_demain/src/assets/scss/partials/header.scss b/web/themes/custom/quartiers_de_demain/src/assets/scss/partials/header.scss index 9d693b4..19a32c7 100644 --- a/web/themes/custom/quartiers_de_demain/src/assets/scss/partials/header.scss +++ b/web/themes/custom/quartiers_de_demain/src/assets/scss/partials/header.scss @@ -184,14 +184,18 @@ header{ transform: translateX(0); transition: transform 0.3s ease-in-out; z-index: -1 ; + display: flex; + flex-direction: column; + @media(max-width: 1090px){ // text-align:left; - height: fit-content; + // height: fit-content; } @media(max-width: 500px){ flex: 0 0 40%; } #block-quartiers-de-demain-entete{ + margin: auto; h2{ display: none; } @@ -307,7 +311,7 @@ header{ flex: 1 0 100%; position: relative; left: -100%; - top: -45px; + // top: -45px; /* a remettre et faire varier si ajoute éléments dans menu */ } } @@ -343,7 +347,10 @@ header{ flex: 1 0 100%; position: relative; left: -100%; - top: -75px; + // top: -75px; + } + @media(max-width: 550px){ + top: 0px; } } diff --git a/web/themes/custom/quartiers_de_demain/templates/node--actualite.html.twig b/web/themes/custom/quartiers_de_demain/templates/node--actualite.html.twig index 7394958..25ffad1 100644 --- a/web/themes/custom/quartiers_de_demain/templates/node--actualite.html.twig +++ b/web/themes/custom/quartiers_de_demain/templates/node--actualite.html.twig @@ -92,22 +92,17 @@ {# {{ content }} #} {# #} {% block content %} - -{{ label }} -{{content.field_images}} + {{ label }} + {{content.field_images}}
{{content.field_type_d_actualite}} {{content.field_date}}
- - - {{content.body}} - {{content.field_liens}} + {{content.field_liens}} - -
- + + {% endblock %} From 104633faa1a339f0d56a8543d67503abf4dc3525 Mon Sep 17 00:00:00 2001 From: ouidade Date: Mon, 3 Mar 2025 22:39:58 +0100 Subject: [PATCH 21/22] actu page --- .../quartiers_de_demain/dist/assets/css/bundle.css | 5 +++++ .../src/assets/scss/pages/actualite.scss | 12 +++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/web/themes/custom/quartiers_de_demain/dist/assets/css/bundle.css b/web/themes/custom/quartiers_de_demain/dist/assets/css/bundle.css index 488ee37..beab4e9 100644 --- a/web/themes/custom/quartiers_de_demain/dist/assets/css/bundle.css +++ b/web/themes/custom/quartiers_de_demain/dist/assets/css/bundle.css @@ -3184,6 +3184,8 @@ body { #page-node .content_container .node-type-actualite { width: 100%; padding-bottom: 7rem; +} +#page-node .content_container .node-type-actualite a { display: flex; flex-direction: column; } @@ -3228,8 +3230,11 @@ body { #page-node .content_container .node-type-actualite .field_field_liens { order: 3; padding-bottom: 2rem; + padding-top: 2rem; } #page-node .content_container .node-type-actualite .field_field_liens a { + display: flex; + flex-direction: row; padding-left: 0.5rem; display: inline-flex; align-items: center; diff --git a/web/themes/custom/quartiers_de_demain/src/assets/scss/pages/actualite.scss b/web/themes/custom/quartiers_de_demain/src/assets/scss/pages/actualite.scss index a2ff58f..64f80c0 100644 --- a/web/themes/custom/quartiers_de_demain/src/assets/scss/pages/actualite.scss +++ b/web/themes/custom/quartiers_de_demain/src/assets/scss/pages/actualite.scss @@ -33,8 +33,11 @@ .node-type-actualite{ width: 100%; padding-bottom: 7rem; - display: flex; - flex-direction: column; + a{ + display: flex; + flex-direction: column; + } + .infos-actu{ order: 1; display: flex; @@ -77,7 +80,10 @@ .field_field_liens{ order: 3; padding-bottom: 2rem; - a{ + padding-top: 2rem; + a{ + display: flex; + flex-direction: row; padding-left: 0.5rem; display: inline-flex; align-items: center; From 735a9a0278ee3345ff47d6d74781a1794e7557ad Mon Sep 17 00:00:00 2001 From: ouidade Date: Mon, 3 Mar 2025 23:35:36 +0100 Subject: [PATCH 22/22] retrouve page lessites --- .../quartiers_de_demain/dist/assets/bundle.js | 2 +- .../src/assets/js/quartiers_de_demain.js | 1109 ++++++++--------- 2 files changed, 505 insertions(+), 606 deletions(-) diff --git a/web/themes/custom/quartiers_de_demain/dist/assets/bundle.js b/web/themes/custom/quartiers_de_demain/dist/assets/bundle.js index 82a34d8..a35ba2b 100644 --- a/web/themes/custom/quartiers_de_demain/dist/assets/bundle.js +++ b/web/themes/custom/quartiers_de_demain/dist/assets/bundle.js @@ -36,7 +36,7 @@ eval("document.addEventListener('scroll', function() {\n const scrolled = win \**********************************************/ /***/ (function() { -eval("/**\n * @file\n * quartiers_de_demain behaviors.\n */\n (function (Drupal) {\n\n 'use strict';\n \n Drupal.behaviors.quartiers_de_demain = {\n attach: function (context, settings) {\n console.log('It works!');\n }\n };\n } (Drupal));\n\n\n //////// start header ////////////\n document.addEventListener('DOMContentLoaded', function() {\n\n const header = document.querySelector('header');\n const logo = document.querySelector('#block-quartiers-de-demain-logoquartiersdedemain > div:nth-child(1) > div:nth-child(1) > a:nth-child(1) > svg:nth-child(1)');\n const headerNavContainer = document.querySelector('.header_nav_container');\n const isFirstLoad = !performance.getEntriesByType(\"navigation\")[0].type.includes('back_forward');\n const isTargetPath = window.location.pathname === '/';\n\n // Fonction pour démarrer l'animation du logo SVG\n function startLogoAnimation() {\n logo.classList.add('animated');\n }\n \n // Fonction pour arrêter l'animation du logo SVG\n function stopLogoAnimation() {\n logo.classList.remove('animated');\n }\n \n // Vérifier si le header a la classe header--collapse\n function checkHeaderCollapse() {\n if (header.classList.contains('header--collapsed')) {\n stopLogoAnimation();\n } else if (header.classList.contains('header--collapsed-already')) {\n stopLogoAnimation();\n } else {\n startLogoAnimation();\n }\n\n }\n \n // Appeler la fonction au chargement initial\n checkHeaderCollapse();\n \n // Observer les changements de classe sur le header\n const observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(mutation) {\n if (mutation.attributeName === 'class') {\n checkHeaderCollapse();\n }\n });\n });\n observer.observe(header, { attributes: true });\n \n\n // Si ce n'est pas la première charge ou si le chemin n'est pas le chemin cible, ajouter la classe immédiatement\n if (!isFirstLoad || !isTargetPath) {\n header.classList.add('header--collapsed-already');\n // logo.classList.remove('animated');\n stopLogoAnimation();\n } else {\n // Sinon, appliquer la transition après un délai\n setTimeout(() => {\n header.classList.add('header--collapsed');\n }, 5000);\n }\n\n //////////////////////////////////////\n\n let lastScrollTop = 0;\n let threshold = 100; // Change this value as needed\n let isHidden = false;\n \n function slideOut() {\n headerNavContainer.animate([\n { transform: 'translateX(0)' },\n { transform: 'translateX(-100%)' }\n ], {\n duration: 300,\n fill: 'forwards'\n });\n isHidden = true;\n }\n \n function slideIn() {\n headerNavContainer.animate([\n { transform: 'translateX(-100%)' },\n { transform: 'translateX(0)' }\n ], {\n duration: 300,\n fill: 'forwards'\n });\n isHidden = false;\n }\n \n function slideDown() {\n // headerNavContainer.style.display = 'block';\n headerNavContainer.animate([\n { transform: 'translateY(0%)' },\n { transform: 'translateY(+100%)' }\n ], {\n duration: 300,\n fill: 'forwards'\n });\n isHidden = false;\n }\n \n function slideUp() {\n headerNavContainer.animate([\n { transform: 'translateY(100%)' },\n { transform: 'translateY(0%)' }\n ], {\n duration: 300,\n fill: 'forwards'\n }).onfinish = function() {\n // headerNavContainer.style.display = 'none';\n };\n isHidden = true;\n }\n // Fonction pour ajuster la hauteur du header lors du défilement\n function adjustHeaderHeight() {\n if (window.scrollY > 0) {\n header.classList.add('shrink');\n } else {\n header.classList.remove('shrink');\n }\n }\n\n function handleScroll() {\n let scrollTop = window.pageYOffset || document.documentElement.scrollTop;\n const isMobile = window.innerWidth < 811;\n\n if (scrollTop > threshold && !isHidden) {\n if (isMobile) {\n slideUp();\n } else {\n slideOut();\n }\n } else if (scrollTop <= threshold && isHidden) {\n if (isMobile) {\n slideDown();\n } else {\n slideIn();\n }\n }\n \n \n lastScrollTop = scrollTop <= 0 ? 0 : scrollTop; // For Mobile or negative scrolling\n }\n \n function handleTouchAndMouseEnter() {\n if (isHidden) {\n if (window.innerWidth < 811) {\n slideDown();\n } else {\n slideIn();\n }\n }\n }\n \n function handleTouchAndMouseLeave() {\n if (lastScrollTop > threshold && !isHidden) {\n if (window.innerWidth < 811) {\n slideUp();\n } else {\n slideOut();\n }\n }\n }\n \n window.addEventListener('scroll', handleScroll);\n window.addEventListener('scroll', adjustHeaderHeight);\n \n // Mouse events for desktop\n header.addEventListener('mouseenter', handleTouchAndMouseEnter);\n header.addEventListener('mouseleave', handleTouchAndMouseLeave);\n \n // Touch events for tablets and mobile devices\n header.addEventListener('touchstart', handleTouchAndMouseEnter);\n header.addEventListener('touchend', handleTouchAndMouseLeave);\n \n // Initial check to see if we're at the top of the page\n if (window.pageYOffset <= threshold) {\n if (window.innerWidth < 811) {\n slideDown();\n } else { \n slideIn();\n } \n } else {\n if (window.innerWidth < 811) {\n slideUp();\n } else {\n slideIn();\n }\n }\n \n });\n\n//////// end header ////////////\n \n\n\n//// ancre dans texte au click paragraphe correspondant arrive en dessous du header \n\n\n(function($, window) {\n var adjustAnchor = function() {\n var $anchor = $('.sidebar_first_container'),\n fixedElementHeight = 500;\n if ($anchor.length > 0) {\n $('html, body').stop().animate({scrollTop: $anchor.offset().top - fixedElementHeight }, 0);\n }\n };\n\n $(window).on('hashchange', function() {\n adjustAnchor();\n });\n\n\n //////////////////////// start script smooth apparition des textes /////////////////\n\n function scrollReaveal(){\n\n const nodes = {\n logo : document.querySelectorAll('#logo-animated-container'),\n chapeau : document.querySelectorAll('.field_body'),\n paragraph: document.querySelectorAll('.field_field_textes .paragraph--type--static-parts'),\n enjeux : document.querySelectorAll('.field_field_textes .paragraph--type--static-parts .enjeux'),\n // mapHome : document.querySelectorAll('.field_field_map_block #block-sitesmapblock'),\n // mapSite : document.querySelectorAll('#sites-map-container'),\n lienDoc : document.querySelectorAll('.field_field_documents'),\n lienURL : document.querySelectorAll('.field_field_liens_site'),\n }\n\n const showUp = {\n origin: 'bottom',\n delay: 100,\n duration: 1000,\n distance: '50px',\n easing: 'cubic-bezier(0.5, 0, 0, 1)'\n }\n\n const Show = {\n delay: 100,\n duration: 600,\n easing: 'cubic-bezier(0.5, 0, 0, 1)'\n }\n\n console.log(nodes);\n\n ScrollReveal().reveal(nodes.logo, Show);\n ScrollReveal().reveal(nodes.chapeau, showUp);\n ScrollReveal().reveal(nodes.paragraph, showUp);\n ScrollReveal().reveal(nodes.enjeux, showUp);\n // ScrollReveal().reveal(nodes.mapHome, showUp);\n // ScrollReveal().reveal(nodes.mapSite, showUp);\n ScrollReveal().reveal(nodes.lienDoc, showUp);\n ScrollReveal().reveal(nodes.lienURL, showUp);\n\n }\n\n\n $( document ).ready(function() {\n scrollReaveal();\n });\n\n //////////////////////// end script smooth apparition des textes /////////////////\n\n // //////////////////// start Timeline script ///////////////////////\n\n // Update month field to only show the first 3 letters\n document.querySelectorAll('.paragraph--type--phase-deroulement').forEach(function(paragraph) {\n const monthField = paragraph.querySelector('.field_field_date_de_moi div:nth-of-type(2)');\n if (monthField) {\n const monthText = monthField.textContent.trim();\n if (monthText === \"juillet\") {\n monthField.textContent = monthText.slice(0, 4);\n monthField.classList.add('after');\n } else if (monthText === \"juin\") {\n monthField.textContent = monthText.slice(0, 4);\n } else if (monthText.length > 3) {\n monthField.textContent = monthText.slice(0, 3);\n monthField.classList.add('after');\n }\n }\n });\n \n // Fonction pour ajouter ou retirer la classe .only\n function updateDateClasses() {\n document.querySelectorAll('.paragraph--type--phase-deroulement .date').forEach(function(dateElement) {\n const date2Element = dateElement.querySelector('.date2');\n const yearElement = dateElement.querySelector('.field_field_date_de_annee');\n \n if (date2Element && !date2Element.textContent.trim()) {\n if (yearElement) {\n yearElement.classList.add('only');\n }\n } else {\n if (yearElement) {\n yearElement.classList.remove('only');\n }\n }\n });\n }\n \n // Exécuter la fonction une première fois pour le contenu déjà présent\n updateDateClasses();\n \n // MutationObserver pour surveiller les changements dans le DOM\n const observer = new MutationObserver(function(mutationsList, observer) {\n for(let mutation of mutationsList) {\n if (mutation.type === 'childList') {\n updateDateClasses();\n }\n }\n });\n\n\n // ////////////////////// start calendrier home /////////////////////////////////\n $(document).ready(function(){\n $('.__timeline-content').slick({\n slidesToShow: 3,\n slidesToScroll: 1,\n dots: false,\n arrows: true,\n centerMode: false,\n draggable: true,\n infinite: false,\n responsive: [\n {\n breakpoint: 810,\n settings: {\n slidesToShow: 1,\n adaptiveHeight: false,\n arrows: true,\n draggable: true,\n centerMode: false,\n infinite: false,\n }\n }]\n });\n console.log('salut slick calendrier');\n \n });\n \n //////////////////////// end calendrier home /////////////////////////////////\n \n \n\n //////////////////////// end Timeline script /////////////////////////////////////////////\n\n /////////////////// caracteres body actus/////////////////////////\n\n document.addEventListener('DOMContentLoaded', function() {\n // Nombre maximum de caractères à afficher\n const maxChars = 140; // Ajustez cette valeur selon vos besoins\n\n document.querySelectorAll('#actus-caroussel .node-type-actualite').forEach(function(node) {\n let paragraphs = node.querySelectorAll('.field_body p');\n let fullText = \"\";\n \n // Concaténer tous les paragraphes\n paragraphs.forEach(p => fullText += p.textContent.trim() + \" \");\n fullText = fullText.trim();\n\n // Vérifier si le texte dépasse la limite\n if (fullText.length > maxChars) {\n let truncatedText = fullText.slice(0, maxChars) + '...';\n\n // Vider tout le contenu et insérer seulement le texte tronqué\n let firstParagraph = paragraphs[0];\n firstParagraph.textContent = truncatedText;\n\n // Masquer les autres paragraphes\n for (let i = 1; i < paragraphs.length; i++) {\n paragraphs[i].style.display = \"none\";\n }\n }\n });\n });\n\n \n\n //////////// start slideshow home ////////////////////////// \n\n\n\n $(document).ready(function(){\n let actuview = $('.content-actus .view ')\n if (actuview) {\n actuview.slick({\n slidesToShow: 3,\n // slidesToScroll: 1,\n dots: false,\n arrows: true,\n // centerMode: true,\n adaptiveHeight: false,\n autoplay: false,\n // autoplaySpeed: 1500,\n // infinite: true,\n // centerPadding: '100px',\n responsive: [\n {\n breakpoint: 810,\n settings: {\n slidesToShow: 1,\n // slidesToScroll: 1,\n adaptiveHeight: false,\n arrows: true,\n draggable: true,\n // centerMode: true,\n // centerPadding: '100px',\n autoplay: false,\n // autoplaySpeed: 2000,\n }\n }]\n });\n console.log('salut slick home');\n \n }\n $('.slick-carousel').slick({\n lazyLoad: 'progressive', // Option 'ondemand' ou 'progressive'\n });\n\n });\n\n\n\n\n $(document).ready(function () {\n let diapohome = $('.config_pages--type--diaporama-home .diaporama');\n\n if (diapohome.length) {\n // Initialisation de Slick\n diapohome.slick({\n slidesToShow: 1,\n dots: false,\n arrows: false,\n // centerMode: true,\n adaptiveHeight: false,\n autoplay: true, // Activer l'autoplay\n autoplaySpeed: 4000, // Changement de slide toutes les 4 secondes\n // infinite: true,\n pauseOnHover: false, // Ne pas arrêter l'autoplay lors du survol\n pauseOnFocus: false,\n responsive: [\n {\n breakpoint: 810,\n settings: {\n slidesToShow: 1,\n adaptiveHeight: false,\n arrows: false,\n draggable: true,\n centerMode: false,\n }\n }]\n });\n\n }\n});\n\n //////////// end slideshow home ////////////////////////// \n\n//////////////// start lightbox galerie image page site////////////////////////\n\n// Sélection des images et de leurs légendes dans la galerie\nlet images = document.querySelectorAll('.paragraph--type--site-diapo .lightbox-trigger');\nlet currentIndex;\n\n// Création de la lightbox et de ses éléments\nconst lightbox = document.createElement('div');\nlightbox.id = 'lightbox';\nlightbox.classList.add('lightbox');\ndocument.body.appendChild(lightbox);\n\nconst img = document.createElement('img');\nlightbox.appendChild(img);\n\n// Élément pour afficher la légende\nconst caption = document.createElement('p');\ncaption.classList.add('caption');\nlightbox.appendChild(caption);\n\nconst closeBtn = document.createElement('span');\ncloseBtn.classList.add('close');\ncloseBtn.innerHTML = '×';\nlightbox.appendChild(closeBtn);\n\nconst prevBtn = document.createElement('a');\nprevBtn.classList.add('prev');\nprevBtn.innerHTML = '❮';\nlightbox.appendChild(prevBtn);\n\nconst nextBtn = document.createElement('a');\nnextBtn.classList.add('next');\nnextBtn.innerHTML = '❯';\nlightbox.appendChild(nextBtn);\n\n// Fonction pour afficher l'image et la légende à l'index donné\nfunction showImage(index) {\n if (index < 0) index = images.length - 1;\n if (index >= images.length) index = 0;\n currentIndex = index;\n\n // Mettre à jour l'image\n img.src = images[currentIndex].getAttribute('src');\n\n // Récupérer la légende associée (le paragraphe dans blockquote suivant l'image)\n const captionText = images[currentIndex]\n .closest('.cadre-img-zoom')\n .nextElementSibling.querySelector('.image-field-caption p')\n .textContent;\n \n caption.textContent = captionText || ''; // Affiche la légende ou une chaîne vide si elle est absente\n lightbox.style.display = 'flex';\n}\n\n// Événements de clic sur chaque image pour ouvrir le lightbox avec la légende\nimages.forEach((image, index) => {\n image.addEventListener('click', () => {\n showImage(index);\n });\n});\n\n// Fermer le lightbox\ncloseBtn.addEventListener('click', () => {\n lightbox.style.display = 'none';\n});\n\n// Navigation pour images précédente et suivante\nprevBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n showImage(currentIndex - 1);\n});\n\nnextBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n showImage(currentIndex + 1);\n});\n\n// Fermer le lightbox en cliquant en dehors de l'image\nlightbox.addEventListener('click', (e) => {\n if (e.target === lightbox) {\n lightbox.style.display = 'none';\n }\n});\n\n// Ajout des contrôles clavier (Échap, flèches gauche/droite)\ndocument.addEventListener('keydown', (e) => {\n if (lightbox.style.display === 'flex') {\n if (e.key === 'Escape') {\n lightbox.style.display = 'none';\n } else if (e.key === 'ArrowLeft') {\n showImage(currentIndex - 1);\n } else if (e.key === 'ArrowRight') {\n showImage(currentIndex + 1);\n }\n }\n});\n\n\n//////////////// end lightbox galerie image page site////////////////////////\n\n \n\n//////////////////// start wrapper views-row lessites /////////////////////////\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n // Sélectionne le conteneur principal avec l'ID 'lessites'\n const container = document.getElementById(\"lessites\");\n\n // Vérifie si le conteneur existe pour éviter toute erreur sur d'autres pages\n if (container) {\n // Sélectionne l'élément 'view' à l'intérieur de '.views-element-container'\n const viewContainer = container.querySelector(\".views-element-container .view\");\n\n // Vérifie si 'viewContainer' existe pour éviter les erreurs\n if (viewContainer) {\n // Crée une div englobante pour tous les éléments 'views-row'\n const wrapperDiv = document.createElement(\"div\");\n wrapperDiv.classList.add(\"views-row-wrapper\"); // ajoute une classe pour faciliter le style CSS\n\n // Déplace tous les éléments 'views-row' dans la nouvelle div\n const viewsRows = viewContainer.querySelectorAll(\".views-row\");\n viewsRows.forEach(row => wrapperDiv.appendChild(row));\n\n // Ajoute la div englobante dans le 'viewContainer'\n viewContainer.appendChild(wrapperDiv);\n }\n }\n});\n\n\n//////////////////// end wrapper views-row lessites /////////////////////////\n\n\n\n//////////////////// start div infos site ////////////////////////\n\n// Vérifie si la page a la classe 'node-type-site' dans le \nif (document.body.classList.contains('node-type-site')) {\n // Sélectionne le conteneur principal\n const blockRegion = document.querySelector('.block-region-second');\n\n // Liste des classes spécifiques à cibler\n const fieldClasses = [\n '.field_field_region',\n '.field_field_nom_du_qpv_nb_d_hab',\n '.field_field_departement_s',\n '.field_field_programme_de_l_etat',\n '.field_field_porteur_s_de_site',\n '.field_field_nom_de_la_commune_nb_d_hab'\n ];\n\n // Sélectionne les div parents de chacun des champs listés\n const elementsToWrap = [];\n fieldClasses.forEach(className => {\n const fieldElement = blockRegion.querySelector(className);\n if (fieldElement) {\n // Ajoute le parent du champ au tableau si trouvé\n elementsToWrap.push(fieldElement.parentElement);\n }\n });\n\n // Vérifie que des éléments ont été trouvés\n if (elementsToWrap.length > 0) {\n // Crée le conteneur avec la classe 'infos'\n const infosContainer = document.createElement('div');\n infosContainer.className = 'infos';\n\n // Insère le conteneur `.infos` avant le premier élément ciblé\n const firstElement = elementsToWrap[0];\n blockRegion.insertBefore(infosContainer, firstElement);\n\n // Déplace chaque élément dans le conteneur `.infos`\n elementsToWrap.forEach(element => infosContainer.appendChild(element));\n }\n}\n//////////////////// end div infos site ////////////////////////\n\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n // Sélectionner les éléments à déplacer\n const documentsField = document.querySelector(\".field_field_documents\");\n const liensSiteField = document.querySelector(\".field_field_liens_site\");\n \n // Sélectionner la destination\n const thirdRegion = document.querySelector(\".block-region-third > div\");\n\n // Créer une nouvelle div pour englober les éléments déplacés\n const wrapperDiv = document.createElement(\"div\");\n wrapperDiv.classList.add(\"documents-liens-wrapper\");\n\n // Déplacer les éléments dans la nouvelle div\n if (documentsField && liensSiteField && thirdRegion) {\n wrapperDiv.appendChild(documentsField);\n wrapperDiv.appendChild(liensSiteField);\n\n // Ajouter la nouvelle div dans la destination\n thirdRegion.appendChild(wrapperDiv);\n }\n});\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n // Sélectionner les éléments pertinents\n const documentsLiensWrapper = document.querySelector(\".documents-liens-wrapper\");\n const blockRegionThird = document.querySelector(\".block-region-third\");\n\n // Vérifier que les éléments existent avant de les manipuler\n if (documentsLiensWrapper && blockRegionThird) {\n // Déplacer .documents-liens-wrapper en dehors du div contenant les boutons prev/next\n blockRegionThird.appendChild(documentsLiensWrapper);\n }\n});\n\n\ndocument.addEventListener(\"DOMContentLoaded\", function () {\n // Fonction pour déplacer le bloc en fonction de la taille de l'écran\n function moveLanguageSwitcher() {\n const languageSwitcher = document.getElementById(\"block-quartiers-de-demain-selecteurdelangue\");\n const navContainer = document.querySelector(\".header_nav_container\");\n\n if (window.innerWidth <= 810) { // Si écran téléphone\n if (languageSwitcher && navContainer && !navContainer.contains(languageSwitcher)) {\n navContainer.appendChild(languageSwitcher); // Déplace le bloc dans header_nav_container\n }\n } else { // Si écran non téléphone\n const headerRightContainer = document.querySelector(\".header_right_container\");\n if (languageSwitcher && headerRightContainer && !headerRightContainer.contains(languageSwitcher)) {\n headerRightContainer.appendChild(languageSwitcher); // Remet le bloc dans sa position initiale\n }\n }\n }\n\n // Déclencher au chargement et au redimensionnement\n moveLanguageSwitcher();\n window.addEventListener(\"resize\", moveLanguageSwitcher);\n});\n\n\n//////////////////////////////////////////\n\n\n/////////// Start script ressources ////////////////////////////////\n\ndocument.addEventListener(\"DOMContentLoaded\", () => {\n const view = document.querySelector(\".view\");\n const elements = Array.from(view.children);\n\n let newView = document.createElement(\"div\");\n newView.classList.add(\"view\");\n\n let group = null;\n let groupContent = null;\n\n elements.forEach((el) => {\n if (el.tagName === \"H3\") {\n if (group) {\n newView.appendChild(group);\n }\n\n group = document.createElement(\"div\");\n group.classList.add(\"group\");\n\n groupContent = document.createElement(\"div\");\n groupContent.classList.add(\"group-content\");\n\n groupContent.appendChild(el);\n group.appendChild(groupContent);\n } else if (el.classList.contains(\"views-row\")) {\n groupContent.appendChild(el);\n }\n });\n\n if (group) {\n newView.appendChild(group);\n }\n\n view.replaceWith(newView);\n\n // Ajouter un bouton \"Voir plus\" dans chaque groupe\n document.querySelectorAll(\".group\").forEach((group) => {\n const rows = group.querySelectorAll(\".views-row\");\n const button = document.createElement(\"button\");\n button.classList.add(\"toggle-btn\");\n button.textContent = \"Voir plus de\";\n\n rows.forEach((row, index) => {\n if (index >= 3) {\n row.classList.add(\"hidden\");\n row.style.maxHeight = \"0\";\n row.style.opacity = \"0\";\n }\n });\n\n button.addEventListener(\"click\", () => {\n const isExpanded = button.textContent === \"Voir moins de\";\n const hiddenRows = group.querySelectorAll(\".views-row.hidden\");\n\n if (isExpanded) {\n // Cacher les lignes avec un délai pour l'effet de transition\n hiddenRows.forEach((row) => {\n row.style.maxHeight = \"0\";\n row.style.opacity = \"0\";\n setTimeout(() => row.classList.add(\"hidden\"), 500); // Délai pour la transition\n });\n } else {\n // Afficher les lignes\n hiddenRows.forEach((row) => {\n row.classList.remove(\"hidden\");\n row.style.maxHeight = row.scrollHeight + \"px\";\n row.style.opacity = \"1\";\n });\n }\n\n button.textContent = isExpanded ? \"Voir plus de\" : \"Voir moins de\";\n });\n\n group.appendChild(button);\n });\n});\n\n\n/////////// end script ressources ////////////////////////////////\n\n})(jQuery, window);\n\n\n\n\n//# sourceURL=webpack://quartiers_de_demain/./src/assets/js/quartiers_de_demain.js?"); +eval("/**\n * @file\n * quartiers_de_demain behaviors.\n */\n (function (Drupal) {\n\n 'use strict';\n\n Drupal.behaviors.quartiers_de_demain = {\n attach: function (context, settings) {\n console.log('It works!');\n }\n };\n} (Drupal));\n\n\n//////// start header ////////////\ndocument.addEventListener('DOMContentLoaded', function() {\n\n const header = document.querySelector('header');\n const logo = document.querySelector('#block-quartiers-de-demain-logoquartiersdedemain > div:nth-child(1) > div:nth-child(1) > a:nth-child(1) > svg:nth-child(1)');\n const headerNavContainer = document.querySelector('.header_nav_container');\n const isFirstLoad = !performance.getEntriesByType(\"navigation\")[0].type.includes('back_forward');\n const isTargetPath = window.location.pathname === '/';\n\n // Fonction pour démarrer l'animation du logo SVG\n function startLogoAnimation() {\n logo.classList.add('animated');\n }\n\n // Fonction pour arrêter l'animation du logo SVG\n function stopLogoAnimation() {\n logo.classList.remove('animated');\n }\n\n // Vérifier si le header a la classe header--collapse\n function checkHeaderCollapse() {\n if (header.classList.contains('header--collapsed')) {\n stopLogoAnimation();\n } else if (header.classList.contains('header--collapsed-already')) {\n stopLogoAnimation();\n } else {\n startLogoAnimation();\n }\n\n }\n\n // Appeler la fonction au chargement initial\n checkHeaderCollapse();\n\n // Observer les changements de classe sur le header\n const observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(mutation) {\n if (mutation.attributeName === 'class') {\n checkHeaderCollapse();\n }\n });\n });\n observer.observe(header, { attributes: true });\n\n\n // Si ce n'est pas la première charge ou si le chemin n'est pas le chemin cible, ajouter la classe immédiatement\n if (!isFirstLoad || !isTargetPath) {\n header.classList.add('header--collapsed-already');\n // logo.classList.remove('animated');\n stopLogoAnimation();\n } else {\n // Sinon, appliquer la transition après un délai\n setTimeout(() => {\n header.classList.add('header--collapsed');\n }, 5000);\n }\n\n //////////////////////////////////////\n\n let lastScrollTop = 0;\n let threshold = 100; // Change this value as needed\n let isHidden = false;\n\n function slideOut() {\n headerNavContainer.animate([\n { transform: 'translateX(0)' },\n { transform: 'translateX(-100%)' }\n ], {\n duration: 300,\n fill: 'forwards'\n });\n isHidden = true;\n }\n\n function slideIn() {\n headerNavContainer.animate([\n { transform: 'translateX(-100%)' },\n { transform: 'translateX(0)' }\n ], {\n duration: 300,\n fill: 'forwards'\n });\n isHidden = false;\n }\n \n function slideDown() {\n // headerNavContainer.style.display = 'block';\n headerNavContainer.animate([\n { transform: 'translateY(0%)' },\n { transform: 'translateY(+100%)' }\n ], {\n duration: 300,\n fill: 'forwards'\n });\n isHidden = false;\n }\n\n function slideUp() {\n headerNavContainer.animate([\n { transform: 'translateY(100%)' },\n { transform: 'translateY(0%)' }\n ], {\n duration: 300,\n fill: 'forwards'\n }).onfinish = function() {\n // headerNavContainer.style.display = 'none';\n };\n isHidden = true;\n }\n // Fonction pour ajuster la hauteur du header lors du défilement\n function adjustHeaderHeight() {\n if (window.scrollY > 0) {\n header.classList.add('shrink');\n } else {\n header.classList.remove('shrink');\n }\n }\n\n function handleScroll() {\n let scrollTop = window.pageYOffset || document.documentElement.scrollTop;\n const isMobile = window.innerWidth < 811;\n\n if (scrollTop > threshold && !isHidden) {\n if (isMobile) {\n slideUp();\n } else {\n slideOut();\n }\n } else if (scrollTop <= threshold && isHidden) {\n if (isMobile) {\n slideDown();\n } else {\n slideIn();\n }\n }\n\n\n lastScrollTop = scrollTop <= 0 ? 0 : scrollTop; // For Mobile or negative scrolling\n }\n\n function handleTouchAndMouseEnter() {\n if (isHidden) {\n if (window.innerWidth < 811) {\n slideDown();\n } else {\n slideIn();\n }\n }\n }\n\n function handleTouchAndMouseLeave() {\n if (lastScrollTop > threshold && !isHidden) {\n if (window.innerWidth < 811) {\n slideUp();\n } else {\n slideOut();\n }\n }\n }\n\n window.addEventListener('scroll', handleScroll);\n window.addEventListener('scroll', adjustHeaderHeight);\n\n // Mouse events for desktop\n header.addEventListener('mouseenter', handleTouchAndMouseEnter);\n header.addEventListener('mouseleave', handleTouchAndMouseLeave);\n\n // Touch events for tablets and mobile devices\n header.addEventListener('touchstart', handleTouchAndMouseEnter);\n header.addEventListener('touchend', handleTouchAndMouseLeave);\n\n // Initial check to see if we're at the top of the page\n if (window.pageYOffset <= threshold) {\n if (window.innerWidth < 811) {\n slideDown();\n } else { \n slideIn();\n } \n } else {\n if (window.innerWidth < 811) {\n slideUp();\n } else {\n slideIn();\n }\n }\n\n});\n\n//////// end header ////////////\n\n\n\n//// ancre dans texte au click paragraphe correspondant arrive en dessous du header \n\n\n(function($, window) {\nvar adjustAnchor = function() {\n var $anchor = $('.sidebar_first_container'),\n fixedElementHeight = 500;\n if ($anchor.length > 0) {\n $('html, body').stop().animate({scrollTop: $anchor.offset().top - fixedElementHeight }, 0);\n }\n};\n\n$(window).on('hashchange', function() {\n adjustAnchor();\n});\n\n\n//////////////////////// start script smooth apparition des textes /////////////////\n\nfunction scrollReaveal(){\n\n const nodes = {\n logo : document.querySelectorAll('#logo-animated-container'),\n chapeau : document.querySelectorAll('.field_body'),\n paragraph: document.querySelectorAll('.field_field_textes .paragraph--type--static-parts'),\n enjeux : document.querySelectorAll('.field_field_textes .paragraph--type--static-parts .enjeux'),\n // mapHome : document.querySelectorAll('.field_field_map_block #block-sitesmapblock'),\n // mapSite : document.querySelectorAll('#sites-map-container'),\n lienDoc : document.querySelectorAll('.field_field_documents'),\n lienURL : document.querySelectorAll('.field_field_liens_site'),\n }\n\n const showUp = {\n origin: 'bottom',\n delay: 100,\n duration: 1000,\n distance: '50px',\n easing: 'cubic-bezier(0.5, 0, 0, 1)'\n }\n\n const Show = {\n delay: 100,\n duration: 600,\n easing: 'cubic-bezier(0.5, 0, 0, 1)'\n }\n\n console.log(nodes);\n\n ScrollReveal().reveal(nodes.logo, Show);\n ScrollReveal().reveal(nodes.chapeau, showUp);\n ScrollReveal().reveal(nodes.paragraph, showUp);\n ScrollReveal().reveal(nodes.enjeux, showUp);\n // ScrollReveal().reveal(nodes.mapHome, showUp);\n // ScrollReveal().reveal(nodes.mapSite, showUp);\n ScrollReveal().reveal(nodes.lienDoc, showUp);\n ScrollReveal().reveal(nodes.lienURL, showUp);\n\n}\n\n\n$( document ).ready(function() {\n scrollReaveal();\n});\n\n//////////////////////// end script smooth apparition des textes /////////////////\n\n// //////////////////// start Timeline script ///////////////////////\n\n // Update month field to only show the first 3 letters\n document.querySelectorAll('.paragraph--type--phase-deroulement').forEach(function(paragraph) {\n const monthField = paragraph.querySelector('.field_field_date_de_moi div:nth-of-type(2)');\n if (monthField) {\n const monthText = monthField.textContent.trim();\n if (monthText === \"juillet\") {\n monthField.textContent = monthText.slice(0, 4);\n monthField.classList.add('after');\n } else if (monthText === \"juin\") {\n monthField.textContent = monthText.slice(0, 4);\n } else if (monthText.length > 3) {\n monthField.textContent = monthText.slice(0, 3);\n monthField.classList.add('after');\n }\n }\n });\n\n // Fonction pour ajouter ou retirer la classe .only\n function updateDateClasses() {\n document.querySelectorAll('.paragraph--type--phase-deroulement .date').forEach(function(dateElement) {\n const date2Element = dateElement.querySelector('.date2');\n const yearElement = dateElement.querySelector('.field_field_date_de_annee');\n\n if (date2Element && !date2Element.textContent.trim()) {\n if (yearElement) {\n yearElement.classList.add('only');\n }\n } else {\n if (yearElement) {\n yearElement.classList.remove('only');\n }\n }\n });\n }\n\n // Exécuter la fonction une première fois pour le contenu déjà présent\n updateDateClasses();\n\n // MutationObserver pour surveiller les changements dans le DOM\n const observer = new MutationObserver(function(mutationsList, observer) {\n for(let mutation of mutationsList) {\n if (mutation.type === 'childList') {\n updateDateClasses();\n }\n }\n });\n\n\n// ////////////////////// start calendrier home /////////////////////////////////\n $(document).ready(function(){\n $('.__timeline-content').slick({\n slidesToShow: 3,\n slidesToScroll: 1,\n dots: false,\n arrows: true,\n centerMode: false,\n draggable: true,\n infinite: false,\n responsive: [\n {\n breakpoint: 810,\n settings: {\n slidesToShow: 1,\n adaptiveHeight: false,\n arrows: true,\n draggable: true,\n centerMode: false,\n infinite: false,\n }\n }]\n });\n console.log('salut slick calendrier');\n \n });\n \n//////////////////////// end calendrier home /////////////////////////////////\n\n\n\n//////////////////////// end Timeline script /////////////////////////////////////////////\n\n/////////////////// caracteres body actus/////////////////////////\n\ndocument.addEventListener('DOMContentLoaded', function() {\n // Maximum number of characters to display\n const maxChars = 140; // Adjust this value as needed\n\n document.querySelectorAll('#actus-caroussel .node-type-actualite .field_body p').forEach(function(paragraph) {\n let text = paragraph.textContent.trim();\n if (text.length > maxChars) {\n let truncatedText = text.slice(0, maxChars) + '...';\n paragraph.textContent = truncatedText;\n }\n });\n});\n\n\n//////////// start slideshow home ////////////////////////// \n\n\n\n$(document).ready(function(){\n let actuview = $('.content-actus .view ')\n if (actuview) {\n actuview.slick({\n slidesToShow: 3,\n // slidesToScroll: 1,\n dots: false,\n arrows: true,\n // centerMode: true,\n adaptiveHeight: false,\n autoplay: false,\n // autoplaySpeed: 1500,\n // infinite: true,\n // centerPadding: '100px',\n responsive: [\n {\n breakpoint: 810,\n settings: {\n slidesToShow: 1,\n // slidesToScroll: 1,\n adaptiveHeight: false,\n arrows: true,\n draggable: true,\n // centerMode: true,\n // centerPadding: '100px',\n autoplay: false,\n // autoplaySpeed: 2000,\n }\n }]\n });\n console.log('salut slick home');\n \n }\n $('.slick-carousel').slick({\n lazyLoad: 'progressive', // Option 'ondemand' ou 'progressive'\n });\n\n});\n\n\n\n\n$(document).ready(function () {\n let diapohome = $('.config_pages--type--diaporama-home .diaporama');\n\n if (diapohome.length) {\n // Initialisation de Slick\n diapohome.slick({\n slidesToShow: 1,\n dots: false,\n arrows: false,\n // centerMode: true,\n adaptiveHeight: false,\n autoplay: true, // Activer l'autoplay\n autoplaySpeed: 4000, // Changement de slide toutes les 4 secondes\n // infinite: true,\n pauseOnHover: false, // Ne pas arrêter l'autoplay lors du survol\n pauseOnFocus: false,\n responsive: [\n {\n breakpoint: 810,\n settings: {\n slidesToShow: 1,\n adaptiveHeight: false,\n arrows: false,\n draggable: true,\n centerMode: false,\n }\n }]\n });\n\n}\n});\n\n//////////// end slideshow home ////////////////////////// \n\n//////////////// start lightbox galerie image page site////////////////////////\n\n// Sélection des images et de leurs légendes dans la galerie\nlet images = document.querySelectorAll('.paragraph--type--site-diapo .lightbox-trigger');\nlet currentIndex;\n\n// Création de la lightbox et de ses éléments\nconst lightbox = document.createElement('div');\nlightbox.id = 'lightbox';\nlightbox.classList.add('lightbox');\ndocument.body.appendChild(lightbox);\n\nconst img = document.createElement('img');\nlightbox.appendChild(img);\n\n// Élément pour afficher la légende\nconst caption = document.createElement('p');\ncaption.classList.add('caption');\nlightbox.appendChild(caption);\n\nconst closeBtn = document.createElement('span');\ncloseBtn.classList.add('close');\ncloseBtn.innerHTML = '×';\nlightbox.appendChild(closeBtn);\n\nconst prevBtn = document.createElement('a');\nprevBtn.classList.add('prev');\nprevBtn.innerHTML = '❮';\nlightbox.appendChild(prevBtn);\n\nconst nextBtn = document.createElement('a');\nnextBtn.classList.add('next');\nnextBtn.innerHTML = '❯';\nlightbox.appendChild(nextBtn);\n\n// Fonction pour afficher l'image et la légende à l'index donné\nfunction showImage(index) {\nif (index < 0) index = images.length - 1;\nif (index >= images.length) index = 0;\ncurrentIndex = index;\n\n// Mettre à jour l'image\nimg.src = images[currentIndex].getAttribute('src');\n\n// Récupérer la légende associée (le paragraphe dans blockquote suivant l'image)\nconst captionText = images[currentIndex]\n .closest('.cadre-img-zoom')\n .nextElementSibling.querySelector('.image-field-caption p')\n .textContent;\n \ncaption.textContent = captionText || ''; // Affiche la légende ou une chaîne vide si elle est absente\nlightbox.style.display = 'flex';\n}\n\n// Événements de clic sur chaque image pour ouvrir le lightbox avec la légende\nimages.forEach((image, index) => {\nimage.addEventListener('click', () => {\n showImage(index);\n});\n});\n\n// Fermer le lightbox\ncloseBtn.addEventListener('click', () => {\nlightbox.style.display = 'none';\n});\n\n// Navigation pour images précédente et suivante\nprevBtn.addEventListener('click', (e) => {\ne.stopPropagation();\nshowImage(currentIndex - 1);\n});\n\nnextBtn.addEventListener('click', (e) => {\ne.stopPropagation();\nshowImage(currentIndex + 1);\n});\n\n// Fermer le lightbox en cliquant en dehors de l'image\nlightbox.addEventListener('click', (e) => {\nif (e.target === lightbox) {\n lightbox.style.display = 'none';\n}\n});\n\n// Ajout des contrôles clavier (Échap, flèches gauche/droite)\ndocument.addEventListener('keydown', (e) => {\nif (lightbox.style.display === 'flex') {\n if (e.key === 'Escape') {\n lightbox.style.display = 'none';\n } else if (e.key === 'ArrowLeft') {\n showImage(currentIndex - 1);\n } else if (e.key === 'ArrowRight') {\n showImage(currentIndex + 1);\n }\n}\n});\n\n\n//////////////// end lightbox galerie image page site////////////////////////\n\n\n\n//////////////////// start wrapper views-row lessites /////////////////////////\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n// Sélectionne le conteneur principal avec l'ID 'lessites'\nconst container = document.getElementById(\"lessites\");\n\n// Vérifie si le conteneur existe pour éviter toute erreur sur d'autres pages\nif (container) {\n // Sélectionne l'élément 'view' à l'intérieur de '.views-element-container'\n const viewContainer = container.querySelector(\".views-element-container .view\");\n\n // Vérifie si 'viewContainer' existe pour éviter les erreurs\n if (viewContainer) {\n // Crée une div englobante pour tous les éléments 'views-row'\n const wrapperDiv = document.createElement(\"div\");\n wrapperDiv.classList.add(\"views-row-wrapper\"); // ajoute une classe pour faciliter le style CSS\n\n // Déplace tous les éléments 'views-row' dans la nouvelle div\n const viewsRows = viewContainer.querySelectorAll(\".views-row\");\n viewsRows.forEach(row => wrapperDiv.appendChild(row));\n\n // Ajoute la div englobante dans le 'viewContainer'\n viewContainer.appendChild(wrapperDiv);\n }\n}\n});\n\n\n//////////////////// end wrapper views-row lessites /////////////////////////\n\n\n\n//////////////////// start div infos site ////////////////////////\n\n// Vérifie si la page a la classe 'node-type-site' dans le \nif (document.body.classList.contains('node-type-site')) {\n// Sélectionne le conteneur principal\nconst blockRegion = document.querySelector('.block-region-second');\n\n// Liste des classes spécifiques à cibler\nconst fieldClasses = [\n '.field_field_region',\n '.field_field_nom_du_qpv_nb_d_hab',\n '.field_field_departement_s',\n '.field_field_programme_de_l_etat',\n '.field_field_porteur_s_de_site',\n '.field_field_nom_de_la_commune_nb_d_hab'\n];\n\n// Sélectionne les div parents de chacun des champs listés\nconst elementsToWrap = [];\nfieldClasses.forEach(className => {\n const fieldElement = blockRegion.querySelector(className);\n if (fieldElement) {\n // Ajoute le parent du champ au tableau si trouvé\n elementsToWrap.push(fieldElement.parentElement);\n }\n});\n\n// Vérifie que des éléments ont été trouvés\nif (elementsToWrap.length > 0) {\n // Crée le conteneur avec la classe 'infos'\n const infosContainer = document.createElement('div');\n infosContainer.className = 'infos';\n\n // Insère le conteneur `.infos` avant le premier élément ciblé\n const firstElement = elementsToWrap[0];\n blockRegion.insertBefore(infosContainer, firstElement);\n\n // Déplace chaque élément dans le conteneur `.infos`\n elementsToWrap.forEach(element => infosContainer.appendChild(element));\n}\n}\n//////////////////// end div infos site ////////////////////////\n\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n// Sélectionner les éléments à déplacer\nconst documentsField = document.querySelector(\".field_field_documents\");\nconst liensSiteField = document.querySelector(\".field_field_liens_site\");\n\n// Sélectionner la destination\nconst thirdRegion = document.querySelector(\".block-region-third > div\");\n\n// Créer une nouvelle div pour englober les éléments déplacés\nconst wrapperDiv = document.createElement(\"div\");\nwrapperDiv.classList.add(\"documents-liens-wrapper\");\n\n// Déplacer les éléments dans la nouvelle div\nif (documentsField && liensSiteField && thirdRegion) {\n wrapperDiv.appendChild(documentsField);\n wrapperDiv.appendChild(liensSiteField);\n\n // Ajouter la nouvelle div dans la destination\n thirdRegion.appendChild(wrapperDiv);\n}\n});\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n// Sélectionner les éléments pertinents\nconst documentsLiensWrapper = document.querySelector(\".documents-liens-wrapper\");\nconst blockRegionThird = document.querySelector(\".block-region-third\");\n\n// Vérifier que les éléments existent avant de les manipuler\nif (documentsLiensWrapper && blockRegionThird) {\n // Déplacer .documents-liens-wrapper en dehors du div contenant les boutons prev/next\n blockRegionThird.appendChild(documentsLiensWrapper);\n}\n});\n\n\ndocument.addEventListener(\"DOMContentLoaded\", function () {\n// Fonction pour déplacer le bloc en fonction de la taille de l'écran\nfunction moveLanguageSwitcher() {\n const languageSwitcher = document.getElementById(\"block-quartiers-de-demain-selecteurdelangue\");\n const navContainer = document.querySelector(\".header_nav_container\");\n\n if (window.innerWidth <= 810) { // Si écran téléphone\n if (languageSwitcher && navContainer && !navContainer.contains(languageSwitcher)) {\n navContainer.appendChild(languageSwitcher); // Déplace le bloc dans header_nav_container\n }\n } else { // Si écran non téléphone\n const headerRightContainer = document.querySelector(\".header_right_container\");\n if (languageSwitcher && headerRightContainer && !headerRightContainer.contains(languageSwitcher)) {\n headerRightContainer.appendChild(languageSwitcher); // Remet le bloc dans sa position initiale\n }\n }\n}\n\n// Déclencher au chargement et au redimensionnement\nmoveLanguageSwitcher();\nwindow.addEventListener(\"resize\", moveLanguageSwitcher);\n});\n\n\n})(jQuery, window);\n\n\n\n\n//# sourceURL=webpack://quartiers_de_demain/./src/assets/js/quartiers_de_demain.js?"); /***/ }) diff --git a/web/themes/custom/quartiers_de_demain/src/assets/js/quartiers_de_demain.js b/web/themes/custom/quartiers_de_demain/src/assets/js/quartiers_de_demain.js index 5b5dff8..1b85ec6 100644 --- a/web/themes/custom/quartiers_de_demain/src/assets/js/quartiers_de_demain.js +++ b/web/themes/custom/quartiers_de_demain/src/assets/js/quartiers_de_demain.js @@ -4,468 +4,452 @@ */ (function (Drupal) { - 'use strict'; - - Drupal.behaviors.quartiers_de_demain = { - attach: function (context, settings) { - console.log('It works!'); - } - }; - } (Drupal)); + 'use strict'; - - //////// start header //////////// - document.addEventListener('DOMContentLoaded', function() { - - const header = document.querySelector('header'); - const logo = document.querySelector('#block-quartiers-de-demain-logoquartiersdedemain > div:nth-child(1) > div:nth-child(1) > a:nth-child(1) > svg:nth-child(1)'); - const headerNavContainer = document.querySelector('.header_nav_container'); - const isFirstLoad = !performance.getEntriesByType("navigation")[0].type.includes('back_forward'); - const isTargetPath = window.location.pathname === '/'; - - // Fonction pour démarrer l'animation du logo SVG - function startLogoAnimation() { - logo.classList.add('animated'); + Drupal.behaviors.quartiers_de_demain = { + attach: function (context, settings) { + console.log('It works!'); } - - // Fonction pour arrêter l'animation du logo SVG - function stopLogoAnimation() { - logo.classList.remove('animated'); - } - - // Vérifier si le header a la classe header--collapse - function checkHeaderCollapse() { - if (header.classList.contains('header--collapsed')) { - stopLogoAnimation(); - } else if (header.classList.contains('header--collapsed-already')) { - stopLogoAnimation(); - } else { - startLogoAnimation(); - } + }; +} (Drupal)); - } - - // Appeler la fonction au chargement initial - checkHeaderCollapse(); - - // Observer les changements de classe sur le header - const observer = new MutationObserver(function(mutations) { - mutations.forEach(function(mutation) { - if (mutation.attributeName === 'class') { - checkHeaderCollapse(); - } - }); - }); - observer.observe(header, { attributes: true }); - - // Si ce n'est pas la première charge ou si le chemin n'est pas le chemin cible, ajouter la classe immédiatement - if (!isFirstLoad || !isTargetPath) { - header.classList.add('header--collapsed-already'); - // logo.classList.remove('animated'); +//////// start header //////////// +document.addEventListener('DOMContentLoaded', function() { + + const header = document.querySelector('header'); + const logo = document.querySelector('#block-quartiers-de-demain-logoquartiersdedemain > div:nth-child(1) > div:nth-child(1) > a:nth-child(1) > svg:nth-child(1)'); + const headerNavContainer = document.querySelector('.header_nav_container'); + const isFirstLoad = !performance.getEntriesByType("navigation")[0].type.includes('back_forward'); + const isTargetPath = window.location.pathname === '/'; + + // Fonction pour démarrer l'animation du logo SVG + function startLogoAnimation() { + logo.classList.add('animated'); + } + + // Fonction pour arrêter l'animation du logo SVG + function stopLogoAnimation() { + logo.classList.remove('animated'); + } + + // Vérifier si le header a la classe header--collapse + function checkHeaderCollapse() { + if (header.classList.contains('header--collapsed')) { stopLogoAnimation(); - } else { - // Sinon, appliquer la transition après un délai - setTimeout(() => { - header.classList.add('header--collapsed'); - }, 5000); + } else if (header.classList.contains('header--collapsed-already')) { + stopLogoAnimation(); + } else { + startLogoAnimation(); } - ////////////////////////////////////// + } - let lastScrollTop = 0; - let threshold = 100; // Change this value as needed - let isHidden = false; - - function slideOut() { - headerNavContainer.animate([ - { transform: 'translateX(0)' }, - { transform: 'translateX(-100%)' } - ], { - duration: 300, - fill: 'forwards' - }); - isHidden = true; - } - - function slideIn() { - headerNavContainer.animate([ - { transform: 'translateX(-100%)' }, - { transform: 'translateX(0)' } - ], { - duration: 300, - fill: 'forwards' - }); - isHidden = false; - } - - function slideDown() { - // headerNavContainer.style.display = 'block'; - headerNavContainer.animate([ - { transform: 'translateY(0%)' }, - { transform: 'translateY(+100%)' } - ], { - duration: 300, - fill: 'forwards' - }); - isHidden = false; - } - - function slideUp() { - headerNavContainer.animate([ - { transform: 'translateY(100%)' }, - { transform: 'translateY(0%)' } - ], { - duration: 300, - fill: 'forwards' - }).onfinish = function() { - // headerNavContainer.style.display = 'none'; - }; - isHidden = true; - } - // Fonction pour ajuster la hauteur du header lors du défilement - function adjustHeaderHeight() { - if (window.scrollY > 0) { - header.classList.add('shrink'); - } else { - header.classList.remove('shrink'); - } - } + // Appeler la fonction au chargement initial + checkHeaderCollapse(); - function handleScroll() { - let scrollTop = window.pageYOffset || document.documentElement.scrollTop; - const isMobile = window.innerWidth < 811; + // Observer les changements de classe sur le header + const observer = new MutationObserver(function(mutations) { + mutations.forEach(function(mutation) { + if (mutation.attributeName === 'class') { + checkHeaderCollapse(); + } + }); + }); + observer.observe(header, { attributes: true }); - if (scrollTop > threshold && !isHidden) { - if (isMobile) { - slideUp(); - } else { - slideOut(); - } - } else if (scrollTop <= threshold && isHidden) { - if (isMobile) { - slideDown(); - } else { - slideIn(); - } - } + + // Si ce n'est pas la première charge ou si le chemin n'est pas le chemin cible, ajouter la classe immédiatement + if (!isFirstLoad || !isTargetPath) { + header.classList.add('header--collapsed-already'); + // logo.classList.remove('animated'); + stopLogoAnimation(); + } else { + // Sinon, appliquer la transition après un délai + setTimeout(() => { + header.classList.add('header--collapsed'); + }, 5000); + } + + ////////////////////////////////////// + + let lastScrollTop = 0; + let threshold = 100; // Change this value as needed + let isHidden = false; + + function slideOut() { + headerNavContainer.animate([ + { transform: 'translateX(0)' }, + { transform: 'translateX(-100%)' } + ], { + duration: 300, + fill: 'forwards' + }); + isHidden = true; + } + + function slideIn() { + headerNavContainer.animate([ + { transform: 'translateX(-100%)' }, + { transform: 'translateX(0)' } + ], { + duration: 300, + fill: 'forwards' + }); + isHidden = false; + } - - lastScrollTop = scrollTop <= 0 ? 0 : scrollTop; // For Mobile or negative scrolling - } - - function handleTouchAndMouseEnter() { - if (isHidden) { - if (window.innerWidth < 811) { - slideDown(); - } else { - slideIn(); - } + function slideDown() { + // headerNavContainer.style.display = 'block'; + headerNavContainer.animate([ + { transform: 'translateY(0%)' }, + { transform: 'translateY(+100%)' } + ], { + duration: 300, + fill: 'forwards' + }); + isHidden = false; + } + + function slideUp() { + headerNavContainer.animate([ + { transform: 'translateY(100%)' }, + { transform: 'translateY(0%)' } + ], { + duration: 300, + fill: 'forwards' + }).onfinish = function() { + // headerNavContainer.style.display = 'none'; + }; + isHidden = true; + } + // Fonction pour ajuster la hauteur du header lors du défilement + function adjustHeaderHeight() { + if (window.scrollY > 0) { + header.classList.add('shrink'); + } else { + header.classList.remove('shrink'); } } - - function handleTouchAndMouseLeave() { - if (lastScrollTop > threshold && !isHidden) { - if (window.innerWidth < 811) { - slideUp(); - } else { - slideOut(); - } - } - } - - window.addEventListener('scroll', handleScroll); - window.addEventListener('scroll', adjustHeaderHeight); - - // Mouse events for desktop - header.addEventListener('mouseenter', handleTouchAndMouseEnter); - header.addEventListener('mouseleave', handleTouchAndMouseLeave); - - // Touch events for tablets and mobile devices - header.addEventListener('touchstart', handleTouchAndMouseEnter); - header.addEventListener('touchend', handleTouchAndMouseLeave); - - // Initial check to see if we're at the top of the page - if (window.pageYOffset <= threshold) { - if (window.innerWidth < 811) { - slideDown(); - } else { - slideIn(); - } - } else { - if (window.innerWidth < 811) { + + function handleScroll() { + let scrollTop = window.pageYOffset || document.documentElement.scrollTop; + const isMobile = window.innerWidth < 811; + + if (scrollTop > threshold && !isHidden) { + if (isMobile) { slideUp(); + } else { + slideOut(); + } + } else if (scrollTop <= threshold && isHidden) { + if (isMobile) { + slideDown(); } else { slideIn(); } } - - }); + + + lastScrollTop = scrollTop <= 0 ? 0 : scrollTop; // For Mobile or negative scrolling + } + + function handleTouchAndMouseEnter() { + if (isHidden) { + if (window.innerWidth < 811) { + slideDown(); + } else { + slideIn(); + } + } + } + + function handleTouchAndMouseLeave() { + if (lastScrollTop > threshold && !isHidden) { + if (window.innerWidth < 811) { + slideUp(); + } else { + slideOut(); + } + } + } + + window.addEventListener('scroll', handleScroll); + window.addEventListener('scroll', adjustHeaderHeight); + + // Mouse events for desktop + header.addEventListener('mouseenter', handleTouchAndMouseEnter); + header.addEventListener('mouseleave', handleTouchAndMouseLeave); + + // Touch events for tablets and mobile devices + header.addEventListener('touchstart', handleTouchAndMouseEnter); + header.addEventListener('touchend', handleTouchAndMouseLeave); + + // Initial check to see if we're at the top of the page + if (window.pageYOffset <= threshold) { + if (window.innerWidth < 811) { + slideDown(); + } else { + slideIn(); + } + } else { + if (window.innerWidth < 811) { + slideUp(); + } else { + slideIn(); + } + } + +}); //////// end header //////////// - + //// ancre dans texte au click paragraphe correspondant arrive en dessous du header (function($, window) { - var adjustAnchor = function() { - var $anchor = $('.sidebar_first_container'), - fixedElementHeight = 500; - if ($anchor.length > 0) { - $('html, body').stop().animate({scrollTop: $anchor.offset().top - fixedElementHeight }, 0); - } - }; - - $(window).on('hashchange', function() { - adjustAnchor(); - }); - - - //////////////////////// start script smooth apparition des textes ///////////////// - - function scrollReaveal(){ - - const nodes = { - logo : document.querySelectorAll('#logo-animated-container'), - chapeau : document.querySelectorAll('.field_body'), - paragraph: document.querySelectorAll('.field_field_textes .paragraph--type--static-parts'), - enjeux : document.querySelectorAll('.field_field_textes .paragraph--type--static-parts .enjeux'), - // mapHome : document.querySelectorAll('.field_field_map_block #block-sitesmapblock'), - // mapSite : document.querySelectorAll('#sites-map-container'), - lienDoc : document.querySelectorAll('.field_field_documents'), - lienURL : document.querySelectorAll('.field_field_liens_site'), +var adjustAnchor = function() { + var $anchor = $('.sidebar_first_container'), + fixedElementHeight = 500; + if ($anchor.length > 0) { + $('html, body').stop().animate({scrollTop: $anchor.offset().top - fixedElementHeight }, 0); } +}; - const showUp = { - origin: 'bottom', - delay: 100, - duration: 1000, - distance: '50px', - easing: 'cubic-bezier(0.5, 0, 0, 1)' - } +$(window).on('hashchange', function() { + adjustAnchor(); +}); - const Show = { - delay: 100, - duration: 600, - easing: 'cubic-bezier(0.5, 0, 0, 1)' - } - console.log(nodes); +//////////////////////// start script smooth apparition des textes ///////////////// - ScrollReveal().reveal(nodes.logo, Show); - ScrollReveal().reveal(nodes.chapeau, showUp); - ScrollReveal().reveal(nodes.paragraph, showUp); - ScrollReveal().reveal(nodes.enjeux, showUp); - // ScrollReveal().reveal(nodes.mapHome, showUp); - // ScrollReveal().reveal(nodes.mapSite, showUp); - ScrollReveal().reveal(nodes.lienDoc, showUp); - ScrollReveal().reveal(nodes.lienURL, showUp); +function scrollReaveal(){ + const nodes = { + logo : document.querySelectorAll('#logo-animated-container'), + chapeau : document.querySelectorAll('.field_body'), + paragraph: document.querySelectorAll('.field_field_textes .paragraph--type--static-parts'), + enjeux : document.querySelectorAll('.field_field_textes .paragraph--type--static-parts .enjeux'), + // mapHome : document.querySelectorAll('.field_field_map_block #block-sitesmapblock'), + // mapSite : document.querySelectorAll('#sites-map-container'), + lienDoc : document.querySelectorAll('.field_field_documents'), + lienURL : document.querySelectorAll('.field_field_liens_site'), } + const showUp = { + origin: 'bottom', + delay: 100, + duration: 1000, + distance: '50px', + easing: 'cubic-bezier(0.5, 0, 0, 1)' + } - $( document ).ready(function() { - scrollReaveal(); + const Show = { + delay: 100, + duration: 600, + easing: 'cubic-bezier(0.5, 0, 0, 1)' + } + + console.log(nodes); + + ScrollReveal().reveal(nodes.logo, Show); + ScrollReveal().reveal(nodes.chapeau, showUp); + ScrollReveal().reveal(nodes.paragraph, showUp); + ScrollReveal().reveal(nodes.enjeux, showUp); + // ScrollReveal().reveal(nodes.mapHome, showUp); + // ScrollReveal().reveal(nodes.mapSite, showUp); + ScrollReveal().reveal(nodes.lienDoc, showUp); + ScrollReveal().reveal(nodes.lienURL, showUp); + +} + + +$( document ).ready(function() { + scrollReaveal(); +}); + +//////////////////////// end script smooth apparition des textes ///////////////// + +// //////////////////// start Timeline script /////////////////////// + + // Update month field to only show the first 3 letters + document.querySelectorAll('.paragraph--type--phase-deroulement').forEach(function(paragraph) { + const monthField = paragraph.querySelector('.field_field_date_de_moi div:nth-of-type(2)'); + if (monthField) { + const monthText = monthField.textContent.trim(); + if (monthText === "juillet") { + monthField.textContent = monthText.slice(0, 4); + monthField.classList.add('after'); + } else if (monthText === "juin") { + monthField.textContent = monthText.slice(0, 4); + } else if (monthText.length > 3) { + monthField.textContent = monthText.slice(0, 3); + monthField.classList.add('after'); + } + } }); - //////////////////////// end script smooth apparition des textes ///////////////// + // Fonction pour ajouter ou retirer la classe .only + function updateDateClasses() { + document.querySelectorAll('.paragraph--type--phase-deroulement .date').forEach(function(dateElement) { + const date2Element = dateElement.querySelector('.date2'); + const yearElement = dateElement.querySelector('.field_field_date_de_annee'); - // //////////////////// start Timeline script /////////////////////// - - // Update month field to only show the first 3 letters - document.querySelectorAll('.paragraph--type--phase-deroulement').forEach(function(paragraph) { - const monthField = paragraph.querySelector('.field_field_date_de_moi div:nth-of-type(2)'); - if (monthField) { - const monthText = monthField.textContent.trim(); - if (monthText === "juillet") { - monthField.textContent = monthText.slice(0, 4); - monthField.classList.add('after'); - } else if (monthText === "juin") { - monthField.textContent = monthText.slice(0, 4); - } else if (monthText.length > 3) { - monthField.textContent = monthText.slice(0, 3); - monthField.classList.add('after'); + if (date2Element && !date2Element.textContent.trim()) { + if (yearElement) { + yearElement.classList.add('only'); + } + } else { + if (yearElement) { + yearElement.classList.remove('only'); } } }); - - // Fonction pour ajouter ou retirer la classe .only - function updateDateClasses() { - document.querySelectorAll('.paragraph--type--phase-deroulement .date').forEach(function(dateElement) { - const date2Element = dateElement.querySelector('.date2'); - const yearElement = dateElement.querySelector('.field_field_date_de_annee'); - - if (date2Element && !date2Element.textContent.trim()) { - if (yearElement) { - yearElement.classList.add('only'); - } - } else { - if (yearElement) { - yearElement.classList.remove('only'); - } - } - }); + } + + // Exécuter la fonction une première fois pour le contenu déjà présent + updateDateClasses(); + + // MutationObserver pour surveiller les changements dans le DOM + const observer = new MutationObserver(function(mutationsList, observer) { + for(let mutation of mutationsList) { + if (mutation.type === 'childList') { + updateDateClasses(); + } } - - // Exécuter la fonction une première fois pour le contenu déjà présent - updateDateClasses(); - - // MutationObserver pour surveiller les changements dans le DOM - const observer = new MutationObserver(function(mutationsList, observer) { - for(let mutation of mutationsList) { - if (mutation.type === 'childList') { - updateDateClasses(); - } - } + }); + + +// ////////////////////// start calendrier home ///////////////////////////////// + $(document).ready(function(){ + $('.__timeline-content').slick({ + slidesToShow: 3, + slidesToScroll: 1, + dots: false, + arrows: true, + centerMode: false, + draggable: true, + infinite: false, + responsive: [ + { + breakpoint: 810, + settings: { + slidesToShow: 1, + adaptiveHeight: false, + arrows: true, + draggable: true, + centerMode: false, + infinite: false, + } + }] }); + console.log('salut slick calendrier'); + + }); + +//////////////////////// end calendrier home ///////////////////////////////// - // ////////////////////// start calendrier home ///////////////////////////////// - $(document).ready(function(){ - $('.__timeline-content').slick({ + +//////////////////////// end Timeline script ///////////////////////////////////////////// + +/////////////////// caracteres body actus///////////////////////// + +document.addEventListener('DOMContentLoaded', function() { + // Maximum number of characters to display + const maxChars = 140; // Adjust this value as needed + + document.querySelectorAll('#actus-caroussel .node-type-actualite .field_body p').forEach(function(paragraph) { + let text = paragraph.textContent.trim(); + if (text.length > maxChars) { + let truncatedText = text.slice(0, maxChars) + '...'; + paragraph.textContent = truncatedText; + } + }); +}); + + +//////////// start slideshow home ////////////////////////// + + + +$(document).ready(function(){ + let actuview = $('.content-actus .view ') + if (actuview) { + actuview.slick({ slidesToShow: 3, - slidesToScroll: 1, + // slidesToScroll: 1, dots: false, arrows: true, - centerMode: false, - draggable: true, - infinite: false, + // centerMode: true, + adaptiveHeight: false, + autoplay: false, + // autoplaySpeed: 1500, + // infinite: true, + // centerPadding: '100px', responsive: [ { breakpoint: 810, settings: { slidesToShow: 1, + // slidesToScroll: 1, adaptiveHeight: false, arrows: true, draggable: true, - centerMode: false, - infinite: false, + // centerMode: true, + // centerPadding: '100px', + autoplay: false, + // autoplaySpeed: 2000, } }] }); - console.log('salut slick calendrier'); - - }); - - //////////////////////// end calendrier home ///////////////////////////////// - - - - //////////////////////// end Timeline script ///////////////////////////////////////////// - - /////////////////// caracteres body actus///////////////////////// - - document.addEventListener('DOMContentLoaded', function() { - // Nombre maximum de caractères à afficher - const maxChars = 140; // Ajustez cette valeur selon vos besoins - - document.querySelectorAll('#actus-caroussel .node-type-actualite').forEach(function(node) { - let paragraphs = node.querySelectorAll('.field_body p'); - let fullText = ""; - - // Concaténer tous les paragraphes - paragraphs.forEach(p => fullText += p.textContent.trim() + " "); - fullText = fullText.trim(); - - // Vérifier si le texte dépasse la limite - if (fullText.length > maxChars) { - let truncatedText = fullText.slice(0, maxChars) + '...'; - - // Vider tout le contenu et insérer seulement le texte tronqué - let firstParagraph = paragraphs[0]; - firstParagraph.textContent = truncatedText; - - // Masquer les autres paragraphes - for (let i = 1; i < paragraphs.length; i++) { - paragraphs[i].style.display = "none"; - } - } + console.log('salut slick home'); + + } + $('.slick-carousel').slick({ + lazyLoad: 'progressive', // Option 'ondemand' ou 'progressive' }); - }); - - - //////////// start slideshow home ////////////////////////// - - - - $(document).ready(function(){ - let actuview = $('.content-actus .view ') - if (actuview) { - actuview.slick({ - slidesToShow: 3, - // slidesToScroll: 1, - dots: false, - arrows: true, - // centerMode: true, - adaptiveHeight: false, - autoplay: false, - // autoplaySpeed: 1500, - // infinite: true, - // centerPadding: '100px', - responsive: [ - { - breakpoint: 810, - settings: { - slidesToShow: 1, - // slidesToScroll: 1, - adaptiveHeight: false, - arrows: true, - draggable: true, - // centerMode: true, - // centerPadding: '100px', - autoplay: false, - // autoplaySpeed: 2000, - } - }] - }); - console.log('salut slick home'); - - } - $('.slick-carousel').slick({ - lazyLoad: 'progressive', // Option 'ondemand' ou 'progressive' - }); - - }); - - - - - $(document).ready(function () { - let diapohome = $('.config_pages--type--diaporama-home .diaporama'); - - if (diapohome.length) { - // Initialisation de Slick - diapohome.slick({ - slidesToShow: 1, - dots: false, - arrows: false, - // centerMode: true, - adaptiveHeight: false, - autoplay: true, // Activer l'autoplay - autoplaySpeed: 4000, // Changement de slide toutes les 4 secondes - // infinite: true, - pauseOnHover: false, // Ne pas arrêter l'autoplay lors du survol - pauseOnFocus: false, - responsive: [ - { - breakpoint: 810, - settings: { - slidesToShow: 1, - adaptiveHeight: false, - arrows: false, - draggable: true, - centerMode: false, - } - }] - }); - - } }); - //////////// end slideshow home ////////////////////////// + + + +$(document).ready(function () { + let diapohome = $('.config_pages--type--diaporama-home .diaporama'); + + if (diapohome.length) { + // Initialisation de Slick + diapohome.slick({ + slidesToShow: 1, + dots: false, + arrows: false, + // centerMode: true, + adaptiveHeight: false, + autoplay: true, // Activer l'autoplay + autoplaySpeed: 4000, // Changement de slide toutes les 4 secondes + // infinite: true, + pauseOnHover: false, // Ne pas arrêter l'autoplay lors du survol + pauseOnFocus: false, + responsive: [ + { + breakpoint: 810, + settings: { + slidesToShow: 1, + adaptiveHeight: false, + arrows: false, + draggable: true, + centerMode: false, + } + }] + }); + +} +}); + +//////////// end slideshow home ////////////////////////// //////////////// start lightbox galerie image page site//////////////////////// @@ -504,95 +488,95 @@ lightbox.appendChild(nextBtn); // Fonction pour afficher l'image et la légende à l'index donné function showImage(index) { - if (index < 0) index = images.length - 1; - if (index >= images.length) index = 0; - currentIndex = index; +if (index < 0) index = images.length - 1; +if (index >= images.length) index = 0; +currentIndex = index; - // Mettre à jour l'image - img.src = images[currentIndex].getAttribute('src'); +// Mettre à jour l'image +img.src = images[currentIndex].getAttribute('src'); - // Récupérer la légende associée (le paragraphe dans blockquote suivant l'image) - const captionText = images[currentIndex] - .closest('.cadre-img-zoom') - .nextElementSibling.querySelector('.image-field-caption p') - .textContent; - - caption.textContent = captionText || ''; // Affiche la légende ou une chaîne vide si elle est absente - lightbox.style.display = 'flex'; +// Récupérer la légende associée (le paragraphe dans blockquote suivant l'image) +const captionText = images[currentIndex] + .closest('.cadre-img-zoom') + .nextElementSibling.querySelector('.image-field-caption p') + .textContent; + +caption.textContent = captionText || ''; // Affiche la légende ou une chaîne vide si elle est absente +lightbox.style.display = 'flex'; } // Événements de clic sur chaque image pour ouvrir le lightbox avec la légende images.forEach((image, index) => { - image.addEventListener('click', () => { - showImage(index); - }); +image.addEventListener('click', () => { + showImage(index); +}); }); // Fermer le lightbox closeBtn.addEventListener('click', () => { - lightbox.style.display = 'none'; +lightbox.style.display = 'none'; }); // Navigation pour images précédente et suivante prevBtn.addEventListener('click', (e) => { - e.stopPropagation(); - showImage(currentIndex - 1); +e.stopPropagation(); +showImage(currentIndex - 1); }); nextBtn.addEventListener('click', (e) => { - e.stopPropagation(); - showImage(currentIndex + 1); +e.stopPropagation(); +showImage(currentIndex + 1); }); // Fermer le lightbox en cliquant en dehors de l'image lightbox.addEventListener('click', (e) => { - if (e.target === lightbox) { - lightbox.style.display = 'none'; - } +if (e.target === lightbox) { + lightbox.style.display = 'none'; +} }); // Ajout des contrôles clavier (Échap, flèches gauche/droite) document.addEventListener('keydown', (e) => { - if (lightbox.style.display === 'flex') { - if (e.key === 'Escape') { - lightbox.style.display = 'none'; - } else if (e.key === 'ArrowLeft') { - showImage(currentIndex - 1); - } else if (e.key === 'ArrowRight') { - showImage(currentIndex + 1); - } +if (lightbox.style.display === 'flex') { + if (e.key === 'Escape') { + lightbox.style.display = 'none'; + } else if (e.key === 'ArrowLeft') { + showImage(currentIndex - 1); + } else if (e.key === 'ArrowRight') { + showImage(currentIndex + 1); } +} }); //////////////// end lightbox galerie image page site//////////////////////// - + //////////////////// start wrapper views-row lessites ///////////////////////// document.addEventListener("DOMContentLoaded", function() { - // Sélectionne le conteneur principal avec l'ID 'lessites' - const container = document.getElementById("lessites"); +// Sélectionne le conteneur principal avec l'ID 'lessites' +const container = document.getElementById("lessites"); - // Vérifie si le conteneur existe pour éviter toute erreur sur d'autres pages - if (container) { - // Sélectionne l'élément 'view' à l'intérieur de '.views-element-container' - const viewContainer = container.querySelector(".views-element-container .view"); +// Vérifie si le conteneur existe pour éviter toute erreur sur d'autres pages +if (container) { + // Sélectionne l'élément 'view' à l'intérieur de '.views-element-container' + const viewContainer = container.querySelector(".views-element-container .view"); - // Vérifie si 'viewContainer' existe pour éviter les erreurs - if (viewContainer) { - // Crée une div englobante pour tous les éléments 'views-row' - const wrapperDiv = document.createElement("div"); - wrapperDiv.classList.add("views-row-wrapper"); // ajoute une classe pour faciliter le style CSS + // Vérifie si 'viewContainer' existe pour éviter les erreurs + if (viewContainer) { + // Crée une div englobante pour tous les éléments 'views-row' + const wrapperDiv = document.createElement("div"); + wrapperDiv.classList.add("views-row-wrapper"); // ajoute une classe pour faciliter le style CSS - // Déplace tous les éléments 'views-row' dans la nouvelle div - const viewsRows = viewContainer.querySelectorAll(".views-row"); - viewsRows.forEach(row => wrapperDiv.appendChild(row)); + // Déplace tous les éléments 'views-row' dans la nouvelle div + const viewsRows = viewContainer.querySelectorAll(".views-row"); + viewsRows.forEach(row => wrapperDiv.appendChild(row)); - // Ajoute la div englobante dans le 'viewContainer' - viewContainer.appendChild(wrapperDiv); - } + // Ajoute la div englobante dans le 'viewContainer' + viewContainer.appendChild(wrapperDiv); } +} }); @@ -604,188 +588,103 @@ document.addEventListener("DOMContentLoaded", function() { // Vérifie si la page a la classe 'node-type-site' dans le if (document.body.classList.contains('node-type-site')) { - // Sélectionne le conteneur principal - const blockRegion = document.querySelector('.block-region-second'); +// Sélectionne le conteneur principal +const blockRegion = document.querySelector('.block-region-second'); - // Liste des classes spécifiques à cibler - const fieldClasses = [ - '.field_field_region', - '.field_field_nom_du_qpv_nb_d_hab', - '.field_field_departement_s', - '.field_field_programme_de_l_etat', - '.field_field_porteur_s_de_site', - '.field_field_nom_de_la_commune_nb_d_hab' - ]; +// Liste des classes spécifiques à cibler +const fieldClasses = [ + '.field_field_region', + '.field_field_nom_du_qpv_nb_d_hab', + '.field_field_departement_s', + '.field_field_programme_de_l_etat', + '.field_field_porteur_s_de_site', + '.field_field_nom_de_la_commune_nb_d_hab' +]; - // Sélectionne les div parents de chacun des champs listés - const elementsToWrap = []; - fieldClasses.forEach(className => { - const fieldElement = blockRegion.querySelector(className); - if (fieldElement) { - // Ajoute le parent du champ au tableau si trouvé - elementsToWrap.push(fieldElement.parentElement); - } - }); +// Sélectionne les div parents de chacun des champs listés +const elementsToWrap = []; +fieldClasses.forEach(className => { + const fieldElement = blockRegion.querySelector(className); + if (fieldElement) { + // Ajoute le parent du champ au tableau si trouvé + elementsToWrap.push(fieldElement.parentElement); + } +}); - // Vérifie que des éléments ont été trouvés - if (elementsToWrap.length > 0) { - // Crée le conteneur avec la classe 'infos' - const infosContainer = document.createElement('div'); - infosContainer.className = 'infos'; +// Vérifie que des éléments ont été trouvés +if (elementsToWrap.length > 0) { + // Crée le conteneur avec la classe 'infos' + const infosContainer = document.createElement('div'); + infosContainer.className = 'infos'; - // Insère le conteneur `.infos` avant le premier élément ciblé - const firstElement = elementsToWrap[0]; - blockRegion.insertBefore(infosContainer, firstElement); + // Insère le conteneur `.infos` avant le premier élément ciblé + const firstElement = elementsToWrap[0]; + blockRegion.insertBefore(infosContainer, firstElement); - // Déplace chaque élément dans le conteneur `.infos` - elementsToWrap.forEach(element => infosContainer.appendChild(element)); - } + // Déplace chaque élément dans le conteneur `.infos` + elementsToWrap.forEach(element => infosContainer.appendChild(element)); +} } //////////////////// end div infos site //////////////////////// document.addEventListener("DOMContentLoaded", function() { - // Sélectionner les éléments à déplacer - const documentsField = document.querySelector(".field_field_documents"); - const liensSiteField = document.querySelector(".field_field_liens_site"); - - // Sélectionner la destination - const thirdRegion = document.querySelector(".block-region-third > div"); +// Sélectionner les éléments à déplacer +const documentsField = document.querySelector(".field_field_documents"); +const liensSiteField = document.querySelector(".field_field_liens_site"); - // Créer une nouvelle div pour englober les éléments déplacés - const wrapperDiv = document.createElement("div"); - wrapperDiv.classList.add("documents-liens-wrapper"); +// Sélectionner la destination +const thirdRegion = document.querySelector(".block-region-third > div"); - // Déplacer les éléments dans la nouvelle div - if (documentsField && liensSiteField && thirdRegion) { - wrapperDiv.appendChild(documentsField); - wrapperDiv.appendChild(liensSiteField); +// Créer une nouvelle div pour englober les éléments déplacés +const wrapperDiv = document.createElement("div"); +wrapperDiv.classList.add("documents-liens-wrapper"); - // Ajouter la nouvelle div dans la destination - thirdRegion.appendChild(wrapperDiv); - } +// Déplacer les éléments dans la nouvelle div +if (documentsField && liensSiteField && thirdRegion) { + wrapperDiv.appendChild(documentsField); + wrapperDiv.appendChild(liensSiteField); + + // Ajouter la nouvelle div dans la destination + thirdRegion.appendChild(wrapperDiv); +} }); document.addEventListener("DOMContentLoaded", function() { - // Sélectionner les éléments pertinents - const documentsLiensWrapper = document.querySelector(".documents-liens-wrapper"); - const blockRegionThird = document.querySelector(".block-region-third"); +// Sélectionner les éléments pertinents +const documentsLiensWrapper = document.querySelector(".documents-liens-wrapper"); +const blockRegionThird = document.querySelector(".block-region-third"); - // Vérifier que les éléments existent avant de les manipuler - if (documentsLiensWrapper && blockRegionThird) { - // Déplacer .documents-liens-wrapper en dehors du div contenant les boutons prev/next - blockRegionThird.appendChild(documentsLiensWrapper); - } +// Vérifier que les éléments existent avant de les manipuler +if (documentsLiensWrapper && blockRegionThird) { + // Déplacer .documents-liens-wrapper en dehors du div contenant les boutons prev/next + blockRegionThird.appendChild(documentsLiensWrapper); +} }); document.addEventListener("DOMContentLoaded", function () { - // Fonction pour déplacer le bloc en fonction de la taille de l'écran - function moveLanguageSwitcher() { - const languageSwitcher = document.getElementById("block-quartiers-de-demain-selecteurdelangue"); - const navContainer = document.querySelector(".header_nav_container"); +// Fonction pour déplacer le bloc en fonction de la taille de l'écran +function moveLanguageSwitcher() { + const languageSwitcher = document.getElementById("block-quartiers-de-demain-selecteurdelangue"); + const navContainer = document.querySelector(".header_nav_container"); - if (window.innerWidth <= 810) { // Si écran téléphone - if (languageSwitcher && navContainer && !navContainer.contains(languageSwitcher)) { - navContainer.appendChild(languageSwitcher); // Déplace le bloc dans header_nav_container - } - } else { // Si écran non téléphone - const headerRightContainer = document.querySelector(".header_right_container"); - if (languageSwitcher && headerRightContainer && !headerRightContainer.contains(languageSwitcher)) { - headerRightContainer.appendChild(languageSwitcher); // Remet le bloc dans sa position initiale - } + if (window.innerWidth <= 810) { // Si écran téléphone + if (languageSwitcher && navContainer && !navContainer.contains(languageSwitcher)) { + navContainer.appendChild(languageSwitcher); // Déplace le bloc dans header_nav_container + } + } else { // Si écran non téléphone + const headerRightContainer = document.querySelector(".header_right_container"); + if (languageSwitcher && headerRightContainer && !headerRightContainer.contains(languageSwitcher)) { + headerRightContainer.appendChild(languageSwitcher); // Remet le bloc dans sa position initiale } } +} - // Déclencher au chargement et au redimensionnement - moveLanguageSwitcher(); - window.addEventListener("resize", moveLanguageSwitcher); +// Déclencher au chargement et au redimensionnement +moveLanguageSwitcher(); +window.addEventListener("resize", moveLanguageSwitcher); }); -////////////////////////////////////////// - - -/////////// Start script ressources //////////////////////////////// - -document.addEventListener("DOMContentLoaded", () => { - const view = document.querySelector(".view"); - const elements = Array.from(view.children); - - let newView = document.createElement("div"); - newView.classList.add("view"); - - let group = null; - let groupContent = null; - - elements.forEach((el) => { - if (el.tagName === "H3") { - if (group) { - newView.appendChild(group); - } - - group = document.createElement("div"); - group.classList.add("group"); - - groupContent = document.createElement("div"); - groupContent.classList.add("group-content"); - - groupContent.appendChild(el); - group.appendChild(groupContent); - } else if (el.classList.contains("views-row")) { - groupContent.appendChild(el); - } - }); - - if (group) { - newView.appendChild(group); - } - - view.replaceWith(newView); - - // Ajouter un bouton "Voir plus" dans chaque groupe - document.querySelectorAll(".group").forEach((group) => { - const rows = group.querySelectorAll(".views-row"); - const button = document.createElement("button"); - button.classList.add("toggle-btn"); - button.textContent = "Voir plus de"; - - rows.forEach((row, index) => { - if (index >= 3) { - row.classList.add("hidden"); - row.style.maxHeight = "0"; - row.style.opacity = "0"; - } - }); - - button.addEventListener("click", () => { - const isExpanded = button.textContent === "Voir moins de"; - const hiddenRows = group.querySelectorAll(".views-row.hidden"); - - if (isExpanded) { - // Cacher les lignes avec un délai pour l'effet de transition - hiddenRows.forEach((row) => { - row.style.maxHeight = "0"; - row.style.opacity = "0"; - setTimeout(() => row.classList.add("hidden"), 500); // Délai pour la transition - }); - } else { - // Afficher les lignes - hiddenRows.forEach((row) => { - row.classList.remove("hidden"); - row.style.maxHeight = row.scrollHeight + "px"; - row.style.opacity = "1"; - }); - } - - button.textContent = isExpanded ? "Voir plus de" : "Voir moins de"; - }); - - group.appendChild(button); - }); -}); - - -/////////// end script ressources //////////////////////////////// - })(jQuery, window);