Auto-filling Forms with jQuery and the Web Storage API

By Aurelio De Rosa

In a project I developed a few years ago there was a search form made of a main field and then many other fields to refine the search. In that project a user typically needed to perform the same search multiple times with just one or two fields changed. Filling the form again and again was a pain so we decided to help the users in quickly achieving their goal.

In this article I’ll show you how to recreate the same improvement using jQuery, jQuery.deserialize, and the Web Storage API.

The Requirements

To improve the form I mentioned in the introduction, we decided to show a list of previously performed searches, up to 20. The searches are stored into the browser using the Web Storage API. If you have a login system in place, you may want to modify the demo so that the searches are stored in a database. In my case this wasn’t an option as there wasn’t a login system.

Each item of the list is made of text representing the value the user wrote in the main field, and a sublist showing the name of the field and the value(s) written or selected (in case of checkboxes and radio buttons). When the user clicks one of these searches, the form’s fields are automatically filled with the values of that search. Doing so, if the user needs to perform the same research he/she has nothing to do but click the Submit button; otherwise the user can change the fields needed and then perform the search. This small improvement saved a lot of time for the users of that project and was much appreciated.

The final result of this article is shown below and also available as a JSFiddle:

The Markup

The first step is to create the form to enhance. If you’ll use this approach in a project you are working on, you’ll have your own with its own specific fields, but for the sake of the example here I’ll create a dummy one containing a different type for each field. For instance, I’ll use the search, text, email, checkbox, radioand date type. This way you can see how this method works with different types.

There is nothing more to say about the form, so here is the code that we’ll employ:

<form name="form" id="form">
   <label for="search">This is the main search field:</label>
   <input type="search" name="search" id="search" />
   <label for="text">This a text field:</label>
   <input type="text" name="text" id="text" />
   <label for="email">This an email field:</label>
   <input type="email" name="email" id="email" />
   <label>This a set of checkbox:</label>
      <input type="checkbox" name="checkbox[]" value="checkbox1" />
      <input type="checkbox" name="checkbox[]" value="checkbox2" />
   <label>This a set of radio buttons:</label>
      <input type="radio" name="radio" value="radio1" checked />
      <input type="radio" name="radio" value="radio2" />
      <input type="radio" name="radio" value="radio3" />
   <label for="date">This a date field:</label>
   <input type="date" name="date" id="date" />

   <input type="reset" value="Reset" />
   <input type="submit" value="Submit" />

With the form in place we also need an element to show the previous searches. To do that, I’ll add the following ordered list to the page:

<ol id="searches-list">

That’s it! Our demo doesn’t need other elements, at least not static ones as we’ll see in a later section.

The Style

By default the list of the old searches will show only the main field’s value, leaving the sublist of field name/value hidden. This is useful, especially if you have a form with many fields because the whole list can easily become long, so long in fact that the user needs to scroll. As always we also want to consider that showing something only when the user hovers an element is a bad approach due to accessibility problem. Therefore, we’ll display the sublist when the main value gains the focus. This is done with the following CSS:

#searches-list > li:hover dl,
#searches-list > li:focus dl
   display: block;

#searches-list dl
   margin: 0;
   display: none;

Finally, we want to give a visual clue that the list can do something, hence we’ll also change the cursor to be a pointer:

   cursor: pointer;

Now that we’ve done with the style, it’s time to discuss the business logic that powers the improvement.

The Business Logic

This small demo will use jQuery and jQuery.deserialize, so the first thing you need to do is to grab a copy of them and include them in the page. You also need some knowledge of the Web Storage API, so I encourage you to read the article An Overview of the Web Storage API.

The first step for this section is to retrieve and store into a variable the main elements of our page, the form and the list of searches, because we’ll use them many times:

var $searchesList = $('#searches-list');
var $form = $('#form');

Then we need to verify if the user has already some searches stored. If this is the case we’ll save them into a variable, otherwise we’ll initialize the variable to an empty array:

var searches = window.localStorage.getItem('searches');
searches = (searches === null) ? [] : JSON.parse(searches);

Very imaginatively I’ve named the key where the code will store the searches as “searches”. In the second statement I needed to use the JSON.parse() method because the Web Storage API doesn’t allow to store complex data.

At this point we have to instruct what our page should do when the user performs a new search. Therefore, we’ll add an event handler for the submit event of the form.

In the code of the live demo I showed at the beginning, the first statement of the handler stops the form to actually submit the data. This is done because the demo doesn’t have a backend but in a real-world project you don’t need it.

