Autofocus na prvi i navigiranje kroz dropdown iteme preko up/down tipki na tipkovnici

Imam slijedeci HTML kod:

<div class="dropdown-content">
<a href="#" class="dropdown-item" data-value="al">alabama</a>
<a href="#" class="dropdown-item" data-value="ak">alaska</a>
<a href="#" class="dropdown-item" data-value="as">american samoa</a>
<a href="#" class="dropdown-item" data-value="az">arizona</a>
<a href="#" class="dropdown-item" data-value="ar">arkansas</a>
</div>

Koji kreira JS na ovaj nacin:

 function(t, n, e) {
    "use strict";
    e.r(n);
    var r = e(3)
      , o = e.n(r);
    const i = (t,n,e,r,i,u=2)=>{
        const a = document.getElementById(t)
          , c = document.getElementById(n);
        c.innerHTML = '<div class="dropdown-content"></div>';
        const l = t=>{
            t.preventDefault();
            var n = t.target.text
              , e = t.target.dataset.value;
            return a.value = n,
            c.style.display = "none",
            r && r({
                label: n,
                value: e
            }),
            !1
        }
          , f = t=>{
            const n = t.target.value;
            c.style.display = "none",
            c.innerHTML = '<div class="dropdown-content"></div>',
            n.length <= u || e(n).then(t=>{
                t.map(({label: t, value: n})=>{
                    const e = document.createElement("a");
                    return e.href = "#",
                    e.classList.add("dropdown-item"),
                    e.innerHTML = t,
                    e.dataset.value = n,
                    e.addEventListener("click", l),
                    e
                }
                ).map(t=>{
                    c.childNodes[0].appendChild(t)
                }
                ),
                t.length > 0 && (c.style.display = "block")
            }
            )
        }
        ;
        a.addEventListener("input", o()(f, i)),
        a.addEventListener("focusout", t=>{
            null !== t.relatedTarget && t.relatedTarget.classList.contains("dropdown-item") || (c.style.display = "none")
        }
        ),
        a.addEventListener("focusin", f)
    }
    ;
    n.default = i,
    window.bulmahead = i
}

To je autocomplete na input form i trebao bi dodati preko JS class na prvi is-active te zatim ukoliko se ide keybordom up/down mijenja focus i taj is-active.
Klikom na enter ili klik cursorom na odredjeni koji je aktivan da submita.

Radi se o Bulmahead
Probajte utipkati “Ala” u input pa cete vidjeti da nema autofocus na prvi i kretanje kroz iteme u dropdownu putem tipkovnice.
Isprobao sam danas valjda 150 razlicitih scenarija i procitao cijeli internet al nisam uspio doci do rjesenja, ima netko ideju sto napraviti?

Koristio sam ovaj pa vidi možeš li nešto izmiksati.

Bio sam prckao s tim samo ne znam zasto sam odustao, vjerojatno je falilo nekih funkcija pa sam se odlucio na JS povezan direktno na Bulma framework.
Evo opet sam se vratio na taj, nekako mi je ipak jednostavniji za dorade poput dinamickog arrayja i jos nekih sitnica…
Odustao sam od svoje gornje implementacije, ovaj je bar fino dokumentiran.

Ružan je kod al može se snaći.
Ja čim vidim var deklaraciju dobro pazim kako je ostatak pisan pa prema tome i doradjujem onako kako mi treba.

Zavrsio god pa se i ja malo bacio u rad, evo i ja sam uzeo taj malo ga modificirao, zatim pokusao pozvati na ovaj nacin dolje, ali ne funkcionira.
Ako napravim ovo ispod onda radi…

var data = [ "TANJUG", "TBC", "TCP/IP", "TE", "TIR", "TIROS", "TNT", "TV" ]

Moj kod uredno pokupi vanjski array s autocomplete.php, ali se ne izvrsi kao da je odmah ucitan.
Ima netko ideju zasto?
Kad unesem jedno slovo i napravim klik izvan input forme i vratim klikom focus u input formu, onda napravi dropdown.

$('#text1').on("input", function(e) {
term = "autocomplete.php?term="+ $(this).val()+"";
valinp=$(this).val();
    fetch(term)
    .then(
      function(response) {
        if (response.status !== 200) {
          console.log('Looks like there was a problem. Status Code: ' +
            response.status);
          return;
        }
        // Examine the text in the response
        response.json().then(function(data) {
         
         autocomplete(document.getElementById("text1"), data);
      
        });
      }
    )
    .catch(function(err) {
      console.log('Fetch Error :-S', err);
    });
});

Ovo je autocomplete funkcija:

