<div class="shadow bg-success text-white p-2 text-center mb-4">
  <span class="h3 mb-0">Autocomplete using vanilla JavaScript</span>
  <br/>
  <small>with Bootstrap for style</small>
</div>
<div class="container">
  <div class="row">
    <div class="col-lg-6 m-auto">
      <div class="mb-3">
        <label class="form-label">Programming Language :</label>
        <input type="text" placeholder="Start typing..." class="form-control" id="myInput" autocomplete="off">
      </div>
    </div>
  </div>
</div>
body {
  background: #333;
  color: #fff;
}
var programming_languages = ["Ada", "APL", "Assembly language", "BASIC", "C", "C#", "C++", "Cobol", "Dart", "Delphi", "Forth", "Fortran", "FoxPro", "Golang (Go)", "Groovy", "Haskell", "Java", "JavaScript", "Kotlin", "Lisp", "Lua", "MATLAB", "Objective C", "Pascal", "Perl", "PHP", "PowerShell", "Python", "Qbasic", "R", "Ruby", "Rust", "Scala", "Shell", "Smalltalk", "SQL", "Swift", "TypeScript", "Visual Basic", "Visual Basic .NET"];

function autocomplete(autocomplete_input, suggestions) {
    var currentOption;
    var total_autocomplete = document.getElementsByClassName('autocomplete-input').length

    autocomplete_input.parentNode.style.position = "relative";
    autocomplete_input.classList.add('autocomplete-input');
    autocomplete_input.setAttribute('data-autocomplete-list-id', "autocomplete-list-" + (total_autocomplete + 1));
    autocomplete_input.setAttribute('autocomplete', "off");

    autocomplete_input.addEventListener("input", function(e) {
    	var $this = this;
        var string_to_match = $this.value.toLowerCase();
        var autocomplete_list_id = $this.getAttribute('data-autocomplete-list-id');

        removeLists();

        if (string_to_match) {
            currentOption = -1;
            var regex = new RegExp( '(' + string_to_match + ')', 'gi' );

            var autocomplete_list = document.createElement("DIV");
	        autocomplete_list.setAttribute("id", autocomplete_list_id);
	        autocomplete_list.setAttribute("class", "autocomplete-list shadow border");
	        autocomplete_list.style.marginTop = "5px";
	        autocomplete_list.style.maxHeight = "300px";
	        autocomplete_list.style.overflowY = "auto";

	        var autocomplete_items = document.createElement("DIV");
	        autocomplete_items.setAttribute("class", "list-group list-group-flush autocomplete-items");

	        suggestions.forEach(function(suggestion) {
	        	if (suggestion.toLowerCase().includes(string_to_match)) {
	        		var autocomplete_item = document.createElement("DIV");
	                autocomplete_item.setAttribute('class', 'list-group-item list-group-item-action');
		        	autocomplete_item.setAttribute("data-autocomplete-text", suggestion);
	                autocomplete_item.innerHTML = suggestion.replace(regex, "<b>$1</b>" );

	                autocomplete_item.addEventListener("click", function(e) {
	                    autocomplete_input.value = this.getAttribute("data-autocomplete-text");
	                    autocomplete_items.remove();
	                });

	                autocomplete_items.appendChild(autocomplete_item);
	        	}
	        });

	        autocomplete_list.appendChild(autocomplete_items);
	        $this.parentNode.appendChild(autocomplete_list);
        }
    });

    autocomplete_input.addEventListener("keydown", function(e) {
        var autocomplete_list_id = this.getAttribute('data-autocomplete-list-id');
    	var autocomplete_list = document.getElementById(autocomplete_list_id);

    	if ( autocomplete_list ) {
    		var autocomplete_items = autocomplete_list.querySelector('.autocomplete-items').getElementsByTagName("div");
    		
    		if (e.keyCode == 40) {
	            currentOption++;
	            selectItem(autocomplete_items);
	        } else if (e.keyCode == 38) {
	            currentOption--;
	            selectItem(autocomplete_items);
	        } else if (e.keyCode == 13) {
	            e.preventDefault();
	            if (currentOption > -1) {
	                if (autocomplete_items) {
	                	autocomplete_items[currentOption].click();
	                }
	            }
	        }
    	}
    });

    function selectItem(autocomplete_items) {
        if (autocomplete_items) {
		    Array.from(autocomplete_items).forEach(autocomplete_item => {
		    	autocomplete_item.classList.remove("active");
			});
		    
		    currentOption = currentOption >= autocomplete_items.length ? 0 : currentOption;
		    currentOption = currentOption < 0 ? autocomplete_items.length - 1 : currentOption;

	        autocomplete_items[currentOption].classList.add("active");
        }
    }

    function removeLists(element) {
        var autocomplete_lists = document.getElementsByClassName("autocomplete-list");
        Array.from(autocomplete_lists).forEach(autocomplete_list => {
            if (element != autocomplete_list && element != autocomplete_input) {
    			autocomplete_list.remove();
            }
		});
    }

    document.addEventListener("click", function(e) {
        removeLists(e.target);
    });
}

autocomplete(document.getElementById("myInput"), programming_languages);

External CSS

  1. https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/css/bootstrap.min.css

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/js/bootstrap.min.js