When the user fills the form and submits it, we need to store the values inserted into the local storage before the request is sent. To do that we first serialize the form by using the jQuery’s serialize() method and then place the last performed search at the top of the list. In this demo we’ll avoid storing the same search multiple times, so the code searches for duplicates and removes them. Finally, the demo stores a maximum of 10 searches per user but you change this value to whatever you want. Once we have performed all these operations on the searches, we need to store them back in the local storage.

This is achieved with the following code:

$form.submit(function(event) {
   // Serializes the form
   var currentSearch = $(this).serialize();
   // Removes the duplicates
   for(var i = 1; i < searches.length; i++) {
      if (searches[0] === searches[i]) {
         searches.splice(i, 1);

   // Stores only the last 10 searches
   if (i === searches.length && searches.length > 10) {

   // Stores the new list into the local storage
   window.localStorage.setItem('searches', JSON.stringify(searches));

In the demo as the last statement I’ll call a function named buildSearchesList() that we’ll discuss shortly. It’s needed because the demo hasn’t a backend, so the HTML list needs to be recreated every time the form is submitted.

So far the page is able to store the searches performed but we need to show the list to the user so that if he/she clicks one of the items the form is autofilled. For this last part we’ll create a function called buildSearchesList(). Inside it, we empty any previously built list and then loop over the old searches. As I mentioned, each item of the list shown will display as a mnemonic name the value of the main field, and a sublist containing all the fields of the form displayed only when the user hovers or focuses on the mnemonic name. Every time the user clicks, or presses ENTER or SPACE on an item of the list, the form is autofilled using the selected set of values.

Based on this description the skeleton of the function is as follows:

function buildSearchesList(searches, $searchesList, $form) {

   for (var i = 0; i < searches.length; i++) {
      // Other code goes here...

Inside the for, we have to convert each item in the list retrieved from the local storage into a JSON-parsable string and then convert it into its equivalent object. Then, we loop over the properties of this object to create the sublist containing the name and values of the fields. The sublist is created using a dl element and its related dt and dd.

The code that implements these steps is reported below:

var params = JSON.parse('{"' +
         .replace(/&/g, '","')
         .replace(/=/g, '":"')
         .replace(/\+/g, ' ')
   ) +

var text = '<dl>';
for (var key in params) {
   text += '<dt>' + key + ':</dt><dd> ' + params[key] + '</dd>';
text += '</dl>';

Now that we have created the item of the list of the previous searches, we need to add it to the list and also instruct that if the user clicks or press one of the two keys mentioned before the form is autofilled. The form is autofilled by the jQuery.deserialize plugin and a call to its deserialize() method. But because we’re in a loop and dealing with event handlers we have to wrap the code into an IIFE to avoid any closure issues. Finally, each list item (li) must have a tabindex="0" attribute otherwise it cannot be focused using the TAB key. The code that implements this last part is listed below:

(function(searchData) {
      $('<li tabindex="0">')
         .on('click keypress', function(event) {
            if (
               event.type !== 'keypress' ||
               event.keyCode === 13 ||
               event.keyCode === 32
            ) {

With this last snippet we’ve concluded our demo. Once again, the final result of this article is shown below and also available as a JSFiddle:


In this article I’ve discussed a simple technique to enhance the experience of your users in case your project has a form that is filled many times during a typical session. By using jQuery and jQuery.deserialize, in addition to the Web Storage API, we’ve created a page that is able to store a given set of searches and restore them if necessary. I hope you’ve enjoyed the article and you find it useful.


I tried this example on iPhone. I get this error SecurityError: DOM Exception 18: An attempt was made to break through the security policy of the user agent.

I looked this up and this seemed to be because of the Safari privacy settings on iPhone.
I switched to 'Allow all'. Then the error in the console dissapeared. Then I wasn't able to submit the form.
when i submitted the form in the console with $('#form').submit() I had this error

QuotaExceededError: DOM Exception 22

Checked this also and Safari seemed to be in 'Private Browsing mode'. When I turned this of I was able to run the examle on iPhone



To summarize your comment, we can say that Safari is a PITA smile


Yes you can smile I am wondering what the default settings are for Safari on iPhone. Can't find a list anywhere. Ofcourse if this autofill doesn't work for most iPhone users because of their Safari settings you want to create something specific for these users.



Learn Coding Online
Learn Web Development

Start learning web development and design for free with SitePoint Premium!

Get the latest in JavaScript, once a week, for free.