function autocomplete(inp, arr) {
  /*the autocomplete function takes two arguments,
  the text field element and an array of possible autocompleted values:*/
  var currentFocus;
  /* a function to open dropdown autocomplete:*/
  var openDropdown =  function (e) {
      var a, b, i, val = this.value;
      /*close any already open lists of autocompleted values*/
      closeAllLists();
      if (!val) { return false;}
      currentFocus = -1;
      var k=0;
      /*for each item in the array...*/
      for (i = 0; i < arr.length; i++) {
        /*check if the item starts with the same letters as the text field value:*/
        if (arr[i].substr(0, val.length).toUpperCase() == val.toUpperCase()) {
          if (k==0) {
            /*create a DIV element that will contain the items (values):*/
            a = document.createElement("DIV");
            a.setAttribute("id", this.id + "autocomplete-list");
            a.setAttribute("class", "autocomplete-items");
            /*append the DIV element as a child of the autocomplete container:*/
            this.parentNode.appendChild(a);
            k++;
          }
          /*create a DIV element for each matching element:*/
          b = document.createElement("DIV");
          b.setAttribute("class", "dropdown-item");
          /*make the matching letters bold:*/
           b.innerHTML = "<i class=\"sl sl-icon-magnifier icon-search\"></i>";
          b.innerHTML += "" + arr[i].substr(0, val.length) + "";
          b.innerHTML += "<strong>" + arr[i].substr(val.length)+ "</strong>";
          /*insert a input field that will hold the current array item's value:*/
          b.innerHTML += "<input type='hidden' value='" + arr[i] + "'>";

          /*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:*/
              inp.value = this.getElementsByTagName("input")[0].value;
              /*close the list of autocompleted values,
              (or any other open lists of autocompleted values:*/
              closeAllLists();
              /*submit form when is selected*/
               document.getElementById("searchForm").submit(); 
          });
          a.appendChild(b);
        } 
      }
  }
  /*execute a function when someone writes in the text field:*/
  inp.addEventListener("input", openDropdown);
  inp.addEventListener("focus", openDropdown);

  var openActive = function(e) {
      var x = document.getElementById(this.id + "autocomplete-list");    
      if (x) x = x.getElementsByTagName("div");
      if (e.keyCode == 40) {
        /*If the arrow 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 arrow 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();
        }
      }
  }
  /*execute a function presses a key on the keyboard:*/
  inp.addEventListener("keydown", openActive);

  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 closeAllLists(elmnt) {
    /*close all autocomplete lists in the document,
    except the one passed as an argument:*/
    var x = document.getElementsByClassName("autocomplete-items");
    for (var i = 0; i < x.length; i++) {
      if (elmnt != x[i] && elmnt != inp) {
      x[i].parentNode.removeChild(x[i]);
    }
  }
}
/*execute a function when someone clicks in the document:*/
document.addEventListener("click", function (e) {
    closeAllLists(e.target);
    currentFocus = -1;
});
}

Za početak, ovo skloni.

console.log(data)

prije tog hard-coded niza da budeš siguran da podaci stižu kako treba?

To mi ostalo jer trebam jos neke varijable proslijediti, al kuzim… :slight_smile:

Naravno da sam to isprobavao, tim vise mi nije jasno…
image

$('#text1').on('keyup', function(e) {

})

Il’ ako ti je to previše zahtjeva onda

$('#text1').on("input", function(e) {
    e.preventDefault()// !important
    // rest
})

Meni maje vise ovdje izgleda sve ok, ali ima nekih stvari koje bi se mogle unaprijediti (a mozda i rijese problem hehe)

Nemoj deklarisati varijable ovako kao sto si uradio za term i valinp, na taj nacin zavrsavaju u globalnom scope-u, a to je nesto sto zelis izbjeci.

Chain-aj ove promise, nemoj raditi callback hell

Ovaj 200 check je prakticno beskoristan, ako je nesto 4xx/5xx status code to ce biti uhvaceno u .catch promise bloku

$('#text1').on("input", function(e) {
    var valinp = $(this).val();
    var term = "autocomplete.php?term=" + valinp + "";
    fetch(term)
        .then(res => res.json())
        .then(function(data) {
            autocomplete(document.getElementById("text1"), data);
        })
        .catch(function(err) {
            console.log('Fetch Error :-S', err);
        });
});

Kod od autocomplete funkcije nemam kad desifrovat, pretpostavljam da je c/p sa w3 schools.

1 Like

Nije loše izbjeći i var. Djeluje mi da ovde const radi pos’o (let u svakom slučaju).

Probao sam oboje sto ste mi savjetovali, ali jednostavno ne zeli raditi.
Kao da odbija poslati array i u istoj funkciji napraviti dropdown. Dok klik izvan i focus natrag na input otvori fetch vrijednosti.

Stavi sve to u

$(document).ready(function () {
    // autocomplete block

    // jquery field search block
})

Jesi li stavio e.preventDefault() u prvu liniju u bloku il’ testir’o sa keyup event-om umjesto input?

Jesam sve valjda jos 10 kombinacija paralelno, ali keyup mi nije bas opcija s obzirom da ce i key down/up raditi novi req na autocomplete.php, a oni mi trebaju za navigaciju kroz iteme.

U autocomplete() ima jos jedan inp.addEventListener("input", openDropdown);
Sad vidim da uopce array ne dodje u openDropdown kod prvog unosa slova, u prvom console ima output a drugi se ne izvrsi.

function autocomplete(inp, arr) {
   console.log(arr);     
   var openDropdown =  function (e) {  
       console.log(arr);
   }

   inp.addEventListener("input", openDropdown);
}

@belmin @tpojka hvala na trudu i pomoci, vasi komentari su me usmjerili da pronadjem rjesenje.
Evo koda ukoliko nekome bude trebao dynamic autocomplete search vezan uz w3school primjer, napokon radi :smiley:

function autocomplete(inp) {
  /*the autocomplete function takes two arguments,
  the text field element and an array of possible autocompleted values:*/
  var variable = inp;
  var currentFocus;
  /* a function to open dropdown autocomplete:*/
  var openDropdown =  function (e) {
      var a, b, i, val = this.value;    
      if (!val) { return false;}
      var term = "autocomplete.php?term=" + val + "";
      fetch(term)
        .then(res => res.json())
        .then(function(data) {    
            arr = data;
            /*close any already open lists of autocompleted values*/
            closeAllLists();
            currentFocus = -1;
            var k=0;
            /*for each item in the array...*/
            for (i = 0; i < arr.length; i++) {
              /*check if the item starts with the same letters as the text field value:*/
              if (arr[i].substr(0, val.length).toUpperCase() == val.toUpperCase()) {
                if (k==0) {
                  /*create a DIV element that will contain the items (values):*/
                  a = document.createElement("DIV");
                  a.setAttribute("id", variable.id + "autocomplete-list");
                  a.setAttribute("class", "autocomplete-items");
                  /*append the DIV element as a child of the autocomplete container:*/
                  variable.parentNode.appendChild(a);
                  k++;
                }
                /*create a DIV element for each matching element:*/
                b = document.createElement("DIV");
                b.setAttribute("class", "dropdown-item");
                /*make the matching letters bold:*/
                 b.innerHTML = "<i class=\"sl sl-icon-magnifier icon-search\"></i>";
                b.innerHTML += "" + arr[i].substr(0, val.length) + "";
                b.innerHTML += "<strong>" + arr[i].substr(val.length)+ "</strong>";
                /*insert a input field that will hold the current array item's value:*/
                b.innerHTML += "<input type='hidden' value='" + arr[i] + "'>";

                /*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:*/
                    inp.value = this.getElementsByTagName("input")[0].value;
                    /*close the list of autocompleted values,
                    (or any other open lists of autocompleted values:*/
                    closeAllLists();
                    /*submit form when is selected*/
                     document.getElementById("searchForm").submit(); 
                });
                a.appendChild(b);
              } 
            }
        })
        .catch(function(err) {
            closeAllLists(); //console.log('Fetch Error :-S', err);
        });  
  }
  /*execute a function when someone writes in the text field:*/
  inp.addEventListener("input", openDropdown);
  inp.addEventListener("focus", openDropdown);

  var openActive = function(e) {
      var x = document.getElementById(this.id + "autocomplete-list");    
      if (x) x = x.getElementsByTagName("div");
      if (e.keyCode == 40) {
        /*If the arrow 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 arrow 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();
        }
      }
  }
  /*execute a function presses a key on the keyboard:*/
  inp.addEventListener("keydown", openActive);

  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 closeAllLists(elmnt) {
    /*close all autocomplete lists in the document,
    except the one passed as an argument:*/
    var x = document.getElementsByClassName("autocomplete-items");
    for (var i = 0; i < x.length; i++) {
      if (elmnt != x[i] && elmnt != inp) {
      x[i].parentNode.removeChild(x[i]);
    }
  }
}
/*execute a function when someone clicks in the document:*/
document.addEventListener("click", function (e) {
    closeAllLists(e.target);
    currentFocus = -1;
});
} 

autocomplete(document.getElementById("text1"));
1 Like