Autocomplete dropdown in WordPress without a plugin

Autocomplete dropdown in WordPress without a plugin

If you are trying to create an ‘autocomplete dropdown’ in WordPress but don’t want to use a plugin, like most of the approaches, then here is the code tutorial you are after. The method of coding I’ve used is very fast with respect to the time it takes for results to show after a user starts typing. That’s because the data is already loaded and on the page and as such we don’t need to ask the database for it.

Table of Contents

Demo – what does it look like?

The end result will look something like this. I have tested this on my own site and it works well. You’ll notice that this method is very fast with respect to the time it takes for results to show after a user starts typing. That’s because the data is already loaded and on the page and as such we don’t need to ask the database for it.

The final search will look something like this…. its fast!

Step 1 – the PHP you need:

This function will be called to gather all the users in the database. We will put it in the functions.php.

<?php
// existing code in functions.php

function getList(){
    
    $get_users = get_users();
    $user_array = array();
    foreach ( $get_users as $user ) {
	        	
    	$searchable_string = str_replace(' ', '', $user->display_name);
        $user_array[] = $searchable_string;
    }
    return $user_array;
}

$listOfAllUsers = getList();
$users_array = array(
    'users' => $listOfAllUsers
);
wp_localize_script('users-array','usersarray_object',$users_array);
wp_enqueue_script('users-array');
wp_register_script( 'users-array', get_template_directory_uri() . '/userSearch.js', array('jquery'), $theme_version, false );

To explain what this is doing,

  • First we add a function called getList() which simply gets all the users in the database, loops through them and adds each ones display_name to an array. This data will end up being the data visible to users in the searchable dropdown.
  • Then we take our getList() and use it to create a JS variable and load it to the page. This is the aspect which makes it fast because when the page loads the users are already loaded and ready to search through as soon as the user starts to type instead of accessing the database each time the user types.
  • Then we load a JS file called userSearch.js, using WordPress’s wp_register_script native function. This file uses the array of users to we retrieved in PHP and feeds it to the autocomplete() function so it can access it. The autocomplete function is a JS one which we will get to in the next step.

Step 2 – The Javascript you need

Add the below to your https://yoursite.com/wp-content/themes/yourtheme/userSearch.js file.

jQuery(document).ready(function($) {
    
// here is a function we will use below
function autocomplete(inp, arr) {
  /*the autocomplete function takes two arguments,
  the text field element and an array 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*/
      closeAllLists();
      if (!val) { return false;}
      currentFocus = -1;
      /*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);
      /*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()) {
          /*create a DIV element for each matching element:*/
          b = document.createElement("DIV");
          /*make the matching letters bold:*/
          b.innerHTML = "<strong>" + arr[i].substr(0, val.length) + "</strong>";
          b.innerHTML += arr[i].substr(val.length);
          /*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();
          });
          a.appendChild(b);
        }
      }
  });
  /*execute a function presses a key on the keyboard:*/
  inp.addEventListener("keydown", 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();
        }
      }
  });
  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);
  });
}

// add the list of users as a JS variable to the page
    var users = usersarray_object.users;
    autocomplete(document.getElementById('searchableField'), users);
});

First, we add a function which will do the searching for us. Just ad it, it’s too complex to explain in full. I got this function from StackOverflow.

Then we access the JS variable which has a list of users in it. Then we tell the autocomplete() to the page and tell it which HTML field we will be adding the searchable field functionality to and give it the list of users to populate the search values for.

Step 3 – The HTML you need

Then we will add some HTML to the page which will be where a user can type and search for users.

<div class="autocomplete">
    <input id="searchableField" type="text">
</div>

Learn WordPress customization throughly with an online course at Udemy

If you are having difficulty understanding this tutorial and then I suggest you start from scratch with WordPress in general. The best way to learn is with a better all around general understanding of WordPress. Check out some of the courses on Udemy related to WordPress. They cover developer level courses and more non-dev CMS editor type tutorials as well.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *