浏览代码

Autocomplete presque fonctionnel

Sangfroid 8 月之前
父节点
当前提交
bb2785e71f
共有 2 个文件被更改,包括 102 次插入18 次删除
  1. 100 17
      assets/js/autocomplete.js
  2. 2 1
      assets/styles/app.scss

+ 100 - 17
assets/js/autocomplete.js

@@ -1,17 +1,86 @@
 export function autocomplete (inputField, path) {
-    
     const input = inputField.querySelector('input');
+    const inputId = input.id;
     input.autocomplete = 'off';
 
     const results = document.createElement('ul');
     results.className="autocomplete-results";
 
+    let selectedLi = null;
+    let inputValue = '';
+
+    let clickOccured = false;
+
+    const leaveSelectedLi = () => {
+        if (selectedLi !== null) {
+            selectedLi.classList.remove('selected');
+            selectedLi = null;
+        }
+    }
+
+    const selectLi = (element) => {
+        leaveSelectedLi();
+        selectedLi = element;
+        if (element !== null) {
+            selectedLi.classList.add('selected');
+        }
+        return selectedLi;
+    }
+
+    input.addEventListener('blur', () => {
+        setTimeout(() => {
+            if (!clickOccured) {
+                results.hidden = true;
+            }
+        },500);
+        clickOccured = false;
+    });
+
+    input.addEventListener('keydown', (e) => {
+        if (e.key === 'Enter') {
+            e.preventDefault();
+            if (selectedLi !== null) {
+                selectedLi.click();
+            }
+        }
+        const liste = results.querySelectorAll('li');
+        if(liste.length === 0) {
+            return;
+        } else {
+            results.hidden = false;
+        }
+        if (e.key === 'ArrowDown') {
+            e.preventDefault();
+            if (selectedLi === null) {
+                input.value = selectLi(results.querySelector('li')).innerText;
+            } else {
+                selectLi(results.querySelector('#' + inputId + '-ui-' + (Number(selectedLi.dataset.id) + 1)));
+                input.value = selectedLi !== null ? selectedLi.innerText : inputValue
+            }
+        }
+        if(e.key === 'ArrowUp') {
+            e.preventDefault();
+            if (selectedLi === null) {
+                input.value = selectLi(liste[liste.length - 1]).innerText;
+            } else {
+                selectLi(results.querySelector('#' + inputId + '-ui-' + (Number(selectedLi.dataset.id) - 1)));
+                input.value = selectedLi !== null ? selectedLi.innerText : inputValue
+            }
+        }
+    })
+
+    const clearResults = () => {
+        results.innerHTML = '';
+        results.hidden = true;
+    }
+
     input.addEventListener('input', (e) => {
         const term = input.value.trim();
 
         if (term.length === 0) {
             // Ne pas envoyer de requête si le champ est vide
-            results.remove()
+            results.innerText = '';
+            clearResults();
             return;
         }
 
@@ -28,20 +97,7 @@ export function autocomplete (inputField, path) {
             return response.json();
         })
         .then(data => {
-            results.innerHTML = '';
-            data.forEach(element => {
-                const li = document.createElement('li');
-                li.innerText = element;
-                li.classList.add('autocomplete-item');
-                results.appendChild(li);
-                li.addEventListener('click', (e) => {
-                    input.value = element;
-                    results.remove()
-                })
-            })
-            if (data.length > 0) {
-                input.after(results);
-            }
+            showResults(data);
             return true;
         })
         .catch(error => {
@@ -50,4 +106,31 @@ export function autocomplete (inputField, path) {
         });
     });
 
-}
+    const showResults = (data) => {
+        inputValue = input.value;
+        results.hidden = false;
+        results.innerHTML = '';
+        let i = 0;
+        leaveSelectedLi();
+        data.forEach(element => {
+            const li = document.createElement('li');
+            li.innerText = element;
+            li.classList.add('autocomplete-item');
+            li.id = inputId + '-ui-' + (++i);
+            li.dataset.id = i;
+            results.appendChild(li);
+            li.addEventListener('mouseover', (e) => {
+                selectLi(e.target);
+            });
+            
+            li.addEventListener('click', (e) => {
+                clickOccured = true;
+                input.value = e.target.innerText;
+                clearResults();
+            },true)
+        })
+        if (data.length > 0) {
+            input.after(results);
+        }
+    }
+}

+ 2 - 1
assets/styles/app.scss

@@ -43,6 +43,7 @@ body {
     background-color: $dark;
 }
 
-.autocomplete-item:hover, .autocomplete-item:active {
+.autocomplete-item:active, .selected {
     background-color: $primary;
 }
+