One of my goals during my retreat at the Recurse Center, was to get better at web development and with JavaScript in particular. I’ve had experience in the past creating a Firefox extension, which was a very good learning practice. This time, I came up with the idea of having the browser show the definition of words by double-clicking on them.
In this post, I’ll explain the motivation behind the creation of this extension as well as some details of its implementation.
You can get the extension here and check the code here.
Motivation
Not so long ago, I used to search for the definitions of words in physical dictionaries, which took a few minutes. With the advent of the internet, this process has been simplified a lot with online dictionaries and even more with just querying search engines to directly get definitions.
The dictionary extension that is presented here, is one extra simplification in that process. Instead of needing to access an external web-site to get a word definition, you can get it directly by double-clicking on a word and have a popup show its definition.
Implementation
Getting into more technical details, I used vanilla JS to develop this extension. The extension performs the following operations after double-clicking on a word:
- Creating a modal (popup),
- requesting the word definition from an API, and
- populating the modal with the definition and placing it in the correct position.
Creating a modal
In this implementation, the modal is just an HTML div element placed on top of the web-site’s content. This is done by breaking the normal flow of the document to position the element (position : absolute
CSS rule). A great, in-detail, tutorial to create modals can be found here.
class Definition { constructor(wordSearched) { // Create modal }
A particularity of this implementation was having the popups as instances of a class. This was done in order to have the possibility of creating several word definitions as popups.
Requesting word definition from an API
To get word definitions, the extension queries an external API. Fortunately, I found a free-access dictionary API for this purpose.
The core of the requesting process takes place in the following two lines of code.
let response = await fetch( `https://api.dictionaryapi.dev/api/v2/entries/en_US/${word}` ); let body = await response.json();
The fetch
statement requests a word
definition. Once a response
has been obtained, it’s converted to an object to process it. See an example below for the case word = "hi"
.
[ ({ "word": "hi", "phonetics": [ { "text": "/haɪ/", "audio": "https://lex-audio.useremarkable.com/mp3/hi_us_1.mp3" } ], "meanings": [ { "partOfSpeech": "exclamation", "definitions": [ { "definition": "Used as a friendly greeting or to attract attention." } ] } ] } ]
Populating and placing the modal
Once a definition has been obtained from the previous step, the popup is populated with the contents of the response. This process involves changing the text content of the popup elements (headings, lists, etc). Finally, the position of the modal is changed so that it’s right next to the clicked word.
Most of this process can be seen in the event listener below, which is activated when double-clicking.
document.addEventListener("dblclick", async () => { const text = window.getSelection(); const textString = text.toString(); if (textString) { const textPosition = text.getRangeAt(0).getBoundingClientRect(); const definition = new Definition(textString); await definition.writeDefinitionContent(textString); definition.setPosition(textPosition); definition.add(); } });
Learning outcomes
This project was a very rewarding and fun learning experience. Some of the things I’ve learned:
JavaScript classes
Once the definition popup class was defined, it was possible to create as many of them as wanted without increasing the complexity of the project. It was also very helpful and orderly to have all the popup elements and methods “encapsulated”.
Fetch API
I still don’t understand fetch
100%, but it makes a lot more sense now. Among other resources, this video tutorial offered a good explanation.
HTML and text content insertion
I was never really sure about the best way of changing the text of an HTML element or injecting new HTML elements into the page. There are several approaches: innerHTML
, insertAdjacentHTML
, textContent
, and createTextNode
. Regarding performance, innerHTML
is clearly the worst. And from a security standpoint, both innherHTML
and insertAdjacentHTML
come with the risk of injecting insecure content to the page. That was something I was able to learn during the review process while submitting this extension.