Refactoring A Simple JavaScript App

January 06, 2015

Over 8 months ago I coded my first interactive web app — a sleep cycle calculator called Slumbr. Slumbr suggests optimal times to sleep or wake up by estimating when you’ll most likely be in your lightest phase of sleep.

I haven’t looked at the code in quite some time so I figured that since I’m more experienced now than I was 8 months ago, it would be a fun exercise to see how my first iteration of Slumbr can be improved.

The original javascript file is a total 150 lines, and after refactoring it I was easily able to reduce the number of lines by more than half, to 70.

Here’s the original file- notice any redundancy?:

First Iteration

//Obtaining current Time
var now = new Date(); //Gets current Time
var cycle = 90 * 60000; //This is the length of a sleep cycle, expressed in milliseconds
function sleepNow() {
    document.getElementById("1").innerHTML = "";
    document.getElementById("2").innerHTML = "";
    document.getElementById("3").innerHTML = "";
    document.getElementById("4").innerHTML = "";
    document.getElementById("5").innerHTML = "";
    document.getElementById("6").innerHTML = "";
    var i = 0;
    for (i = 1; i < 7; i++) {
        var d = new Date(now.getTime() + 900000 + i * cycle); //Adding a cycle for each loop
        var hh = d.getHours();
        var m = d.getMinutes();
        var dd = 'AM';
        var h = hh;
        if (h >= 12) {
            h = hh - 12;
            dd = 'PM';
        }
        if (h == 0) {
            h = 12;
        }
        if (m < 10) {
            m = "0" + m;
        }
        if (i == 1) {
            document.getElementById("6").innerHTML += h + ":" + m + " " + dd + "  ";
        } 
        else if (i == 2) {
            document.getElementById("5").innerHTML += h + ":" + m + " " + dd + "  ";
        } 
        else if (i == 3) {
            document.getElementById("4").innerHTML += h + ":" + m + " " + dd + "  ";
        } 
        else if (i == 4) {
            document.getElementById("3").innerHTML += h + ":" + m + " " + dd + "  ";
        } 
        else if (i == 5) {
            document.getElementById("2").innerHTML += h + ":" + m + " " + dd + "  ";
        } 
        else if (i == 6) {
            document.getElementById("1").innerHTML += h + ":" + m + " " + dd + "  ";
        }
    }
}

function wakeUp() {
    //RETRIEVE TIMES FROM PERSON
    var hourInput = parseInt(document.getElementById('hourInput').value);
    var minInput = parseInt(document.getElementById('minInput').value);
    
    //MAKE SURE IT IS EMPTY EACH TIME YOU ARE PRESSING CALC
    document.getElementById("1").innerHTML = "";
    document.getElementById("2").innerHTML = "";
    document.getElementById("3").innerHTML = "";
    document.getElementById("4").innerHTML = "";
    document.getElementById("5").innerHTML = "";
    document.getElementById("6").innerHTML = "";


    //CHECKING TO MAKE SURE INPUTS ARE CORRECT
    if ((isNaN(hourInput || minInput)) || (hourInput > 12 || minInput < 0 || minInput > 59 || hourInput === "")) {
        document.getElementById("xxx").innerHTML = "Please use the correct HH:MM format"
    }
    if (document.getElementById('myonoffswitch').checked && hourInput == 12) {
        hourInput = 0;
    }


    var wakeTime = new Date(0, 0, 0, hourInput, minInput);

    //IF SET TO WAKE UP, THEN DO THIS
    if (document.getElementById('myonoffswitch2').checked) {
        for (i = 6; i > 0; i--) {
            var d = new Date(wakeTime.getTime() - i * cycle);
            var hh = d.getHours();
            var m = d.getMinutes();
            var dd = 'AM';
            var h = hh;
            if (h >= 12) {
                h = hh - 12;
                dd = 'PM';
            }
            if (h == 0) {
                h = 12;
            }
            if (m < 10) {
                m = "0" + m;
            } 
            else if (i == 1) {
                document.getElementById("6").innerHTML += h + ":" + m + " " + dd + "  ";
            } 
            else if (i == 2) {
                document.getElementById("5").innerHTML += h + ":" + m + " " + dd + "  ";
            } 
            else if (i == 3) {
                document.getElementById("4").innerHTML += h + ":" + m + " " + dd + "  ";
            } 
            else if (i == 4) {
                document.getElementById("3").innerHTML += h + ":" + m + " " + dd + "  ";
            } 
            else if (i == 5) {
                document.getElementById("2").innerHTML += h + ":" + m + " " + dd + "  ";
            } 
            else if (i == 6) {
                document.getElementById("1").innerHTML += h + ":" + m + " " + dd + "  ";
            }
        }
    }
    //IF SET TO SLEEP, THEN DO THIS
    if (!(document.getElementById('myonoffswitch2').checked)) {
        for (i = 1; i < 7; i++) {
            var d = new Date(wakeTime.getTime() + i * cycle);
            var hh = d.getHours();
            var m = d.getMinutes();
            var dd = 'AM';
            var h = hh;
            if (h >= 12) {
                h = hh - 12;
                dd = 'PM';
            }
            if (h == 0) {
                h = 12;
            }
            if (m < 10) {
                m = "0" + m;
            }
            if (i == 1) {
                document.getElementById("6").innerHTML += h + ":" + m + " " + dd + "  ";
            } 
            else if (i == 2) {
                document.getElementById("5").innerHTML += h + ":" + m + " " + dd + "  ";
            } 
            else if (i == 3) {
                document.getElementById("4").innerHTML += h + ":" + m + " " + dd + "  ";
            } 
            else if (i == 4) {
                document.getElementById("3").innerHTML += h + ":" + m + " " + dd + "  ";
            } 
            else if (i == 5) {
                document.getElementById("2").innerHTML += h + ":" + m + " " + dd + "  ";
            } 
            else if (i == 6) {
                document.getElementById("1").innerHTML += h + ":" + m + " " + dd + "  ";
            }
        }
    }
}

Ew. Let’s take a look at a slightly improved version:

Refactored version

var now = new Date(); //Gets current Time
var cycle = 90 * 60000; //Length of a sleep cycle, expressed in ms

function convertHour(h){
  if (h >= 12) {
    return h - 12;
  } else if (h == 0) {
    return 12;
  } else { return h }
}

function convertMin(m){
  return (m < 10) ? "0" + m : m
}

function setAM_PM(h) {
  return (h == 0) ? 'PM' : 'AM'
}    

function sleepNow() {
  for (i = 1; i < 7; i++) {
    var d = new Date(now.getTime() + 900000 + i * cycle); //Adding a cycle for each loop
    var h = convertHour(d.getHours());
    var m = convertMin(d.getMinutes());
    var dd = setAM_PM(h);

    document.getElementById(i).innerHTML = h + ":" + m + " " + dd;
  }
}

function wakeUp() {

  //RETRIEVE TIMES FROM PERSON
    var hourInput = parseInt(document.getElementById("hourInput").val)
    var minInput = parseInt(document.getElementById("minInput").val);
  
  //CHECKING TO MAKE SURE INPUTS ARE CORRECT
    if ((isNaN(hourInput || minInput)) || (hourInput > 12 || minInput < 0 || minInput > 59 || hourInput === "")) {
      document.getElementById("xxx").innerHTML = "Please use the correct HH:MM format"
    }
  //IF MIDNIGHT, SET HOUR TO ZERO (JS uses 24 hour time)  
    if ($('#myonoffswitch').is(':checked') && hourInput == 12) {
      hourInput = 0;
    }

    var wakeTime = new Date(0, 0, 0, hourInput, minInput);

    //IF SET TO WAKE UP, THEN DO THIS
    if ($('#myonoffswitch2').is(':checked')) {
        for (i = 6; i > 0; i--) {
            var d = new Date(wakeTime.getTime() - i * cycle);
            var h = convertHour(d.getHours());
            var m = convertMin(d.getMinutes());
            var dd = setAM_PM(h);

			document.getElementById(i).innerHTML = h + ":" + m + " " + dd;
        }
    }
    //IF SET TO SLEEP, THEN DO THIS
    if (!$('#myonoffswitch2').is(':checked')) {
        for (i = 1; i < 7; i++) {
            var d = new Date(wakeTime.getTime() + i * cycle);
            var h = convertHour(d.getHours());
            var m = convertMin(d.getMinutes());
            var dd = setAM_PM(h);

            document.getElementById(i).innerHTML = h + ":" + m + " " + dd;
        }
    }
}

This refactored version of Slumbr still has some repetition that can get factored out, so I might revisit this again and cut it down even more.


Patrick El-Hage

I'm Patrick El-Hage and I live and work in San Francisco. I like to hang on Twitter.