Rewriting a pile of ugly 2012 JavaScript
Cleaning up the code for our Network SouthEast clock, and revisiting younger, caffeine-fuelled, reckless versions of ourselves. (May 2023)
Some time ago, we had a fun idea: re-implement the rapidly-disappearing Network SouthEast electro-mechanical clocks in HTML and JavaScript. By the very early hours of the following morning, we had a working prototype. We bashed that out pretty quickly. And it kept working for over a decade!
In the time since, at intervals of a few years, our HTML5 Network SouthEast clock has done the rounds among railway enthusiasts. Actually, it might go around more often than that; it's still overwhelmingly the most popular thing on our website by every measure. But we know it's really doing the rounds if it appears in our social feeds when we weren't looking for it. This happens often enough that it isn't even unsettling anymore.
On a couple of those occasions, we have seen photographs of it in use in real world railway control centres (seriously!!). The second time that happened, we thought that we could enable this use case even better by adding a "distraction free" mode which would hide the text controls underneath the clock. And then we looked at the code we wrote in a caffeine-fuelled rush in 2012...and noped out, figuring that this was old and bad code that no human being should ever have to see again. Like that time we found an ISDN modem inside a false wall with the lights still blinking, we figured that some things are left best alone. You keep trucking, little buddy.
In a quiet moment a few weeks ago, we decided to attack that code in a big rewrite. It took a couple of days of our free time. It combined refurbishment, archaeology, and self-reflection. Here are some of the things we did, found, and learned.
We are much better programmers than we were
By the measure of number of lines changed, the biggest improvement was making the code less bad. We could have done that without modernising a single line of it.
In 2012, we did not take JavaScript seriously as a programming language. This may not have been fully forgivable even 11 years ago. Gmail demonstrated that it could be used for serious web applications eight years before. Douglas Crockford demonstrated that JavaScript contained a kernel of goodness in 2008, and arguably Crockford made the first demonstration of "good JavaScript" in 2004 with JSLint.
But, our attitude at the time was that JS was a toy language, and we employed it to build a browser toy. We saw no reason to care about the quality of that code any more than we'd go to extra efforts to make a cheese sandwich well-presented. That code continued to work because of web browsers' dedication to backwards compatibility, so we never touched it.
That was a mistake. The longer we left it untouched, the more we were reluctant to touch it. If it had broken as web browsers moved on, we may well have left it broken, or removed it altogether. No bones about it, the code was bad. It gleefully polluted the global window namespace. It might have had exactly one good idea which remains in the new code; that lone good part was buried under a pile of spaghetti and philosophical confusion. It was inconsistently formatted, too, which was probably the biggest barrier to understanding what we were thinking 11 years ago.
We mentioned not taking JS seriously above. To the extent that we prefer our sites server-rendered with a sprinkle of JS for interactivity, some would argue that we still do not. But that is no reason for the code to be unreadable nonsense. So, we've ensured that it is statically analysed for problems (such as the global namespace pollution above). It uses ES6 features, to the extent those features are not bugs. There is now a consistent code formatting style. It should, at the least, not cause anyone with a solid knowledge of JavaScript to recoil in horror, and it does not actively discourage investigation.
There is no more cross-browser nonsense
2012 was, as any mathematician will tell you, eleven years ago. There are seasoned professional web developers working today who have no first-hand idea of the nonsense we had to deal with back in our day. This is demonstrated every time a seasoned web developer says that any browser other than Internet Explorer is the new Internet Explorer. While we disagree, we can be thankful that those people have either never dealt with Internet Explorer or have forgotten how bad it actually was.
Eleven years later, Internet Explorer is dead. And the auto-updating nature of web browsers today means we no longer have to worry about old, bad browsers at all. Poking around this code gave us a pleasant reminder of just how much better things are these days. Here is a sample of the things we had to deal with back then:
- Opera, the Presto-engined version, did not implement `border-radius` properly. We had to specifically detect that browser and disable the subtle rounding of corners. That made it look subtly wrong, but that was better than looking terrible.
- Vertically centering things used to be hard! In fact, doing it reliably in CSS alone was impossible. We needed JavaScript for that.
- Not all browsers supported the <audio> tag for playing audio, so we had to detect that case to avoid an exception being thrown.
- Various still-extant versions of Internet Explorer did not support SVGs, so the little NSE logo "flash" was implemented as a PNG image embedded into the document as Base64.
None of which we needed to bother with anymore! And to think that back then we thought we had it good because we remembered the days of having to deal with incompatibilities between Internet Explorer and Netscape. Things are far better these days.
It no longer uses jQuery.
As said, cross-browser compatibility used to be hard. jQuery was an invaluable JavaScript library which papered over the differences between them (and once again for anyone who has come into web development in the last decade: imagine not being able to depend on document.querySelector!). It did what it had to do for many years. Arguably, it still has a nicer interface for interacting with the DOM than browsers do today; jQuery is still popular today for that reason. But, necessity no longer required us to use it, so we did not.
If the removal was gleeful, it was only because jQuery was to be celebrated for its enormous contribution to an era of web development. Thank you, jQuery!
...and no longer uses any framework at all
We considered rewriting the clock with a JavaScript framework such as Vue or Alpine. Certainly, our code would have been much simpler; it's currently just about at the level of complexity that, in our view, would merit something to handle reactivity at least.
We didn't do that. We wanted to rewrite it for longevity. Remember that our clock predates the existence of React by a year and Vue by two years; in that time, both those frameworks have seen rewrites that have completely changed their APIs. We did not want to rewrite it every few years to keep up with framework changes, because we have real work to do.
We added a couple of features, too
Now that the code didn't actively resist modification, we added that "distraction free" mode we spoke of earlier.
We un-broke one more use case while we were there. In the past, we had noticed that people had embedded our clock on their site in an IFrame. We said "well, that's cool", then forgot about it, and we accidentally broke that use case at some point. We knew about that for a while, but the clock was confined to a "some things are best left alone" corner of our minds, and so we left it unfixed. The rewrite gave us a renewed attitude towards the clock's code. We unbroke embedding it in IFrames while we were there.
We also added a secret feature which you'll only find out by reading the source code. Have fun!
What do you think?
Go have a look!
We went to efforts to ensure that the clock behaves exactly as it did before, so if you thought the old one was awesome you will think this is awesome too, and if you thought it was a waste of time before there's no helping you.
We were happy with the rewrite. We were happy with the result, we were happy to have learned things about ourselves, and we were happy for the reminder that web development is better these days than it has ever been. There might still be ways it can be improved. If you think of some, let us know!