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..080fb10 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 // 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) {\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})(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 // 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) {\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 46dc0b8..1777c24 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 @@ -3467,6 +3467,7 @@ body { .node-type-site .layout--threecol-25-50-25 .layout__region--third .block-region-third div { display: flex; flex-direction: row; + margin-bottom: 1rem; } @media (max-width: 500px) { .node-type-site .layout--threecol-25-50-25 .layout__region--third .block-region-third div { @@ -3571,10 +3572,6 @@ body { flex-direction: column; } -.html.js.sr body.node-type-site.node-id-40 div.dialog-off-canvas-main-canvas div#page-node.layout-container main div.layout-content div.content_container div.layout.layout--threecol-25-50-25 div.layout__region.layout__region--third div.block-region-third div div.field_field_documents div div span { - visibility: hidden; -} - main { background-color: #f6f7f3; } @@ -3694,4 +3691,135 @@ main { height: auto; aspect-ratio: 1/1; object-fit: cover; +} + +#ressources { + background-color: #f6f7f3; +} +#ressources .layout-content .content_container { + display: flex; + flex-direction: column; + align-items: center; +} +#ressources .layout-content .content_container #block-quartiers-de-demain-titredepage { + margin-top: 1rem; + width: fit-content; +} +@media (max-width: 810px) { + #ressources .layout-content .content_container #block-quartiers-de-demain-titredepage { + margin-top: 14rem; + } +} +#ressources .layout-content .content_container #block-quartiers-de-demain-titredepage h1 { + text-transform: none; + color: black; + font-size: 2rem; + font-family: "gilroy-medium"; +} +#ressources .layout-content .content_container .views-element-container { + margin-left: 15%; + width: 70%; +} +#ressources .layout-content .content_container .views-element-container .group-content { + display: flex; + flex-direction: row; + flex-wrap: wrap; +} +#ressources .layout-content .content_container .views-element-container .group-content h3 { + text-align: center; + flex: 0 0 100%; +} +#ressources .layout-content .content_container .views-element-container .group-content h3::before { + content: ""; + display: block; + border-bottom: solid 2px rgb(7, 50, 194); + margin: auto; +} +#ressources .layout-content .content_container .views-element-container .group-content h3 div .field_name h2 a { + font-family: "gilroy-light"; + color: rgb(7, 50, 194); + font-size: 2rem; +} +#ressources .layout-content .content_container .views-element-container .group-content h3 div .field_description { + font-family: "gilroy-light"; +} +#ressources .layout-content .content_container .views-element-container .group-content .views-row { + width: 30%; + font-size: 0.5rem; +} +#ressources .layout-content .content_container .views-element-container .group-content .views-row h2 { + font-family: "gilroy-semibold"; + color: rgb(7, 50, 194); + font-size: 0.6rem; +} +#ressources .layout-content .content_container .views-element-container .group-content .views-row p { + font-size: 0.5rem; +} +#ressources .layout-content .content_container .views-element-container .group-content .views-row .field_field_mots_clefs div { + display: flex; + flex-direction: row; +} +#ressources .layout-content .content_container .views-element-container .group-content .views-row .field_field_mots_clefs div div { + border: solid 1px rgb(7, 50, 194); + margin-right: 0.2rem; + padding: 1.3%; + padding-bottom: 0.2%; + padding-top: 0.2%; + font-size: 0.4rem; + font-family: "gilroy-semibold"; +} +#ressources .layout-content .content_container .views-element-container .group-content .views-row .field_field_mots_clefs div div a { + color: rgb(7, 50, 194); +} +#ressources .layout-content .content_container .views-element-container .group-content .views-row .field_field_site div a { + position: relative; + padding-left: 20px; + color: rgb(247, 0, 43); + font-family: "gilroy-semibold"; +} +#ressources .layout-content .content_container .views-element-container .group-content .views-row .field_field_site div a:before { + content: ""; + position: absolute; + left: 0; + top: 50%; + transform: translateY(-50%); + width: 1em; + height: 1em; + background-image: url("../img/map_pointer.svg"); + background-size: contain; + background-repeat: no-repeat; +} + +#ressources .group-content { + padding: 10px; + border-radius: 8px; + margin-bottom: 10px; +} +#ressources .views-row { + padding: 8px; + margin: 2px 0; + border-radius: 4px; + transition: max-height 0.5s ease, opacity 0.5s ease; +} +#ressources .hidden { + max-height: 0; + overflow: hidden; + opacity: 0; +} +#ressources .toggle-btn { + background: none; + color: rgb(7, 50, 194); + border: solid rgb(7, 50, 194) 1px; + padding: 8px 12px; + cursor: pointer; + margin-top: 5px; + display: block; + margin: auto; + width: 20%; + text-align: center; + transition: background 0.3s; +} +#ressources .toggle-btn:hover { + background: rgb(7, 50, 194); + color: white; } \ No newline at end of file diff --git a/web/themes/custom/quartiers_de_demain/quartiers_de_demain.theme b/web/themes/custom/quartiers_de_demain/quartiers_de_demain.theme index e6ea426..e8c6a83 100644 --- a/web/themes/custom/quartiers_de_demain/quartiers_de_demain.theme +++ b/web/themes/custom/quartiers_de_demain/quartiers_de_demain.theme @@ -62,6 +62,7 @@ function quartiers_de_demain_preprocess_field(&$variables) { } } + /** * Prepares variables for block templates. * 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 8e7c646..9bb15c1 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 @@ -685,6 +685,91 @@ document.addEventListener("DOMContentLoaded", function () { }); +////////////////////////////////////////// + + +/////////// 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); diff --git a/web/themes/custom/quartiers_de_demain/src/assets/scss/pages/bouton-ressources.scss b/web/themes/custom/quartiers_de_demain/src/assets/scss/pages/bouton-ressources.scss new file mode 100644 index 0000000..413c155 --- /dev/null +++ b/web/themes/custom/quartiers_de_demain/src/assets/scss/pages/bouton-ressources.scss @@ -0,0 +1,42 @@ +#ressources{ + .group-content { + // background: #f9f9f9; + padding: 10px; + border-radius: 8px; + margin-bottom: 10px; + // box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); + } + + .views-row { + padding: 8px; + // background: #f3f3f3; + margin: 2px 0; + border-radius: 4px; + transition: max-height 0.5s ease, opacity 0.5s ease; + } + + .hidden { + max-height: 0; + overflow: hidden; + opacity: 0; + } + + .toggle-btn { + background: none; + color: $blue_QDD; + border: solid $blue_QDD 1px; + padding: 8px 12px; + cursor: pointer; + margin-top: 5px; + display: block; + margin: auto; + width: 20%; + text-align: center; + transition: background 0.3s; + } + + .toggle-btn:hover { + background: $blue_QDD; + color:white; + } +} \ No newline at end of file diff --git a/web/themes/custom/quartiers_de_demain/src/assets/scss/pages/node-type-site.scss b/web/themes/custom/quartiers_de_demain/src/assets/scss/pages/node-type-site.scss index 84f7e9d..6359aa6 100644 --- a/web/themes/custom/quartiers_de_demain/src/assets/scss/pages/node-type-site.scss +++ b/web/themes/custom/quartiers_de_demain/src/assets/scss/pages/node-type-site.scss @@ -340,6 +340,7 @@ div{ display: flex; flex-direction: row; + margin-bottom: 1rem; @media(max-width: 500px){ justify-content: center; } @@ -460,6 +461,3 @@ display: flex; flex-direction: column; } -.html.js.sr body.node-type-site.node-id-40 div.dialog-off-canvas-main-canvas div#page-node.layout-container main div.layout-content div.content_container div.layout.layout--threecol-25-50-25 div.layout__region.layout__region--third div.block-region-third div div.field_field_documents div div span{ - visibility: hidden; -} diff --git a/web/themes/custom/quartiers_de_demain/src/assets/scss/pages/ressources.scss b/web/themes/custom/quartiers_de_demain/src/assets/scss/pages/ressources.scss new file mode 100644 index 0000000..dbb5b08 --- /dev/null +++ b/web/themes/custom/quartiers_de_demain/src/assets/scss/pages/ressources.scss @@ -0,0 +1,128 @@ + +#ressources{ + background-color: #f6f7f3; + + + .layout-content{ + // padding-top: 1rem; + .content_container{ + display: flex; + flex-direction: column; + align-items: center; + + #block-quartiers-de-demain-titredepage{ + margin-top: 1rem; + width: fit-content; + @media(max-width: 810px){ + margin-top: 14rem; + } + h1{ + text-transform: none; + color: black; + font-size: 2rem; + font-family: "gilroy-medium" + } + + + } + .views-element-container{ + margin-left: 15%; + width: 70%; + .group-content{ + display: flex; + flex-direction: row; + flex-wrap: wrap; + + h3{ + &::before{ + content:""; + display: block; + border-bottom: solid 2px $blue_QDD; + // width: 80% ; + margin: auto; + } + text-align: center; + // width: 100%; + flex: 0 0 100%; + div{ + .field_name{ + h2{ + a{ + font-family: "gilroy-light"; + color: $blue_QDD; + font-size: 2rem; + } + + } + } + .field_description{ + font-family: "gilroy-light"; + } + } + + } + .views-row{ + width: 30%; + font-size: 0.5rem; + h2{ + font-family: "gilroy-semibold"; + color: $blue_QDD; + font-size: 00.6rem; + } + p{ + font-size: 0.5rem; + } + .field_field_mots_clefs{ + div{ + display: flex; + flex-direction: row; + div{ + border: solid 1px $blue_QDD; + margin-right: 0.2rem; + padding: 1.3%; + padding-bottom: 0.2%; + padding-top: 0.2%; + font-size: 0.4rem; + font-family: "gilroy-semibold"; + a{ + color: $blue_QDD; + } + } + } + + } + .field_field_site{ + div { + + a { + position: relative; + padding-left: 20px; // Ajuster selon la taille de l'icône + + &:before { + content: ""; + position: absolute; + left: 0; + top: 50%; + transform: translateY(-50%); + width: 1em; + height: 1em; + background-image: url("../img/map_pointer.svg"); + background-size: contain; + background-repeat: no-repeat; + } + + color: $red_QDD; + font-family: "gilroy-semibold"; + } + } + + } + } + + } + + } + + } + } +} diff --git a/web/themes/custom/quartiers_de_demain/src/assets/scss/quartiers_de_demain.scss b/web/themes/custom/quartiers_de_demain/src/assets/scss/quartiers_de_demain.scss index d6c24e9..1eaa9ec 100644 --- a/web/themes/custom/quartiers_de_demain/src/assets/scss/quartiers_de_demain.scss +++ b/web/themes/custom/quartiers_de_demain/src/assets/scss/quartiers_de_demain.scss @@ -48,6 +48,8 @@ @import "pages/actualite"; @import "pages/node-type-site"; @import "pages/lessites.scss"; +@import "pages/ressources"; +@import "pages/bouton-ressources"; @import "/home/ouidade/Developer/docker-quartiersdedemain/src/web/modules/custom/q2d_mod/assets/css/carte-interactive-qdd.css"; \ No newline at end of file diff --git a/web/themes/custom/quartiers_de_demain/templates/page--ressources.html.twig b/web/themes/custom/quartiers_de_demain/templates/page--ressources.html.twig new file mode 100644 index 0000000..200cdb1 --- /dev/null +++ b/web/themes/custom/quartiers_de_demain/templates/page--ressources.html.twig @@ -0,0 +1,97 @@ +{# +/** + * @file + * Claro's theme implementation to display a single Drupal page. + * + * The doctype, html, head, and body tags are not in this template. Instead + * they can be found in the html.html.twig template normally located in the + * core/modules/system directory. + * + * Available variables: + * + * General utility variables: + * - base_path: The base URL path of the Drupal installation. Will usually be + * "/" unless you have installed Drupal in a sub-directory. + * - is_front: A flag indicating if the current page is the front page. + * - logged_in: A flag indicating if the user is registered and signed in. + * - is_admin: A flag indicating if the user has permission to access + * administration pages. + * + * Site identity: + * - front_page: The URL of the front page. Use this instead of base_path when + * linking to the front page. This includes the language domain or prefix. + * + * Page content (in order of occurrence in the default page.html.twig): + * - node: Fully loaded node, if there is an automatically-loaded node + * associated with the page and the node ID is the second argument in the + * page's path (e.g. node/12345 and node/12345/revisions, but not + * comment/reply/12345). + * + * Regions: + * - page.header: Items for the header region. + * - page.pre_content: Items for the pre-content region. + * - page.breadcrumb: Items for the breadcrumb region. + * - page.highlighted: Items for the highlighted region. + * - page.help: Dynamic help text, mostly for admin pages. + * - page.content: The main content of the current page. + * + * @see template_preprocess_page() + * @see html.html.twig + */ +#} +