Introduced page navigation on results

This commit is contained in:
Florian SYLVAIN
2021-11-12 14:59:55 +01:00
parent 344493832e
commit 8890a310b4
5 changed files with 130 additions and 40 deletions
+1 -1
View File
@@ -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>
+99 -38
View File
@@ -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() {
elementsToFade.forEach(elem => { let elementsToFade = document.querySelectorAll(".result-element")
let distInView = elem.getBoundingClientRect().top - window.innerHeight + 20; if (elementsToFade !== null) {
if (distInView < 0) { elementsToFade.forEach(elem => {
elem.classList.add("fade-in"); let distInView = elem.getBoundingClientRect().top - window.innerHeight + 20;
} if (distInView < 0) {
}) 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() {
} }
} }
function switchHam(q) {
if (q) {
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')
} 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 => { 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) {
hideSuggestions() hideSuggestions()
switchNavTitle(true)
title.style.display = 'block'
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') if (ham.classList.contains('spin-fade'))
let cross = document.querySelector('#crossSvg') switchHam(false)
if (ham.classList.contains('spin-fade')) { else
cross.classList.add('spin-fade') switchHam(true)
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) { 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'))
}) })
+8
View File
@@ -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)">&#60;-</p>
<div>
</div>
<p onclick="browseResults(currentPage+1)">-&#62;</p>
</div>
<div id="results"></div> <div id="results"></div>
<div id="error"> <div id="error">
+1 -1
View File
@@ -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>
+21
View File
@@ -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) {