Learn Javascript – How to write well-organized code with Object Literal Pattern

Share on Facebook0Tweet about this on Twitter0Share on LinkedIn2

 

Most of the Novice javascript developers are good at writing code but as the project grows I find they have a hard time maintaining it. This is normal and if you feel that way then this blog will guide you to write clean, well-organized and maintainable code no matter what changes you need to make over a period of time, you will have a full control over what’s going on with your code. By end of reading this blog, you will be able to write well-organized code that can be easily scalable upon adding new features with less time and bug. Let’s do it.

 

If you are new to Javascript and do not have any programming experience before, I would highly recommend brushing up your javascript skills before reading it further. If you have any other programming experience and new to Javascript, you will have no problem understanding the concepts I will be discussing in this blog.

 

What will I be covering:

1. I will be showing a simple country list application with spaghetti javascript code then I will be showing you the same application in a well-organized way.

 

2. Along the way, you will learn how to create an Object Literal Pattern which is one of the popular Javascript Design patterns and MVC (Model-View controller) or Separation of concerns.

 

Here is the screenshot of the simple country list application .

Learn Javascript – How to write clean, well-organized and maintainable code with MVC and Object Literal Pattern

As I mentioned earlier, we take a look at spaghetti javascript code  first then we are going to learn how to make the code more readable and maintainable. The HTML and CSS for both Javascript code are the same. This blog is intended to explain more on the Javascript side, there is no explanation further about HTML and CSS explanation apart from the code below. Let’s take a look at them.

 

index.html

<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="UTF-8">
    <title>Country List App with MVC</title>
    <link rel="stylesheet" href="style.css">
  </head>

  <body>
    <h1>Javascript MVC -  Object Literal Pattern</h1>
    <p> Country List App</p>
    <section class="wrap"> <!--container-->
      <!--leftview-->
      <div class="wrap-listview">
        <ul id="contry-list"></ul>
      </div>
        <!--rightview-->
        <div class="wrap-detailsview">
          <!--img-view-->
          <div class="img-view">
            <img src=""  width='300' id="country-flag"/>
          </div>
          <!--text-view-->
          <div class="text-view">
            <h2 id="country-name"></h2>
            <h3>Country</h3>
            <h2 id="country-capital"></h2>
          	<h3>Capital</h3>
           	<h2 id="country-language"></h2>
           	<h3>Language(s)</h3>
          </div>
        </div> <!-- /wrap-detailsview -->
      </section>  <!-- /container -->

      <script
        src="https://code.jquery.com/jquery-3.1.1.min.js"
        integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8="
        crossorigin="anonymous"></script>
        <script src="app.js"></script>
      </body>

</html>

style.css

/*=======reset===========*/

* {
  box-sizing:border-box;
}

body, h1, h2, h3 {
  margin:0;
  padding:0;
  font-family:Arial;
}

h1 {
  text-align: center;
  padding:20px;
  background:black;
  font-weight:300;
  color:#999;
  font-size:1.4em;
}

p {
  padding:5px 10px;
  background: orange;
  display:inline-block;
  margin:10px;
}

/*=======container===========*/

.wrap {
  padding:10px;
}

/* ======left-listView====== */

.wrap-listview, .img-view {
  min-width:250px;
  float:left;
}

.img-view {
   min-width:50px;
}


.text-view {
  margin-top:-4px;
  text-indent:10px;
}

.text-view h2 {
  font-size:1.3em;
  color:#666;
  font-weight:500;
}

.text-view h3 {
  font-size:1em;
  font-weight:300;
  color:#999;
}

ul {
  margin:0;
  padding:0;
}

li {
  border:1px solid #cccccc;
  border-bottom:none;
  list-style-type:none;
  padding:10px;
}

li:last-of-type {
   border-bottom:1px solid #cccccc;
}

li:hover, li:hover h2,  li:hover h3{
  cursor:pointer;
  background:#63c7fc;
  color:white;
}

.active {
  background:#63c7fc;
}

/* ========right-detailsView====== */

.wrap-detailsview {
  overflow:auto;
  padding-left:10px;
}

.wrap-detailsview .img-view{
  min-width:300px;
}

.wrap-detailsview .text-view {
  overflow:auto;
}

.wrap-detailsview .text-view  h2 {
  margin-top:5px;
}

.wrap-detailsview .text-view  h3 {
    margin-bottom:25px;
}

Javascript with Spaghetti Code app.js

