We can’t change history, but we can change the future.
Be nice to each other.
@robertnyman

Is invalid code created through JavaScript ok?

Published on Monday, March 12, 2007

When developing web sites with heavy interactivity, your scripting skills are really put to the test. And, sooner or later, you will be put in a situation where it’s a fine line between following web standards and what’s best from a performance and structure perspective. One question that follows that is: is it ok to apply invalid attributes via script to elements?

Generally, I’ve had the stance that code should be valid, no matter if it’s in the initial code when the web page is loaded, or if it’s dynamically altered through JavaScript. By doing some DOM manipulation, you can create great interactivity for web sites which really helps the end user and improves the experience. I’m glad that most scripting is of that kind (or is moving in that direction, at least), as opposed to doing things just because they’re technically possible.

When invalid feels good

So, let me give you a very basic example of invalid code created through JavaScript that I find more structured and efficient than the valid equivalent. Let’s say that you have one or several links in your web page that will show/hide certain elements. First, let’s find all those links and apply the event (example code is written using DOMAssistant):

Now we have applied the events to all links. Let’s examine different ways to achieve the showing/hiding of them:

Option 1: Look up related elements each time

Let’s say that the function executed each time the link is clicked first gets some elements through a getElementsByClassname function (try The Ultimate getElementsByClassName or DOMAssistant‘s core file for that), and loops through them.

Global variables are seldom good coding practice, because the risk of having them being overwritten. No direct reference between the element and the actual related elements exist either. Also, personally, I don’t think it’s that suitable for scalability.

Option 3: Object property

One way to do it is to save all the elements in an object’s property as an array, as soon as the click events are applied to them (an index class is used for each link, to avoid looping through the property array and comparing objects each time).

Little code in the expandCollapse function. Good overview and direct reference between the link and the elements it will interact with.

Downside

Invalid code.

Summary

In my opinion, the code in Option 4 seems to be the best for performance reasons, while at the same time establishing a direct relation between the link itself and its associated elements that will be affected. It is invalid, but only in the DOM and not from a general SEO or accessibility perspective.

Which option would you choose? And generally, is invalid code in the DOM ok if it’s justified from a performance or structure angle?

There's nothing invalid about option 4. There is a difference between HTML attributes, which are strictly defined, and properties of the DOM node, which are not strictly defined.

Let's look at the three standards concerned: HTML, DOM (Core and HTML) and ECMAScript.

From the viewpoint of HTML, adding an attribute that is not specified is an error.

From the viewpoint of ECMAScript, an object is completely dynamic, and you can add whatever properties to that you want.

From the viewpoint of the DOM, there are some predefined properties that map directly to HTML attributes. Setting these properties also sets the corresponding attributes, and if the attribute changes through any other means, the property changes as well. However, the DOM makes no statement at all about properties that it doesn't define, which means that JavaScript should fall back to simple ECMAScript behaviour.

In other words, setting an arbitrary property of a DOM node does not mean that you set any attribute of the element. In particular, calling linkElm.getAttribute("elementsToExpand") in your code above should return null.

No setting of element attributes -> no possible violation of the HTML standard -> no invalid code. q.e.d.

The only exception is Internet Explorer, which doesn't understand the difference between element attributes and node properties. But worrying about code doing invalid things when processed under invalid rules is stupid.

See the way I look at it this is about extending a Javascript Object that just happens to be a DOM Node too. I'd go for your last option every time because it makes sense from a Javascript point of view. It has to be said I hadn't thought about the fact your new attributes aren't valid because if you were do look at the generated code they wouldn't display (being invalid).

I'm not explaining myself very well I guess but basically while I don't like new random attributes being added to HTML pages I see no problem in extending any arbitrary Javascript Object as required.

Hmm, for the most part, i try to avoid relying on the DOM to do my bidding, preferring objects to package stuff.

<code>

myobject = {

myItems = [];

}

</code>

This does add more code, but allows me to keep cached references to nodes and collections, and wraps most of my functionality in a way that doesn't usually class with third-party code (or even code I write myself).

Inspired by the work of Christian Heilman (http://icant.co.uk/sandbox/eventdelegation/) , I've done some work on a recent project, using event delegates instead of event listeners. This works very well, especially for generated / ajaxed content, where you don't really want to clutter it up with inline event listeners, and we all know what a pain IE can be, when trying to manipulate DOM with content inserted with innerHTML (which is another MS innovation, that's off the plantation, but very handy).

Ironically enough, MS created innerHTML and yet IE has the poorest implementation.

So, I guess my approach goes kindof between the options outlined, since I try to keep references to ancestor elements, and have them deal with the events, instead of repeating the same event listeners over and over and over again. This scales really well, and Chris, if you're listening, GREAT WORK!

Sebastian gava a correct reply, so I won't repeat that. On the other hand, I do firmly agree with your viewpoint that option 4 is the best practice. Altough I tend to use option 3 regulary too. But I can't say I have a fixed rule for this: it's more a decision based on what feels good depending on the situation.

About the semicolons: copy/paste can be a real bitch in cases like this, no ;)? Easely missed, and I've done far worse before…

Well, to me it's a question of compliance. I tend to follow the standards in first hand but in some cases other methods seem more feasible (I'm not necessarily speaking of HTML here). Depending on the task, i tend to take different actions. Say, inserting content from a remote webpage, .innerHTML is the way to go. When adding elements that's to be manipulated later, I'll use the DOM construction.

I never use write(), innerHTML (even though that’s “OK” now) or hide invalid code in javascript.

Why write valid code? It’s easier to debug, cheaper, blah blah blah…… I’m not doing it for ideals, I’m doing it because I find my document easier to manage if it remains valid. I don’t hide invalid code in javascript.

I think that one of the reasons for invalid things to be hidden in javascript is the way people see documents such as web pages. You learn to edit it using a text editor, and you first learn to manipulate it with string manipulation functions.People think: “HTML documents are strings.”
This is only superficially true!In fact: HTML documents are serializations of objects – not strings.

When I saw the light, my skill doubled overnight. I’m still amateur and my work is still low quality and slow in appearing, but seeing things as they are does help me to improve.