This week I thought I should have a go at building something with plain old Javascript. I mean, I have been using Angular for the last few years so I thought, ahh well, why not? It’s good to revisit some basics especially just how awesome Javascript is with some of the new ES6 innovations. Learning something or getting back into something is most effective when there’s an end-goal in sight i.e. when you are building something. In this case, my end-goal was to build a simple browser based quiz game using vanilla Javascript. As I started working on it, I realised, It’s been what? 7 years, since I built something using vanilla Javascript. Yes, since 2013!!! It’s been a while, but honestly, it’s easier to do this now than it as back then! In this post, I will talk about how to dynamically generate DOM elements, add event handlers etc using plain old Javascript. The post aims to serve as a foundation to building a browser based game i.e. this post will provide some basic information on disparate aspects of manipulating the DOM using Javascript.

Vanilla Javascript

As of 2014, I have been using Angular quite a bit. I used it at my old job, I used it in my startup to build hybrid apps and I am using it to build the e-commerce platform for 10POiNT2. Prior to that I was using jQuery at the places I worked. The only time I used vanilla Javascript was when I was building this diagramming tool as a side-project. Actually, it wasn’t purely vanilla Javascript, I was using this library called Raphael.js to create SVG charts. However that project came to a halt when I had my accident in 2013. I have not built anything in vanilla Javascript since then. For the last 2 years, I have been going nuts over Typescript. Ahh man, I love Typescript. It’s so so so awesome, however I guess the reason I like it is because of my love for Java or static typing in general. As great as Typescript is, it is not Javascript and it’s good to write vanilla Javascript once in a while. Javascript frameworks save us a lot of time and it’s very easy to forget how to do things without them. Even simple things such as selecting a DOM element or dynamically creating DOM elements. So let’s see how to do those things, but first…

What’s the document interface?

First things first, before moving ahead, let’s learn a little bit about “document”. Something you will see very commonly used throughout this post. Document represents any web page loaded in the browser. The keyword document provides an interface to access a web page’s properties and methods used to manipulate it. Let’s start with a simple example of how to retrieve div defined in a web page.

Getting a DIV

There are a few ways in which we can do this, but for this post, let’s look at the document.querySelector. Remember how we did that in jQuery? It was something like,
$("#startMenu") //Javascript to select the green div

<<div id="startMenu" class="startMenuClass showElem"> </div>
Now, if you want to select the div with id startMenu using vanilla Javascript, you do that in a somewhat similar way, except you use document.querySelector. Except, the querySelector will only return the first element that matches the string. So for the following html element, You will get the first element who’s id matches the string startMenu,
let startMenuDiv = document.querySelector("#startMenu");
Or you can also get it by it’s class name, let startMenuDiv = document.querySelector(".startMenuClass"); Here we will get the first element with the class startMenuClass. Great, we can get an element but what about creating an element? p.s. you will see what the class showElem does a little later

Creating buttons

Let’s create a radio button for the user to select the type of game they want to play.
var radioLbl = document.createElement("label");
var radio = document.createElement("input");
radio.type = "radio";
radio.name = "gameMode";
radio.value = "SP"; //single player
radio.onclick = () => userAns = value;
radioLbl.appendChild(radio);
radioLbl.appendChild(document.createTextNode("Single Player"));
Now, after selecting the gameplay option, the next thing we want the user to do is start playing. So how about we add a play button and add an onclick event handler.
let playBtn = document.createElement("button");
playBtn.innerText = "Play"; //we can also use document.createTextNode...

playBtn.onclick = () => {
  console.log("Start Game");
};
Great, now about we add the above things to our div?

Adding buttons to a DIV

This is by far the easiest of the lot, all you need to do is,
startMenuDiv.appendChild(radioLbl); startMenuDiv.appendChild(playBtn);
Exactly, that’s all you need to do. Now, perhaps we want to hide the start menu div after the user clicks play? Let’s see how,

Modifying CSS (add/remove css classes)

For this, let’s have a look at some very basic CSS for this,
showElem {
    display: block;
}
hideElem {
    display: none;
}
Hence, when the user clicks play, we would want to remove the showElem class and add hideElem class. Let’s see how we can do that,
startMenuDiv.classList.remove("showElem");
startMenuDiv.classList.add('hideElem');
After this the user starts playing and say we want to add the save game feature after that? How? We can use the save game feature.

