How to style search results from html input form

Viewed 432

I'm using a html input field to search for results from OMDb, currently I just have them shown below the form in a list, but would like them to appear below the input field, kinda like when you're on Google's homepage and you get a few results, where it drops down showing potential search results from what you've typed already (ie if I type Shang it might pop down below it showing Shang-Chi, Shei xian ai shang ta de, Hai shang hua, Da Shang Hai etc..).

<li>
   <label for="search">OMDb lookup:</label>
   <input id="search" placeholder="start typing film title" type="input" name="search" maxlength="255" onkeyup="waitForIt()">
</li>
<li>
   <ul id="omdbReturn">
   </ul>
</li>

Is what I have for the HTML, then my javascript is:

var timer = null;

function waitForIt() {
    clearTimeout(timer);
    timer = setTimeout(omdbSearch, 1000)
};

function omdbSearch() {
    let searchTerm = encodeURI(document.getElementById("search").value);
    $.getJSON('https://www.omdbapi.com/?apikey=<apikey>&type=movie&page=1&s=' + searchTerm).then(function(omdbResults) {
        if (omdbResults.Response !== 'False') {
            let tot = omdbResults.totalResults;
            if (tot > 10) { //only return up to first ten results
                tot = 10;
            }
            document.getElementById('omdbReturn').innerHTML = '';
            for (i = 0; i < tot; i++) {
                document.getElementById('omdbReturn').innerHTML += ('<li id="' + omdbResults.Search[i].imdbID + '">' + omdbResults.Search[i].Title + ' (' + omdbResults.Search[i].Year + ')</li>');
            }
            let list = document.getElementById("omdbReturn");

            function Populate() {
                $.getJSON('https://www.omdbapi.com/?apikey=<apikey>&type=movie&plot=full&i=' + this.id).then(function(omdbMovie) {
                    document.getElementById("film").value = omdbMovie.Title + " (" + omdbMovie.Year + ")";
                    document.getElementById("image_url").value = omdbMovie.Poster;
                    document.getElementById("desc").value = omdbMovie.Plot;
                    document.getElementById("imdb").value = "https://www.imdb.com/title/" + omdbMovie.imdbID + "/";
                    document.getElementById('omdbReturn').innerHTML = '';
                });
            }
            for (i = 0; i <= list.childElementCount - 1; i++) {
                list.children[i].addEventListener("click", Populate);
            }
        } else {
            document.getElementById('omdbReturn').innerHTML = '';
        }
    });
}
                        

So this all works great, produces a nice little list of results and if I click on a result it will populate the relevant fields in the rest of my form (saving the user having to go to IMDb and copy/paste the results themselves) - I would just like to improve how it appears on screen but my CSS is terrible and google isn't really understanding what I'm trying to ask (so lacking the wording I guess to nail the search).

Not looking for someone to bespokely script it for me, just pointers in the right direction would be greatly appreciated!

[edit]

Just a thought, here's what the Javascript injected HTML looks like, using the "Shang" search example again:

<ol id="omdbReturn">
  <li id="tt9376612">Shang-Chi and the Legend of the Ten Rings (2021)</li>
  <li id="tt8443704">Shei xian ai shang ta de (2018)</li>
  <li id="tt0156587">Hai shang hua (1998)</li>
  <li id="tt2169322">Bei Jing yu shang Xi Ya Tu (2013)</li>
  <li id="tt6628322">Shang hai bao lei (2019)</li>
  <li id="tt2458314">Da Shang Hai (2012)</li>
  <li id="tt0492473">Kan shang qu hen mei (2006)</li>
  <li id="tt0101864">Fei zhou he shang (1991)</li>
  <li id="tt9081562">Bi bei shang geng bei shang de gu shi (2018)</li>
  <li id="tt11448076">Xuan ya zhi shang (2021)</li>
</ol>
1 Answers

Thanks to mplungjan who pointed us at datalist. I've updated the above html & javascript so it references a datalist instead of making a html list and then onclicking that there's another bit of code that grabs the associated imdb ID and runs the query to push the data in to the form:

html:

<li>
    <label for="search">OMDb lookup:</label>
    <input list="omdb" id="search" placeholder="start typing film title" type="input" name="search" maxlength="255" onkeyup="waitForIt()">
    <datalist id="omdb">
    </datalist>
</li>

javascript:

var timer = null;
function waitForIt() {
       clearTimeout(timer); 
       timer = setTimeout(omdbSearch, 1000)
};
function omdbSearch() {
  let searchTerm = encodeURI(document.getElementById("search").value);
  $.getJSON('https://www.omdbapi.com/?apikey=<apikey>&type=movie&page=1&s=' + searchTerm).then(function(omdbResults){
    if(omdbResults.Response !== 'False') {
        let tot = omdbResults.totalResults;
        if(tot > 10) {
            tot = 10;
        }
        omdbRes = "";
        for(i=0; i < tot; i++) {
            omdbRes += '<option id="' + omdbResults.Search[i].imdbID + '" value="' + omdbResults.Search[i].Title+' ('+omdbResults.Search[i].Year + ')" />';
        }
        document.getElementById("omdb").innerHTML = omdbRes;
        
        var inputs = document.querySelectorAll('input[list]');
        for (var i = 0; i < inputs.length; i++) {
          inputs[i].addEventListener('change', function() {
            var optionFound = false,
              datalist = this.list;
            for (var j = 0; j < datalist.options.length; j++) {
                if (this.value == datalist.options[j].value) {
                    Populate(datalist.options[j].id);
                    break;
                }
            }
          });
        }
        
        function Populate(imdb){
            $.getJSON('https://www.omdbapi.com/?apikey=<apikey>&type=movie&plot=full&i=' + imdb).then(function(omdbMovie){
                document.getElementById("film").value = omdbMovie.Title + " (" + omdbMovie.Year + ")";
                document.getElementById("image_url").value = omdbMovie.Poster;
                document.getElementById("desc").value = omdbMovie.Plot;
                document.getElementById("imdb").value = "https://www.imdb.com/title/" + omdbMovie.imdbID + "/";
                
            });
        }
    }
  });
}

So if anyone comes across needing to do the same, that's how I handled it. You could improve by adding pagination to the search (I've kept at the first page, a limit of 10 as I feel that's enough for a drop down to display and people can type more to refine rather than scroll and search..).

Related