mirror of
https://github.com/Floriansylvain/projet_programmation_web.git
synced 2026-08-19 11:43:16 +02:00
✨ Introduced page navigation on results
This commit is contained in:
Generated
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||||
<data-source source="LOCAL" name="MySQL - projet_prog_web@localhost" uuid="f88d17ea-9fdd-429c-bb65-b7ce88663237">
|
<data-source source="LOCAL" name="MySQL - projet_prog_web@localhost" uuid="d14307eb-f643-4626-83b4-cc3ddbc56c70">
|
||||||
<driver-ref>mysql.8</driver-ref>
|
<driver-ref>mysql.8</driver-ref>
|
||||||
<synchronize>true</synchronize>
|
<synchronize>true</synchronize>
|
||||||
<jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>
|
<jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>
|
||||||
|
|||||||
+92
-31
@@ -1,3 +1,8 @@
|
|||||||
|
const SMALL = 576
|
||||||
|
const MEDIUM = 768
|
||||||
|
const LARGE = 992
|
||||||
|
const EXTRA_LARGE = 1200
|
||||||
|
|
||||||
let navbarForm = document.querySelector('.navbar-form')
|
let navbarForm = document.querySelector('.navbar-form')
|
||||||
let searchBar = document.querySelector('#searchbar')
|
let searchBar = document.querySelector('#searchbar')
|
||||||
let searchBarButton = document.querySelector('#search-button')
|
let searchBarButton = document.querySelector('#search-button')
|
||||||
@@ -9,6 +14,11 @@ let errorButton = document.querySelector('#error-button')
|
|||||||
let hamMenu = document.querySelector('#hamburger-menu')
|
let hamMenu = document.querySelector('#hamburger-menu')
|
||||||
let header = document.querySelector('header')
|
let header = document.querySelector('header')
|
||||||
let title = document.querySelector('#title')
|
let title = document.querySelector('#title')
|
||||||
|
let ham = document.querySelector('#hamburgerSvg')
|
||||||
|
let cross = document.querySelector('#crossSvg')
|
||||||
|
let pagesNumbers = document.querySelector('.page-nav div')
|
||||||
|
let resultsDiv = document.querySelector('#results')
|
||||||
|
let resultsCount = document.querySelector('#results-count')
|
||||||
|
|
||||||
function sanitize(chain) {
|
function sanitize(chain) {
|
||||||
return chain.replace(/[^a-zA-Z0-9 ]/g,'')
|
return chain.replace(/[^a-zA-Z0-9 ]/g,'')
|
||||||
@@ -34,15 +44,21 @@ function hideSuggestions() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function emptyResults(withCount = false) {
|
||||||
|
if (withCount)
|
||||||
|
resultsCount.innerHTML = ""
|
||||||
|
resultsDiv.innerHTML = ""
|
||||||
|
}
|
||||||
|
|
||||||
let authorName = "";
|
let authorName = "";
|
||||||
let lastRequest = null
|
let lastRequest = null
|
||||||
|
|
||||||
function requestToApi(author) {
|
function apiRequestThese(author) {
|
||||||
hideSuggestions()
|
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 = ""
|
emptyResults(true)
|
||||||
document.querySelector('#results').innerHTML = ""
|
pagesNumbers.innerHTML = ""
|
||||||
loader.style.display = "block"
|
loader.style.display = "block"
|
||||||
authorName = sanitize(author)
|
authorName = sanitize(author)
|
||||||
fetch(`api.php?q=theses&author=${author}`)
|
fetch(`api.php?q=theses&author=${author}`)
|
||||||
@@ -53,18 +69,23 @@ function requestToApi(author) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener('scroll', fadeIn);
|
|
||||||
let elementsToFade = null
|
|
||||||
function fadeIn() {
|
function fadeIn() {
|
||||||
|
let elementsToFade = document.querySelectorAll(".result-element")
|
||||||
|
if (elementsToFade !== null) {
|
||||||
elementsToFade.forEach(elem => {
|
elementsToFade.forEach(elem => {
|
||||||
let distInView = elem.getBoundingClientRect().top - window.innerHeight + 20;
|
let distInView = elem.getBoundingClientRect().top - window.innerHeight + 20;
|
||||||
if (distInView < 0) {
|
if (distInView < 0) {
|
||||||
elem.classList.add("fade-in");
|
elem.classList.add("fade-in");
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO : Faire un système de page plutôt que de charger 10000 résultats en une fois s'il y en a 10000..
|
window.addEventListener('scroll', fadeIn);
|
||||||
|
|
||||||
|
let resultsArray = []
|
||||||
|
let count = 0
|
||||||
|
|
||||||
function displayResults(results) {
|
function displayResults(results) {
|
||||||
|
|
||||||
if (results.status === 400) {
|
if (results.status === 400) {
|
||||||
@@ -73,32 +94,61 @@ function displayResults(results) {
|
|||||||
errorMessage.innerHTML = results.message
|
errorMessage.innerHTML = results.message
|
||||||
return;
|
return;
|
||||||
} else if (results.status === 200) {
|
} else if (results.status === 200) {
|
||||||
let count = 0
|
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')
|
||||||
let i = 0
|
let i = 0
|
||||||
elem.forEach(e => {
|
elem.forEach(e => {
|
||||||
let child = document.createElement(i === 0 ? 'h1' : 'p')
|
let child = document.createElement(i === 0 ? 'h2' : 'p')
|
||||||
child.innerText = e
|
child.innerText = e
|
||||||
result.appendChild(child)
|
result.appendChild(child)
|
||||||
i += 1
|
i += 1
|
||||||
})
|
})
|
||||||
count += 1
|
count += 1
|
||||||
document.getElementById('results').appendChild(result)
|
|
||||||
|
resultsArray.push(result)
|
||||||
})
|
})
|
||||||
|
|
||||||
let nb = document.createElement("p")
|
let nb = document.createElement("p")
|
||||||
nb.innerHTML = `Nombre de résultats pour "${authorName}": ${count}.`
|
nb.innerHTML = `Nombre de résultats pour "${authorName}": ${count}.`
|
||||||
document.getElementById('results-count').appendChild(nb)
|
resultsCount.appendChild(nb)
|
||||||
|
|
||||||
loader.style.display = "none"
|
loader.style.display = "none"
|
||||||
|
|
||||||
elementsToFade = document.querySelectorAll(".result-element")
|
let nbPages = Math.ceil(count / 10)
|
||||||
|
|
||||||
|
for (let i = 0 ; i < nbPages ; i++) {
|
||||||
|
let number = document.createElement('p')
|
||||||
|
number.innerHTML = i + 1
|
||||||
|
if (i === 0)
|
||||||
|
number.style.textDecoration = 'underline'
|
||||||
|
number.onclick = (e) => {
|
||||||
|
document.querySelectorAll('.page-nav div p').forEach(elem => {
|
||||||
|
elem.style.textDecoration = 'none'
|
||||||
|
})
|
||||||
|
e.target.style.textDecoration = 'underline'
|
||||||
|
browseResults(i + 1)
|
||||||
|
}
|
||||||
|
pagesNumbers.appendChild(number)
|
||||||
|
}
|
||||||
|
|
||||||
|
browseResults(1)
|
||||||
fadeIn()
|
fadeIn()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let currentPage = 1
|
||||||
|
|
||||||
|
function browseResults(wantedPage) {
|
||||||
|
emptyResults()
|
||||||
|
currentPage = wantedPage
|
||||||
|
wantedPage *= 10
|
||||||
|
resultsArray.slice(wantedPage - 10, wantedPage).forEach(result => {
|
||||||
|
resultsDiv.appendChild(result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
let lastSearch = ""
|
let lastSearch = ""
|
||||||
let lastSuggestion = new Date().getTime()
|
let lastSuggestion = new Date().getTime()
|
||||||
let suggestionsDisplayed = false
|
let suggestionsDisplayed = false
|
||||||
@@ -123,7 +173,7 @@ function realTimeDisplay() {
|
|||||||
name.innerHTML = elem
|
name.innerHTML = elem
|
||||||
name.addEventListener('click', () => {
|
name.addEventListener('click', () => {
|
||||||
searchBar.value = elem
|
searchBar.value = elem
|
||||||
requestToApi(elem)
|
apiRequestThese(elem)
|
||||||
})
|
})
|
||||||
suggestions.appendChild(name)
|
suggestions.appendChild(name)
|
||||||
})
|
})
|
||||||
@@ -131,30 +181,41 @@ function realTimeDisplay() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener('click', e => {
|
function switchHam(q) {
|
||||||
if (e.target.id !== 'suggestions' && e.target !== searchBar && e.target !== searchBarButton) {
|
if (q) {
|
||||||
|
|
||||||
hideSuggestions()
|
|
||||||
|
|
||||||
title.style.display = 'block'
|
|
||||||
|
|
||||||
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')
|
ham.classList.add('spin-fade')
|
||||||
cross.classList.remove('spin-fade')
|
cross.classList.remove('spin-fade')
|
||||||
header.classList.remove('slide-out-header')
|
header.classList.remove('slide-out-header')
|
||||||
header.classList.add('slide-in-header')
|
header.classList.add('slide-in-header')
|
||||||
hamMenu.classList.remove('slide-out')
|
hamMenu.classList.remove('slide-out')
|
||||||
hamMenu.classList.add('slide-in')
|
hamMenu.classList.add('slide-in')
|
||||||
|
} else {
|
||||||
|
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')
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function switchNavTitle(q) {
|
||||||
|
if (q) {
|
||||||
|
title.style.display = 'block'
|
||||||
|
} else if (window.innerWidth < SMALL) {
|
||||||
|
title.style.display = 'none'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('click', e => {
|
||||||
|
if (e.target.id !== 'suggestions' && e.target !== searchBar && e.target !== searchBarButton) {
|
||||||
|
|
||||||
|
hideSuggestions()
|
||||||
|
switchNavTitle(true)
|
||||||
|
|
||||||
|
if (e.target.id === 'hamburger' || e.target.id === 'hamburgerSvg' || e.target.id === 'crossSvg') {
|
||||||
|
if (ham.classList.contains('spin-fade'))
|
||||||
|
switchHam(false)
|
||||||
|
else
|
||||||
|
switchHam(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.target === errorButton) {
|
if (e.target === errorButton) {
|
||||||
@@ -179,12 +240,12 @@ document.addEventListener('click', e => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
searchBar.addEventListener('focus', () => {
|
searchBar.addEventListener('focus', () => {
|
||||||
title.style.display = 'none'
|
switchNavTitle(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
navbarForm.addEventListener('submit', e => {
|
navbarForm.addEventListener('submit', e => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
let data = new FormData(navbarForm)
|
let data = new FormData(navbarForm)
|
||||||
searchBar.blur()
|
searchBar.blur()
|
||||||
requestToApi(data.get('author'))
|
apiRequestThese(data.get('author'))
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -28,6 +28,14 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="results-count"></div>
|
<div id="results-count"></div>
|
||||||
|
|
||||||
|
<div class="page-nav">
|
||||||
|
<p onclick="browseResults(currentPage-1)"><-</p>
|
||||||
|
<div>
|
||||||
|
</div>
|
||||||
|
<p onclick="browseResults(currentPage+1)">-></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="results"></div>
|
<div id="results"></div>
|
||||||
|
|
||||||
<div id="error">
|
<div id="error">
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
<div class="research-section">
|
<div class="research-section">
|
||||||
<form class="navbar-form">
|
<form class="navbar-form">
|
||||||
<input type="text" name="author" placeholder="nom auteur" onkeyup="realTimeDisplay()" id="searchbar">
|
<input type="text" name="author" placeholder="recherche" onkeyup="realTimeDisplay()" id="searchbar">
|
||||||
<button id="form-button">
|
<button id="form-button">
|
||||||
<img src="assets/search.svg" alt="search" id="search-button" class="animation-in">
|
<img src="assets/search.svg" alt="search" id="search-button" class="animation-in">
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ header {
|
|||||||
box-shadow: rgba(0, 0, 0, 0.15) 0 2px 5px;
|
box-shadow: rgba(0, 0, 0, 0.15) 0 2px 5px;
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
|
max-width: 500px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
@@ -135,6 +136,7 @@ header {
|
|||||||
border-radius: 0 0 15px 15px;
|
border-radius: 0 0 15px 15px;
|
||||||
padding: 0 10px 10px 10px;
|
padding: 0 10px 10px 10px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
max-width: 500px;
|
||||||
border: none;
|
border: none;
|
||||||
border-top: solid 1px lightgray;
|
border-top: solid 1px lightgray;
|
||||||
}
|
}
|
||||||
@@ -406,6 +408,25 @@ header {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.page-nav {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
font-size: 18px;
|
||||||
|
line-height: 0;
|
||||||
|
margin: 15px auto 15px auto;
|
||||||
|
padding: 0 15px 0 15px;
|
||||||
|
border-radius: 20px;
|
||||||
|
color: #1a5f7d;
|
||||||
|
background: linear-gradient(245deg, rgba(57, 179, 231, 0.50) -15%, rgba(0, 149, 219, 0.50) 110%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-nav div {
|
||||||
|
display: flex;
|
||||||
|
gap: 5px;
|
||||||
|
max-width: 155px;
|
||||||
|
overflow-x: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
/* Small */
|
/* Small */
|
||||||
@media (min-width: 576px) {
|
@media (min-width: 576px) {
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user