Maintaining state

I won’t get into the details of this aspect here, but you can use LocalStorage for this. If you have some arbitrary object for game state, you can set it with
let gameState; //arbitrary game state object
saveBtn.onclick = () => {
    localStorage.set('saveGame', gameState);
}
//now let's resume from the save game on button click
resumeGameBtn.onclick = () => {
    gameState = localStorage.get('saveGame');
    resumeGame(gameState); //some game resume function
}
The above code aims to illustrate the concepts rather than provide an accurate implementation of game save and load feature. Local Storage is quite handy and as you can see not that hard to use.

Some more Vanilla Javascript

Now let us try some more vanilla Javascript by dynamically creating some more HTML elements. This time, let us try to create some radio buttons. Like any interface element radio buttons are one of the most important elements in any web interface. Also like other elements in an HTML interface, you can create radio buttons via the HTML input tag. All you need to do is create an input tag, set it is type to radio, but also set a value and a name property. Now let us look at a scenario to dynamically generate four radio buttons using vanilla/pure Javascript.
function radioButtons() {
    let totalElems = 4;
    const groupName = "radioGroup";
    let radioButtons = [];
    for(let idx=0; idx < totalElems; idx++) {
        let input = document.createElement("input");
        input.name = groupName;
        //+1 so we don't label them according to their index position
        input.value = (idx+1); 
        input.type = "radio";
        //let's set the last element to checked
        if(idx === 3) {
            input.checked = "checked";
        }
        radioButtons.push(input);
    }
    return radioButtons;
}

module.exports = {
    radioButtons: radioButtons
}
I think the above code is fairly straight forward and it has comments it’s got comments to help you understand. All, we are doing is generating four input elements using the document.createElement, setting them to be radio buttons and adding them to a collection. Let’s review a few key lines from the above code,
  1. A new input element is created via input = document.createElement 
  2. To ensure all radio buttons apply to the same group, set input.name property
  3. A radio button is set via input.type = “radio”;
  4. A radio button is marked as checked via input.checked = true, we only do that for the last input element in the above code
  5. Lastly, we export our function via the module.exports, so we can test it

Get updates?

Speaking of testing this code,

The test class for above

const genDomModule = require("./generateDom");

describe("Determine whether we generate dom elems properly", () => {
    test("Function generates 4 radio buttons", () => {
        let buttons = genDomModule.radioButtons();
        expect(buttons.length).toBe(4);
    });
    test("Generate all radio buttons", ()=> {
        let buttons = genDomModule.radioButtons();
        let allRadioBtns = true;
        for(let btn in buttons) {
            if(buttons[btn].type !== 'radio') {
                allRadioBtns = false;
            }
        }
        expect(allRadioBtns).toBe(true);
    });
    test('Expect radio button at index 1 to not be checked', () => {
        let buttons = genDomModule.radioButtons();
        expect(buttons[1].checked).toBe(false);
    });
    test("Expect radio btn at index 3 to be checked", () => {
        let buttons = genDomModule.radioButtons();
        expect(buttons[3].checked).toBe(true);
    });
    test("Check if the radio button values are init properly", () => {
        let buttons = genDomModule.radioButtons();
        expect(buttons[1].value).toBe("2");
    });
});
Again, the code for the test above should be easy to understand, if not, then please leave a comment and ask me.

How to run it?

You can simply navigate to the directory on command line and run it by executing npm run test. Alternatively, you can checkout the Github repository for this project, have a look at the source code and follow instructions to execute this code.

Conclusion

As time consuming and verbose as it is, it’s really not that difficult to code with vanilla Javascript. As shown here, creating some basic elements, adding them to the DOM and modifying them is quite straightforward. I would recommend this, I mean, every few years try and have a play with vanilla Javascript. It’s just fun and especially given how the language is evolving, it’s a lot of fun to work with.

Get updates?

If you find any of my posts useful and want to support me, you can buy me a coffee 🙂 https://www.buymeacoffee.com/bhumansoni Or you can  buying or even try one of my apps on the App Store.  https://mydaytodo.com/apps/ In addition the above, have a look at a few of the other posts,
Home of Javascript posts Transpose of a Google Visualisation object
Categories: Javascript

0 Comments

Leave a Reply

Avatar placeholder