Easy enums for custom JavaScript libraries

There’s a ton of information on the internet related to the best way to create JavaScript enums. This post is different in that it focuses on using enums that are immutable and cannot be changed within your own custom libraries.

The challenge with enum usage in JavaScript is global variable leakage can accidentally cause unexpected changes within your application, especially in cases of large, complex applications that may involve your own JavaScript libraries along-side 3rd party libraries. Global variable leakage means two variables can potentially have the same name, and this may not cause an error. Good debuggers help to avoid this problem by using jslint. But, if someone else is using your libraries then you can’t depend on them using best practices. So, variable leakage can cause unexplainable/unpredictable problems and create hard to track bugs. What we need is a coding pattern to protect enums so that we can guarantee that we always get the value expected.

As of today, JavaScript doesn’t have a universally accepted, built-in cross-browser solution for guaranteeing that specific variables can be made immutable. In other words, if we create a statement var BLUE = “blue” there is no way to enforce that something elsewhere in an application, or code that someone else wrote that is running the same application cannot ever change the value of BLUE.

In comparison, strongly typed languages such as C# and Java let you declare constants. If you accidentally try to change them in your code you get a compiler error that prevents the application from running. The compile-time checking can help prevent bugs in your code later on. Here are several examples from Java and C#:

 final int RADIUS = 1000; //Java
 const int RADIUS = 1000; //C#

So here we go. I’ll use six use cases to illustrate a variety of ways to make certain your enums are immutable. This list is not designed to be all inclusive, its intent is to demonstrate patterns that you can use to learn more about JavaScript enums. You can try these out using the following jsfiddle.

USE CASE 1 – Basic public enum function with no namespace protection. This use cases offers the least amount of protection against global variable leakage. I’d only expect to see this type of enum in very small, stand-alone applications.

function basicEnum() {
    var values = {
         BLACK: '#000000',
         RED: '#FF0000',
         GREEN: '#00FF00'
    }

    return values;
}

console.log("test0 " + basicEnum().BLACK); //test0 #000000

USE CASE 2 – Basic public enum that uses an internal, privately scoped namespace in which to define the enum object. This use case offers slightly more protection than Use Case 1, but the public function itself is still not protected within the global namespace. It’s possible there could be two functions with the same name “colorEnum”. And, the larger the application gets the higher probability there is of having accidental name duplication.

function colorEnum() {
    var values = values || {}
    values.colorEnum = {
         BLACK: '#000000',
         RED: '#FF0000',
         GREEN: '#00FF00'
      };

      return values;
};

console.log("test1 " + colorEnum().colorEnum.GREEN); //test1 #00FF00

USE CASE 3 – Public enum with no namespace protection using an anonymous function expression to define the enum. This is a variation of Use Case 2 showing you can define multiple categories of enums. And, like Use Case 2 it still offers zero public/global namespace protection. I’m using the terms public and global to mean the same thing.

DoSomething = (function(){

    var constValues = constValues || {}
    constValues.color = {"BLACK" : "#000000" }
    constValues.error = {"ERROR_TIMEOUT" : "Connection Timeout" }
    return constValues;
});

console.log("test2 " + DoSomething().color.BLACK); //test2 #000000
console.log("test3 " + DoSomething().error.ERROR_TIMEOUT); //test3 Connection Timeout

USE CASE 4 – Public enum with namespace protection using an anonymous function expression and internal (private) namespaces to differentiate multiple categories of custom enum objects. This use case starts to offer better protection against global variable leakage by wrapping the public function in a namespace.

var my_test = my_test || {}
my_test.DoSomething = (function(){

    var constValues = constValues || {}
    constValues.color = {
        "BLACK" : "#000000",
        "RED" : "#FF0000"
    }
    constValues.error = {
        "ERROR_TIMEOUT" : "Connection Timeout",
        "ERROR_FAULT" : "Connection problem"
    }
    return constValues;
});

console.log("test4 " + my_test.DoSomething().color.BLACK); //test4 #000000
console.log("test5 " + my_test.DoSomething().error.ERROR_TIMEOUT); //test5 Connection Timeout

USE CASE 5 – Namespace protected public anonymous function expression along with an internally (private) scoped function that defines the enum. This is a variation of Use Case 5 showing how to use switch/case statements along with a privately scoped function that are all wrapped inside the anonymous function.

var my_second_test = my_second_test || {};
my_second_test.DoSomething = (function(val){

    var color;

    switch(val)
    {
        case 1:
            color = basicEnum().BLACK;
            break;
        case 2:
            color = basicEnum().RED;
            break;
        case 3:
            color = basicEnum().GREEN;
            break;
    }

    function basicEnum() {
        var values = {
             BLACK: '#000000',
             RED: '#FF0000',
             GREEN: '#00FF00'
        }

        return values;
    }

    return color;
});

