A Simple Notes App & Word Counter


Getting into coding can seem intimidating, with countless languages, frameworks, and methodologies to consider. It may even feel easier to outsource everything to an AI. Be reassured: programming for the web can be simple, fun, and—best of all—totally free!



What You’ll Build

Following this tutorial, you’ll build a simple web app to store text notes and count characters and words in them.


The app persists data, so it remembers text when you refresh the page or reopen it. This means it’s a convenient way of keeping any text you might want to refer back to later, such as addresses, URLs, etc.

An example of the simple text web app showing notes including a calendar entry and a list of URLs.

It also counts characters and words, which is a useful introduction to working with strings (text). Of course, the app is very simple: that’s the point. But, with this tutorial, you’ll learn the basic concepts behind building a web app, and the world will then be your oyster.

How You’ll Build It

Although web apps differ greatly, they usually involve three core technologies: HTML, CSS, and JavaScript. These technologies have vital roles that you should understand before you begin.


  • HTML: HyperText Markup Language lets you define the structure of your content. Using it, you can mark text according to its meaning, indicating whether it is a paragraph, a heading, or an item in a list, for example.
  • CSS: Cascading Style Sheets allow you to style your content. Using HyperText Markup Language the language, you can color a certain paragraph green, make all your links bold, or position a sidebar next to your main article.
  • JavaScript: Using this programming language, you can add functionality to your web page. You can make buttons show or hide parts of your document when clicked, or implement an entire word processor or video game.

The web.dev site (written by members of the Chrome team) and MDN, the Mozilla Developer Network, are two excellent sources of information about core web technologies.

The homepage of the web.dev site with learning resources for HTML, CSS, and JavaScript.


The App Structure

The app you’ll build will consist of three simple files: index.html, styles.css, and script.js.

There are no special requirements to run the app, all you need is a web browser. There is no backend functionality, so you don’t need a scripting language like PHP or a local web server. Once you’re done, you can open the index.html file directly in your browser and everything will work.

It’s important to note that this app saves your text without writing to a specific file on disk, since JavaScript cannot access the file system. It does this using the Web Storage API, a powerful alternative to cookies.

How to Build the Note Taker

Create the following three files in the same directory, then open index.html in a web browser. Alternatively, you can download the files from this GitHub repository.

Building the Structure With HTML

The index.html file defines your app’s content structure in HTML. It includes references to the other two files so a browser can combine them for the finished product.

Like all HTML documents, the top-level structure includes a head section containing metadata and a body containing the actual content that will appear on the page:


html>
<html>
<head>
    ...
head>

<body>
    ...
body>
html>

The metadata in the head is very short, with just a title of the page (which appears in your browser’s title bar) and a reference to the styles.css file:

    <title>Texttitle>
    <link rel="stylesheet" href="styles.css" />

The body is more complicated, but there are just a few important parts to it:

    <div id="counter">
        words: <span id="words">0span>
        /
        characters: <span id="chars">0span>
    div>

    <textarea id="text" autofocus="1">textarea>

    <script src="script.js">script>

The div element (“division”) contains the app’s word and character counts. It will sit at the top of the web app and update whenever the text changes.

Note the id attributes, which are vital to the operation. The value of an id must be unique, so the app can use it to identify a specific element. Doing so can help us style these elements and also target them when we add functionality.

The textarea is a built-in form element that lets you type plain text in a browser. With the autofocus attribute, it will be ready for typing in as soon as the page loads. Finally, the page references the javascript file, script.js.

At this point, you can open the index.html file in a browser. It won’t do anything right now, and it won’t even look right, but it’s useful to check your app at each stage to ensure the basics are working as you’d expect.


A view of the note-taking web app with default browser styles, showing everything bunched up in the top-left corner.

Making Things Look Good With CSS

CSS lets you change the style of parts of your web page, by targeting those parts and specifying values for properties like font-size and background-color. This sample app doesn’t need a lot of finely-tweaked design because its interface is so basic. Nonetheless, we can clean up the rough edges a bit with a smattering of style.

First, style the body to define the overall layout:

body {
    margin: 0;
    padding: 0;
    display: grid;
    min-height: 100vh;
    grid-template-rows: min-content 1fr;
}

This CSS uses grid layout to position the word and character counts in a narrow row above the textarea. The grid-template-rows property specifies that the count row should be as short as possible (min-content) and the textarea should fill the remaining space (1fr).

The counter row has some basic style to differentiate it from the remaining text, mainly via its background:


#counter {
    font-family: sans-serif;
    background-color: #f7f7f7;
    text-align: center;
    width: 100%;
    padding: 0.5em 0;
}

Finally, the textarea is styled to display readable text with enough space to breathe. The line that separates counts from the text is actually this textarea’s top border.

textarea {
    width: 100%;
    height: 100%;
    font-size: 16pt;
    padding: 1em;
    box-sizing: border-box;
    outline: 0;
    border: none;
    border-top: 1px solid #999;
}
The note-taking app with customized styles shows the counter bar at the top with a full-sized textarea below.

Adding Functionality With JavaScript

With the structure and style in place, you’re ready to add functionality: the code that makes this simple app actually do something.

Before you start writing even the simplest code, it’s sensible to understand what you want it to do. In this case, there are just a couple of general requirements:

  • Save the text entered, and reload it when needed.
  • Update character and word counts to provide live statistics.

Both requirements involve updating elements in the document. So the script starts by obtaining references to these nodes using the getElementById method:


const words = document.getElementById("words");
const chars = document.getElementById("chars");
const textarea = document.getElementById("text");

Note that words, chars, and text are the IDs of their respective elements in the document, assigned in the HTML file with the id attribute.

Next, we need the app to react when the text is changed:

textarea.addEventListener("input", function(ev) {
    localStorage.setItem("text", ev.target.value);
    update_counts(ev.target.value);
});

An event listener is a function that JavaScript will run automatically when a certain event occurs. In this case, we attach a listener to the textarea node which runs when the “input” event occurs. This is, effectively, when someone interacts with the textarea.

Next, we use the Web Storage API to save the current contents of the textarea, from ev.target.value. In this structure, ev is an object representing the event that triggered the listener, ev.target is the node that received the event, and ev.target.value is the text of that textarea.

The setItem method takes two parameters: a key name to associate with the data, and the actual data to store.

After that, we call update_counts(), passing the same text to it. We’ll explain that function in a bit.


Now that we’re saving the text, we’ll want to load it again when the app is opened or refreshed. We can take care of that using another listener:

window.addEventListener("load", function(ev) {
    var text = localStorage.getItem("text");
    textarea.value = text;
    update_counts(text);
});

This one handles the load event that occurs on the window object, a top-level representation of the browser window itself. When the window loads, a call to getItem() returns the stored value of our text from local storage. This code then sets the textarea’s value to the loaded text and, like the previous listener, calls update_counts() with this text.

The remaining work takes place in the update_counts() function which looks like this:

function update_counts(text) {
    chars.innerHTML = text.length;
    words.innerHTML = text.split(' ').length;
}

Unlike a textarea, normal text doesn’t have a value property, so we set the innerHTML property instead. The length property of a string is a simple read-only property that gives us the number of characters.

text.split(‘ ‘) breaks up the string at space characters, returning the result as an array of strings. Like strings, arrays have a length property which gives us the number of items in an array.

If you try this code, however, you might notice a couple of bugs:


  1. It won’t count a word on its own on a line properly, since there are no space characters either side of it.
  2. With no text at all, it will report a single word because of how split works.

To fix the first problem, you can split on a regular expression (\s means “a whitespace character”) instead of the space. To fix the second, filter out empty strings from the result:

    words.innerHTML = text.split(/\s/).filter(function(n) { return n != ''; }).length;

If you don’t fully understand that line, check out the MDN pages for split and filter.

The web app with example text, showing accurate character and word counts.


You can build many useful web apps with just a few files. You can also extend this simple notes app to add more functionality. For example, you can use the window.location property to retrieve the current URL and support multiple notes by varying the name you pass to localStorage.setItem.



Source link