dean.edwards.name/weblog/2007/03/yet-another/

Yet Another JavaScript Library Without Documentation

Just what the world needs, another JavaScript library.

Intro

Because this library is standards-based it means that you don’t have to learn a new API. It uses standard DOM properties and methods throughout which also means that I don’t have to write any documentation. ;-) It is part of a suite of little libraries that I’m developing called base2. This is the first library under that umbrella and is called base2.DOM. Not a great name I know.

The library is structured so that it can be used in a variety of ways. In this post I’m only going to show you one way to use the library. The easy way. I’ll show you alternative ways to use base2.DOM in subsequent posts.

Highlights

So, as you can see, it doesn’t do much. But what it does, it does consistently across a lot of platforms. There is a full list of supported methods below.

Making It Work

I said that I was going to show you the easy way to use the library. The first thing we need to do is make a little function call:

base2.DOM.bind(document);

The bind() method fixes broken DOM methods and adds new methods like querySelectorAll() and querySelector() from the Selectors API. The DOM.bind() method can be applied to any DOM node. Most of the time you don’t need to think about it as it is automatically applied to every element retrieved using the Selectors API. We can now use methods like addEventListener and querySelectorAll without worrying about browser differences:

var menuItems = document.querySelectorAll("ul.menu li");

All elements returned by querySelectorAll()/querySelector() will automatically have the DOM.bind() method applied to them so they will be also be magically “fixed”:

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 querySelectorAll() method returns a StaticNodeList object. You must use the item() method to retrieve elements from StaticNodeList objects. To help, I’ve added enumeration methods (forEach, map etc) to the object so you can do this instead if you prefer:

document.querySelectorAll("ul.menu li").forEach(function(element) {
	var para1 = element.querySelector("p:first-child");
	para1.addEventListener("click", youClickedMe, false);
});

Support

Remember that you must call base2.DOM.bind(document) first. After that the following propeties and methods will be fixed or implemented:

I need to add more fixes to the event object but I have to do some reading and testing first. I also added some sugar to HTML elements:

All of the above fixes apply only to elements retrieved using the Selectors API or nodes that have been passed to base2.DOM.bind(). These are the properties and methods that I consider important for basic DOM scripting. Everything else either works consistently already or is not used often enough to consider worth fixing (e.g. hasAttributes()). Having said that, I am open to suggestion. If there are some core DOM bugs that I’ve missed or there is a useful method that you think needs to be implemented then let me know.

Platforms

I’ve tested base2.DOM successfully on the following platforms:

* MSIE5.0 (Windows) and MSIE5.2 (Mac) require an additional file base2-legacy.js (2KB).

Caveats

Only a few:

One Last (Cool) Thing

Just to show off how flexible the underlying library is I’ll demonstrate one last neat feature. You can do this:

base2.DOM.HTMLElement.prototype.myCustomMethod = function() {
	alert("Wow! Just like Mozilla!");
};
var form = document.querySelector("form");
form.myCustomMethod(); // ==> Wow! Just like Mozilla!

There is also a mechanism to apply bindings by tag name so we can fix specific elements. I don’t use this functionality in this release though. But we could, for example, define a serialize() method that got applied to all form elements retrieved using the Selectors API.

Download

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

And the compressed version of the first two files:

If you want to support IE5.0 (Mac or Windows) then you need to include the legacy file before any other base2 files.

The base2 core library is also quite useful in its own way. It includes things like my Base class and enumeration methods. I’ll document this library sometime in the future (it’s only little). For the time being I am only supporting the base2.DOM module and even then only if you are using the bind() method that I’ve demonstrated here.

Finally

This library doesn’t do anything interesting like script.aculo.us or jQuery. It only does standards. But it is my belief that if you build on standards in the right way, you can help future-proof your scripted pages.

If there is enough interest in this library then I’ll upload the code to code.google.com and turn it into a proper open-source project. Consider this an alpha release for now but I’m prepared to bump it to a full release quite quickly. It needs a round of decent testing before I can do that though (hint).

Please report any bugs or errors that you find.

Comments (173)

Leave a comment

Very nice, Dean! This is a fantastic package – keep up the great work! I’m going to have to pour through this to see what tasty morsels I can find.

And while jQuery might’ve been the first library to try and become faster, I think it’s safe to say that we’ve been officially leap-frogged now. Time to get back to work!

  • Comment by: John Resig
  • Posted:

Awesome work Dean. Thanks a bunch! :-)

I especially like the elegant way you add the Selectors API methods to DOM elements that are already in the tree. Is there any special way to add these standards based methods to new DOM elements that are inserted using appendChild and so on, or do they automatically inherit the Selectors API methods?

So judging by the linked standards documents and a quick look through the source, it looks like this library supports both css and xpath, is that correct?

Also, is this meant to replace your cssQuery library (which I find infinitely useful btw – this’ll be similarly useful)?

Finally, it’d be awesome if you put this on code.google.com ;-)

@John – Thanks. You know what a fan I am of jQuery. :-)

@Kevin – You can use base2.DOM.bind(element) to fix newly created elements. I considered overriding createElement() to do this automatically. What do you think? If you bind the document then all new elements are bound too?

This is pretty much a replacement for cssQuery and a lot of other stuff. I’ll post some code later that will allow you to use the cssQuery interface, it’s only a few lines of code.

I probably will submit the project to code.google.com. I’m just testing the water for now.

  • Comment by: -dean
  • Posted:

[...] Dean Edwards has come out with what he calls Yet Another JavaScript Library Without Documentation. [...]

Excellent! I’ve been planning to update my DOM scripts that do a similar thing (mostly for DOM Events), but haven’t had the time to work on it. Now I don’t have to, thanks! I think this is a great project and it would be good for you to make it an open source project. I haven’t reviewed the code yet, but I’m particularly interested to see how you solved the issue of applying methods to Elements in IE, since it doesn’t support the Element interface. That’s one of the things I struggled with when I wrote my script, and my solution is sub-optimal.

However, I just wanted to mention that the name of the Selectors API methods (matchAll()/matchSingle()) are highly subject to change. It has, unfortunately, become a major issue with the spec because no-one can agree on it, so when that is resolved (hopefully soon), you’ll probably need to update the script.

Brilliant work, as always.

Don’t like the name though. Why not just call it “base” rather than “base2″? Is anyone really going to use the revision in the same document as the original “base”?

I noticed some time back on Anne’s blog that he’d changed the naming for the Selectors API. I guess the naming thing got sorted? Or is that still up in the air?

http://annevankesteren.nl/2007/01/web-api-stuff

@Lachlan – I’m aware of the controversy surrounding the method names for the Selectors API. I emailed Anne about it, he said that matchAll() and matchSingle() were most likely. If the names change then I’ll change too. No biggie.

  • Comment by: -dean
  • Posted:

@dean – it’s a tough call, whether or not to override that method. I’d say if it can be done safely to go for it – or maybe to do your compromise, and assume that if the user binds the document that they are looking to get this functionality everywhere with no extra effort. I’d say go with that compromise.

Just for an alternative option, you could add a new method, something like base2.DOM.autoBindOnCreate() or a property to set (something like cssQuery’s cache property).

@Kevin – like I said in my post there are two ways to use the library. My thinking is that if you use the bind() method on the document then you have decided to do everything automatically. But there are other ways to use the library where this does not happen.

  • Comment by: -dean
  • Posted:

I was interested to see how you implemented activeElement. I noticed your “-dean: is onfocus good enough?” note, and want to answer that with “no”. You can’t support “If no element specifically has focus, this must return the root element.” without also handling onblur, otherwise it becomes lastActiveElement.

Nice library though!

  • Comment by: Milo
  • Posted:

@Milo – OK I need to tighten that up. I like activeElement and was glad to see it added to HTML5.

  • Comment by: -dean
  • Posted:

Excellent work Dean, as usual. Simple, graceful, and extremely useful.

  • Comment by: Neil Mix
  • Posted:

I had just come to the conclusion that something like this would be the best way to do javascript development. Thank you very much for putting the work into this.

  • Comment by: Rowan Nairn
  • Posted:

!excellent! (as usual)

  • Comment by: mamund
  • Posted:

Amazing work Dean! I’m really excited about this library, can’t wait to start using it!

I think it’s safe to assume that if a user binds the document they’ll want the same functionality for newly created nodes that exists for all already existing nodes. I don’t think it’d make sense to have createElement create a node that doesn’t function the same…

  • Comment by: David Zuch
  • Posted:

I am absolutely sold.

I love that this lets you use javascript in the style of javascript instead of forcing javascript to act like ruby or python or whatever else.

Fantastic!

  • Comment by: Mislav
  • Posted:
form.myCustomMethod(); // ==> Wow! Just like Prototype!

Sorry but I couldn’t help myself ^^

Again I must congratulate you. The code is a bit unreadable, but I like how it was all done; there’s strong JavaScript-fu in there!

+1 for moving it to Google Code

  • Comment by: Mislav
  • Posted:

David said:

I think it’s safe to assume that if a user binds the document they’ll want the same functionality for newly created nodes that exists for all already existing nodes.

I think you’re right.

  • Comment by: -dean
  • Posted:

[...] Dean Edwards has built a really nice JavaScript library intended (maybe not intended? I’m not too sure what the bigger picture here is) to fix and expand on the current DOM where needed. What’s most exciting here is the implementation of the DOM Level 3 Core Selectors API. It’s only 20kb when compressed so definitely worth using, and has none of that fancy shit that other libraries do (don’t know why, but I just don’t like it all. reminds me of <blink>). [...]

Gold!

Are you thinking of replacing the selector engine in your IE7 library with this one?

IE7 0.9.1? ;-)

This is very exciting! Another vote for the Google Code project.

  • Comment by: adriand
  • Posted:

Great work as always, Dean.

Two quick notes about your selector benchmarks:

  1. (1) You have Prototype failing on “#test-data span:nth-child(0n+3)” — it was pointed out on the prototype-core mailing list last week that I’d screwed up the “an+b” logic. The SVN trunk (and soon 1.5.1 final) will fix this.
  2. (2) You also have Prototype failing on two uses of “:not,” both of which are actually invalid selectors. Only a “simple selector” (i.e., one token) can be used as the argument within “:not.” (Which means Prototype can take a shortcut and not start a new instance of Selector for the “:not” clause.)

That’s all. The benchmark numbers themselves are 100% accurate. :)

@Andrew:

A simple selector is either a type selector or universal selector followed immediately by zero or more attribute selectors, ID selectors, or pseudo-classes, in any order.

http://www.w3.org/TR/REC-CSS2/selector.html#q2
  • Comment by: -dean
  • Posted:

@Dean: Damn. Now I know what I’ll be doing tomorrow evening.

Great stuff :-)

I like to second the question about using the Selector code in the IE7 script. I hope it does not involve too much snipping around in its guts, I hacked around my copy of the code a bit.

A minimal drop-in replacement would be way cool and make for some very happy people :-)

  • Comment by: Martin
  • Posted:

Great! Dean is always close to standard! Maybe those selector projects will follow this in one or two months.

  • Comment by: linb
  • Posted:

Hello Dean, after using your packer for quite some time now, i must say that it is very exciting to see this being build upon standards. I didn’t even know there was a W3C standard for selectors, and now i am wondering why nobody else all ready made this!

There has been a lot to do about selector speeds.Through the push of jQuery, MochiKit, Prototype, and behavior.js and DomQuery, we are seeing boundaries tested and built upon. Everybody is beating everybody each time they release a new version of their library.

I was wondering if you guys even talk to each other to combine your work into 1 universal selector library. I mean; I see John of jQuery here, and Andrew Dupont which contributes to Prototype. Why not create something like the OpenAjaxAliance.. Create 1 universal way of selecting elements.

For instance; If i want to combine your code with jQuery and also use Ext-JS.. I than have basicly 3 different selector engines, which only add to the size of the library’s used.

Maybe it would be a good idea to make the other library’s compatible with each other to make the selector engine underneath inter-changeable.

Very nice work ! And +1 for “OpenAjaxAliance”. Having multiple JS frameworks is a good thing for sure, but agreeing on some common low-level features such as selectors, inheritance, etc. (hence creating a de facto standard for JS developers on these points) would be a good point IMHO. Dean, John, Mislav, Andrew… What do you think ?

  • Comment by: Romain
  • Posted:

Good job Dean. Not simply another javascript library!

  • Comment by: Bleyder
  • Posted:

Dean Edwards zeigt erste Teile von base2 – base2.DOM Wenn jemand wirklich selten bloggt, dann ist das Dean Edwards. Wenn dann aber jedesmal etwas so geiles dabei rauskommt wie dieses mal, ist das schon OK Dean arbeitet offensichtlich an einer neuen Version seiner Base-Klasse auf der z.B. auch die Mootools

  • Trackback by: web output
  • Posted:

[...] Full Article [...]

I am going to release a new version of IE7 with faster selectors. The main complaint about IE7 is speed so hopefully this will solve that problem.

@Romain – Yes JS library authors do talk to each other! I don’t think we should merge our libraries just yet as competition seems to be driving innovation. There is some co-operation already, witness the jQuery/Ext cross-over.

  • Comment by: -dean
  • Posted:

Am I the only one that finds it humorous that with all the libraries available that the DOM Query Speed Test has available to it that it still uses an inline onclick attribute on each of the button elements? :)

  • Comment by: Brian LePore
  • Posted:

[...] http://dean.edwards.name/weblog/2007/03/yet-another/ [...]

Instead of a single unified library worked on by everyone, I would like to see a single unified API that all libraries implement. I don’t care what the API is. Maybe it’s $(‘#id’).addClass(“myclass”). Fine. Let every library implement these “standards” in their own way, still encouraging innovation and competition in the best way to implement things. But then, moving from lib to lib would not be painful, and the world would not be so overwhelmed by js libraries.

  • Comment by: Matt Kruse
  • Posted:

@Brian – I deliberately avoided using any library methods in my speedtest script. Trying to be neutral. :-)

@Matt – that is why I settled on existing standards for my API.

  • Comment by: -dean
  • Posted:

Wow, that’s an amazing work!

+1 for making it a code.google.com project, I’m going to add it to my js toolbox as it will really save me a lot of time (and headaches, given my js skills) since I was going to cook up a small library on my own, using some “must have” script from around the web (like you onload solution, or enumerable), but this is really a masterpiece and I love the “standard” approach you’ve taken.

Just out of curiosity, what do you think of adding some additional methods to HTMLElement?

- show/hide/toggle to change the display style of a element - remove to remove the element from the DOM - insertAfter/update/append/insertBefore/…

Are them standard enough?

I think they are really useful when dealing with the DOM and I must admit that I’ve felt in love with them after using jack slocum’s excellent yui-ext library (the Element class) so having them available on every HTMLElement would rock, but given your last example I could easily add them myself ;-)

Another things I can’t live without is (yet again) DomHelper from yui-ext, but I don’t think something like this belongs to your library.

Finally, just of curiosity, what’s the performance impact of using only the match* methods? for example it seems that matchSingle(‘#test’) is slower than getElementById(‘#test’) at least for base2 that takes 1.0 ms while DomQuery and dojo are doing it in 0.0 ms.

Thanks again and keep up the excellent work!

Ciao Michele

PS What about matchOne and matchMany? I think they sound better than matchSingle and matchAll, but I know this is really a matter of personal taste. :-D

PS2 Sorry if you get a double post, I’ve posted a comment some hours ago but it doesn’t show up, maybe I forgot to *really* post it after the preview step.

  • Comment by: michele
  • Posted:

Dean, just a heads-up: your selector benchmarks page doesn’t work in Safari. (It also takes like one million seconds to load.)

@Andrew – Thanks. I’ll check that out. I’m thinking of taking down that test page anyway. It almost kills Firefox loading so much code. It loads huge files for Dojo and YUI and I don’t know how to cut down on the file sizes of those libraries.

  • Comment by: -dean
  • Posted:

Dean,

Wouldn’t hosting the libraries on different hostnames speed up the speed test slightly? I believe browsers can only download between 2-4 objects per hostname at once, but can download from multiple hostsnames at once (I think there is a limit of 4 concurrent connections, but don’t quote me).

Just awesome! You deserved being dugg! :)

Dean, feel free to grab smaller packages for Dojo and YUI from my benchmark page for Prototype.

Fricking genius. I’ve spent years trying to learn JavaScript on and off. I haven’t seriously tried to use any of the libraries, but they all looked a bit like I’d have to learn a reasonable amount of alternative syntax. I’d rather use my existing knowledge, but avoid cross-browser nastiness. This looks like my kinda thang.

  • Comment by: pauldwaite
  • Posted:

D’oh!

Please, forget my request regarding hide/show/toggle, these already doable (and in a cleaner way) using addClass/removeClass/hasClass and an css class that sets the display/visibility property. ;-)

  • Comment by: michele
  • Posted:

[...] Dean Edwards has come out with what he calls Yet Another JavaScript Library Without Documentation. This library doesn’t do anything interesting like script.aculo.us or jQuery. It only does standards. But if you build on standards in the right way, you can help future-proof your scripted pages. [...]

At last! A JS library I might actually consider using :) No bizarre syntax to learn, no strange perversions of JS into some other language’s idioms, no documentation to read. A library that understands how the ultimate purpose of libraries is to become redundant ;)

I’m seriously glad to see you’re supporting IE5.0 these days no one does. Thanks!

  • Comment by: manuel
  • Posted:

A library that understands how the ultimate purpose of libraries is to become redundant.

brothercake

Yay! You understand! :-) I don’t want to add to the API madness. I dream of the day when this library becomes obsolete.

  • Comment by: -dean
  • Posted:

@michele – I added addClass/removeClass/hasClass to HTMLElement because I consider that most stylistic changes should occur unobtrusively using className. I don’t really want to mess with the style object at all in this (or in any other) library.

  • Comment by: -dean
  • Posted:

[...] Dean Edwards’ base2 – Yet Another JavaScript Library Without Documentation Because this library is standards-based it means that you don’t have to learn a new API. It uses standard DOM properties and methods throughout which also means that I don’t have to write any documentation. (tags: JavaScript) [...]

It seems to me that you’re now doing object detection for the addEvent logic which once you ditched. (I’m interested in the reason as I’m also trying out a better (?) addEvent for my humble EventS lib.)

[...] Дин Эдвардс на днях опубликовал очень многообещающую разработку. [...]

Dean,

great stuff. Please make this a project at code.google.com.

I just played around with events in IE in humble hope to see event capturing supported, but you know it isn’t. Do you plan anything in this direction ? I know this might be hard to implement, since it effectively means to recreate the whole dispatch logic.

  • Comment by: unl
  • Posted:

@unl – oops I seem to have broken the event handling in IE. I’ll re-release the code later today. Sorry!

  • Comment by: -dean
  • Posted:

[...] Dean Edwards: Yet Another JavaScript Library Without Documentation (tags: javascript library dom programming) [...]

Damned, I want a jQuery plugin to use these fast selectors with it ! ;-)

  • Comment by: Baptiste
  • Posted:

Is this still released under a CC licence? If you put it on Google Code, will you dual licence it?

It looks very cool! I didn’t know there was a W3C standard for selectors.

  • Comment by: Dannii
  • Posted:

@Baptiste – John will speed up jQuery soon — he’s good like that. :-)

@Danni – It will be MIT license.

@Everyone – if you downloaded the code in the last two days then you need to re-download. There was quite a bad bug in the first release which meant that events weren’t being fired for IE.

  • Comment by: -dean
  • Posted:

Awesome work, Dean. I have always been a fan of your standards based approach, and this is just what the doctor ordered.

It will be very helpful to freshers, as they needn’t go through the same browser compatibility issues we faced. And since this is standards based, its all the more better.

  • Comment by: Saleem
  • Posted:

[...] Previous post: ← Yet Another JavaScript Library Without Documentation [...]

[...] I wrote this about six months ago before starting work on base2. I decided not to post it at the time as I thought it sounded a little pompous. On reflection, they aren’t bad rules and I managed to stick to them. So, here the rules I wrote for myself way back in October. [...]

Can I request the feature of some *STANDARD* property/method, such as event.pageX in next version? thanks.

  • Comment by: Realazy
  • Posted:

[...] Es gibt da draussen Lösungen verschiedenster Ausprägung: Tuning der Kernfunktionalität (Objekte, DOM, Event handling, XMLHttpRequests: z.B. prototype, jQuery, base2), UI bezogen mit und ohne Widgets (z.B. script.aculo.us), YUI), Spezielle Aufgaben (Lightbox, JSJaC) oder aber umfangreiche Lösungen, die eine möglichst große Bandbreite abdecken (Dojo toolkit, prototype + script.aculo.us). [...]

Dean,

sorry to bother again, it’s just that events are fired in IE, but DOM 2 event capture doesn’t work (since IE has its own, broken understanding of things). Below a snippet for illustration:

base2.DOM.bind(document);
document.addEventListener(
        "DOMContentLoaded",
        function(event) {
            document.matchAll("tr").forEach(function(element) {
                element.addEventListener("click",
                        function(e) {
                            alert("captured for " + e.target.id);
                        },
                        true);
            });
            document.matchAll("tr > td").forEach(function(element) {
                element.addEventListener("click",
                        function(e) {
                            alert("at target " + e.target.id);
                        },
                        false);
            });
        },
        false);

When you run this against a document containing a table, you should get two alerts when clicking on a table cell: first “captured for …”, second “at target …”. Works in all browsers except for IE. Furthermore, IE’s event object does not conform to DOM 2 (missing currentTarget property etc.).

So the bottom-line is: Are you planning to improve this, maybe by starting a project at code.google.com or sourceforge.net which might help to join forces ?

  • Comment by: unl
  • Posted:

It looks great. Thank you Dean for such a contribution for the humanity. ;-)

I will try it soon in replacement of Prototype. Still I will have too keep the reference of Prototype because of Scriptaculous. Is there any project of an effects library using base2?

  • Comment by: eddy
  • Posted:

Wow Dean,

Amazing stuff.

I’m really impressed.

[...] 如果说ppk是浏览器的测试专业户,那么Dean Edwards就是浏览器的技术解决专业户。自从出了一批成为众多框架/库的参考,如IE7, cssQuery, Base等,沉寂了一段时间,终于,有新料放出了:base2.DOM。 [...]

@unl – I should probably make it clear that this particular bug is not fixed. TBH, I have no idea how to fix it.

  • Comment by: -dean
  • Posted:

[...] Dean Edwards: Yet Another JavaScript Library Without Documentation “This library doesn’t do anything interesting like script.aculo.us or jQuery. It only does standards. But it is my belief that if you build on standards in the right way, you can help future-proof your scripted pages.” (tags: base2 dom javascript) [...]

Dean, as always thank you for the new code, it’s amazing to see the amount and quality of work you put for free in the hands of javascript developers. Your efforts are really appreciated by the comunity. I am going to swap my current events with your code and let you know.

Good work Dean. Finally, the beginnings of an true unobtrusive library!

@unl I’ve ran across the same bug.

Aside from that, there seems to be issues with getElementsByClassName. According to the proposed specs, getElementsByClassName should expect either a string (single class name) or an array of classes. Right now the function seems to be always expecting an array object.

Also per the specs:

A call to getElementsByClassName(['ccc', 'bbb']) would only return one node, however…

An array of class names should return only the nodes that have all specified classes. base2 returns either/or, it looks like.

And for the life of me, I can only seem to get the function working with document.getElementsByClassName. Calling element.getElementsByClassName always returns an error.

@unl if you can use setCapture/releaseCapture for IE you are half a way… I personally use that for dragging IFRAMES as fast as possible on IE.

@Dean it would be nice to have this used in some way so please don’t throw away the “useCapture” argument. Unfortunately in IE “capturing” only works on mouse events but that’s enough for most practical use.

I am not sure this should be in your YAJLWD, or the user should provide a workaround them self from their code by using these IE only native methods. That highly depends on how many are using these features. However in the IE addEventListener something like this will allow for more IE feature being used:

if ( element.nodeType  == 1  && /mouse/.test(type) && useCapture ) {
   element.setCapture(); // element.releaseCapture() is the companion
}

This can be done outside of the library in @unl example, though in the case of ‘click’ events the code must reset the setCapture from inside the event handler for each click, or, as an alternative, do that by using the ‘onlosecapture’, another specific IE event.

the only javascript library i’ll ever use: http://dean.edwards.name/weblog/2007/03/yet-another/

Andrea Giammarchi had done some of this goodies before, in JSL, i think you should ask him his source, there are some errors that we already found in the past that are already corrected..see apply .. Ask Andrea for the source it should have a brand new one (we follows the standards) Regards.

[...] That hasn’t stopped him from creating Yet Another JavaScript Library Without Documentation™. But this isn’t a big full-featured library along the lines of jQeury or YUI. Instead, this works more along the lines of Dean’s famous IE7 script: it’s a patch for current browsers. For example, it fixes Internet Explorers buggy implentation of getAttribute and setAttribute. It also fixes broken browser implementations of the event handling addEventListener method: So, as you can see, it doesn’t do much. But what it does, it does consistently across a lot of platforms. [...]

this script work everywhere..except IE:

base2.DOM.bind(document); onload=function(){ var para1 = document.getElementById(“pippo”); /* using this don’t work in opera var para1 = document.matchSingle(“#pippo”); */ para1.setAttribute(“style”,”display:block;border:1px solid gray;width:100px;”); }

i’ve include the legacy file.. please take a look at http://mykenta.blogspot.com/2006/07/standardise-ie-setattribute-part-2.html

[...] Eingetragen in Allgemein von malte am März 26th, 2007   base2 scheint doch mal eine vernünftige JavaScript-Bibliothek zu werden…:-) [...]

For the HTML attributes to get around IE bugs, there’s a few missing.

Was:

$htmlAttributes: “colSpan, rowSpan, vAlign, dateTime, accessKey, tabIndex, encType, maxLength, readOnly, longDesc”

Needs: ‘frameBorder’ (for un-setting default 3D inset border ‘frameborder’ in IE for iframes) ‘className’ (not sure how you handle this, but foo.setAttribute(‘class’ = ‘…’); works in all but IE… the className is req’d to make IE behave.) ‘htmlFor’ (if you want to set the ‘for’ attribute, on a label element) ‘cssText’ (if you want to set the ‘style’ attribute, on any element in IE) ‘cellPadding’ (for table cells ‘cellpadding’) ‘cellSpacing’ (for table cells ‘cellspacing’)

Otherwise, a nifty little library!

  • Comment by: steve
  • Posted:

@kentaromiura – You still can’t set the attribute style. I would have to write a specific fix for it. Is it necessary though? Does anybody really set the style attribute like that? I don’t want to bloat the library for edge cases.

  • Comment by: -dean
  • Posted:

@Diego – yeah, I’m going to look into providing some capture support. I didn’t know there was an onlosecapture event. Thanks!

@Steve – thanks! I’ll update the code.

  • Comment by: -dean
  • Posted:

On link I provided i use cssText to fix style on IE and others fixes. I think that setAttribute and getAttribute are 2 basic function for everything else, and probably they need a big library only to fix these 2 functions (without fixing at 100%, I think is impossible). think at libraries like innerDom and dombuilder, they heavily use these functions..to replace innerHTML.. You are just asking me the “Big question” Speed or Compatibility?

;) the mine was only a suggest, i don’t pretent nothing, but seeing the #79 there are lots of cases out of consideration(untested).tomorrow i do a stress test, now i don’t have time to look at an undocumented library ;)))))

[...] What is happening now is an explosion of different libraries that all do similar things in different ways.  Of course, I am a staunch support of jQuery.  It’s ease of use make it the perfect tool for html/css developers like me.  But there have been all kinds of new libraries out there.  Recently Dean Edwards, who is famous for his HTML/CSS ad JS expertise released a library called Base2.  He is a big fan of jQuery, but apparently wanted to build his own. [...]

@Dean,
the following are a couple of extra W3C properties I tried to fix in your addEvent function, hope they can be included/fixed in the new events in the library:

    function fixEvent(event) {
        event.currentTarget = this;
        event.target = event.target || event.srcElement;
        event.eventPhase=event.target == event.currentTarget ? Event.AT_TARGET : Event.BUBBLING_PHASE;
        if (event.target && (/3|4/).test(event.target.nodeType)) {
            event.target = event.target.parentNode;
        }
        if (!event.relatedTarget) {
            if (event.type == 'mouseout') { event.relatedTarget = event.toElement; }
            if (event.type == 'mouseover') { event.relatedTarget = event.fromElement; }
        }
        event.preventDefault = fixEvent.preventDefault;
        event.stopPropagation = fixEvent.stopPropagation;
        return event;
   }

I am not completely sure about the way I coded the “currentTarget” and “eventPhase” properties, handy to have, also rarely used in my projects. The Event.AT_TARGET and Event.BUBBLING_PHASE constants are missing in IE so must be declared.

@Diego – thanks. I definitely want to add support for my event properties. I left a note in the source code to remind me. Your code is a good starting point.

  • Comment by: -dean
  • Posted:

@dean,

I toyed around with your getElementsByClassName function to get it to conform closer to the proposed spec, here's what I came up with:

getElementsByClassName: function(node, classNames) {
	if (typeof classNames == "string") {
		if (classNames.indexOf(" ") != -1) {
			var newClassNames = [];
			var split = classNames.split(" ");
			for (var i = 0; i < split.length; i++) {
				newClassNames[i] = split[i];
			}
			classNames = newClassNames;
		}
	}
	if (typeof classNames == "object") {
		classNames = classNames.join(".");
	}
	if (classNames == "") return 0;
	return this.matchAll(node, "." + classNames);
}

Given the following XHTML fragment:

<div id="example">
 <p id="p1" class="aaa bbb"/>
 <p id="p2" class="aaa ccc"/>
 <p id="p3" class="bbb ccc"/>
</div>
document.getElementsByClassName("aaa") // returns a NodeList with p1 and p2
document.getElementsByClassName(["ccc", "bbb"]) // returns p3
document.getElementsByClassName("ccc bbb") // returns p3
document.getElementsByClassName("aaa bbb ccc") // returns 0
document.getElementsByClassName("") // returns 0

Of course, you might want to implement it differently, but there it is for reference. The only thing left is the element.getElementsByClassName bug.

This is pretty cool stuff. I am dreaming of a server-side delivery vehicle that will allow slicing a JS library into “as-needed” pieces, based on URL in the src attribute of the script element. This library looks as close as it gets for a perfect fit for this type of thing.

@unl, the IE behavior in the example you submitted is fixed in this test-case: Capturing Events.

As I said above I should add the “onlosecapture” feature to my events, I was also missing that, also if you look at the sources you will see I had used another method to achieve the same result “EVENTS_FIFO=true/false”.

Hope Dean can also pick up something interesting for his new events emulation.

@unl,
I have to do a step back…
As Dean said, I realized it’s not an easy task to do exactly the same specified in your example on IE.

I am using the IE “setCapture” method to drag elements with the “mousemove” event but it is not the same thing. As I said it seems that the “onclick” event (mousedown then mouseup) makes so that the element is disengaged from the capture and somehow it have to be reset. I tried with the “onlosecapture” to reset it but anyway I could not exactly mimic what you asked. I can just fire once in the capture phase, probably not enough.

It seems to me that the “click” event is not bubbling up to the parent element after a capture has been set on it, also some scarce Microsoft documentation seems to state the contrary (but probably only for mouse(move|over|out) and not for “clicks”.

Sorry for stating something still uncertain about capturing.

I realize that using attachEvent causes problems with the ‘this’ keyword and with memory leaks. Are there any additional reasons for avoiding it in event handling?

The reason why I ask is that it is possible to avoid those 2 problems with attachEvent, so I am wondering if there are deeper reasons involved.

  • Comment by: Eric Gerds
  • Posted:

@Eric,
the first other two reasons that I know about avoiding “attachEvent” that come to my mind are:

1) events are not fired in the order they where set (not in the reverse order either!!!)
2) it is difficult to “detachEvent” if you don’t use function references, so anonymous function will not be detached.

Those two extra problems (and the two you described) should be solved with this event manager. Also I have not written any documentation yet.

You can select to work with “Event Registration” or “Inline Event” models, and also select if you want to run your handlers chain in a first-in or last-in way (the latter you can do even runtime). You can add events directly or through a listener wrapper (the preferred way). Events are removed cleanly and there shouldn’t be memory leaks that I am aware of.

Well Dean, as always using your blog for extras…hope not to break the limits. :-)

I am thinking of renaming this blog to diego.perini.name. ;-)

  • Comment by: -dean
  • Posted:

@Diego, make sure your ‘this’ keyword in your event manager is actually pointing to the element.

BTW, the ‘this’ keyword has two problems with it for IE.

A) attachEvent causes ‘this’ to point to the window object

B) When you use obj[] = handler and then execute obj[]() the ‘this’ keyword is fixed, EXCEPT for the case where obj = window/frame in Internet Explorer. In that exception, the ‘this’ keyword misbehaves.

Namely, let handler = function(){ alert( (this==window) + “\n” + (window==this) ) }

and use addEvent(window, “load”, handler)

  • Comment by: Eric Gerds
  • Posted:

Neat. I just realized there is a much simpler way to fix the ‘this’ keyword for IE.

for (x in handlers){ handlers[x].call(obj, e); // addEvent(obj, type, handler) };

call() does not work in IE 5, but it does work in IE 5.5. This trick appears appears to make ‘this’ work even when obj = window.

Can anyone else confirm for Safari?

  • Comment by: Eric Gerds
  • Posted:

Well, I got the handler[x].call(obj) trick to work completely in my own script now.

Thanks for the tip Diego!

Even though my own little hack worked, I think using .call() is more elegant and requires slightly less code.

  • Comment by: Eric Gerds
  • Posted:

[...] Dean Edwards has written base2, which he calls Yet Another JavaScript Library Without Documentation.. Don’t let that fool you. [...]

Awesome!

This is so the way to go. I totally support the idea of sticking to the specs rather than trying to make JavaScript act like other languages (i.e. Ruby), which just adds to the conceptual overhead of developing applications.

You’ve implemented the W3C features I always wanted to use but didn’t expect to work for a long time. Nice one!

  • Comment by: Adam Bones
  • Posted:

[...] unknown wrote an interesting post today onHere’s a quick excerptBecause this library is standards-based it means that you don’t have to learn a new API . It uses standard DOM properties and methods throughout which also means that I don’t have to write any documentation. … [...]

[...] It [the base2.DOM library, Red.] feels right because: [...]

[...] Podéis ver el artículo en: http://dean.edwards.name/weblog/2007/03/yet-another/ [...]

Your site keeps crashing my firefox. Great job.

  • Comment by: Name Here
  • Posted:

@Name – If you gave me some more information or at least left a real email address then I could look into it. Great job.

  • Comment by: -dean
  • Posted:

[...] First off, congrats to Jack Slocum on launching ext and Dean Edwards on unleashing base2. It’s great to see solid work pushing things forward in the JavaScript world. [...]

@dean: it seems that I’m too stupid to click “submit” instead of “preview”. “Killed” a rather lengthy comment of mine. To make it short:

change

return attribute && attribute.specified ? attribute.nodeValue : null;

to

return attribute && (attribute.nodeValue != "" || attribute.specified) ? attribute.nodeValue : null;

It catches an edge-case that never appears in FF (and imho WebKit), because of non-standard or gray-area behaviour. They don’t create attribute nodes for “default” attributes (i.e. method=’get’ for forms). IE and Opera do. Don’t know about iCab, but KHTML is likely to do the same as WebKit.

  • Comment by: Grey
  • Posted:

@Grey – There is no need to what you suggest. getAttribute() is only overridden for IE.

  • Comment by: -dean
  • Posted:

@dean: I know it is only for IE. That’s what I was saying… you wouldn’t experience that Problem in FF/WebKit.

//in IE
attr = document.createElement('form').getAttributeNode('method');
alert(attr.value); // => "get"
alert(attr.specified); // => false
  • Comment by: Grey
  • Posted:

@Grey – OK. Gotcha now. Thanks.

  • Comment by: -dean
  • Posted:

[...] base2.DOM: Yet Another JavaScript Library Without Documentation Just what the world needs, another JavaScript library. Because this library is standards-based it means that you don’t have to learn a new API. It uses standard DOM properties and methods throughout which also means that I don’t have to write any documentation. It is part of a suite of little libraries that I’m developing called base2. This is the first library under that umbrella and is called base2.DOM. [...]

@Dean,
great ( for us ;-) ) you have put Base2 on Google Code…
I saw you made several changes and fixes in V12. Was looking into events and appreciate the correction to the “returnValue”, however I am unclear about this line into the $dispatch for loop:

if (event.returnValue === false) returnValue = false;

The case you are looking at is when the event listener does not return a value but set the “event.returnValue” property to false to prevent the default action. Is that correct ?

[...] base2.DOM: Yet Another JavaScript Library Without Documentation Just what the world needs, another JavaScript library. Because this library is standards-based it means that you don’t have to learn a new API. It uses standard DOM properties and methods throughout which also means that I don’t have to write any documentation. It is part of a suite of little libraries that I’m developing called base2. This is the first library under that umbrella and is called base2.DOM. [...]

pars.js@154:

if (attr == "class") attr == "className";
else if (attr == "for") attr == "htmlFor";
attr = format("(e%1.getAttribute('%2')||e%1['%2'])", index, attr);

Did you mispelled the ==?

Otherwise, it has a bug with label[for="something"] in IE. I suggest you to replace with this:

if (attr == "for") {
	attr = format(
		MSIE ? "Element.getAttribute(e%1,'for')" : "(e%1.getAttribute('for')||e%1.htmlFor)",
		index
	);
} else {
	if (attr == "class") attr = "className";
	attr = format("(e%1.getAttribute('%2')||e%1['%2'])", index, attr);
}
  • Comment by: Pusztai Tibor
  • Posted:

Sorry, the file is: /src/base2/DOM/selectors-api/Selector/parse.js

  • Comment by: Pusztai Tibor
  • Posted:

Maybe the else part:

if (attr == "class") attr = format("(e%1.getAttribute('class')||e%1.className)", index);
else attr = format("(e%1.getAttribute('%2')||e%1['%2'])", index, attr);

I stop the spamming… :)

  • Comment by: Pusztai Tibor
  • Posted:

[...] I just made some updates to the base2 source code. There are some bug fixes for base2.DOM and a number of new libraries. For the time being I am only supporting the base2.DOM library. After I have documented the base2 core I will support that too. [...]

your simply the god of javascript standards

I’d pay you, for a project if you have some time

  • Comment by: Xsss4hell
  • Posted:

[...] Dean Edwards: Yet Another JavaScript Library Without Documentation (tags: js Javascript library dom framework web) [...]

I’m curious why document.matchAll() returns a StaticNodeList instead of an array of DOM elements. Was there a reason specifically or some obvious constraint I’m missing? Also, any idea on what document.matchAll() will return in the next generation of browsers? Thanks for the library, we need more devs with your approach.

  • Comment by: Jared
  • Posted:

@Jared – The item() method of a StaticNodeList provides a way for base2.DOM to augment elements on retrieval. This results in faster queries and allows the basic premise of base2.DOM to work. That means that once you have bound the document, so long as you stick with the Selectors API for element retrieval, you can script according to Web Standards.

  • Comment by: -dean
  • Posted:

@dean – It’s the most useful library from ones I know, and so far the only that I decided to use in it’s entirety just the way it is :) Big thanks for that!

However I miss XPath (document.evaluate) implementation for Internet Explorer. XPath is much more powerful than Selectors and as it’s already in native javascript implementation of most browsers it’s probably faster than any Selectors API implementation through javascript. Internet Explorer has as well native support for XPath but through ActiveX object and I saw one script on web which ports document.evaluate for IE. Is there any chance that in near future you’ll implement it in base2 ?

  • Comment by: medyk
  • Posted:

@medyk – IE natively supports XPath for XML but not for HTML. If I implemented XPath support for HTML it would have to use the same query engine as the Selectors API. This basically means replacing one syntax with another, XPath instead of CSS, but without any of the speed improvements of XPath. I’m not sure it is worth it. The base2 framework is very pluggable, maybe someone else can write it? :-)

  • Comment by: -dean
  • Posted:

@dean – few years ago Dimitri Glazkov came up with XPath solution for IE. His script works by importing html nodes into xml document and then getting result nodes through xsl transformation (powered by xpath query) – so it’s not just another query parser :) – anyway Dimitri’s script have some minor and major issues (according to people’s comments) and probably algorithm could be smarter and more efficient.. I was just wondering have you thought about porting this solution to base2 your way :)

  • Comment by: medyk
  • Posted:

@medyk – that’s an interesting idea, I will try it.

  • Comment by: -dean
  • Posted:

I’v got a wrapper on document.createElement, so i can easily bind, but, is there a way you provide a fixed document.createElementNS ?

Thanks !

  • Comment by: project131
  • Posted:

I’ve tried Dmitri’s xpath solution some years ago, from what I remember it was noticeable problems with perfomance

Dean you did an amazing job. The library is really useful and simple which is what I like. getElementsByClassName() is an excellent function, and the platform list is impressing.

  • Comment by: Kevin
  • Posted:

Thinking this was a drop-in replacement for your older Base.js, I simply exchanged them. But my old code using Base.extend() fails. What’s the proper way for doing inheritance in Base2?

  • Comment by: Sebastian Winkler
  • Posted:

@Sebastien – if you only want the Base class then you only need to reference that file:

http://base2.googlecode.com/svn/trunk/src/base2/Base.js

If you use the full base2 library then you should reference the Base class like this:

var MyClass = base2.Base.extend();
  • Comment by: -dean
  • Posted:

[...] To use it you will need base2 and my responder script. [...]

[...] To use it you will need base2 and my responder script. [...]

I would think the following would be easy, but I’m getting an error (Object doesn’t support this property or method) in IE7

base2.DOM.bind(document);
base2.DOM.bind(window);
window.addEventListener('load', function(){cbp.init();}, false);

Any ideas?

  • Comment by: John
  • Posted:

Change your code to this:

base2.DOM.bind(document);
document.addEventListener('DOMContentLoaded', function(){cbp.init();}, false);

Does that help? In the meantime I’ll change the bind() method so that it does not default to Node.bind().

@Everyone, please raise further issues here:

http://code.google.com/p/base2/issues/list

  • Comment by: -dean
  • Posted:

Dean, just a heads-up: your selector benchmarks page doesn’t work in Safari.

  • Comment by: Sahibinden
  • Posted:

@Sahibinden

I tested the selector benchmark with “konqueror 3.5.6″. It worked all fine. Safari und konqueror shares their engine – so the problem may be Mac-specific. What’s with Safari-Beta on Windows? Does anybody test this?

  • Comment by: Guxx
  • Posted:

[...] I’ve finally produced some documentation for base2. It is still incomplete but at least it’s a start. The base2 core is mostly documented now. The core is tiny (6KB gzipped) but includes enough juicy bits to allow me to build something more complex like base2.DOM. [...]

@guxx: I have tested the selector benchmark with the Safari 3 Public Beta for Windows, it works fine. So i also think that the problem must be Mac-specific… I´m not really a Mac-expert, but maybe here is a pro with knowledge …

  • Comment by: Marc S.
  • Posted:

Now you could update this page’s title in “Yet Another JavaScript Library With a Short and Easy Documentation”…

  • Comment by: Alberto
  • Posted:

[...] Reseamos aqu las “10 reglas para los desarrolladores de libreras Javascript”, segn la traduccin de anieto2k del original Rules For JavaScript Library Authors, de Dean Edwards, conocido desarrollador de Javascript y creador de base2. [...]

[...] The application uses the base2 Javascript library to iron out some of the differences between browsers. I like this library because it doesn’t do things for you the way some frameworks do, but it removes a lot of the headaches for developing cross-browser applications (attachEvent vs. addEventListener, anyone?). [...]

Just a question – Are you going to rename matchAll/matchSingle as selectAllElements/selectElement now that these seem to be the ones that have been settled on for the selectors API?

good job Dean,i will introduce ur library face to Chinese person.i has made my first step,u could find a link following:http://www.aspstat.com/77

  • Comment by: Daniel Lin
  • Posted:

[...] I am going to rename the base2.DOM methods to stay in line with the standard. If you are using base2.DOM then this is a heads up. [...]

[...] Plus d’informations sur le blog de Dean Tags: base2.dom, javascript, librairie javascript [...]

Nice javascript library.But it seems there is a problem in IE 7…It gives error.

  • Comment by: Alex De Souza
  • Posted:

Hi Dean,

It seems the http://base2.googlecode.com/svn/trunk/src/base2/Base.js file isn’t usable standalone anymore, it depends on the “delegate” function that isn’t defined in this file. Unless i have misunderstood your comment at, it seems to me it s a bug: http://dean.edwards.name/weblog/2007/03/yet-another/#comment104534

  • Comment by: Max Penet
  • Posted:

@Max – Base.js is no longer standalone. You can still use the original version.

  • Comment by: -dean
  • Posted:

Wouldn’t hosting the libraries on different hostnames speed up the speed test slightly? I believe browsers can only download between 2-4 objects per hostname at once, but can download from

  • Comment by: Charvaka
  • Posted:

This is so the way to go. I totally support the idea of sticking to the specs rather than trying to make JavaScript act like other languages (i.e. Ruby), which just adds to the conceptual overhead of developing applications.

I know what I’ll be doing tomorrow evening…

  • Comment by: Mike
  • Posted:

I’m seriously glad to see you’re supporting IE5.0 these days no one does. Thanks!

@ Kevin

I don’t see many people use IE 5.0.Now everybody uses IE 6.0 and IE 7.0.IE 7 is getting popular day to day.But i only suggest Fireofx.It’s best browser for me :)

  • Comment by: saç
  • Posted:

@Kevin, on my site since 01/01/07 on the 82,514 visits from IE users, only 53 run IE 5.0 and 83 run IE 5.01. So it’s for that no one support IE 5.0 today ;)

  • Comment by: henri
  • Posted:

good job Dean, keep up the your great work. thank you.

  • Comment by: Sedyac
  • Posted:

I know what I’ll be doing tomorrow evening…

  • Comment by: JackRouse
  • Posted:

JackRouse dont spam…

  • Comment by: Sleepy
  • Posted:

[...] Either that, or I could just use Base2. [...]

[...] Come across a Javascript library recommend by Lachlan Hunt (front end guru, participating in W3 working groups as an invited member), here is his blog: http://lachy.id.au/log/ He has his own library but mentioned that he would probably stop updating his own library in favour of this one: http://dean.edwards.name/weblog/2007/03/yet-another/ [...]

[...] base2.DOM is now ready for a beta release. As previously discussed, I’ve renamed the Selectors API methods to keep in line with the standard. [...]

[...] Base2 has just come out in beta on Google Code. It’s hosted there and can be included straight off the Google Code server. [...]

[...] A mechanism for grouping functions and classes. base2.DOM is an example of a Package. I will explain this in more detail in a later blog post. [...]

[...] IE7 is now much faster (it uses the selector engine from base2.DOM) [...]

[...] Voici les améliorations apportées IE7.js : The IE7 project is now hosted on googlecode (I got fed up with SourceForge). IE7 is no longer modular. Instead I’ve merged the scripts into two: IE7.js and IE8.js IE7.js includes only fixes that are included in the real MSIE7 browser. All other enhancements are moved to IE8.js. IE7 is now much smaller (11KB gzipped). IE7 is now much faster (it uses the selector engine from base2.DOM) There are no dependencies on other files (except blank.gif) You can hotlink IE7/IE8.js directly from Google’s servers (usage instructions below) [...]

[...] IE7 ist auch viel schneller (es verwendet die Selektorengine von base2.DOM) [...]

[...] 2007.03.21: base2.DOM. [source] [...]

[...] base2.DOM [...]

In your examples of querySelectorAll(), the element.querySelector(“p:first-child”) code can be written: element.querySelector(“p”) because only the first paragraph is returned for each li element.

If I decided not to support IE5 and prevent it trying to process the code, to prevent an error would you advice an excluding conditional comment or a JavaScript sniff to achieve this? I have not been successful with excluding IE5 with conditional comments and also achieving strict markup validation.

  • Comment by: Billy
  • Posted:

[...] on September 21st, 2008 in JavaScript & DOM by lifesinger 这是base2的作者Dean Edwards 2007年3月份的一篇文 [...]

[...] read more | digg story [...]

[...] 这是base2的作者Dean Edwards 2007年3月份的一篇文 。最近正在折腾JavaScript库,感觉Dean给出的这些规则很中肯,忍不住翻译了下,原文在这里:http://dean.edwards.name/weblog/2007/03/rules/ [...]

[...] que nous sommes chez Dean Edwards , profitez-en pour tester base2 un mini-framework Javascript intelligent (c’est Yves qui le dit sur twitter [...]

Looks like an nice library! Why no documentation thought?

[...] que nous sommes chez Dean Edwards, profitez-en pour tester base2 un mini-framework Javascript intelligent (c’est Yves qui le dit sur [...]

  • Pingback by: Anonymous
  • Posted:

[...] 顺便声明,base2没有更改任何内建的javascript对象。 [...]

[...] base2 – older class library [...]

Leave A Comment

Line and paragraph breaks automatic, email address never displayed. Some HTML allowed.