console.log("test6 " + my_second_test.DoSomething(2)); //test6 #FF0000

USE CASE 6 – This Use Case shows placing a privately scoped anonymous function expression defining the enum inside a public anonymous function expression, and finally accessed through another prototyped anonymous function expression. Yikes, that was a lot of technical mumbo-jumbo verbiage, right?! It also offers several tests to validate if the enum is immutable or not.

var my_third_test = my_third_test || {};
my_third_test.DoSomething = (function(){

    this.basicEnum = (function() {
        var values = {
             BLACK: '#000000',
             RED: '#FF0000',
             GREEN: '#00FF00'
        }

        return values;
    });

});

my_third_test.DoSomething.prototype.findColor = (function(val){
    var color;

    switch(val)
    {
        case 1:
            color = this.basicEnum().BLACK;
            break;
        case 2:
            color = this.basicEnum().RED;
            break;
        case 3:
            color = this.basicEnum().GREEN;
            break;
    }

    return color;
});

var myColor = new my_third_test.DoSomething();

console.log("test7 " + myColor.findColor(3)); //test7 #00FF00

//The enum properties cannot be changed
myColor.basicEnum().BLACK = "test";

console.log("test8 " + myColor.basicEnum().BLACK); //test8 #000000

try{
    //test that basicEnum() is immutable
    myColor.basicEnum() = "test"; //Throws ERROR!
}
catch(err){
    console.log("test9 " + err);
    //test9 ReferenceError: Invalid left-hand side in assignment
}

Conclusion. So that’s all there is to it. Hopefully these examples help to not only demonstrate some patterns to protect your data, but also give you ideas for saving time while building larger applications.

Reference.

JSFiddle project

jQuery Mobile – Setting full content width

Here are some hints to help get all of your jQuery content stretched to the full width of your mobile browser screen regardless of screen size or orientation. These techniques have been tested on jQuery 1.7.x, jQuery 2.0 and jQuery mobile 1.3.1.

Lets start with a look at the minimum required CSS:

html,body,div[data-role ="page"], div[data-role="content"] {
    height: 100%;
    width: 100%;
    margin: 0px;
    padding: 0px;
}

Problem – Using the minimum CSS above, leaves a spacer on the top and left hand sides of the app, and the right hand border and/or bottom border disappears. I noticed the right hand margin extends approximately 9 to 15 pixels (or greater depending on device) beyond the visible view. I verified this behavior on Android 4.1 native browser and Chrome 26, as well as on iPad 3 using Safari and Chrome 25.

Solution – set certain CSS width properties as shown below. This solution has been tested on Android 4.1 native and Chome 26, Android 2.3.2 native, and on iPad Safari and Chrome 25. Just a bit of a warning that if displayed on a desktop browser you will see vertical scrollbars. But, you should be detecting the different between mobile and desktop anyway, right!

Note: this solution doesn’t address the problem with content height, it only looks at width. So, yes, you will notice that the height of my sample is off the page.


<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=7,IE=9">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0,user-scalable=no">
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">

    <title>jQuery Test</title>

    <link rel="stylesheet" href="https://code.jquery.com/mobile/1.3.0/jquery.mobile-1.3.0.min.css" />

    <script type="text/javascript" src="https://code.jquery.com/jquery-2.0.0.js"></script>
    <script type="text/javascript" src="https://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.js"></script>
<style>
        html,body, div[data-role ="page"] {
            height: 100%;
            width: 100%;
            margin: 0px;
            padding: 0px;
        }

         .ui-content{
            height: 100%;
            width: 100%;
            margin: 0px;
            padding: 0px;
            border-style: solid;
            border-color: chartreuse;
            border-width: 5px;
        }

        #map {
            height: 100%;
            width: 100%;
            padding: 0px;
            border-style: solid;
            border-color: crimson;
            border-width: 10px;
        }
</style>
</head>

<body>

<div data-role="page" id="page1" >

    <div data-role="content">
        <div id="map"</div>
    </div>

</div>
</body>

References

Determining the dimensions of an [HTML] element

Check HTML5 Browser Height and Width using Canvas

[Modified April 26, 2013 – fixed code bug]

Fastest way to figure out x and y image offsets

Here is an app that will help you quickly visualize x and y image offsets. I think everyone has tried to eyeball offsets by tweaking the x and y a bit, hitting build again (and again) and then viewing your changes. Simply upload your image in the embedded app below and then adjust the sliders until the image is in the right place.

You can download a zip file (5kb) of the code here.

If you don’t see the slider bars in the app below you need to upgrade to a browser that supports HTML5 <input type=’range’> tag, or feel free to download and modify the code.