Document Fragments and jQuery and Star Trek

For those of you who don’t already know, I’m a big-time Star Trek fan. I’m especially interested in the original series, and some of my favorite content comes from an old role-playing game from a company called FASA in the 1980’s. The game had an extensive timeline of events, and I’ve always wanted an easier way to read through it. Since I grew up to be a web developer, the obvious choice is to build an app and give it a project page!

Scotty in The Naked Time
Here I go again. Will I finish this one or just wave a tuning fork at it for the rest of my life?

The idea was to gather up all of the timelines from all of the books into something that I could easily navigate without digging through my embarrassingly extensive collection of nerdy things. It would need to sort events by stardate and filter by the source of the events.

For example, you may want to look at Romulan history but not Klingon history. The app would need some toggles too, because there’s are sometimes multiple timelines for the same source. For Klingons, there’s a timeline for their full history and another one for what the Federation knows about them. It’s a detailed bunch of information. The folks at FASA took their writing assignments very seriously.

Starting Materials

I wanted to get right to the data, so I wasn’t interested in building a fancy-pants UI from scratch. I started with Bootstrap, and then did a bit of searching for a responsive timeline design. Lucky for me there’s a guy out there named Luis Rudge who was nice enough to post this example on Bootsnip. These gave me a starting point to work from so I could get right to the data.

Geordi working on Data
No, not this guy. I mean “data” in lowercase.

These are role-playing books from the 1980’s, and they’re all out of print. To get them into an app, they would have to be OCR scanned and edited. Holy crap. I was lucky enough to find some of it online, but much of it had to be scanned and some of the rough stuff had enough errors that I wound up typing it. Lucky for me I took a typing class back in the day.

By the way, you should tell your kids to take a typing class. It’s the most useful course I have ever taken in my entire life. Seriously. I use it all the time.

But I digress. After lots of work in small increments over an amount of time that I refuse to calculate, I finally wound up with a Google Sheet filled with all sorts of Trekkie goodness. Typos were corrected, content was sorted and everything was in some kind of order. From there, I could finally start building my app.

The JavaScripty Part

I was originally going to pull the data via an AJAX call from a Google Sheet with a timeline on each worksheet. That works, but it’s a lot of calls to Google, and I had a slight worry that I would suddenly get super-Internet famous and everybody would look at it and then I would get a frightening bill from Google… or something. Since the data isn’t going to change at all, I decided to just copy the results of the Google call to some JSON files and use those locally. (This would also allow me to work on this thing offline if necessary.)

You can see the code in my GitHub repo, but the basic workflow is to grab the various JSON files and then loop through them with some jQuery Deferred magic. We loop through the array of sources with the jQuery each() method, adding a Deferred Object to each one as we go. We could do something when each one comes in, but in this case we only care about what happens when they’re all finished. Once that happens, we use a neat trick I found on Stack Overflow to attach a when() to the endgame of the array. When everything is available, we sort the events by year and build the timeline.

Guardian of Forever

The timeline is built using document fragments. I normally make these with vanilla JavaScript, but in this case I made them with jQuery since it was already loaded and sitting right there, bored, hoping for something to do. That looks like this:

$body = $("<div/>", { class: "timeline-body" });

The elements for the event are built into a list item, and that’s appended to the main document fragment. When they’re all in, the final, finished fragment is appended to the DOM inside a ul. That results in just one reflow of the page, even though the app is creating all of these crazy elements. Document fragments rock.

<!-- The document fragment will be appended to this list. -->
<ul id="timeline" class="timeline"></ul>

The code is documented pretty well, but my favorite trick is alternating which side the events are on. Whenever the filters change, classes are added and subtracted to make sure that you don’t end up with two consecutive events on one side. It reads “left-right-left” all the way down. I was surprised at how fast that works, even with so many events in the markup.

And that’s it. Mostly. I got to tinker with document fragments while playing around with some nerdy Star Trek content. Good nerdy fun.