dean.edwards.name/weblog/2007/03/other-way/

The Other Way To Use base2.DOM

In my last post I previewed a JavaScript library I’m developing called base2.DOM. The aim of this library is to provide cross-browser support for new and existing W3C specs. I started off by showing you the easy way to use the library which involved using the base2.DOM.bind() function to provide automatic support for DOM methods like addEventListener(). In this post I will you show the other way to use the library. The slightly harder way.:-)

The Easy Way – A Recap

In my last post I introduced the base2.DOM.bind() method, which once applied to the document object, automatically augments elements retrieved using the Selectors API:

// call this first
base2.DOM.bind(document);

// now you can use standard DOM methods
var menuItems = document.querySelectorAll("ul.menu li");
for (var i = 0; i < menuItems.length; i++) {
    var element = menuItems.item(i); // you must use the item() method. Sorry!
    var para1 = element.querySelector("p:first-child");
    para1.addEventListener("click", youClickedMe, false);
}

The Other Way – Library Functions

base2 has been developed so that all of those useful DOM methods also exist as library functions. So the code above can also be written like this:

//base2.DOM.bind(document); // no need to call this if we are using library methods

// use base2 library methods
var menuItems = base2.DOM.Document.querySelectorAll(document, "ul.menu li");
for (var i = 0; i < menuItems.length; i++) {
    var element = menuItems.item(i); // you must use the item() method. Sorry!
    var para1 = base2.DOM.Element.querySelector(element, "p:first-child");
    base2.DOM.Element.addEventListener(para1, "click", youClickedMe, false);
}

When you use the library methods like this there is no augmentation of elements. That means that elements are not automatically fixed when retrieved by the Selectors API. This is a very important difference. But it means that you can choose if you are going to automatically augment elements or not.

Too Much Namespacing?

The namespacing is quite verbose but you can reduce that by doing this:

// create a closure
new function() {
	// evaluate base2.DOM.namespace to alleviate typing	
	eval(base2.DOM.namespace);
	
	// now you can use the library methods without the namespacing
	
	var menuItems = Document.querySelectorAll(document, "ul.menu li");
	for (var i = 0; i < menuItems.length; i++) {
	    var element = menuItems.item(i); // you must use the item() method. Sorry!
	    var para1 = Element.querySelector(element, "p:first-child");
	    Element.addEventListener(para1, "click", youClickedMe, false);
	}
};

The base2 namespace also provides a few useful methods (which I’ll document later) and the above code can be reduced further:

new function() {
	eval(base2.namespace);
	eval(base2.DOM.namespace);
	
	var menuItems = Document.querySelectorAll(document, "ul.menu li");
	forEach (menuItems, function(element) {
	    var para1 = Element.querySelector(element, "p:first-child");
	    Element.addEventListener(para1, "click", youClickedMe, false);
	});
};

You can find most of the library methods you need on either the base2.DOM.Document or base2.DOM.Element interfaces. The only exceptions are the addClass(), hasClass() and removeClass() methods which are defined on base2.DOM.HTMLElement.

Download

If you downloaded the code recently then you need to re-download as the first release contained a pretty horrendous bug.

You can browse the raw source or you can download the full source code:

And the compressed version of the first two files:

Comments (14)

Leave a comment

Wow. I’m loving this stuff!

Javascript is a wonderful language, it’s time to embrace it and learn it. Too many people keep trying to squeeze javascript into some other mold. Javascript isn’t Ruby, or Python or Java (despite the stupid name). Those languages have their place, but not in my javascript!

This just feels like “the right way” to do this stuff… the _javascript_ way.

(I’m sure I must be missing something here…)

Why not reduce namespacing with ‘with’ instead of new function context’s and eval statements?

with (base2.namespace) with (base2.DOM.namespace) {
    var menuItems = Document.matchAll(document, "ul.menu li");
    forEach (menuItems, function(element) {
        var para1 = Element.matchSingle(element, "p:first-child");
        Element.addEventListener(para1, "click", youClickedMe, false);
    });
};
  • Comment by: Ash Searle
  • Posted:

Of course, I meant to remove the namespace properties:

with (base2) with (base2.DOM) {
    var menuItems = Document.matchAll(document, "ul.menu li");
    forEach (menuItems, function(element) {
        var para1 = Element.matchSingle(element, "p:first-child");
        Element.addEventListener(para1, "click", youClickedMe, false);
    });
};
  • Comment by: Ash Searle
  • Posted:

@Ash – with is slightly slower as you are introducing new objects into the scope chain. And using with can sometimes lead to confusion as to which object’s properties you are addressing. But you are right, you can also use with to reduce namespacing.

I don’t really recommend creating a new closure for each block of code.:-)Rather, that your entire script runs in a closure. Alternatively, you can call eval(base2.DOM.namespace) in a global context to globalise the base2 namespace. Or you can just use with like you suggest.:-)

  • Comment by: -dean
  • Posted:

[…] Dean Edwards has followed up on his base2 library posting with another way to use base2 and rules for JavaScript Library Authors. […]

Dean; can you use this in your lib? It’s brand new;) http://www.alistapart.com/articles/crossbrowserscripting

Great work, Dean. Just wanna say thanks for making my j-scripts better.

Thanks for the base2.DOM, Dean! It will help me a lot in my work, even though I see it is not as easy to use as I thought, after reading this post. This is not “slightly” harder:)

Dean, I often use your base2.DOM. library in my JavaScripts. It is a great library and I find it really simple to use, but as I can see there are more complex ways of using it. JavaScript is a wonderful language and I would really like to see more libraries like this.

  • Comment by: Andrew
  • Posted:

base2.DOM is a fantastic library Dean, and I really like that you can use it in many ways as you have shown in this post. It is a good idea to focus on cross browser support because different browsers can cause a lot of problems, they sure gave me quite a few headaches…

  • Comment by: Chris
  • Posted:

I found your BAse2.DOM yesterday and now I found this other way. I think my WE will be full off javascript;)

  • Comment by: henri
  • Posted:

You’ve got some great tips on this site. I’m now trying to decide whether it will be worth going through and cleaning up some of my old files with some of what I’m learning here, Or just add it to future code.

You’ve inspired me into taking a good look at base2.DOM. Thanks

  • Comment by: ADAC
  • Posted:

This is exactly how I see we should move forward with JavaScript libraries. Not made to look like some server-side language but to look like the latest recommended standards (and use compliant, client-side JavaScript where it belongs).

Which Ajax library community will take base2 as its foundation or is there already one out there?

We should all support and build on Dean’s efforts to standardise all that we do in web development. If all the expertise of all the various JavaScript development projects focused on and contributed to what Dean has already done, we would all progress very quickly and the future would be safe.

Check if user agent supports requirement and if not -
 - make it support

If new version of user agent now supports – No problem.

Well done Dean. Keep up the excellent work.

  • Comment by: Billy Wallace
  • Posted:

Thanks Billy, I’m glad you get it.

  • Comment by: -dean
  • Posted:

Comments are closed.