Added autocomplete
diff --git a/ajax/getusers.php b/ajax/getusers.php
index e797c7b..7d9f52e 100644
--- a/ajax/getusers.php
+++ b/ajax/getusers.php
@@ -1,13 +1,14 @@
-<option selected disabled hidden>Selecciona usuari...</option>
-
<?php
require '../credentials.php';
require '../php/utils.php';
- $users = get_users(0);
-
- foreach ($users as $user) {
- $nopassword = $user->md5password == "" ? "nopassword" : "";
- $mort = $user->mort ? "disabled" : "";
- echo "<option ".$mort." class='".$nopassword."' value='".$user->id."'>".$user->nomcomplet."</option>\n";
+
+ $users = get_users(0, false);
+ foreach ($users as &$user) {
+ if ($user["mort"]) continue;
+
+ $user["nopassword"] = $user["md5password"] == "" ? "nopassword" : "";
+ unset($user["md5password"]);
}
+
+ echo json_encode($users);
?>
diff --git a/css/login.css b/css/login.css
index 6b6b20f..2ad3b75 100644
--- a/css/login.css
+++ b/css/login.css
@@ -8,3 +8,123 @@
font-size: 18px;
height: 2em;
}
+
+.md-google-search__metacontainer {
+ position: relative;
+ height: 48px;
+ width: 100%;
+ margin-bottom: 16px;
+}
+
+.md-google-search__container {
+ display: block;
+ height: 48px;
+ width: 100%;
+ max-width: 720px;
+ white-space: nowrap;
+}
+
+.md-google-search {
+ height: 48px;
+ background-color: rgba(245, 245, 245, 1);
+ border: 1px solid rgba(0, 0, 0, 0.2);
+ -webkit-border-radius: 4px;
+ border-radius: 4px;
+ max-width: 600px;
+ position: relative;
+ -webkit-transition: background-color 100ms ease-in, width 100ms ease-out;
+ transition: background-color 100ms ease-in, width 100ms ease-out;
+}
+
+.md-google-search:focus-within {
+ border: 1px solid rgba(0, 0, 0, 0.45);
+ background-color: rgba(255, 255, 255, 1);
+ -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .2);
+ box-shadow: 0 1px 1px rgba(0, 0, 0, .2);
+}
+
+.md-google-search__search-btn {
+ float: left;
+ background: none;
+ border: none;
+ opacity: .54;
+ outline: none;
+ padding: 0 4px;
+ line-height: 0;
+ color: #212121;
+}
+
+.md-google-search__search-btn svg, .md-google-search__empty-btn svg {
+ padding: 7px;
+ margin: 4px;
+}
+
+.md-google-search__field-container {
+ height: 46px;
+ padding: 0 11px;
+ margin-right: 48px;
+}
+
+.md-google-search__field {
+ border: none;
+ font: normal 16px Roboto, sans-serif;
+ height: 24px;
+ outline: none;
+ padding: 11px 0 11px 16px;
+ width: 100%;
+ background: transparent;
+ box-sizing: unset;
+}
+
+.md-google-search__empty-btn {
+ position: absolute;
+ right: 0;
+ top: 0;
+ background: none;
+ border: none;
+ opacity: .54;
+ outline: none;
+ padding: 0 4px;
+ line-height: 0;
+ color: #212121;
+ cursor: pointer;
+}
+
+/**
+ * Search Box Autocomplete
+ */
+.autocomplete-container {
+ z-index: 110;
+ position: absolute;
+ top: Calc(100% + 2px);
+ left: 0;
+ width: 100%;
+}
+
+.autocomplete-items {
+ display: block;
+ width: 100%;
+ max-width: 600px;
+ background-color: white;
+ color: black;
+ box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.258824), 0 2px 10px 0
+ rgba(0, 0, 0, 0.156863) !important;
+ max-height: 510px;
+ overflow-y: auto;
+}
+
+.autocomplete-item {
+ font-size: 16px;
+ padding: 12px 14px;
+ cursor: pointer;
+}
+
+.autocomplete-item:hover, .autocomplete-active {
+ background: #eee;
+}
+
+.autocomplete-grau-curs {
+ position: relative;
+ z-index: 120;
+ color: #222;
+}
diff --git a/index.php b/index.php
index f62abd9..9ef86fe 100644
--- a/index.php
+++ b/index.php
@@ -20,8 +20,28 @@
<h1>Selecciona el teu nom</h1>
<p>Per entrar al joc de la Pastanaga Assessina</p>
<form action="./php/login.php" method="POST">
- <select name="user" id="list">
- </select>
+ <input type="hidden" name="user" id="user">
+
+ <!-- MD Search Box -->
+ <div class="md-google-search__metacontainer">
+ <div class="md-google-search__container">
+ <div class="md-google-search">
+ <span class="md-google-search__search-btn">
+ <svg height="24px" viewBox="0 0 24 24" width="24px" xmlns="http://www.w3.org/2000/svg"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg>
+ </span>
+ <div class="md-google-search__field-container">
+ <input id="search-input" class="md-google-search__field" autocomplete="off" placeholder="Usuari" value="" name="search" type="text" spellcheck="false" style="outline: none;">
+ </div>
+ <span class="md-google-search__empty-btn" style="display: none;">
+ <svg focusable="false" height="24px" viewBox="0 0 24 24" width="24px" xmlns="http://www.w3.org/2000/svg"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg>
+ </span>
+ </div>
+ </div>
+
+ <div class="autocomplete-container" style="display: none;">
+ <div id="autocomplete-list" class="autocomplete-items"></div>
+ </div>
+ </div>
<input disabled required placeholder="Clau d'accés..." id="password" type="password" name="password"/>
<input type="submit" value="Entrar" />
@@ -29,10 +49,12 @@
</div>
</div>
+ <script src="./js/autocomplete.js"></script>
<script>
- $.post("./ajax/getusers.php", function(data, status){
- $("#list").html(data);
-
+ fetch("./ajax/getusers.php").then(result => result.json()).then(users => {
+ console.log(users);
+ autocomplete(document.getElementById("search-input"), users, "search");
+
userid = <?=isset($_COOKIE['user']) ? $_COOKIE['user'] : -1 ?>;
username = $('option[value=' + userid + ']').text();
@@ -42,11 +64,6 @@
}
});
- $('select').on('change', function() {
- let nopassword = $('select option:selected').hasClass('nopassword');
- $('#password').prop('disabled', nopassword);
- });
-
$(document).ready(function() {
// Notify of messages
if (getUrlParameter("passwordchanged")) read_message("La teva clau d'accés ha canviat", "error");
diff --git a/js/autocomplete.js b/js/autocomplete.js
new file mode 100644
index 0000000..28b9abf
--- /dev/null
+++ b/js/autocomplete.js
@@ -0,0 +1,122 @@
+function autocomplete(inp, obj, act) {
+ /*the autocomplete function takes two arguments,
+ the text field element and an objay of possible autocompleted values:*/
+ var currentFocus;
+ /*execute a function when someone writes in the text field:*/
+ inp.addEventListener("input", function(e) {
+ var a, b, i, val = this.value;
+ /*close any already open lists of autocompleted values*/
+ clearLists();
+ document.querySelector(".md-google-search__empty-btn").style.display = (val ? "block" : "none");
+ if (!val || val.length < 3) return false;
+ currentFocus = -1;
+ var is_empty = true;
+
+ /*for each item in the object...*/
+ for (node in obj) {
+ var nomNode = obj[node].nomcomplet;
+
+ if (nomNode.toUpperCase().includes(val.toUpperCase())) {
+ is_empty = false;
+ var parts = nomNode.toUpperCase().split(val.toUpperCase());
+
+ /*create a DIV element for each matching element:*/
+ b = document.createElement("div");
+ b.setAttribute("class", "autocomplete-item");
+
+ /*make the matching letters bold:*/
+ if (parts[0].length == 0) b.innerHTML = "";
+ else b.innerHTML = "<span style='font-weight: bold; position:relative; z-index:120;'>" + nomNode.substr(0, parts[0].length) + "</span>";
+
+ b.innerHTML += nomNode.substr(parts[0].length, val.length);
+ b.innerHTML += "<span style='font-weight: bold; position:relative; z-index:120;'>" + nomNode.substr(parts[0].length + val.length) + "</span>";
+ b.innerHTML += " <span class='autocomplete-year'>(" + obj[node].curs + "-" + obj[node].grau + ")</span>";
+
+ /*include node id to keep track of which is it*/
+ b.dataset.id = node;
+
+ /*execute a function when someone clicks on the item value (DIV element):*/
+ b.addEventListener("click", function(e) {
+ /*insert the value for the autocomplete text field:*/
+ var n = this.dataset.id;
+ inp.value = obj[n].nomcomplet;
+
+ switch (act) {
+ case "search":
+ // Insert hidden input id and show password field if applicable
+ document.getElementById("user").value = obj[n].id;
+ $('#password').prop('disabled', (obj[n].nopassword == "nopassword"));
+ break;
+ }
+
+ /*close the list of autocompleted values,
+ (or any other open lists of autocompleted values:*/
+ clearLists();
+ });
+
+ document.querySelector("#autocomplete-list").appendChild(b);
+ }
+ }
+
+ document.querySelector(".autocomplete-container").style.display = (is_empty ? "none" : "block");
+ });
+
+ document.querySelector(".md-google-search__empty-btn").addEventListener("click", function() {
+ document.querySelector("#search-input").value = "";
+ this.style.display = "none";
+ });
+
+ /*execute a function presses a key on the keyboard:*/
+ inp.addEventListener("keydown", function(e) {
+ var x = document.getElementById("autocomplete-list");
+ if (x) x = x.getElementsByTagName("div");
+ if (x.length == 0) return;
+ if (e.keyCode == 40) {
+ /*If the objow DOWN key is pressed,
+ increase the currentFocus variable:*/
+ currentFocus++;
+ /*and and make the current item more visible:*/
+ addActive(x);
+ } else if (e.keyCode == 38) { //up
+ /*If the objow UP key is pressed,
+ decrease the currentFocus variable:*/
+ currentFocus--;
+ /*and and make the current item more visible:*/
+ addActive(x);
+ } else if (e.keyCode == 13) {
+ /*If the ENTER key is pressed, prevent the form from being submitted,*/
+ e.preventDefault();
+ if (currentFocus > -1) {
+ /*and simulate a click on the "active" item:*/
+ if (x) x[currentFocus].click();
+ }
+ }
+ });
+ function addActive(x) {
+ /*a function to classify an item as "active":*/
+ if (!x) return false;
+ /*start by removing the "active" class on all items:*/
+ removeActive(x);
+ if (currentFocus >= x.length) currentFocus = 0;
+ if (currentFocus < 0) currentFocus = (x.length - 1);
+ /*add class "autocomplete-active":*/
+ x[currentFocus].classList.add("autocomplete-active");
+ }
+ function removeActive(x) {
+ /*a function to remove the "active" class from all autocomplete items:*/
+ for (var i = 0; i < x.length; i++) {
+ x[i].classList.remove("autocomplete-active");
+ }
+ }
+ function clearLists() {
+ /*close all autocomplete lists in the document,
+ except the one passed as an argument:*/
+ var x = document.querySelector("#autocomplete-list");
+ x.innerHTML = "";
+ document.querySelector(".autocomplete-container").style.display = "none";
+ }
+ /*execute a function when someone clicks in the document:*/
+ document.addEventListener("click", function (e) {
+ clearLists();
+ });
+}
diff --git a/php/utils.php b/php/utils.php
index 19b9146..a187aea 100644
--- a/php/utils.php
+++ b/php/utils.php
@@ -29,7 +29,7 @@
return $result;
}
- function get_users($id = 0) {
+ function get_users($id = 0, $getAsObjects = true) {
$users = [];
// Prepare the query
@@ -39,16 +39,27 @@
// Fetch the information of the user
if ($result = query($query)) {
while ($row = $result->fetch_row()) {
- $user = new User();
-
- $user->id = $row[0];
- $user->nomcomplet = $row[1];
- $user->curs = $row[2];
- $user->grau = $row[3];
- $user->quimata = $row[4];
- $user->requested = $row[5];
- $user->mort = $row[6];
- $user->md5password = $row[7];
+ if ($getAsObjects) {
+ $user = new User();
+ $user->id = $row[0];
+ $user->nomcomplet = $row[1];
+ $user->curs = $row[2];
+ $user->grau = $row[3];
+ $user->quimata = $row[4];
+ $user->requested = $row[5];
+ $user->mort = $row[6];
+ $user->md5password = $row[7];
+ } else {
+ $user = [];
+ $user["id"] = $row[0];
+ $user["nomcomplet"] = $row[1];
+ $user["curs"] = $row[2];
+ $user["grau"] = $row[3];
+ $user["quimata"] = $row[4];
+ $user["requested"] = $row[5];
+ $user["mort"] = $row[6];
+ $user["md5password"] = $row[7];
+ }
array_push($users, $user);
}