$(function(){

/*=============Model==================*/
var countryList = {

    countries: [
      {name: 'Canada' , continent: "North America", flagUrl: 'http://flagpedia.net/data/flags/normal/ca.png', capital: "Ottawa", language: "English and French"},
      {name: 'Singapore' , continent: "Asia", flagUrl: 'http://flagpedia.net/data/flags/normal/sg.png', capital: "Singapore", language: "English, Tamil, Malay, Mandarin"},
      {name: 'USA' , continent: "North America", flagUrl: 'http://flagpedia.net/data/flags/normal/us.png', capital: "New York", language: "English"}
    ]

};



// cache ul for left view
let $ul = $("#contry-list");


// get the counties array from the object
let clArray = countryList['countries'];

// create inner html elements
let $li  = '';

// loop through the object and create li
for(let i = 0; i < clArray.length; i++) {

  $li = document.createElement("li");
  $li.innerHTML = `<div class="img-view">
            <img src="${ clArray[i].flagUrl}"  width="50"/>
          </div>

           <div class="text-view">
                 <h2>${ clArray[i].name}</h2>
                 <h3>${ clArray[i].continent}</h3>
                </div>
          `;

    $ul.append($li);

}


// click event
$("li").click ( function(e){

  $('li').removeClass('active');
  $(this).addClass('active');


  // get clicked index
  var getIndex = $(this).index();


  // cache DOM
  var $countryName = $('#country-name');
  var $countryFlag = $('#country-flag');
  var $countryCapital = $('#country-capital');
  var $countryLanguage = $('#country-language');


  var selectedObject = clArray[getIndex];

  // papulate information with detail view
  $countryName.html(selectedObject.name);
  $countryFlag.attr("src", selectedObject.flagUrl);
  $countryCapital.html(selectedObject.capital);
  $countryLanguage.html(selectedObject.language);

});


// select the first one by default
$ul.find("li:first-child").trigger("click");

});

In the above javascript file has comments for everything you need to know and also it’s self-explanatory to see what’s happening. I have used jquery for handling DOM. But the above code is messy in a lot of ways. However, it does not look messy code, in fact, this has less code than the other javascript file. The point is when you add more things into the Spaghetti code it will become very hard to maintain and you can get frustrated easily.

 

There are two main concepts that you need understand in order get the most out of this tutorial.

 

1. MVC

2. Object Literal Pattern

 

The main reason I call it Spaghetti code because it does not follow MVC. What’s MVC? Let’s take a quick look

1. MVC – Model-View-Controller

MVC has been around since 1970 and is highly recommended by Apple and other companies. M – Model is responsible for all your data and business logic. V- View is responsible for your views (This is what the user actually sees and interacts with). C – Controller is a mediator that connects your Model and View.

Model and View should NEVER interact with each other. They can only talk through Controller. Now you understand the rules applying MVC in your application. I know it’s kind of vague and it will make more sense when we apply them in action.

 

2. Object Literal Pattern

var Human = {
   this.name = "Raja",

    speak : function() {
       return this.name + 'can speak';
    }
};

 

As you can see in the above example, you create a simple javascript object literal {} as you normally do but this time I added variables (properties) and functions (methods) into it, as one self-contained module. This is how we are going to organize our code using MVC (separation of concerns). One module for Model, One for Controller and one for View. You can add more than one in any of MVC buckets as your application gets bigger.

 

Now, you understand what’s MVC and Object Literal pattern. Let’s see the well-organized code below and will explain after:

 

