Tutorials / Building Search UI / Autocomplete textarea
Jun. 24, 2019

Autocomplete Textarea

Introduction

Have you ever asked yourself how you could easily integrate in your website, a @mention or #hashtag feature that could be as slick and handy as the one we can find on Twitter, Facebook, …?

One approach is to use Javascript plugins & scripts that perform, most of the time, very basic text search (based on regex) on items already pre-populated in the HTML, or dynamically retrieved from the database via AJAX requests. Those solutions work OK, but quickly show their limits as soon as you want to offer to your users a search experience that handles their typos, is fast, and can work on hundreds, thousands or millions of items.

In this tutorial you will see how you can easily integrate, in a few minutes, an instant search autocomplete within an input or a text area.

Autocomplete textarea 1

You can check out our live demos

We will more specifically focus on implementing a @mention feature, but the same logic can also work if you want to build:

  • A #hashtag feature similar to what you can find on Twitter
  • A mention feature where end-users can easily reference not only people but also places, brands, or any other item/object in your web application
  • An Advanced search with dynamic refinements: see Abacus blogpost

Before moving to the implementation of the feature itself, let’s first have a look at indexing.

Dataset indexing

For this tutorial, we are going to use a dataset of 500 famous actors extracted from themoviedb.org. You can download it here and easily import it using the Dashboard’s explorer and its manual upload feature available in the sidebar on the right.

Autocomplete textarea 2

Screenshot of the upload dialog

If you want to import your own data using the API, you can refer to our guide on importing data.

Below, the actor’s record structure used.

1
2
3
4
5
6
7
{
  "objectID": "551486440",
  "name": "Tom Hanks",
  "alternative_name": "",
  "popularity": 1392,
  "image_path": "/a14CNByTYALAPSGlwlmfHILpEIW.jpg"
}

Once the dataset is imported, we can now quickly tweak the relevance and the ranking in order to get the best relevance and performance from Algolia’s search engine. Select your freshly created index, called actors, and go to the Ranking tab. Then add the attributes called name and alternative_name to the attributeToIndex list. Keep in mind that you only need to add on attributeToIndex the attributes that will be used by the engine to perform a full-text search. In our case, we only want to search for actors using their names.

Autocomplete textarea 3

Define the attribute describing each record popularity

Once that’s done, add the attribute popularity to the customRanking setting. The custom ranking is used to sort results not only based on the textual matching, but also based on a popularity value related to your business specifications and requirements. In our dataset, we know that records with the highest popularity values are the most popular.

Autocomplete textarea 4

We have now imported our actors dataset, and configured our index. Let’s now see how to integrate our search feature in our textarea.

Frontend UI

To ease the autocomplete integration we will leverage the power of the a jQuery plugin called jquery-textcomplete and configure it to perform search calls against the Algolia API. For that, we’ll also use the latest version of our JS API client available on Github (documentation) or directly from the JsDeliver CDN, by including https://cdn.jsdelivr.net/algoliasearch/3/algoliasearch.min.js.

jsDelivr is a third-party CDN. We are not able to provide support regarding third party services.

HTML

Nothing special here. We include the CSS/JS files of the jquery-textcomplete plugin and import the latest version of the Algolia’s JS API Client. We also add a textarea element inside the <body> section.

1
2
3
4
5
6
7
8
9
<head>
  <!-- Text Autocomplete plugin -->
  <script src="./jquery.textcomplete.min.js"></script>
  <!-- Algolia Search API Client - latest version -->
  <script src="https://cdn.jsdelivr.net/algoliasearch/3/algoliasearch.min.js"></script>
</head>
<body>
  <textarea class="form-control" rows="5" id="autocomplete-textarea">
</body>

Note: We use a textarea, but the plugin also works on regular text inputs.

Javascript

Now to the most interesting part of this tutorial - where all the @mention and search logic gets integrated.

Go to your Dashboard Credentials page and copy / paste your ALGOLIA_APPID and ALGOLIA_SEARCH_APIKEY to the part #1 of the source code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// #1 - Search configuration - To replace with your own
const ALGOLIA_APPID = '';
const ALGOLIA_SEARCH_APIKEY = '';
const ALGOLIA_INDEX_NAME = 'actors';
const NB_RESULTS_DISPLAYED = 5;
// #2- Algolia API Client Initialization
const algoliaClient = new algoliasearch(ALGOLIA_APPID, ALGOLIA_SEARCH_APIKEY);
const index = algoliaClient.initIndex(ALGOLIA_INDEX_NAME);
let lastQuery = '';
$('#autocomplete-textarea').textcomplete([
  {
    // #3 - Regular expression used to trigger the autocomplete dropdown
    match: /(^|\s)@(\w*(?:\s*\w*))$/,
    // #4 - Function called at every new keystroke
    search(query, callback) {
      lastQuery = query;
      index.search(lastQuery, { hitsPerPage: NB_RESULTS_DISPLAYED })
        .then(content => {
          if (content.query === lastQuery) {
            callback(content.hits);
          }
        })
        .catch(err => {
          console.error(err);
        });
    },
    // #5 - Template used to display each result obtained by the Algolia API
    template({_highlightResult}) {
      // Returns the highlighted version of the name attribute
      return _highlightResult.name.value;
    },
    // #6 - Template used to display the selected result in the textarea
    replace({name}) {
      return ` @${name.trim()} `;
    }
  }
], {
  footer: '&lt;div style="text-align: center; display: block; font-size:12px; margin: 5px 0 0 0;"&gt;Powered by &lt;a href="http://www.algolia.com"&gt;&lt;img src="https://www.algolia.com/assets/algolia128x40.png" style="height: 14px;" /&gt;&lt;/a&gt;&lt;/div&gt;'
});

Looking for more options? Checkout the jquery-textcomplete plugin documentation

Stylesheet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#autocomplete-textarea {
  min-height: 80px;
  color: #000;
}
#autocomplete-textarea a {
  text-decoration: none;
  font-weight: normal;
  color: #181818;
}
.dropdown-menu .textcomplete-item a,
.dropdown-menu .textcomplete-item a:hover {
  cursor: pointer;
  font-weight: normal;
  color: #000;
  position: relative;
  padding: 3px 10px;
}
.dropdown-menu .textcomplete-item.active a {
  background: #F0F0F0;
}
/* Highlighting of the matching part
   of each search result */
.dropdown-menu .textcomplete-item a em {
  font-style: normal;
  font-weight: bold;
}
.dropdown-menu .textcomplete-footer {
  border-top: solid 1px #F0F0F0;
  margin-top: 3px;
}

That’s it, the @mention feature is now ready to use. Give it a try searching for your favorite actor: for instance “Loved the last movie with @tom…”

Autocomplete textarea 5

Basic autocomplete dropdown in a textarea - Live DEMO

UI Customization

Let’s now see how we can improve the overall User Experience by upgrading some UI elements.

Highlighting variants

By default, each hit in the JSON response returned by the API, contains an highlighted version of each matching strings. Those are surrounded by tags and can be easily styled using a few line of CSS. For now, we’ve displayed them in bold, but there are many other handy ways to display them to your users.

a. Using underline

1
2
3
4
.dropdown-menu .textcomplete-item a em {
 &nbsp;font-style: normal;
  text-decoration: underline;
}

Autocomplete textarea 6

b. Using a light colorful background

1
2
3
4
.dropdown-menu .textcomplete-item a em {
 &nbsp;font-style: normal;
  background: #fcf8e3;
}

Autocomplete textarea 7

Adding the actors’ photo

Everyone knows that pictures are worth a 1000 words - they help users to identify faster what they are looking for. So why don’t we add the actors’ photo next to their name in order to make it even easier to use, and more user-friendly?

Autocomplete textarea 8

Play with the Live DEMO

The only thing you need to do is to update the template used the ‘textcomplete’ plugin and the css:

1
2
3
4
// #5 - Template used to display each result obtained by the Algolia API
template(hit) {
  return `<img src="//image.tmdb.org/t/p/w45/${hit.image_path}" /></div>${hit._highlightResult.name.value}`;
},
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
.dropdown-menu .textcomplete-item a {
  box-sizing: border-box;
  height: 42px;
}
.dropdown-menu .textcomplete-item .picture {
  border-radius: 2em;
  -webkit-border-radius: 2em;
  -moz-border-radius: 2em;
  width: 32px;
  height: 32px;
  overflow: hidden;
  float: left;
}
  .dropdown-menu .textcomplete-item .picture img {
    width: 32px;
  }
.dropdown-menu .textcomplete-item .name {
  float: left;
  margin: 5px 0 0 5px;
}

Check out the demo’s Source Code (on Github)

Rich HTML display within the Textarea

Displaying a raw text once a result is selected is nice. But wouldn’t be even nicer to render HTML results instead. Those ones could include rich text formatting, pictures, …

Autocomplete textarea 9

Play with the Live DEMO

We’d need here to slightly modify what we’ve done till now:

a. The textarea needs to be replace by a “contenteditable div”.

By design HTML input[type=text] and textareas cannot render any HTML. To workaround that limitation we need to use a regular div on which we add the property contenteditable="true". The div then behaves like a regular input, but offers the possibility to render HTML.

1
2
<div class="form-control" id="autocomplete-textarea" contenteditable="true"></div>

Learn more about “contenteditable divs” and its browser compatibility, on the Mozilla Developer Network

b. Update the template used when the search result get inserted in the textarea

1
2
3
4
5
6
7
8
9
10
11
// #6 - Template used to display the selected result in the contenteditable's div
replace (hit) {
  const html = `
    <a class="tag-item" href="">
      <div class="picture-wrapper">
        <img src="//image.tmdb.org/t/p/w45/${hit.image_path}" />
      </div>
      <span class="label">${hit.name}</span>
    </a>`;
  return html;
}

c. Tell the jQuery plugin to render HTML based results

1
2
3
// #7 - Special adapter to handle HTMLContentEditable divs
adapter: $.fn.textcomplete.HTMLContentEditable,
footer: '<div style="text-align: center; display: block; font-size:12px; margin: 5px 0 0 0;">Powered by <a href="http://www.algolia.com"><img src="https://www.algolia.com/assets/algolia128x40.png" style="height: 14px;" /></a></div>'

d. Update the Stylesheet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.tag-item, .tag-item:visited {
  font-weight: normal;
  padding: 2px 3px;
  -webkit-border-radius: 2px;
  -moz-border-radius: 2px;
  border-radius: 2px;
  background: #f0f0f0;
  cursor: default;
  border: solid 1px #dadada;
}
  .tag-item:hover {
    text-decoration: none;
  }
  .tag-item .picture-wrapper {
    border-radius: 2em;
    -webkit-border-radius: 2em;
    -moz-border-radius: 2em;
    display: inline-block;
    width: 16px;
    height: 16px;
    position: relative;
    overflow: hidden;
    top: 3px;
  }
    .tag-item .picture-wrapper img {
      width: 16px;
    }
  .tag-item .label {
    color: #181818;
  }

Check out the demo’s Source Code (on Github)

Conclusion

In this tutorial we have seen together how to create an autocomplete dropdown within a textarea, commonly used by websites and apps like Facebook, Twitter, …, to integrate handy @mention and #hashtags features. We hope this tutorial also inspired you to build and integrate new features in your website or mobile application!

Autocomplete textarea 10

Final version - Live DEMO

Did you find this page helpful?