Mention
Tags: tutorial, javascript, webdev
Published: 2023-12-21 07:14:21

The mention feature is a powerful tool that lets you tag and alert specific individuals or groups within a larger conversation. To use it, simply type the "@" symbol followed by the person's username, and they'll receive a notification that they've been tagged. This is particularly useful for group collaborations, ensuring that everyone is on the same page.

Moreover, social media platforms use it to draw attention to specific individuals, increasing engagement and facilitating conversations among users.

In this post, we'll learn how to implement this functionality with JavaScript.

## Finding people

In this post, we'll be using a similar approach as in the previous one to [add word completion](https://phuoc.ng/collection/mirror-a-text-area/add-autocomplete-to-your-text-area/) based on what you're typing. However, there are a few modifications we need to make.

Firstly, we'll check if the word you're typing is not empty and starts with the @ symbol.

```js
const currentWord = currentValue
    .substring(startIndex + 1, cursorPos)
    .toLowerCase();
if (currentWord === '' || !currentWord.startsWith('@')) {
    return;
}
```

Next, we'll extract the keyword by removing the first @ symbol.

```js
const searchFor = currentWord.slice(1);
```

Finally, we'll search for people with names similar to the keyword using the following sample code:

```js
const matches = suggestions
    .filter((suggestion) => suggestion.toLowerCase().indexOf(searchFor) > -1);
```

## Adding mentions

In the previous post, clicking on a suggestion inserted the whole word into the editor. In this example, we will add a person's name with an "@" symbol at the beginning, followed by a blank space so users can keep typing.

To achieve this, we just need to adjust the click event handler as follows:

```js
const option = document.createElement('div');
option.innerText = match;
option.classList.add('container__suggestion');

option.addEventListener('click', function () {
    replaceCurrentWord(`@${this.innerText} `);
    suggestionsEle.style.display = 'none';
});
```

## Highlighting mentioned people

At that time, we were able to suggest people and choose one person from the list to insert into the text area. However, since the text area only displays raw text, it's not possible to distinguish the mentioned people from normal text.

To fix this issue, we decided to create another mirrored element specifically for highlighting the mentioned people. It's a simple solution - we create a new element, copy the text area style, and sync the size with the text area size. Here's some code to demonstrate how we created the element and prepended it to the container.

```js
const highlightEle = document.createElement('div');
highlightEle.textContent = textarea.value;
highlightEle.classList.add('container__mirror');

containerEle.prepend(highlightEle);
```

After preparing the mirrored element, we'll highlight specific individuals. To do this, we'll use the same technique we introduced earlier to [highlight a given keyword](https://phuoc.ng/collection/mirror-a-text-area/highlight-keywords-in-a-text-area/) in a text area.

This time, we'll create a regular expression pattern by joining all the names of the people we want to highlight with the `|` character, which acts as an OR operator. The resulting pattern will match any occurrence of any of the mentioned names.

```js
const highlightReg = new RegExp(
    `(${suggestions.map((s) => `@${s}`).join('|')})`,
    'g'
);
```

To highlight certain people in our text, we can use the `textarea.value.replace` method. This method replaces all instances of a person's name with the same name enclosed in a `<span>` element with the class `container__mention`. Once we've done that, we can set the resulting HTML as the `innerHTML` of our mirrored element.

Here's an example code snippet to illustrate the process:

```js
highlightEle.innerHTML = textarea.value.replace(
    highlightReg,
    '<span class="container__mention">$&</span>'
);
```

In the sample code, the `$&` in the replacement string represents the matched text, which we wrap in a span with the appropriate class.

By inserting this HTML code as the innerHTML of our mirrored element, we can display the original text with all mentioned people highlighted for easy identification.

Now, we have the power to customize the appearance of the mentioned people. For instance, we can add a background:

```css
.container__mention {
    background: rgb(165 180 252);
    border-radius: 0.25rem;
}
```

It's important to note that we must re-highlight the text after users change the value of the text area or select a person from the list. To avoid repetition, we can create a function that handles this task and reuse it as needed.

```js
const highlightMentions = () => {
    highlightEle.innerHTML = textarea.value.replace(
        highlightReg,
        '<span class="container__mention">$&</span>'
    );
};

textarea.addEventListener('input', () => {
    highlightMentions();
});

highlightMentions();
```

Check out the final demo. If you want to mention someone, simply type the @ symbol followed by their name.

{% codepen https://codepen.io/phuocng/pen/YzgKMmb %}

---

It's highly recommended that you visit the [original post](https://phuoc.ng/collection/mirror-a-text-area/mention/) to play with the interactive demos. 

If you found this series helpful, please consider giving the [repository](https://github.com/phuocng/mirror-a-text-area) a star on GitHub or sharing the post on your favorite social networks 😍. Your support would mean a lot to me!

If you want more helpful content like this, feel free to follow me:

-   [Twitter](https://twitter.com/_phuocng)
-   [GitHub](https://github.com/phuocng)