From 214ff958aac615126d26a90d490d92ae62068d2e Mon Sep 17 00:00:00 2001 From: Florian Sylvain Date: Sun, 31 Oct 2021 00:19:53 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Added=20suggestion=20feature?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ProjetProgWeb/api.php | 16 ++++++- ProjetProgWeb/app.js | 51 +++++++++++++++++++-- ProjetProgWeb/class/dump.php | 23 ++++++++++ ProjetProgWeb/navbar.php | 17 ++++--- ProjetProgWeb/stylesheet.css | 88 +++++++++++++++++++++++++++++------- 5 files changed, 166 insertions(+), 29 deletions(-) diff --git a/ProjetProgWeb/api.php b/ProjetProgWeb/api.php index b203e00..f7e3885 100644 --- a/ProjetProgWeb/api.php +++ b/ProjetProgWeb/api.php @@ -2,7 +2,19 @@ require_once("class/dump.php"); +if (!isset($_GET['q']) || !isset($_GET['author'])) { + print_r(json_encode(array("status" => 400, "message" => "Missing query type or attributs."))); + exit(); +} + $author_name = $_GET['author']; -$these_array = dump::getTheseByAuthor($author_name); -$json = json_encode($these_array); +$q = $_GET['q']; + +$json_object = match ($q) { + "theses" => dump::getTheseByAuthor($author_name), + "authors" => dump::getAuthorsByAuthors($author_name), + default => NULL, +}; + +$json = json_encode($json_object); print_r($json); diff --git a/ProjetProgWeb/app.js b/ProjetProgWeb/app.js index 49b7f2d..975ffc0 100644 --- a/ProjetProgWeb/app.js +++ b/ProjetProgWeb/app.js @@ -1,14 +1,23 @@ +let navbarForm = document.getElementsByClassName('navbar-form')[0] +let searchbar = document.getElementById('searchbar') +let suggestions = document.getElementById('suggestions') +let searchBarButton = document.getElementById('search-button') +let loader = document.getElementsByClassName('loader')[0] + +let last = new Date().getTime() let authorName = ""; function requestToApi(author) { + loader.style.display = "block" authorName = author - fetch(`api.php?author=${author}`) + fetch(`api.php?q=theses&author=${author}`) .then(response => response.json()) .then(data => displayResults(data)) } +// TODO : Faire un système de page plutôt que de charger 10000 résultats en une fois s'il y en a 10000.. + function displayResults(results) { - document.getElementsByClassName('loader')[0].style.display = "block" let count = 0 results.forEach(function(elem) { let result = document.createElement('div') @@ -26,5 +35,39 @@ function displayResults(results) { let nb = document.createElement("p") nb.innerHTML = `Nombre de résultats pour "${authorName}": ${count}.` document.getElementById('results-count').appendChild(nb) - document.getElementsByClassName('loader')[0].style.display = "none" -} \ No newline at end of file + loader.style.display = "none" +} + +function realTimeDisplay() { + if (last === null || (new Date().getTime() - last) > 500) { + let search = document.getElementsByName("author")[0].value + if (search.length > 3) { + last = new Date().getTime() + fetch(`api.php?q=authors&author=${search}`) + .then(response => response.json()) + .then(function(data) { + suggestions.innerHTML = "" + data.forEach(function(elem) { + let name = document.createElement('p') + name.innerHTML = elem + suggestions.appendChild(name) + }) + }) + } + } +} + +searchbar.addEventListener('focus', () => { + navbarForm.style.borderRadius = '15px 15px 0 0' + suggestions.style.display = 'block' + searchBarButton.style.boxShadow = 'none' + searchBarButton.classList.remove('animation-in') + searchBarButton.classList.add('animation-out') +}); +searchbar.addEventListener('focusout', () => { + navbarForm.style.borderRadius = '15px' + suggestions.style.display = 'none' + searchBarButton.style.boxShadow = 'rgba(0, 0, 0, 0.15) 4px 2px 5px' + searchBarButton.classList.remove('animation-out') + searchBarButton.classList.add('animation-in') +}); diff --git a/ProjetProgWeb/class/dump.php b/ProjetProgWeb/class/dump.php index b6395f7..affc9ee 100644 --- a/ProjetProgWeb/class/dump.php +++ b/ProjetProgWeb/class/dump.php @@ -43,6 +43,29 @@ class dump { return $theses_array; } + public static function getAuthorsByAuthors(mixed $author_name) : array { + $array = []; + + $author_name = '%' . $author_name . '%'; + + $pdo_obj = new conf(); + $pdo = $pdo_obj->getPDO(); + + $stmt = $pdo->prepare("SELECT author FROM theses WHERE author LIKE :author_name LIMIT 10;"); + $stmt->bindParam(':author_name', $author_name, PDO::PARAM_STR, 100); + $stmt->execute(); + + $i = 0; + while ($obj = $stmt->fetchObject()) { + foreach ($obj as $elem) { + array_push($array, $elem); + } + $i++; + } + + return $array; + } + public function sendThese() { $data = [ 'author' => $this->these->getAuthor(), diff --git a/ProjetProgWeb/navbar.php b/ProjetProgWeb/navbar.php index e578515..f51e978 100644 --- a/ProjetProgWeb/navbar.php +++ b/ProjetProgWeb/navbar.php @@ -1,11 +1,16 @@
diff --git a/ProjetProgWeb/stylesheet.css b/ProjetProgWeb/stylesheet.css index cefc7ff..f6dba14 100644 --- a/ProjetProgWeb/stylesheet.css +++ b/ProjetProgWeb/stylesheet.css @@ -15,7 +15,8 @@ body { .navbar { display: flex; align-items: center; - gap: 10px; + justify-content: center; + flex-direction: column; background-color: rgba(57, 180, 231, 0.50); box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 5px; height: 75px; @@ -24,13 +25,17 @@ body { font-family: sans-serif; } -.navbar-input { +.research-section { + position: relative; + width: 100%; +} + +.navbar-form { box-shadow: rgba(0, 0, 0, 0.15) 0 2px 5px; border-radius: 15px; - height: 35px; + height: 40px; display: flex; align-items: center; - width: 100%; background-color: white; } @@ -40,44 +45,88 @@ body { border: none; height: 100%; font-size: 18px; - padding: 15px 5px 15px 15px; + padding: 20px 5px 20px 20px; width: 100%; } -.navbar img { - background: white; - border-radius: 100px; - width: 50px; - right: 5px; - padding: 10px; - box-shadow: rgba(0, 0, 0, 0.15) 4px 2px 5px; - cursor: pointer; -} - .navbar button { + align-self: center; + height: 60px; border: none; background: none; margin: 0; padding: 0; } +.navbar img { + border-radius: 50px; + width: 60px; + padding: 10px; + cursor: pointer; + background-color: white; + box-shadow: rgba(0, 0, 0, 0.15) 4px 2px 5px; +} + +.animation-in { + animation: bg-in 70ms linear; + box-shadow: rgba(0, 0, 0, 0.15) 4px 2px 5px; + animation-fill-mode: forwards; +} + +.animation-out { + animation: bg-out 70ms linear; + box-shadow: none; + animation-fill-mode: forwards; +} + +@keyframes bg-out { + from {background-color: rgba(255, 255, 255, 1.0);} + to {background-color: rgba(255, 255, 255, 0.0);} +} +@keyframes bg-in { + from {background-color: rgba(255, 255, 255, 0.0);} + to {background-color: rgba(255, 255, 255, 1.0);} +} + .navbar h1 { display: none; } +#suggestions { + display: none; + position: absolute; + z-index: 10; + background-color: white; + box-shadow: rgba(0, 0, 0, 0.15) 0 5px 5px; + border-radius: 0 0 15px 15px; + padding: 0 10px 10px 10px; + width: 100%; + border: none; + border-top: solid 1px lightgray; +} + +#suggestions p { + padding: 10px; + margin: 5px; + border-radius: 10px; +} + +#suggestions p:hover { + background-color: rgba(0, 0, 0, 0.05); +} + #results { font-family: sans-serif; margin: 10px; display: flex; flex-direction: column; gap: 15px; - overflow: scroll; } #results-count { font-family: sans-serif; - margin: 15px; opacity: 50%; + margin: 0 0 0 15px; } .result-element { @@ -93,9 +142,14 @@ body { } .loader { + display: none; width: 150px; height: 150px; align-self: center; + justify-self: center; + position: absolute; + top: 50%; + transform: translateY(-50%); } .loader svg {