After some time of using the concept of live extensions I realised that existing well-known ready
method is useless. Starting from 1.7.6 the DOM.ready
method is deprecated, and it will be removed in the 1.8 release.
In this issue I'll try to explain the reasons of such decision.
What the ready
method does
jQuery made the concept of the ready
method to be popular. But notice: there is no such method in the standard. W3C document contains only the DOMContentLoaded
event, that is fired as soon as browser parses body content on the current web page.
But an important feature of this event is that the event handler is not triggered if you register a it after browser parsers the document tree. To solve this limitation we have ready
method, that triggers the callback as soon as DOMContentLoaded
event is fired or if it was already triggerend.
As I said before there is no ready
method in the existing version of the W3C standard.
Why ready
method was useful
The main goal for the ready
method is to garantie that the code inside of a callback handler will be executed when your document is ready. It allows to do safe DOM querying.
<!DOCTYPE html>
<html>
<head>
<script>
DOM.ready(function() {
DOM.find("button").on("click", function() {
alert("it works from <head>!");
});
});
</script>
</head>
<body>
<button>test</button>
<script>
DOM.ready(function() {
DOM.find("button").on("click", function() {
alert("it works from <body> as well!");
});
});
</script>
</body>
</html>
Inside of the callback people usually do some initialization, DOM mutations, attach event handlers etc. This is kind of safe start point for any JavaScript for DOM.
Live extensions make the ready
method less useful
The main goal for live extensions is to fill gap of the ready
method that doesn't work for future HTML content inserted via JavaScript. Additionally to that there are several issues that I think makes sense to cover to clarify the decision of deprecating the DOM.ready
in favor of DOM.extend
.
Issue 1: code separation
If you use JavaScript a lot on client side, you often need to initialize bunch of plugins. After some time your code looks like below:
DOM.ready(function() {
// init plugin 1
// init plugin 2
...
// init plugin n
});
The ready
method callback quickly becomes to be a huge. It's possible to split it into several calls and move into several separate files but it's a rare practice.
The main reason of such situation is that every ready
call is very similar. There is no distinction and separation between them by sense.
This is what makes live extensions to be different. The first argument of the DOM.extend
call is a CSS selector that usually describes the sense of the extension (based on class or tag name). So it means you are forced to separate your code by sense that in general is a good practice to follow.
To summarize: using live extensions makes your code to be more maintainable.
Issue 2: testability
In JavaScript functions produce a new context, and all local variables are not accessable outside. Because of that ready
methods are usually hard to test or they require additional refactoring.
DOM.ready(function() {
// how to test logic here?
});
During development of the live extensions concept I kept in mind testability. And existing API allows to test constructors very easily.
This is how a live extension looks like:
DOM.extend("selector", {
constructor: function() {
// extension initialization
this.doPartOneOfInit();
...
this.doPartTwoOfInit();
},
doPartOneOfInit: function(a, b) {
// do part one
},
doPartTwoOfInit: function(c) {
// do part two
}
})
Then you can make a mock object that have private methods on it:
var mockObject = DOM.mock("selector");
mockObject.doPartOneOfInit(1, 2);
// assert state
mockObject.doPartTwoOfInit(3);
// assert state
Issue 3: doesn't work for future content
This why live extensions were created. I want to get rid of the ready
calls because they have this limitation that doesn't make sense to do in most of use cases. The better-dom library APIs should ecourage developers to use a good practices, like making plugins that work initially for future content even in case they are not aware of such feature.
Conclusion
I hope the article helps to understand why DOM.ready
is useless. In case you still need it you can just use the construction below:
DOM.extend("body", {
constructor: function() {
// this is equal to DOM.ready callback
}
});
Starting from 1.7.6 the method DOM.ready
is deprecated. It is scheduled for removal in version 1.8.