code

Implementing the DOM Core: A history lesson with a dollop of crazy

If you know anything about how web pages can be edited with JavaScript, you have probably heard of the infamous getElementById function. It is used in nearly all lessons on editing elements on a page and occurs in every JavaScript library I have ever seen in the last decade or so. It is the basis for most element searching and is so commonplace most libraries like jQuery include it as part of something like a ‘$’ search.

However, it didn’t exist in an official capacity prior to 2000. It was introduced as part of the DOM Level 2 Core. A specification for how programs (called user agents) create document-object models of text like HTML and XML into something that can be read and written to by JavaScript. The DOM Level Core specifications detail how the internal parts of a webpage or other file should exist and what functionality they should have exposed to JavaScript. You can think of them as the backbone standard of what basic objects and functions should exist as created by a user agent.

The first one, DOM Core Level 1 specification, dates back to 1998 and includes the introduction of functions like createElement and appendChild. Two, in particular, that are just as common as getElementById and whose presence is nearly as guaranteed. They detail how, you might guess by their names, to create and append child elements to others. Yet, prior to 1998, they weren’t part of the standard. In fact, prior to the specification being published openly, they didn’t officially exist at all. (A very humble thought for me especially, given I’m writing this 16+ years afterwards on software, WordPress, that uses them to create content.)

So why this history lesson? Well, because I’ve been working on implementing them one by one starting with DOM Core Level 1 as part of my XML for CocoonJS project. As I’ve documented in another post, XML support is completely missing. This is, as I’ve come to learn, not something purposely done, as some have accused, but because supporting it adds much more code to projects cloud compiled with CocoonJS. It would mean including a whole other library just to parse XML. Something that, at least at the moment, most people aren’t using anyway.

It’s why, prior to me starting the project, I couldn’t seem to find much on using XML with CocoonJS. Others had tried it, found the functionality missing, complained about it in different places, and then moved on to doing things other ways. There wasn’t a solution to using XML directly. Some, sure, had found ways to convert their XML to JSON and written loaders with that in mind, but it would mean giving up on the problem, not solving it.

So, starting a few days ago, I opened up the specification with an earlier version of the project and worked my way through it, adding objects and functionality to match the DOM Level 1 Core specification as close as I could. An exercise, as I write after posting my new code, that has left me with an appreciation of the history in place that underlines how webpages exist as part of the DOM. Most of what was defined first in that 1998 specification remains with us today as the backbone for later specifications and functionality.

Of course, with that appreciation comes the knowledge of some of the craziness that exists as part of the DOM Core specification too. For example, my current favorite new function to tell people about is DOMImplementation.hasFeature. Within a user agent, it is accessed exclusively through document.implementation and the returned DOMImplementation object. In Firefox, Opera, Safari, and Chrome, it blatantly lies about what features it supports or doesn’t. For great fun, you can even run “document.implementation.hasFeature(‘blah’, ‘blah’)” or different string values in the console and it would return true.

The one major difference, as is expected, is Internet Explorer. It strictly enforces a check for “HTML” or “XML” as the first argument and “1.0” for the second. And, just to be clear about why this is crazy, HTML 1.0 was defined in 1993. If the user agent doesn’t support HTML 1.0, something went spectacularly wrong. In fact, how did you even run the check in the first place? document.implementation was defined almost four years later — and two years after HTML 2.0 was defined in 1995!

However, even with the lying and IE bizarreness, what is even more hilarious to me with its current inclusion is how the DOM Core “living standard” defines the function. Don’t want to click that link? Let me include here what it says, all four words of it: “useless; always returns true.” That’s right, the current recommendation is to include a function whose sole purpose is to return “true.” It has to exist because it was defined as part of the specification back in 1998, but now, 16+ years later, it lives on as some phantom function. A remainder of another age, but “useless” in any current setting or context.