Make Old JavaScript New Again

With the advent of so many different JavaScript libraries, the question often arises, “is there one library that will meet all of my needs?” I can tell you from personal experience, the answer is almost always, “no”. At some point in a full Web site or Web application build, you will need to add custom functionality. If you are one of the poor souls who is faced with using a library you do not know, or who is faced with the absence of a library altogether, then the situation can seem hopeless.

How will you start to develop these features, and how will you integrate them into a production environment? If you want to gain efficiencies, then you will want to reuse code gleaned throughout aging tutorials (in Web years). This can require refactoring a fair amount of JavaScript, so that you can take advantage of fresh design patterns, evolving programming techniques, and general best practices. This tutorial will hopefully help you to manage the process without too much hassle. The best place to start, of course, is with an “old” script.

I will be using Stephen Chapman’s Countdown Timer on About.com. There is a fair number of countdown timers available on the Web, with most counting down to a very specific holiday or event, and that are limited in scope. I chose Stephen’s because it offered some great flexibility, but could still use some improvements. The script is not unlike many you may come across while searching for a tutorial to jump start the process. Below you will find Stephen’s original script, modified slightly for readability.

Deleting what is unwanted

One of the first things you need to do before refactoring is to remove anything that will not serve your purpose. Most of this code is necessary for the functionality of our countdown timer, but there are two utility functions that we will not need. This is the start and loaded function that are tightly coupled to the window.onload event. In your application you will likely want to bind functions with an event handler, so for the purpose of this tutorial we will use a basic onload event in order to eliminate confusion.

You want to focus on the core of the script, and this is always a great way to begin. You may find yourself removing a large portion of code, depending on the size and scope of the original snippet of JavaScript. Test constantly as you delete what is unwanted. Below is the next iteration of the JavaScript countdown timer.

Letting your pattern emerge

Now that you have only what you need, you need to figure out whether or not this functionality will play a small role in the big picture, or if it will be the lead star. I will assume this is one of many features that will appear in your application, and that you need to first write a draft or stub (as some programmers like to call it) of your own custom micro library. You will discover quickly that this emerging pattern very closely mimics the Module Pattern described in depth on the Yahoo! User Interface Blog. Take a look at the stub below, and start to think about how it might apply to the countdown timer script before moving forward.

At this point in the design the stub appears quite cryptic compared to the initial countdown timer. Remember though, you are planning to add other features and functionality unrelated to the timer, so we need to make room for those scripts as well. Initially, the code is nothing more than a namespace blueprint, placed within the global JSANT object. You need to provide access to public properties and methods, and also accommodate private utility properties and methods that are only visible to these public properties and methods. Below is an example of what this access would look like.

Getting into the guts

Now you can begin to build upon this blueprint, and stub the properties and methods that you need for the countdown timer. Stick with what has been provided, and suppress the desire to rename functions or variables. If you get into a jam, it will be easier to compare apples to apples. Get your global variables into the JSANT object, and get into the guts of the old script to pull out the necessary functions that will act as your methods.

You might be wondering how to know if a method should be public or private. A good rule of thumb is to think of a public method like you would a foreman on a home construction site. The foreman is responsible for taking all the requirements (parameters) from the home owner (user agent), and delegating responsibility. There are carpenters, electricians, and bricklayers, all with unique responsibilities, working behind the scenes (private methods). Although foremen will help occasionally with the heavy lifting, their primary responsibility is to make sure the homes display properly when the owners (users) come for a showing.

Beginning to refactor

This is where the process can get interesting. I prefer to move all the code into the appropriate “slots”, and then refactor the code only as needed to get it functional. The first rule of thumb in refactoring old scripts is that at this juncture, you are not trying to gain efficiencies. You simply want it to work as-is, or with minor edits.

In the original script, setCountdown was a public function. Because this function only performs a utility task, I decided it was better suited as a private method. The displayCountdown now only accepts the ID of the element that will display the countdown timer. However, we still need to perform the task that sets the initial time, so I created the countdn method. The countdn_value property will hold this decremented value of time in seconds after it is initialized. I also modified the tz property to represent EST.

Gaining efficiencies — refactoring on steroids

Technically, we could leave our script alone. We no longer have global variables, we took advantage of the Modular Pattern, and our script performs as expected. Other developers could use it on pages throughout the application without having to know anything other than the ID of an element in the DOM. Yet, after looking closer, you might have noticed that this script is not very flexible. Every developer can only use one version, which will perform a single countdown, with a single set of parameters.

What if you wanted multiple countdowns, possibly on an ecommerce Web site? One will countdown to Christmas, and the next will countdown until the end of a sale, or until the hour when the last order will ship for that day. You get the point. Take a look at the final iteration of this script, and notice some of the efficiencies — most notably the elimination of the countdn method and countdn_value property. These are no longer needed, because time can be tracked for each countdown through a key/value pair added to the params object. This is a commonly known trick for passing data around without requiring each function to know all the parameters.

Leave a Reply

Your email address will not be published.