Click here to Skip to main content
11,412,834 members (71,374 online)
Click here to Skip to main content

Encapsulation in JavaScript

, 1 Oct 2010 CPOL
Rate this:
Please Sign up or sign in to vote.
This article demonstrates how to create public and private members in JavaScript through a sample.

Introduction

Encapsulation is one of the main concepts in object oriented programming. It allows an object to group both private and public members under a single name. All the object oriented programming languages support this. Since JavaScript is also an object oriented programming language, it supports it too.

In this article, we will see how to achieve encapsulation in JavaScript by creating a simple object named CssManager that helps to dynamically add, remove, or swap a style-sheet.

Plan

  • Create a namespace named Managers that wraps our object.
  • Create a singleton object named CssManager.
  • Add public methods to the object for adding, removing, and swapping a stylesheet.
  • Create private members.

Code

Create a namespace named Managers that will wrap our object

In JavaScript, creating a namespace is as simple as creating an object literal.

var Managers = {}; //namespace

Very simple, right?

Now you can wrap all the classes and objects related to Managers in a single namespace.

Create a singleton object named CssManager

Managers.CssManager = { //singleton
}

The code between the pair of curly braces forms the part of the object.

Add public methods to the object for adding, removing, and swapping a stylesheet

In JavaScript, an object acts much like an associative array, i.e., an array of key-value pairs. The key is a property or a method.

Create the method addStyleSheet that takes two parameters: the stylesheet element ID, and the reference URL.

Managers.CssManager = {
  addStyleSheet: function(id, url){ //id - link's id, url - link's href
  }
}

In addStyleSheet(), we will do the following things: dynamically create a link element, set its attributes, and append to the head section.

Managers.CssManager = {
    addStyleSheet: function(id, url){
        var newStyleSheet = document.createElement("link");
        newStyleSheet.setAttribute("rel", "stylesheet");
        newStyleSheet.setAttribute("type", "text/css");
        newStyleSheet.setAttribute("id", id);
        newStyleSheet.setAttribute("href", url);
        document.getElementsByTagName("head")[0].appendChild(newStyleSheet);
    }
}

Add the other two methods..

Managers.CssManager = {
    addStyleSheet: function(id, url){    
        var newStyleSheet = document.createElement("link");
        newStyleSheet.setAttribute("rel", "stylesheet");
        newStyleSheet.setAttribute("type", "text/css");
        newStyleSheet.setAttribute("id", id);
        newStyleSheet.setAttribute("href", url);
        document.getElementsByTagName("head")[0].appendChild(newStyleSheet);
    },
    
    removeStyleSheet: function(id){    
        var currentStyleSheet = document.getElementById(id);
        if(currentStyleSheet){
            currentStyleSheet.parentNode.removeChild(currentStyleSheet);
        }
    },
        
    swapStyleSheet: function(id, url){
        this.removeStyleSheet(id);
        this.addStyleSheet(id, url);
    }
}

In removeStyleSheet, we query for the particular stylesheet element (link) and remove it completely from DOM. While in swapStyleSheet, we are calling the other two methods to replace an existing stylesheet with a new one.

Create private members

So far, all the methods created are public. I would like to add two private members for the sake of the article. The first one is a variable that has the reference to the document object.

var doc = document;

The second one is a method that sets multiple attributes to the link element at once instead of calling setAttribute() multiple times.

var setAttributes = function(attributes){
}

Unlike other languages, we can't easily mark members as public or private in JavaScript. To create private members, we have to use Closures. Closures help to create a private space. We are not going to see what closures are here, but let's see how they help to create private members.

Let's modify our CssManager to apply a closure:

Managers.CssManager = (function(){ 
    
    /*
        private space
    */
        
    return{
        //Public members
        addStyleSheet: function(id, url){
            var newStyleSheet = doc.createElement("link");
            setAttributes(newStyleSheet, {
                rel : "stylesheet",
                type : "text/css",
                id : id,
                href: url
            });
            doc.getElementsByTagName("head")[0].appendChild(newStyleSheet);
        },

        removeStyleSheet: function(id){
            var currentStyleSheet = doc.getElementById(id);
            if(currentStyleSheet){
                currentStyleSheet.parentNode.removeChild(currentStyleSheet);
            }
        },
            
        swapStyleSheet: function(id, url){
            this.removeStyleSheet(id);
            this.addStyleSheet(id, url);
        }
    }
})();

What we have done is created a Closure that looks like a self executing anonymous function that returns the public methods we added earlier. The pair of parentheses at the end makes the code get executed automatically. All the members returned by the return statement are public, while the ones that come before are private.

