Check out "Do you speak JavaScript?" - my latest video course on advanced JavaScript.
Language APIs, Popular Concepts, Design Patterns, Advanced Techniques In the Browser

Javascript: autocomplete country script

We are all filling registration forms. It's really nice when the page helps us to do that faster. The script, that I'm going to show you, is designed to be used for a country field.

The result of the script could be seen here. You can download the source files from hereStep 1 - Preparing the HTML. What we need is just a text field. When the user starts typing there our script should suggest all the possible countries that contain the entered symbols.

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
</head>
<body>
  <div class="container">
    Country:
    <input type="text" id="countryField"/>
  </div>
  </body>
</html>

Step 2 - Preparing the CSS. Of course we have to add some CSS to make things look better. Please notice the "helper" object. That's the div that will conain the countries that match the entered symbols by the user. The div has to be with absolute position so we can place it exactly below the text field.

body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  background: #FFF;
  font-family: Arial;
  font-size: 20px;
}

.container {
  display: block;
  width: 300px;
  margin: 0 auto;
  padding: 30px 0 0 0;
}

#countryField {
  width: 300px;
  display: block;
  padding: 8px;
  border: solid 2px #999;
  font-size: 15px;
  margin: 10px 0 0 0;
}

#helper {
  display: block;
  position: absolute;
  left: 0;
  top: 0;
}

#helper a {
  display: block;
  width: 100%;
  padding: 10px;
  border-bottom: solid 1px #999;
  border-left: solid 1px #999;
  border-right: solid 1px #999;
  font-size: 12px;
  color: #000;
  text-decoration: none;
  background: #FFF;
}

#helper a:hover {
  background: #999;
  color: #FFF;
}

Step 3 - Writing the main structure of our JavaScript class. As you can see there are several variables that we will need.

  • minChars - the number of symbols that are required to show the countries' links.
  • field - it will be a reference to the text field.
  • countryLoopId - we will need this for our loop function. I'll explain about it later.
  • helper - it will be a reference to the div that contains the links.
  • helperContent - it will contain the html string that will be send to the helper's div.

The class includes also a method called "init". That's the initial function of our class. It accepts the ID of the text field and checks if there is such element. If not, then it shows a message. After the definition of the class we are creating an instance of it. Also there is a global variable (an array) that contains the names of the countries. It's too long to paste it here, but you can find the complete list in the source files.

var AutoCountry = {};
  AutoCountry = function() {
    this.minChars = 2;
    this.field = null;
    this.countryLoopId = 0;
    this.helper = null;
    this.helperContent = "";
  }
  AutoCountry.prototype = {
    init: function(idOfTheField) {
      this.field = document.getElementById(idOfTheField);
      if (!this.field) {
        alert("Wrong input !");
      } else {}
    }
  }
  var AC = new AutoCountry();
  var countries = [
    // Africa
    "Algeria",
    "Angola",
    "Benin",
    "Botswana", ........."Paraguay", "Peru", "Suriname", "Uruguay",
    "Venezuela"
  ];

Step 4 - Starting the process. To start the process we have to pass the field's ID to the JavaScript class, so it can use the field's data.

<html>
  <head>
    <link href="css/styles.css" rel="stylesheet" type="text/css" media="all" />
    <script type="text/javascript" language="javascript" src="js/AutoCountry.js"></script>
    <script language="JavaScript" type="text/javascript">
      window.onload = function() {
        AC.init("countryField");
      }
    </script>
  </head>
  <body>
    <div class="container">
      Country:
      <input type="text" id="countryField"/>
    </div>
  </body>
</html>

Step 5 - Start the loop function. We need a loop function that has to check the field's data and compare it with the names of the countries. We have to start this function when the user is in the field and stop it when the user leaves the field. That's why we add two additional functions - onFieldIn and onFieldOut. The loop effect is made with setTimeout function. To stop it we will use clearTimeout function. As you can see in the body of the loop method we are composing the html string that comprises the neccessary countries' links.

AutoCountry.prototype = {
  init: function (idOfTheField) {
    this.field = document.getElementById(idOfTheField);
    if (!this.field) {
      alert("Wrong input !");
    } else {
      this.field.onfocus = this.onFieldIn;
      this.field.onblur = this.onFieldOut;
    }
  },
  onFieldIn: function () {
    AC.loop();
  },
  onFieldOut: function () {
    clearTimeout(AC.countryLoopId);
  },
  loop: function () {
    var list = "";
    var value = AC.field.value;
    if (value.length & gt; = this.minChars) {
      var numOfCountries = countries.length;
      for (var i = 0; i ' + countries[i] + '
        '
      }
    }
  }
  AC.countryLoopId = setTimeout("AC.loop()", 200);
}

Step 6 - Creating the helper's div. So, now we can access the text field in the loop function. We can get the data from it and find which countries to show. We only need a div that will be shown below the text field and will have the links. I also added functions for showing, hiding and positioning the div. (Add these functions in the class's prototype)

AutoCountry.prototype = {
  createHelper: function () {
    this.helper = document.createElement("div");
    this.helper.style.width = (this.field.offsetWidth - 22) + "px";
    this.helper.setAttribute("id", "helper");
    this.helper.innerHTML = "";
    document.body.appendChild(this.helper);
    this.positionHelper();
    this.hideHelper();
  },
  positionHelper: function () {
    var position = {
      x: 0,
      y: 0
    };
    var e = this.field;
    while (e) {
      position.x += e.offsetLeft;
      position.y += e.offsetTop;
      e = e.offsetParent;
    }
    this.helper.style.left = position.x + "px";
    this.helper.style.top = (position.y + this.field.offsetHeight) + "px";
  },
  showHelper: function () {
    this.helper.style.display = "block";
  },
  hideHelper: function () {
    this.helper.style.display = "none";
  }

Step 7 - Showing the helper's div and filling the text fieldFirst of all we have to call the "createHelper" function. We can do that in the "init" method. After that in the loop we will just check if the composed string is empty and if it is not we will fill the div. Maybe you noticed that the created link for every country is calling a javascript function from our class - setCountry. You can find it below, it simply changes the value of the text field.

AutoCountry.prototype = {
  init: function (idOfTheField) {
    this.field = document.getElementById(idOfTheField);
    if (!this.field) {
      alert("Wrong input !");
    } else {
      this.createHelper();
      this.field.onfocus = this.onFieldIn;
      this.field.onblur = this.onFieldOut;
    }
  },
  onFieldIn: function () {
    AC.loop();
  },
  onFieldOut: function () {
    clearTimeout(AC.countryLoopId);
    setTimeout("AC.hideHelper()", 600);
  },
  loop: function () {
    var list = "";
    var value = AC.field.value;
    if (value.length & gt; = this.minChars) {
      var numOfCountries = countries.length;
      for (var i = 0; i & lt; numOfCountries; i++) {
        if (value.toLowerCase() == countries[i].substr(0, value.length).toLowerCase()) {
          list += '<a href="javascript:AC.setCountry(\\'
          ' + countries[i] + '\\
          ');">' + countries[i] + ''
        }
      }
    }
    if (list != "") {
      if (this.helperContent != list) {
        this.helperContent = list;
        this.helper.innerHTML = this.helperContent;
      }
      this.showHelper();
    } else {
      this.hideHelper();
    }
    AC.countryLoopId = setTimeout("AC.loop()", 200);
  },
  setCountry: function (country) {
    this.field.value = country;
    this.hideHelper();
  }
If you enjoy this post, share it on Twitter, Facebook or LinkedIn.