From 286c3cad969481227da3aeb2b46e4610221583f1 Mon Sep 17 00:00:00 2001 From: Florian Sylvain Date: Tue, 2 Nov 2021 22:29:42 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Hamburger=20menu=20integration=20an?= =?UTF-8?q?d=20style=20improvements?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ProjetProgWeb/app.js | 88 ++++++++++++++++++-------- ProjetProgWeb/index.php | 1 - ProjetProgWeb/navbar.php | 15 +++++ ProjetProgWeb/stylesheet.css | 117 +++++++++++++++++++++++++++++++++-- 4 files changed, 187 insertions(+), 34 deletions(-) diff --git a/ProjetProgWeb/app.js b/ProjetProgWeb/app.js index 8a6e470..ef618b8 100644 --- a/ProjetProgWeb/app.js +++ b/ProjetProgWeb/app.js @@ -3,20 +3,47 @@ let searchBar = document.querySelector('#searchbar') let searchBarButton = document.querySelector('#search-button') let suggestions = document.querySelector('#suggestions') let loader = document.querySelector('.loader') -let error = document.querySelector("#error") -let errorMessage = document.querySelector("#error-message") -let errorButton = document.querySelector("#error-button") +let error = document.querySelector('#error') +let errorMessage = document.querySelector('#error-message') +let errorButton = document.querySelector('#error-button') +let hamMenu = document.querySelector('#hamburger-menu') +let header = document.querySelector('header') + +function sanitize(chain) { + return chain.replace(/[^a-zA-Z0-9 ]/g,'') +} + +function showSuggestions() { + if (!suggestionsDisplayed) { + navbarForm.style.borderRadius = '15px 15px 0 0' + suggestions.style.display = 'block' + searchBarButton.style.boxShadow = 'none' + searchBarButton.classList.replace('animation-in', 'animation-out') + suggestionsDisplayed = true + } +} + +function hideSuggestions() { + if (suggestionsDisplayed) { + navbarForm.style.borderRadius = '15px' + suggestions.style.display = 'none' + searchBarButton.style.boxShadow = 'rgba(0, 0, 0, 0.15) 4px 2px 5px' + searchBarButton.classList.replace('animation-out', 'animation-in') + suggestionsDisplayed = false + } +} let authorName = ""; let lastRequest = null function requestToApi(author) { + hideSuggestions() if (lastRequest === null || (new Date().getTime() - lastRequest) > 1000) { lastRequest = new Date().getTime() document.querySelector('#results-count').innerHTML = "" document.querySelector('#results').innerHTML = "" loader.style.display = "block" - authorName = author.replace(/[^a-zA-Z0-9]/g,'') + authorName = sanitize(author) fetch(`api.php?q=theses&author=${author}`) .then(response => response.json()) .then(data => displayResults(data)) @@ -25,6 +52,7 @@ function requestToApi(author) { } } +window.addEventListener('scroll', fadeIn); let elementsToFade = null function fadeIn() { elementsToFade.forEach(elem => { @@ -45,7 +73,6 @@ function displayResults(results) { return; } else if (results.status === 200) { let count = 0 - results.data.forEach(elem => { let result = document.createElement('div') result.classList.add('result-element') @@ -67,7 +94,6 @@ function displayResults(results) { loader.style.display = "none" elementsToFade = document.querySelectorAll(".result-element") - window.addEventListener('scroll', fadeIn); fadeIn() } } @@ -78,15 +104,19 @@ let suggestionsDisplayed = false function realTimeDisplay() { let search = document.querySelector('input[name=\'author\']').value - search = search.replace(/[^a-zA-Z0-9 ]/g,'') - if (search.length > 3 && (search !== lastSearch || (new Date().getTime() - lastSuggestion) > 500)) { - showSuggestions() + search = sanitize(search) + if (search.length > 3 && (search !== lastSearch && (new Date().getTime() - lastSuggestion) > 500)) { lastSearch = search lastSuggestion = new Date().getTime() fetch(`api.php?q=authors&author=${search}`) .then(response => response.json()) .then(results => { suggestions.innerHTML = "" + if (!results.data.length) { + hideSuggestions() + } else { + showSuggestions() + } results.data.forEach(elem => { let name = document.createElement('p') name.innerHTML = elem @@ -100,42 +130,46 @@ function realTimeDisplay() { } } -function showSuggestions() { - if (!suggestionsDisplayed) { - navbarForm.style.borderRadius = '15px 15px 0 0' - suggestions.style.display = 'block' - searchBarButton.style.boxShadow = 'none' - searchBarButton.classList.replace('animation-in', 'animation-out') - suggestionsDisplayed = true - } -} - document.addEventListener('click', e => { if (e.target.id !== 'suggestions' && e.target !== searchBar && e.target !== searchBarButton) { - if (suggestionsDisplayed) { - navbarForm.style.borderRadius = '15px' - suggestions.style.display = 'none' - searchBarButton.style.boxShadow = 'rgba(0, 0, 0, 0.15) 4px 2px 5px' - searchBarButton.classList.replace('animation-out', 'animation-in') - suggestionsDisplayed = false - } - + hideSuggestions() if (e.target.id === 'hamburger' || e.target.id === 'hamburgerSvg' || e.target.id === 'crossSvg') { let ham = document.querySelector('#hamburgerSvg') let cross = document.querySelector('#crossSvg') if (ham.classList.contains('spin-fade')) { cross.classList.add('spin-fade') ham.classList.remove('spin-fade') + header.classList.replace('slide-in-header', 'slide-out-header') + hamMenu.classList.replace('slide-in', 'slide-out') } else { ham.classList.add('spin-fade') cross.classList.remove('spin-fade') + header.classList.remove('slide-out-header') + header.classList.add('slide-in-header') + hamMenu.classList.remove('slide-out') + hamMenu.classList.add('slide-in') } } if (e.target === errorButton) { error.classList.replace('fade-in', 'fade-out') } + + let toggleSwitch = null + if (e.target.classList.contains('slider')) { + toggleSwitch = e.target + } else if (e.target.classList.contains('toggle-switch')) { + toggleSwitch = e.target.firstElementChild + } + if (toggleSwitch !== null) { + if (toggleSwitch.classList.contains('untoggle')) { + toggleSwitch.classList.replace('untoggle', 'toggle') + } else { + toggleSwitch.classList.replace('toggle', 'untoggle') + } + } + } }) diff --git a/ProjetProgWeb/index.php b/ProjetProgWeb/index.php index 3827ab2..d89c56f 100644 --- a/ProjetProgWeb/index.php +++ b/ProjetProgWeb/index.php @@ -4,7 +4,6 @@ - Theses FR diff --git a/ProjetProgWeb/navbar.php b/ProjetProgWeb/navbar.php index bba639b..3ae2589 100644 --- a/ProjetProgWeb/navbar.php +++ b/ProjetProgWeb/navbar.php @@ -1,4 +1,5 @@
+ + +
+ +
+ + + +
+
+
+
+ +
+
diff --git a/ProjetProgWeb/stylesheet.css b/ProjetProgWeb/stylesheet.css index 55c7be2..92c1a00 100644 --- a/ProjetProgWeb/stylesheet.css +++ b/ProjetProgWeb/stylesheet.css @@ -14,14 +14,37 @@ body { overflow-x: hidden; } +header { + height: 75px; +} + +.slide-in-header { + animation: slide-in-header 200ms; + animation-fill-mode: forwards; +} +.slide-out-header { + animation: slide-out-header 200ms; + animation-fill-mode: forwards; +} +@keyframes slide-in-header { + from { margin-bottom: 0 } + to { margin-bottom: 100px } +} +@keyframes slide-out-header { + from { margin-bottom: 100px } + to { margin-bottom: 0 } +} + .navbar { + position: relative; + z-index: 50; display: flex; align-items: center; justify-content: center; gap: 10px; background: linear-gradient(245deg, #39B4E7 -15%, #0096DC 110%); box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 5px; - height: 75px; + height: 100%; padding: 10px; width: 100%; } @@ -50,11 +73,6 @@ body { width: 100%; } -/* TODO : Ajouter une ombre quand on hover ou focus l'input (voir page google.com)*/ -/*.navbar input:hover, .navbar input:focus {*/ -/* box-shadow: rgba(0, 0, 0, 0.15) 0 2px 5px;*/ -/*}*/ - .navbar button { align-self: center; height: 60px; @@ -138,6 +156,93 @@ body { opacity: 0; } +#hamburger-menu { + position: relative; + z-index: 10; + width: 100%; + height: 100px; + background: linear-gradient(245deg, #39B4E7 -15%, #1779A3 110%); + box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 5px; + top: 0; + transform: translateY(-110px); + display: flex; + flex-direction: column; + padding: 10px; + gap: 10px; +} +.slide-in { + animation: slide-in 200ms; + animation-fill-mode: forwards; +} +.slide-out { + animation: slide-out 200ms; + animation-fill-mode: forwards; +} +@keyframes slide-in { + from { transform: translateY(-100px) } + to { transform: translateY(0) } +} +@keyframes slide-out { + from { transform: translateY(0) } + to { transform: translateY(-100px) } +} + +.toggle-switch { + user-select: none; + display: flex; + align-items: center; + background-color: white; + width: 60px; + height: 30px; + border-radius: 25px; + padding: 0 3px 0 3px; +} +.toggle-switch .slider { + user-select: none; + width: 25px; + height: 25px; + border-radius: 25px; +} +.toggle { + animation: toggle 200ms; + animation-fill-mode: forwards; +} +.untoggle { + animation: untoggle 200ms; + animation-fill-mode: forwards; +} +@keyframes toggle { + from { + transform: translateX(0); + opacity: 70%; + background: gray; + } + to { + transform: translateX(29px); + opacity: 100%; + background: #39B4E7; + } +} +@keyframes untoggle { + from { + transform: translateX(29px); + opacity: 100%; + background: #39B4E7; + } + to { + transform: translateX(0); + opacity: 70%; + background: gray; + } +} + +.chart-button { + display: flex; + align-items: center; + fill: white; + gap: 10px; +} + #results { margin: 10px; display: flex;