(function(){
    
    //Private members

    return{
        //Public members
    }
}();

Add our two new members in the private space:

Managers.CssManager = (function(){ 
    
    //Private members
    var doc = document;
    var setAttributes = function(element, attributes){
        for(attribute in attributes){
            element[attribute] = attributes[attribute];
        }
    }
        
    return{
        //Public members
        addStyleSheet: function(id, url){
            var newStyleSheet = doc.createElement("link");
            setAttributes(newStyleSheet, {
                rel : "stylesheet",
                type : "text/css",
                id : id,
                href: url
            });
            doc.getElementsByTagName("head")[0].appendChild(newStyleSheet);
        },

        removeStyleSheet: function(id){
            var currentStyleSheet = doc.getElementById(id);
            if(currentStyleSheet){
                currentStyleSheet.parentNode.removeChild(currentStyleSheet);
            }
        },
            
        swapStyleSheet: function(id, url){
            this.removeStyleSheet(id);
            this.addStyleSheet(id, url);
        }
    }
})();

How to use

Our CssManager is ready! If you want to add a stylesheet to a page dynamically, call the addStyleSheet method, passing a unique ID and the HREF of the external CSS file as below:

Managers.CssManager.addStyleSheet("myStyleSheet", "Default.css");

Likewise, you can even remove it or replace it with a new one:

Managers.CssManager.removeStyleSheet("myStyleSheet");
Managers.CssManager.swapStyleSheet("myStyleSheet", "Advanced.css");

That's all! We have done it!! Thanks for reading this. If you feel this article is helpful to you, don't forget to vote. Please check out the attached sample code that shows how the CssManager helps to dynamically change the theme of a page.

**Coding is poetry**

License

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

Share

About the Author

After2050
Software Developer Trigent Software Private Limited
India India
I'm a software developer from south tip of India. I spent most of the time in learning new technologies. I've a keen interest in client-side technologies especially JavaScript and admire it is the most beautiful language ever seen.

I like sharing my knowledge and written some non-popular articles. I believe in quality and standards but blames myself for lagging them.

I believe in small things and they makes me happy!
Follow on   Twitter

Comments and Discussions

 
QuestionInheritance ? Pin
Nelson Teixeira at 30-May-14 6:04
memberNelson Teixeira30-May-14 6:04 
GeneralMy vote of 5 Pin
Prasad Khandekar at 1-Apr-13 9:23
memberPrasad Khandekar1-Apr-13 9:23 
Generalhiiiiiiiiii Pin
glory444 at 15-Apr-11 9:58
groupglory44415-Apr-11 9:58 
GeneralGood Job!! Pin
Venkatesh Mookkan at 20-Oct-10 20:16
memberVenkatesh Mookkan20-Oct-10 20:16 
GeneralRe: Good Job!! Pin
After2050 at 21-Oct-10 0:15
memberAfter205021-Oct-10 0:15 
GeneralMy vote of 5 Pin
ArvindWanjari at 6-Oct-10 22:25
memberArvindWanjari6-Oct-10 22:25 
GeneralMy vote of 5 [modified] Pin
gkushner at 1-Oct-10 3:43
membergkushner1-Oct-10 3:43 
GeneralMy vote of 5 Pin
Christian Rodemeyer at 24-Sep-10 22:55
memberChristian Rodemeyer24-Sep-10 22:55 
GeneralMy vote of 5 Pin
Member 615277 at 23-Sep-10 22:02
memberMember 61527723-Sep-10 22:02 
GeneralMy vote of 4 Pin
Kaviany at 23-Sep-10 12:52
memberKaviany23-Sep-10 12:52 
GeneralRe: My vote of 4 Pin
After2050 at 23-Sep-10 20:14
memberAfter205023-Sep-10 20:14 
GeneralMy vote of 5 Pin
Yves at 21-Sep-10 13:58
memberYves21-Sep-10 13:58 
GeneralMy vote of 5 Pin
Julian Nicholls at 21-Sep-10 4:17
memberJulian Nicholls21-Sep-10 4:17 
GeneralNot seen this before. Worth a 5 Pin
jsc42 at 20-Sep-10 23:49
memberjsc4220-Sep-10 23:49 
GeneralThanks! Pin
Grant Drury-Green at 20-Sep-10 18:39
memberGrant Drury-Green20-Sep-10 18:39 
GeneralMy vote of 5 Pin
depakb at 19-Sep-10 3:44
memberdepakb19-Sep-10 3:44 
GeneralMy vote of 4 Pin
EvanShooter at 16-Sep-10 0:48
memberEvanShooter16-Sep-10 0:48 
GeneralMy vote of 5 Pin
pigwin32 at 14-Sep-10 15:50
memberpigwin3214-Sep-10 15:50 
GeneralMy vote of 5 Pin
Jitendra Zaa at 13-Sep-10 21:31
memberJitendra Zaa13-Sep-10 21:31 
GeneralRe: My vote of 5 Pin
After2050 at 14-Sep-10 0:37
memberAfter205014-Sep-10 0:37 
GeneralMy vote of 5 Pin
Prosanta Kundu online at 13-Sep-10 19:02
memberProsanta Kundu online13-Sep-10 19:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.150427.1 | Last Updated 1 Oct 2010
Article Copyright 2010 by After2050
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid