Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML5

mojiWriter: An App to Make It Easier to Use and Manage Emojis when Writing Posts/Docs/Email

5.00/5 (1 vote)
25 Jan 2021CPOL7 min read 5.7K   62  
Learn to build an app in using HTML, JavaScript, CSS which will later run on the desktop.
In this article, you will find a good app to show how easy it is to create a complete app using only HTML, JavaScript and CSS, and how Bootstrap (premade buttons, etc.) can make things a lot easier.

Introduction

I run Ubuntu 20.04 as my main dev machine. I remote into work using Remmina (RDP software) to connect to Win10 boxes where I do work.

There are times when I want to use an emoji in a document or an email and there isn't a great solution that provides a way to copy and paste a quick emoji. I decided to create my own. Yes, on Win10, Windows-Key/Comma gets you the emoji pad deal but not on Ubuntu.

Also the limitation of the Win10 version is that you cannot add new emojis (mine provides this ability).

Background

A weekend project turned into a complete app. I also thought this might be a good app to show how easy it is to create a complete app using only HTML, JavaScript and CSS and how Bootstrap (premade buttons, etc.) can make things a lot easier.

No Deployment Challenges

Of course, the huge advantage of creating an app in HTML is that there is no deployment challenge. People just point their browsers at the app and go.

Try It Right Now

You can try the app right now so you can see what you're getting into.

Just point your browser at my website: https://newlibre.com/mojiWriter[^].

Image 1

Usage

  1. Just click one or more emojis, right-click and choose copy and they'll be ready to be pasted into your document.
  2. When you select them for use, they'll be added to your [Recent] list making it easier to use common emojis.
  3. Later, when you come upon an emoji you want to save for your own use, you can copy it and add it to the app.
    1. Click the Custom tab.
    2. Paste in the emoji you want to save.
    3. Click the [Save] button. It'll be written to your localStorage so it'll always be here ready to use.

Image 2

Let's click the XX-Large button (to make the emojis larger and easier to see details). Next, we select one of the newly added emojis and check the [Recent] list and we see that they show up there in the list.

Image 3

App Requirements

Originally, I just wanted one thing:

  • A way to easily select and copy an emoji into a document I was typing.

But, as I began developing the app, I wanted a bit more.

  • A way to see and grab Recently Used emojis (ones I commonly used)
  • UI which grouped similar emojis, so I could find them more easily
  • A way to view emojis at a larger size
  • A way to add new emojis to a custom list so I can expand the emojis I can use
  • A way to select numerous emojis at a time (click all emojis you want, right-click and copy).
  • Create it as a pure HTML5 (HTML, JavaScript, CSS) using Bootstrap
  • Make it available via FOSS (Fully Open Source Software) on Github^.
  • Run as a desktop app (via ElectronJS)

Here's How I Built It

Get Basic App Style Via Bootstrap

The first thing I did was go out to the bootstrap site and check out the navs & tabs area. If you check out the example there, you'll see that it is the basic tabs via what they call pills on the left side.

Image 4

I copied the associated HTML to my index.htm.

The important part is that when one of the pill buttons is clicked on the left, it activates the associated div on the right. It's very easy to use. Just fill in each associated div section with the HTML that you want to display when the pill button is clicked.

WinForms Comparison

I am a WinForms developer too and creating this functionality is way easier in HTML/ Bootstrap and it looks a lot better. There are some things that really are better than WinForms. Take a deep breath and learn something new today. 😉

Static Emojis On Faces Tab

This is super easy code for all of the static emojis that I added.

Here's a partial snapshot you can see in the source code for this article.

HTML
<div class="tab-pane fade show active emoji" id="v-pills-faces" 
          role="tabpanel" aria-labelledby="v-pills-faces-tab">
<span onclick="handleEmojiClick(this)">&#128512;</span>
<span onclick="handleEmojiClick(this)">&#128513;</span>
<span onclick="handleEmojiClick(this)">&#128514;</span>
<span onclick="handleEmojiClick(this)">&#128515;</span>
<span onclick="handleEmojiClick(this)">&#128516;</span>
<span onclick="handleEmojiClick(this)">&#128517;</span>
...
</div>

You can see that I've included the entity character codes for each emoji.

I've also opted to add a simple call to the handleEmojiClick() method that passes in the currently clicked element (this). That makes it easy to make sure the emoji char shows up as a selected item (see frozen face with orange block around it) on the screen with a bit of JavaScript.

Image 5

Here's the JavaScript that makes the character selection so that when the user copies the character(s) will be copied to clipboard.

JavaScript
function selectElementContents() {

    allSelectedElements.forEach(el => {
       var range = document.createRange();
       range.selectNodeContents(el);
       var sel = window.getSelection();
       sel.addRange(range);
    });
}

allSelectedElements is an array. The JavaScript forEach() method of an Array passes each element of the array to your function (an arrow function here) =>{}. In this case, each item passed in (el) is an HTML element that contains the emoji char. We use this to create a document range that will allow us to select element node contents (each individual emoji char).

Main Functionality

This is the main functionality that I originally wanted. I just wanted an easy way to copy one or more emojis to my clipboard so I could use them when posting, emailing or writing a document. It's odd that this isn't as available as you'd think. But, of course, emojis really aren't that important. Or, are they? 😄😎ðŸĪ‘ðŸĪŠ ðŸ’ĨðŸģðŸĪ“ 😂😂😂

Other Interesting Parts

The other interesting parts are where I:

  1. allow you to add custom emojis
  2. create a recently used list
  3. store everything in localStorage so when you reload, you still have your custom emojis and other settings (like using XX-Large to view the details of the emojis)

Adding Custom Emojis

You can get custom emojis anywhere. By custom, I'm just saying ones that are not in my static HTML (because I was too lazy to type them all in).

Emojipedia^ is a very cool resource. You can go there and copy emojis, then paste them into mojiWriter and you'll have them available forever. Forever and ever! Well, as long as you use the same web browser to get to my web site and as long as your localStorage isn't wiped.

The Code Is Kind of Cool

The code to do the custom ones is kind of cool because I had to figure out a way that when you add new ones, the code would still:

  1. add custom ones to the Recent list
  2. make sure they are selected properly for copying
  3. Make sure they are displayed properly on the Custom tab.

Here's how I did it.

  1. Added a way for you to save them to localStorage.
  2. Upon loading the page, I get the custom emojis from localStorage and iterate through them.
  3. Each time the code finds a custom emoji, it does an insert into the HTML DOM (Document Object Model).

The code looks like the following:

JavaScript
function displayCustomEmojis(emoji){
   const newSpan = document.createElement("span");
   newSpan.innerHTML = emoji;

   // set id to custom so that later we can use it to determine
   // if it is an item which can be added to the recently used list.
   newSpan.id = "custom";

   // the call to prepend() allows me to use normal forward iteration
   // thru the array but shows the most recently added emoji
   // (highest index) first.

   document.querySelector("#v-pills-custom").appendChild(newSpan);

   newSpan.addEventListener("click", emojiClickHandler);

}
  1. We just add a new span (each emoji is stored in a span).
  2. Then I add the emoji char into the innerHTML (the text displayed to the user).
  3. I add a special id named custom to each of the spans (I use this later so I know when the user clicked one of these items).
  4. Finally, I appendChild() the new span into the parent element (v-pills-custom represents the original parent div.

Writing to LocalStorage is Easy

When you place a new emoji in the textbox and click the Save button, the following code runs as part of the function saveCustomEmojiHandler(). I don't show the entire function here, because a lot of it is some error handling and message displaying code. This is the interesting meat of the function. 🍔 or ðŸĨ“ðŸĨ“ðŸĨ“ðŸĨ“

JavaScript
   let allUserAddedEmojis = Array.from(document.querySelector("#customEmojiText").value);
   document.querySelector("#customEmojiText").value = "";

   let atLeastOneFailure = false;

   for (let i = 0; i < allUserAddedEmojis.length;i++){

      let emoji = allUserAddedEmojis[i];

      if (isEmojiNew(emoji,customEmojis)){

      // if it's new, push it onto the list and write to localstorage
      customEmojis.push(emoji);
      localStorage.setItem("customEmojis", JSON.stringify(customEmojis));
      displayCustomEmojis(emoji);
}

Look closely at the first line because it is interesting. It uses the Array.from() method to ensure that the custom emoji that the user has pasted is translated from a Unicode char. If you don't convert the string that way, then you'll get all manner of oddity in your localStorage data.

Look at What is Stored In localStorage

Image 6

Pretty cool, right? Emojis are just characters so they are stored right in the localStorage as character array that I use later to populate this Custom tab.

Conclusion

I hope you enjoyed this and I hope you learned a little bit about why HTML development can be cool and can help create apps you can:

  1. create quickly
  2. deploy easily

Future

Later, I will convert this to a ElectronJS^ app which will allow the app to run directly from your desktop on any platform (Win10, Linux, MacOS).

History

  • 25th January, 2020: Initial publication

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)