From 1c180411e0b6c16993b9d95a81dc243102afe4bd Mon Sep 17 00:00:00 2001 From: ouidade Date: Wed, 10 Jul 2024 17:01:16 +0200 Subject: [PATCH] header vm js --- .../quartiers_de_demain/dist/assets/bundle.js | 2 +- .../dist/assets/css/bundle.css | 83 ++++++++++++++--- .../src/assets/js/header.js | 93 +++++++++++++++++++ .../src/assets/js/quartiers_de_demain.js | 64 +++++++++++-- .../src/assets/scss/pages/consultation.scss | 6 +- .../src/assets/scss/pages/home.scss | 1 + .../scss/partials/actu-caroussel-home.scss | 7 +- .../src/assets/scss/partials/header.scss | 44 +++++++-- .../src/assets/scss/partials/slick-theme.scss | 14 ++- 9 files changed, 279 insertions(+), 35 deletions(-) create mode 100644 web/themes/custom/quartiers_de_demain/src/assets/js/header.js 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 4e63732..c1715d6 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("\nfunction setLogoContainerSize() {\n let svgContainer = document.query \**********************************************/ /***/ (() => { -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 // jQuery(document).ready(function($){\n\n // $('.open-block').click(function(){\n // $(this).toggleClass('opened');\n\n // $('.header_nav_container').toggleClass('display-nav-opened');\n \n // if(mobile == true){\n // $(\"body\").css(\"overflow\",\"hidden\");\n // }\n\n // });\n \n // // Hide the header_nav_container when a link inside it is clicked\n // $('.header_nav_container li').click(function() {\n // $('.header_nav_container').fadeOut();\n // });\n\n\n\n\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 // 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 \n if (scrollTop > threshold && !isHidden) {\n slideOut();\n } else if (scrollTop <= threshold && isHidden) {\n slideIn();\n }\n \n lastScrollTop = scrollTop <= 0 ? 0 : scrollTop; // For Mobile or negative scrolling\n }\n \n function handleTouchAndMouseEnter() {\n if (isHidden) {\n slideIn();\n }\n }\n \n function handleTouchAndMouseLeave() {\n if (lastScrollTop > threshold && !isHidden) {\n slideOut();\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 slideIn();\n } else {\n slideOut();\n }\n \n });\n\n //////// end header ////////////\n \n\n\n//// ancre dans texte au click parragraphe 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 }\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 }\n\n\n $( document ).ready(function() {\n scrollReaveal();\n });\n\n //////////////////////// end script smooth apparition des textes /////////////////\n\n //////////////////// start Timeline script ///////////////////////\n\n\n document.addEventListener('DOMContentLoaded', function() {\n let currentSlide = 0;\n\n //// responsive ///\n function getVisibleSlides() {\n if (window.innerWidth <= 600) {\n return 1; // Show 1 slide on small screens\n } else if (window.innerWidth <= 900) {\n return 2; // Show 2 slides on medium screens\n } else {\n return 3; // Show 3 slides on large screens\n }\n }\n\n function showSlides(index) {\n const slides = document.querySelectorAll('.paragraph--type--phase-deroulement');\n const totalSlides = slides.length;\n const visibleSlides = getVisibleSlides();\n const maxSlide = totalSlides - visibleSlides + 1;\n\n // Adjust the index to ensure it stays within bounds\n currentSlide = Math.max(0.6, Math.min(index, maxSlide));\n\n // Calculate the offset for the transform\n const offset = currentSlide * -70 / visibleSlides;\n document.querySelector('.__timeline-content').style.transform = `translateX(${offset}%)`;\n\n // Enable/disable arrows based on the current slide\n document.getElementById('arrowPrev').disabled = currentSlide === 0;\n document.getElementById('arrowNext').disabled = currentSlide === maxSlide;\n }\n\n function prevSlide() {\n showSlides(currentSlide - 1);\n }\n\n function nextSlide() {\n showSlides(currentSlide + 1);\n }\n\n // Attach event listeners\n document.getElementById('arrowPrev').addEventListener('click', prevSlide);\n document.getElementById('arrowNext').addEventListener('click', nextSlide);\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.length >= 3) {\n monthField.textContent = monthText.slice(0, 3);\n }\n }\n });\n\n // for each .date element add or remove ::before \n document.querySelectorAll('.date').forEach(function(dateElement) {\n const date2Element = dateElement.querySelector('.date2');\n const yearElement = dateElement.querySelector('.field_field_date_de_annee');\n\n // Check if the .date2 element is empty\n if (date2Element && !date2Element.textContent.trim()) {\n // Add the .only class to the year element\n yearElement.classList.add('only');\n }\n });\n\n // Handle window resize\n window.addEventListener('resize', function() {\n showSlides(currentSlide); // Recalculate the slides on resize\n });\n // });\n\n\n // Initialize\n showSlides(currentSlide);\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 //////////// slideshow home ////////////////////////// \n\n $(document).ready(function(){\n $('.content-actus .view').slick({\n slidesToShow: 3,\n // slidesToScroll: 1,\n dots: false,\n arrows: true,\n centerMode: true,\n adaptiveHeight: true,\n // centerPadding: '100px',\n responsive: [\n {\n breakpoint: 810,\n settings: {\n slidesToShow: 1,\n adaptiveHeight: false,\n arrows: true,\n draggable: true,\n centerMode: true,\n }\n }]\n });\n console.log('salut slick home');\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 // jQuery(document).ready(function($){\n\n // $('.open-block').click(function(){\n // $(this).toggleClass('opened');\n\n // $('.header_nav_container').toggleClass('display-nav-opened');\n \n // if(mobile == true){\n // $(\"body\").css(\"overflow\",\"hidden\");\n // }\n\n // });\n \n // // Hide the header_nav_container when a link inside it is clicked\n // $('.header_nav_container li').click(function() {\n // $('.header_nav_container').fadeOut();\n // });\n\n\n\n\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 < 810;\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 < 810) {\n slideDown();\n } else {\n slideIn();\n }\n }\n }\n \n function handleTouchAndMouseLeave() {\n if (lastScrollTop > threshold && !isHidden) {\n if (window.innerWidth < 810) {\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 < 810) {\n slideDown();\n } else { \n slideIn();\n } \n } else {\n if (window.innerWidth < 810) {\n slideUp();\n } else {\n slideIn();\n }\n }\n \n });\n\n //////// end header ////////////\n \n\n\n//// ancre dans texte au click parragraphe 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 }\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 }\n\n\n $( document ).ready(function() {\n scrollReaveal();\n });\n\n //////////////////////// end script smooth apparition des textes /////////////////\n\n //////////////////// start Timeline script ///////////////////////\n\n\n document.addEventListener('DOMContentLoaded', function() {\n let currentSlide = 0;\n\n //// responsive ///\n function getVisibleSlides() {\n if (window.innerWidth <= 600) {\n return 1; // Show 1 slide on small screens\n } else if (window.innerWidth <= 900) {\n return 2; // Show 2 slides on medium screens\n } else {\n return 3; // Show 3 slides on large screens\n }\n }\n\n function showSlides(index) {\n const slides = document.querySelectorAll('.paragraph--type--phase-deroulement');\n const totalSlides = slides.length;\n const visibleSlides = getVisibleSlides();\n const maxSlide = totalSlides - visibleSlides + 1;\n\n // Adjust the index to ensure it stays within bounds\n currentSlide = Math.max(0.6, Math.min(index, maxSlide));\n\n // Calculate the offset for the transform\n const offset = currentSlide * -70 / visibleSlides;\n document.querySelector('.__timeline-content').style.transform = `translateX(${offset}%)`;\n\n // Enable/disable arrows based on the current slide\n document.getElementById('arrowPrev').disabled = currentSlide === 0;\n document.getElementById('arrowNext').disabled = currentSlide === maxSlide;\n }\n\n function prevSlide() {\n showSlides(currentSlide - 1);\n }\n\n function nextSlide() {\n showSlides(currentSlide + 1);\n }\n\n // Attach event listeners\n document.getElementById('arrowPrev').addEventListener('click', prevSlide);\n document.getElementById('arrowNext').addEventListener('click', nextSlide);\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.length >= 3) {\n monthField.textContent = monthText.slice(0, 3);\n }\n }\n });\n\n // for each .date element add or remove ::before \n document.querySelectorAll('.date').forEach(function(dateElement) {\n const date2Element = dateElement.querySelector('.date2');\n const yearElement = dateElement.querySelector('.field_field_date_de_annee');\n\n // Check if the .date2 element is empty\n if (date2Element && !date2Element.textContent.trim()) {\n // Add the .only class to the year element\n yearElement.classList.add('only');\n }\n });\n\n // Handle window resize\n window.addEventListener('resize', function() {\n showSlides(currentSlide); // Recalculate the slides on resize\n });\n // });\n\n\n // Initialize\n showSlides(currentSlide);\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 //////////// slideshow home ////////////////////////// \n\n $(document).ready(function(){\n $('.content-actus .view').slick({\n slidesToShow: 3,\n // slidesToScroll: 1,\n dots: false,\n arrows: true,\n centerMode: true,\n adaptiveHeight: true,\n // centerPadding: '100px',\n responsive: [\n {\n breakpoint: 810,\n settings: {\n slidesToShow: 1,\n adaptiveHeight: false,\n arrows: true,\n draggable: true,\n centerMode: true,\n }\n }]\n });\n console.log('salut slick home');\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/dist/assets/css/bundle.css b/web/themes/custom/quartiers_de_demain/dist/assets/css/bundle.css index 2906587..61608c8 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 @@ -243,7 +243,7 @@ header { } @media (max-width: 810px) { header { - height: 170px; + height: 100vh; } } header .contextual-region { @@ -378,6 +378,7 @@ header .header_nav_container #block-quartiers-de-demain-entete ul { @media (max-width: 810px) { header .header_nav_container #block-quartiers-de-demain-entete ul { top: 27.5px; + padding-left: 15%; } } @media (max-width: 1090px) { @@ -421,38 +422,79 @@ header .header:hover + .header_nav_container { } .shrink { - height: 260px !important; + height: 260px; +} +@media (max-width: 810px) { + .shrink { + height: 170px; + } } /* Taille définitive du header après l'animation */ .header--collapsed { height: 320px; /* Ou la hauteur que vous souhaitez pour votre header */ width: 45%; - transform-origin: bottom right; /* Origine de la transformation à l'angle bas droit */ + transform-origin: bottom right; transition: all 1s ease-in-out; } +@media (max-width: 810px) { + .header--collapsed { + width: 100%; + height: 170px; + } +} .header--collapsed .header_left_container { flex: 0 0 60%; - transform-origin: bottom right; /* Origine de la transformation à l'angle bas droit */ + transform-origin: bottom right; +} +@media (max-width: 810px) { + .header--collapsed .header_left_container { + flex: 1 0 100%; + } } .header--collapsed .header_nav_container { flex: 0 0 30%; - transform-origin: bottom right; /* Origine de la transformation à l'angle bas droit */ + transform-origin: bottom right; +} +@media (max-width: 810px) { + .header--collapsed .header_nav_container { + flex: 1 0 100%; + position: relative; + left: -100%; + } } .header--collapsed-already { height: 320px; /* Ou la hauteur que vous souhaitez pour votre header */ width: 45%; - transform-origin: bottom right; /* Origine de la transformation à l'angle bas droit */ + transform-origin: bottom right; transition: all 0s ease-in-out; } +@media (max-width: 810px) { + .header--collapsed-already { + width: 100%; + height: 170px; + } +} .header--collapsed-already .header_left_container { flex: 0 0 60%; - transform-origin: bottom right; /* Origine de la transformation à l'angle bas droit */ + transform-origin: bottom right; +} +@media (max-width: 810px) { + .header--collapsed-already .header_left_container { + flex: 1 0 100%; + } } .header--collapsed-already .header_nav_container { flex: 0 0 30%; - transform-origin: bottom right; /* Origine de la transformation à l'angle bas droit */ + transform-origin: bottom right; +} +@media (max-width: 810px) { + .header--collapsed-already .header_nav_container { + flex: 1 0 100%; + position: relative; + left: -100%; + } } footer { @@ -800,7 +842,7 @@ footer { } @media (max-width: 810px) { .slick-prev { - left: 29%; + left: 35%; } } [dir=rtl] .slick-prev { @@ -809,9 +851,13 @@ footer { } .slick-prev:before { content: url("../img/prev.svg "); + display: block; + transform: scale(0.8); } [dir=rtl] .slick-prev:before { content: url("../img/next.svg "); + display: block; + transform: scale(0.8); } .slick-next { @@ -828,9 +874,13 @@ footer { } .slick-next:before { content: url("../img/next.svg "); + display: block; + transform: scale(0.8); } [dir=rtl] .slick-next:before { content: url("../img/prev.svg "); + display: block; + transform: scale(0.8); } /* Dots */ @@ -1199,7 +1249,7 @@ footer { display: flex; flex-direction: column; align-items: center; - padding-bottom: 3rem; + padding-bottom: 6rem; } #actus-caroussel h2 { width: fit-content; @@ -1222,6 +1272,7 @@ footer { @media (max-width: 550px) { #actus-caroussel .content-actus .views-row { width: 296px !important; + padding-top: 3rem; } } #actus-caroussel .content-actus .views-row article.node-type-actualite { @@ -1328,6 +1379,11 @@ footer { position: relative; top: 60px; } +@media (max-width: 550px) { + #actus-caroussel .content-actus .views-row:nth-child(odd) { + top: 0; + } +} header #block-quartiers-de-demain-logoquartiersdedemain .field_field_logo .qdd-header.animated { transform: scale(2); @@ -1767,6 +1823,7 @@ header #block-quartiers-de-demain-logoquartiersdedemain .field_field_logo .qdd-h #home article.node-type-static #paragraph-id--7 .field_field_texte .colone-picto { grid-template-rows: repeat(10 auto); grid-template-columns: repeat(2 1fr); + padding-left: 0; } } #home article.node-type-static #paragraph-id--7 .field_field_texte .colone-picto h5 { @@ -1963,19 +2020,19 @@ header #block-quartiers-de-demain-logoquartiersdedemain .field_field_logo .qdd-h } @media (max-width: 500px) { #consultation .layout-content .content_container .node-type-static #paragraph-id--10 .colone-picto p:not(:last-of-type) { - flex: 1 25%; + flex: 0 40%; } } #consultation .layout-content .content_container .node-type-static #paragraph-id--10 .colone-picto p:not(:last-of-type)::before { content: ""; display: block; border-left: solid 1px rgb(7, 50, 194); - height: 20%; + height: 30px; margin-bottom: 0.5rem; } @media (max-width: 500px) { #consultation .layout-content .content_container .node-type-static #paragraph-id--10 .colone-picto p:not(:last-of-type)::before { - height: 15%; + height: 30px; } } #consultation .layout-content .content_container .node-type-static #paragraph-id--10 .colone-picto p:last-of-type { diff --git a/web/themes/custom/quartiers_de_demain/src/assets/js/header.js b/web/themes/custom/quartiers_de_demain/src/assets/js/header.js new file mode 100644 index 0000000..a2d908b --- /dev/null +++ b/web/themes/custom/quartiers_de_demain/src/assets/js/header.js @@ -0,0 +1,93 @@ + //////// header //////////// + + document.addEventListener('DOMContentLoaded', function() { + + const header = document.querySelector('header'); + // Vérifier si la page a été rechargée ou si c'est une navigation interne + const isFirstLoad = !performance.getEntriesByType("navigation")[0].type.includes('back_forward'); + // Vérifier si nous sommes sur la page cible + const isTargetPath = window.location.pathname === '/'; // Remplacez '/votre-chemin-cible' par le chemin réel + + // 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'); + } else { + // Sinon, appliquer la transition après un délai + setTimeout(() => { + header.classList.add('header--collapsed'); + }, 1000); // Attendre 1 seconde avant de réduire la taille du header + } + + + // Gestion du scroll pour afficher/masquer le header nav + const headerNavContainer = document.querySelector('.header_nav_container'); + const headerLeftContainer = document.querySelector('header'); + 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 handleScroll() { + let scrollTop = window.pageYOffset || document.documentElement.scrollTop; + + if (scrollTop > threshold && !isHidden) { + slideOut(); + } else if (scrollTop <= threshold && isHidden) { + slideIn(); + } + + lastScrollTop = scrollTop <= 0 ? 0 : scrollTop; // For Mobile or negative scrolling + } + + function handleTouchAndMouseEnter() { + if (isHidden) { + slideIn(); + } + } + + function handleTouchAndMouseLeave() { + if (lastScrollTop > threshold && !isHidden) { + slideOut(); + } + } + + window.addEventListener('scroll', handleScroll); + + // Mouse events for desktop + headerLeftContainer.addEventListener('mouseenter', handleTouchAndMouseEnter); + headerLeftContainer.addEventListener('mouseleave', handleTouchAndMouseLeave); + + // Touch events for tablets and mobile devices + headerLeftContainer.addEventListener('touchstart', handleTouchAndMouseEnter); + headerLeftContainer.addEventListener('touchend', handleTouchAndMouseLeave); + + // Initial check to see if we're at the top of the page + if (window.pageYOffset <= threshold) { + slideIn(); + } else { + slideOut(); + } + }); + + 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 ef0839b..ad561e2 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 @@ -122,6 +122,30 @@ 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) { @@ -133,25 +157,43 @@ function handleScroll() { let scrollTop = window.pageYOffset || document.documentElement.scrollTop; - + const isMobile = window.innerWidth < 810; + if (scrollTop > threshold && !isHidden) { - slideOut(); + if (isMobile) { + slideUp(); + } else { + slideOut(); + } } else if (scrollTop <= threshold && isHidden) { - slideIn(); + if (isMobile) { + slideDown(); + } else { + slideIn(); + } } + lastScrollTop = scrollTop <= 0 ? 0 : scrollTop; // For Mobile or negative scrolling } function handleTouchAndMouseEnter() { if (isHidden) { - slideIn(); + if (window.innerWidth < 810) { + slideDown(); + } else { + slideIn(); + } } } function handleTouchAndMouseLeave() { if (lastScrollTop > threshold && !isHidden) { - slideOut(); + if (window.innerWidth < 810) { + slideUp(); + } else { + slideOut(); + } } } @@ -168,9 +210,17 @@ // Initial check to see if we're at the top of the page if (window.pageYOffset <= threshold) { - slideIn(); + if (window.innerWidth < 810) { + slideDown(); + } else { + slideIn(); + } } else { - slideOut(); + if (window.innerWidth < 810) { + slideUp(); + } else { + slideIn(); + } } }); diff --git a/web/themes/custom/quartiers_de_demain/src/assets/scss/pages/consultation.scss b/web/themes/custom/quartiers_de_demain/src/assets/scss/pages/consultation.scss index e3d2072..60c078f 100644 --- a/web/themes/custom/quartiers_de_demain/src/assets/scss/pages/consultation.scss +++ b/web/themes/custom/quartiers_de_demain/src/assets/scss/pages/consultation.scss @@ -64,16 +64,16 @@ padding: 0.5rem; margin-top: 0; @media(max-width: 500px){ - flex: 1 25%; + flex: 0 40%; } &::before{ content:""; display: block; border-left: solid 1px $blue_QDD; - height: 20%; + height: 30px; margin-bottom: 0.5rem; @media(max-width: 500px){ - height: 15%; + height: 30px; } } } 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 4432bb6..a52929f 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 @@ -347,6 +347,7 @@ @media(max-width: 700px){ grid-template-rows: repeat(10 auto); grid-template-columns: repeat(2 1fr); + padding-left: 0; } h5{ 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 c26a8ff..81fd1d7 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: 3rem; + padding-bottom: 6rem; h2{ width: fit-content; padding-bottom: 1.5rem; @@ -17,7 +17,6 @@ flex-direction: row; flex-wrap: nowrap; width: 100vw; - } .views-row{ width: 650px !important; @@ -25,6 +24,7 @@ @media(max-width: 550px){ width: 296px !important; + padding-top: 3rem; } article.node-type-actualite{ display: flex; @@ -132,6 +132,9 @@ .views-row:nth-child(odd){ position: relative; top: 60px; + @media(max-width: 550px){ + top: 0; + } } 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 a3d8995..4091246 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 @@ -12,7 +12,7 @@ header{ // transition: height 2s ease-in-out, width 2s ease-in-out; /* Transition pour le changement de taille */ // transition: height 0.3s, padding 0.3s; /* Add transition for smooth resizing */ @media(max-width: 810px){ - height: 170px; + height: 100vh; } .contextual-region{ @@ -128,6 +128,7 @@ header{ margin: 0; @media(max-width: 810px){ top: calc($header-height-pad / 4 ); + padding-left: 15%; } li{ @media(max-width: 1090px){ @@ -190,36 +191,63 @@ header{ } } .shrink{ - height: 260px !important; + height: 260px ; + @media(max-width: 810px){ + height: 170px; + } } /* Taille définitive du header après l'animation */ .header--collapsed { height: $header-height; /* Ou la hauteur que vous souhaitez pour votre header */ width: 45%; - transform-origin: bottom right; /* Origine de la transformation à l'angle bas droit */ + transform-origin: bottom right; transition: all 1s ease-in-out; + @media(max-width: 810px){ + width: 100%; + height: 170px; + } .header_left_container{ flex: 0 0 60%; - transform-origin: bottom right; /* Origine de la transformation à l'angle bas droit */ + transform-origin: bottom right; + @media(max-width: 810px){ + flex: 1 0 100%; + } } .header_nav_container{ flex: 0 0 30%; - transform-origin: bottom right; /* Origine de la transformation à l'angle bas droit */ + transform-origin: bottom right; + @media(max-width: 810px){ + flex: 1 0 100%; + position: relative; + left: -100%; + } } } .header--collapsed-already{ height: $header-height; /* Ou la hauteur que vous souhaitez pour votre header */ width: 45%; - transform-origin: bottom right; /* Origine de la transformation à l'angle bas droit */ + transform-origin: bottom right; transition: all 0s ease-in-out; + @media(max-width: 810px){ + width: 100%; + height: 170px; + } .header_left_container{ flex: 0 0 60%; - transform-origin: bottom right; /* Origine de la transformation à l'angle bas droit */ + transform-origin: bottom right; + @media(max-width: 810px){ + flex: 1 0 100%; + } } .header_nav_container{ flex: 0 0 30%; - transform-origin: bottom right; /* Origine de la transformation à l'angle bas droit */ + transform-origin: bottom right; + @media(max-width: 810px){ + flex: 1 0 100%; + position: relative; + left: -100%; + } } } diff --git a/web/themes/custom/quartiers_de_demain/src/assets/scss/partials/slick-theme.scss b/web/themes/custom/quartiers_de_demain/src/assets/scss/partials/slick-theme.scss index bd152fd..cd3f51e 100644 --- a/web/themes/custom/quartiers_de_demain/src/assets/scss/partials/slick-theme.scss +++ b/web/themes/custom/quartiers_de_demain/src/assets/scss/partials/slick-theme.scss @@ -115,7 +115,8 @@ $slick-opacity-not-active: 0.25 !default; .slick-prev { left: 46%; @media(max-width:810px){ - left: 29%; + left: 35%; + } [dir="rtl"] & { left: auto; @@ -123,8 +124,13 @@ $slick-opacity-not-active: 0.25 !default; } &:before { content: $slick-prev-character; + display: block; + transform: scale(0.8); [dir="rtl"] & { content: $slick-next-character; + display: block; + transform: scale(0.8); + } } } @@ -140,8 +146,14 @@ $slick-opacity-not-active: 0.25 !default; } &:before { content: $slick-next-character; + display: block; + transform: scale(0.8); + [dir="rtl"] & { content: $slick-prev-character; + display: block; + transform: scale(0.8); + } } }