mirror of
https://github.com/Floriansylvain/projet_programmation_web.git
synced 2026-08-19 19:53:18 +02:00
✨ Hamburger menu integration and style improvements
This commit is contained in:
+61
-27
@@ -3,20 +3,47 @@ let searchBar = document.querySelector('#searchbar')
|
|||||||
let searchBarButton = document.querySelector('#search-button')
|
let searchBarButton = document.querySelector('#search-button')
|
||||||
let suggestions = document.querySelector('#suggestions')
|
let suggestions = document.querySelector('#suggestions')
|
||||||
let loader = document.querySelector('.loader')
|
let loader = document.querySelector('.loader')
|
||||||
let error = document.querySelector("#error")
|
let error = document.querySelector('#error')
|
||||||
let errorMessage = document.querySelector("#error-message")
|
let errorMessage = document.querySelector('#error-message')
|
||||||
let errorButton = document.querySelector("#error-button")
|
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 authorName = "";
|
||||||
let lastRequest = null
|
let lastRequest = null
|
||||||
|
|
||||||
function requestToApi(author) {
|
function requestToApi(author) {
|
||||||
|
hideSuggestions()
|
||||||
if (lastRequest === null || (new Date().getTime() - lastRequest) > 1000) {
|
if (lastRequest === null || (new Date().getTime() - lastRequest) > 1000) {
|
||||||
lastRequest = new Date().getTime()
|
lastRequest = new Date().getTime()
|
||||||
document.querySelector('#results-count').innerHTML = ""
|
document.querySelector('#results-count').innerHTML = ""
|
||||||
document.querySelector('#results').innerHTML = ""
|
document.querySelector('#results').innerHTML = ""
|
||||||
loader.style.display = "block"
|
loader.style.display = "block"
|
||||||
authorName = author.replace(/[^a-zA-Z0-9]/g,'')
|
authorName = sanitize(author)
|
||||||
fetch(`api.php?q=theses&author=${author}`)
|
fetch(`api.php?q=theses&author=${author}`)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => displayResults(data))
|
.then(data => displayResults(data))
|
||||||
@@ -25,6 +52,7 @@ function requestToApi(author) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window.addEventListener('scroll', fadeIn);
|
||||||
let elementsToFade = null
|
let elementsToFade = null
|
||||||
function fadeIn() {
|
function fadeIn() {
|
||||||
elementsToFade.forEach(elem => {
|
elementsToFade.forEach(elem => {
|
||||||
@@ -45,7 +73,6 @@ function displayResults(results) {
|
|||||||
return;
|
return;
|
||||||
} else if (results.status === 200) {
|
} else if (results.status === 200) {
|
||||||
let count = 0
|
let count = 0
|
||||||
|
|
||||||
results.data.forEach(elem => {
|
results.data.forEach(elem => {
|
||||||
let result = document.createElement('div')
|
let result = document.createElement('div')
|
||||||
result.classList.add('result-element')
|
result.classList.add('result-element')
|
||||||
@@ -67,7 +94,6 @@ function displayResults(results) {
|
|||||||
loader.style.display = "none"
|
loader.style.display = "none"
|
||||||
|
|
||||||
elementsToFade = document.querySelectorAll(".result-element")
|
elementsToFade = document.querySelectorAll(".result-element")
|
||||||
window.addEventListener('scroll', fadeIn);
|
|
||||||
fadeIn()
|
fadeIn()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,15 +104,19 @@ let suggestionsDisplayed = false
|
|||||||
|
|
||||||
function realTimeDisplay() {
|
function realTimeDisplay() {
|
||||||
let search = document.querySelector('input[name=\'author\']').value
|
let search = document.querySelector('input[name=\'author\']').value
|
||||||
search = search.replace(/[^a-zA-Z0-9 ]/g,'')
|
search = sanitize(search)
|
||||||
if (search.length > 3 && (search !== lastSearch || (new Date().getTime() - lastSuggestion) > 500)) {
|
if (search.length > 3 && (search !== lastSearch && (new Date().getTime() - lastSuggestion) > 500)) {
|
||||||
showSuggestions()
|
|
||||||
lastSearch = search
|
lastSearch = search
|
||||||
lastSuggestion = new Date().getTime()
|
lastSuggestion = new Date().getTime()
|
||||||
fetch(`api.php?q=authors&author=${search}`)
|
fetch(`api.php?q=authors&author=${search}`)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(results => {
|
.then(results => {
|
||||||
suggestions.innerHTML = ""
|
suggestions.innerHTML = ""
|
||||||
|
if (!results.data.length) {
|
||||||
|
hideSuggestions()
|
||||||
|
} else {
|
||||||
|
showSuggestions()
|
||||||
|
}
|
||||||
results.data.forEach(elem => {
|
results.data.forEach(elem => {
|
||||||
let name = document.createElement('p')
|
let name = document.createElement('p')
|
||||||
name.innerHTML = elem
|
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 => {
|
document.addEventListener('click', e => {
|
||||||
if (e.target.id !== 'suggestions' && e.target !== searchBar && e.target !== searchBarButton) {
|
if (e.target.id !== 'suggestions' && e.target !== searchBar && e.target !== searchBarButton) {
|
||||||
if (suggestionsDisplayed) {
|
hideSuggestions()
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.target.id === 'hamburger' || e.target.id === 'hamburgerSvg' || e.target.id === 'crossSvg') {
|
if (e.target.id === 'hamburger' || e.target.id === 'hamburgerSvg' || e.target.id === 'crossSvg') {
|
||||||
let ham = document.querySelector('#hamburgerSvg')
|
let ham = document.querySelector('#hamburgerSvg')
|
||||||
let cross = document.querySelector('#crossSvg')
|
let cross = document.querySelector('#crossSvg')
|
||||||
if (ham.classList.contains('spin-fade')) {
|
if (ham.classList.contains('spin-fade')) {
|
||||||
cross.classList.add('spin-fade')
|
cross.classList.add('spin-fade')
|
||||||
ham.classList.remove('spin-fade')
|
ham.classList.remove('spin-fade')
|
||||||
|
header.classList.replace('slide-in-header', 'slide-out-header')
|
||||||
|
hamMenu.classList.replace('slide-in', 'slide-out')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ham.classList.add('spin-fade')
|
ham.classList.add('spin-fade')
|
||||||
cross.classList.remove('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) {
|
if (e.target === errorButton) {
|
||||||
error.classList.replace('fade-in', 'fade-out')
|
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')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport"
|
<meta name="viewport"
|
||||||
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|
||||||
<link rel="stylesheet" href="stylesheet.css">
|
<link rel="stylesheet" href="stylesheet.css">
|
||||||
<title>Theses FR</title>
|
<title>Theses FR</title>
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<header>
|
<header>
|
||||||
|
|
||||||
<nav class="navbar">
|
<nav class="navbar">
|
||||||
<h1>theses.fr</h1>
|
<h1>theses.fr</h1>
|
||||||
|
|
||||||
@@ -18,4 +19,18 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
<div id="hamburger-menu">
|
||||||
|
|
||||||
|
<div class="chart-button">
|
||||||
|
<svg id="chart-svg" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||||
|
<path d="M13.012 5.007v-1.668l2.802-2.771c.409.136.809.293 1.197.471l-3.999 3.968zm7.089-1.93l-7.089 7.058v.853h.877l7.044-7.076c-.263-.292-.541-.57-.832-.835zm-7.089-1.468l1.437-1.406c-.46-.094-.96-.163-1.437-.203v1.609zm10.789 7.962l-1.386 1.417h1.585c-.04-.47-.106-.964-.199-1.417zm-.363-1.366c-.135-.41-.292-.81-.469-1.199l-3.951 3.982h1.668l2.752-2.783zm-1.063-2.337c-.205-.346-.426-.682-.664-1.004l-6.093 6.124h1.668l5.089-5.12zm-3.225-3.57c-.322-.238-.657-.459-1.003-.665l-5.135 5.104v1.668l6.138-6.107zm-8.15 10.702v-13c-6.161.519-11 5.683-11 11.978 0 6.639 5.382 12.022 12.021 12.022 6.296 0 11.46-4.839 11.979-11h-13z"/>
|
||||||
|
</svg>
|
||||||
|
<div class="toggle-switch">
|
||||||
|
<div class="slider untoggle"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
</header>
|
</header>
|
||||||
|
|||||||
@@ -14,14 +14,37 @@ body {
|
|||||||
overflow-x: hidden;
|
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 {
|
.navbar {
|
||||||
|
position: relative;
|
||||||
|
z-index: 50;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
background: linear-gradient(245deg, #39B4E7 -15%, #0096DC 110%);
|
background: linear-gradient(245deg, #39B4E7 -15%, #0096DC 110%);
|
||||||
box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 5px;
|
box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 5px;
|
||||||
height: 75px;
|
height: 100%;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
@@ -50,11 +73,6 @@ body {
|
|||||||
width: 100%;
|
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 {
|
.navbar button {
|
||||||
align-self: center;
|
align-self: center;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
@@ -138,6 +156,93 @@ body {
|
|||||||
opacity: 0;
|
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 {
|
#results {
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
Reference in New Issue
Block a user