(function(){

"use strict";

// ================ Model ======================
const countryList = {
    selectedItem:null,
    countries: [
      {name: 'Canada' , continent: "North America", flagUrl: 'http://flagpedia.net/data/flags/normal/ca.png', capital: "Ottawa", language: "English and French"},
      {name: 'USA' , continent: "North America", flagUrl: 'http://flagpedia.net/data/flags/normal/us.png', capital: "New York", language: "English"},
      {name: 'Singapore' , continent: "Asia", flagUrl: 'http://flagpedia.net/data/flags/normal/sg.png', capital: "Singapore", language: "English, Tamil, Malay, Mandarin"}
    ]
};


// ================ Controller ==================
const countryListApp = {

  init:function(){
    // set first index of an array object as a currentItem
    countryList.selectedItem = countryList.countries[0];



    // initialize two view - ListView (left) and DetailsView (right)
    countryListView.init();
    countryDetailsView.init();

  },

  getCountryList:function(){
    return countryList.countries;
  },

  getSelectedObject:function(){
    return countryList.selectedItem;
  },

  setSelectedObject:function(newSelectedObj){
    countryList.selectedItem = newSelectedObj;
  }

}

// ================ View ======================


// listview
const countryListView = {

    init:function(){
      this.cacheDom();
      this.render();
    },

    cacheDom:function(){
      // cacheDom
      this.$ul = $("#contry-list");
    },

    doClickListItem:function(selectedCountryObject){
      return function(){
        countryListApp.setSelectedObject(selectedCountryObject);
        countryDetailsView.render();
      }
    },

    render:function(){

      // temp vars
      let i, $li, $lichild;

      // add and give event listener at the same time
      const clArray = countryListApp.getCountryList();

      // ----- loop -------
      for(i = 0; i < clArray.length; i++) {
        console.log(clArray[i].name);

        // you could use templet for this
        $li = document.createElement("li");
        $li.innerHTML = `<div class="img-view">
                  <img src="${ clArray[i].flagUrl}"  width="50"/>
                </div>

                 <div class="text-view">
                       <h2>${ clArray[i].name}</h2>
                       <h3>${ clArray[i].continent}</h3>
                      </div>
                `;

        // adding event listener to li
         $li.addEventListener("click", this.doClickListItem(clArray[i]));

        // append li to ul
         this.$ul.append($li);

      }
      // ----- loop -------

    }

}

// detailsview
const countryDetailsView = {
  init:function(){
    this.cacheDOM();
    this.render();
  },

  cacheDOM:function(){
    this.$countryName = $('#country-name');
    this.$countryFlag = $('#country-flag');
    this.$countryCapital = $('#country-capital');
    this.$countryLanguage = $('#country-language');
  },

  render:function(){
    var selectedCountryObj = countryListApp.getSelectedObject();
    this.$countryName.html(selectedCountryObj.name);
    this.$countryFlag.attr("src", selectedCountryObj.flagUrl);
    this.$countryCapital.html(selectedCountryObj.capital);
    this.$countryLanguage.html(selectedCountryObj.language);
  }
}


// ================ Start Point ======================
countryListApp.init();


})();

 

As you can see the above code, I have split into three sections by adding comments: Model, View, and Controller.

 

Let’s take a look at the Model first:

countryList Object Literal that contains some data. In this case, we have one property named selectedItem is set to null initially. This property is basically set the currently selected object when the user clicks a list item. This might be new to you but YES we are storing that information into Model, not in a click event that lives inside View. we have another property named a countries array which contains all the country objects. That’s it for Model Object Literal.

Controller:

we have an another Object literal called countryListApp which is responsible for talking back and forth between Model and View(s). It has an init() method in which we are setting selectedItem (M) property to the first index of an array object. Then, we are initializing two views (In this example I used two Views – one for left that shows all the countries and another view that shows a specific country information).  We have also a few helper methods such as getCountryList(), getSelectedObject(), setSelectedObject(). As you can see all of the help methods are either getters or setters. So that we do not have to set or get any information directly from Model to the View.

View:

countryListView Object Literal has init() method and it has two another methods cacheDOM() and render(). As you know, it’s more efficient to cache the DOM elements into variables then reuse them whenever we need ti. One the other hand, the reason for the render() method that we can call it to update the view whenever we change the data (Model). This View is responsible for looping through the country array and creating the left country list view and bind the click event inside the loop and it has callback function doClickListItem() which is responsible for returning the currently clicked item’s object.

 

countryDetailsView Object literal has also init() function which is responsible for creating a county details view on the right. As you can it’s pretty straight forward, it has cacheDOM() and render() methods very similar to the above view.

 

Finally, countryListApp.init() method will initialize the application to get everything going. That’s it!

 

As you can see a lot of ECMAScript 6 syntax like let, const. If you want to know about those check out my other blog here.

 

You can find the full code on Github.

 

In conclusion, writing well-organized code is easy to add more features later on and easy to maintain as well. If you’re interested Functional programming you can check it out here.

 

There you have it! I hope you enjoy!  Feel free to check out and enroll in our online Javascript and JQuery course. Contact us for one FREE virtual online class from anywhere.

 

 

Share on Facebook0Tweet about this on Twitter0Share on LinkedIn2

About the author
Raja Thangarasu

Raja loves building Web and iOS Applications. He is always curious to explore latest technologies and concepts. He's working as a UI Developer and he is teaching various technologies at SoftAuthor. He likes to write blogs and create youtube videos when he has time to share his knowledge to the world. Visit his website for more information about him.

Sign up for our blog updates and newsletters!


100 % privacy. I hate spam as much as you do!