DOMAss – The DOM assistant
Updated March 2nd 2007
DOMAss now has a new name, DOMAssistant, and it is also possible to run it side-by-side with other JavaScript libraries such as Prototype and jQuery. For more information, please read: DOMAss renamed to DOMAssistant, with added Prototype/jQuery compatibility.
Updated March 6th 2007
Per Zimmerman made me aware of the fact that I wasn’t as consistent when checking for names and whitespace in the addClass
and removeClass
as I am in the hasClass
method, so this has been fixed to address any potential issues you might have had. Just download the DOMAssistantCSS JavaScript file and you should be good to go. 🙂
Updated April 11th 2007
Changed the license to a Creative Commons Deed.
Updated May 11th 2007
Minor fix for strange behavior in IE when using the addEvent
method on the window
object. For more information, please see DOMAssistant fix for addEvent method peculiarity in IE.
Updated July 11th 2007
PDF documentation added, kindly created by Michael Frühmann.
Updated September 20th 2007
Updated October 4th 2007
The DOMAssistantCompressed JavaScript file has been updated. My compression approach was a little too effective for the special DOMReady fix for Internet Explorer, so necessary code for optimal performance was unfortunately removed. This has now been addressed, so please download the new version if you use the compressed file.
Updated October 19th 2007
The DOMAssistantCompressed JavaScript file is updated again. I noticed a problem with the elmsByAttribute
method in IE where the compression resulted in a wrong reference, returning incorrect results. Download the new version and it will be fine.
When I released my EJ code, while I felt that it contained very useful functions, it didn’t feel properly packaged. Also, I’ve always wanted a proper base to stand on for various DOM interaction, so I didn’t have to start from scratch in every project.
So now, I proudly present DOMAss!
DOMAss is short for DOM Assistant, and the idea is to provide a simpler and more consistent way to script against the Document Object Model (DOM) in web browsers. I’ve always felt that the different ways of accessing elements in the DOM and interact with it isn’t always the most logical or practical way, not to mention web browser differences. Being modular and lightweight has also been two very strong demands I’ve had on the library, so to make sure you only use as little code as possible, as opposed to including large libraries where you, in the end, only use 10% of what’s included.
The idea with DOMAss is that everything starts with a desired element, and then performs various methods on it, such as adding/removing classes, finding elements with a certain className
, applying events to it, etc. Basically, you always select an element using the $
method, and then you will perform actions using customized methods applied to it.
Example code
// Get a direct reference to a DOM element
$("id-of-element");
// Get element's child elements with the class of "mandatory"
$("id-of-element").getElementsByClassName("mandatory");
/* Get element's child elements with a "type" attribute
that has the value "text"
*/
$("id-of-element").getElementsByAttribute("type", "text");
// Adds the class "selected" to the element
$("id-of-element").addClass("selected");
// Add a onclick event to the element
$("id-of-element").addEvent("click", functionToCall);
It’s modular!
The strength with DOMAss is that it is completely modular, in that sense that it is only dependent on one single core JavaScript file, DOMAss.js
. That file is only 2.8 kb, and all other modules are optional. Then you can choose to only use the ones you find necessary in your application, and you can easily add your own modules taking advantage of the solid base DOMAss offers. The reasoning behind this is to make the file size usage as small as possible, while at the same time addressing any potential bandwidth issues. The parole is:
Include only what you use.
Different modules are available for various purposes
- DOMAss (2.8 kb)
- The core module for all DOMAss functionality. This one is required, but all other modules are entirely optional.
- DOMAssContent (2.2 kb)
- Offers way to create elements, add, remove and replace content in elements.
- DOMAssCSS (1.6 kb)
- Consists functionality for adding/removing classes from an element, checking if an element has a certain class and to check what rendered style an element has.
- DOMAssEvents (1.7 kb)
- Offering ways to handle events cross-browser, with the ability of seamlessly adding multiple events to the same element. It also consists of methods to remove added events, preventing default event actions and cancelling the bubbling of events.
- DOMAssLoad (1.8 kb)
- Gives you a way to call whatever function/-s you want as soon as the DOM has loaded, without the need of waiting for images, flash movies and other external files to load.
Inspirations
Certain people and their scripts has inspired me in the creation of DOMAss, so I thought it would be fair to acknowledge them for the inspiration they’ve given me:
- The syntax John Resig uses for accessing element and giving them methods in his jQuery library.
- Dean Edwards’ fantastic work with checking for DOM loading and proper adding of events.
PS. I just have to tell you what my friend Henrik though I should name this post: “The only Ass you’ll ever need”. 🙂 DS.
Nice work Robert – looking forward to giving this a test drive!
That is by far the best name for a library ever! Ahaha 😉
I like that name!
Now combine all the file into one file – you got the best library ever.
Those names still haunt me.
Dave,
I hope you'll like it!
Jeroen, pollas,
I'm glad you like the name!
pollas,
Long time, no see! I hope things are good with you!
Binny,
Thanks! But what I really prefer is having separate files, so only what's necessary will be included (as opposed to cutting code in just one large(r) file).
Hi Robert,
A great new add-on to the flurry of frameworks around!
Perfect when a complete framework isn't necessary.
Regarding your <code>getElementsByAttribute</code> method, you might wan't to have a look at the work Andrew and I did on attributes (which is part of Prototype's latest release) as IE's attribute implementation is completely wacky.
Best regards,
Tobie
Great set of methods, Robert! I will study them later in detail, but I can tell already that they will be very helpful 🙂
And by the way: you should have named this article "The only Ass you'll ever need" 😀
Thanks, Robert! I look forward to testing some of these out tonight.
Great idea, by the way.
Cheers!
Played around with it, and found it to be great!!! In fact, this deserves a place in the toolkit for small projects. Why waste my time writing my own when all has been done already? Nice work Robert :)!!!
Very nice stuff ! I was puzzled by the chaining of functions in jQuery, now it's clearer 😉
Just a suggestion : I would shorten some names like "getElementsByClassName" ("byClass" ?) and "getElementsByAttribute" (byAttr ?)… it's such a long type and not really in phase with the "$()" simple style !
Thanks for the great work !
Tobie,
Thanks! Also, thanks for the tip, I need to look into that more closely. IE's attribute handling is indeed weird.
Harmen,
Thank you! And yeah, maybe I should have. 🙂
Matt,
Thanks, I hope you will like it!
Stefan,
I'm really glad to hear that! 🙂
Manuel,
Thanks for the suggestion. I did think of that, but wanted those methods to have the same kind of syntax like real existing DOM methods (like <code>getElementsByTagName</code>, <code>getElementsByName</code>), so there wouldn't be any guessing.
However, if you want to change them in the core JavaScript file for your usage, you definitely have my permission to do that.
While we're proposing alternate post names, I'd like to suggest "Don't be a DOMAss, use this library"
DOMAssLoad is the best name for any piece of code, ever.
this looks great. are there any issues using this alongside prototype, since both make use of the "$" shortcut?
Great idea, I'd been thinking about pulling YUI apart to do something similar, this probably works much better!
Have you done much cross-browser testing? I'm just wondering if anything shouldn't be fed DOMAss…
Scott,
Thanks! Maybe that specific name went a little bit overboard, but I still hope the code will be useful for everyone. 🙂
chris,
As far as I know, that would be the only problem; however, I don't know too much of the spcifics of Prototype.
AlastairC,
Thank you! I've done a fair bit of cross-browser testing, and it seems to work just fine. After all, its foundation is well established ways of interacting with the DOM.
But iuf you, or anyone else for that matter, come across any problems, please let me know and we'll see if I can addres it.
[…] nless using fades and show/hides, etc. I’ve just come across this smaller, modular library DOMAss via 456Berea St.
I think it might be useful for doing the heavyweight D […]
I may ask what’s the point on using this instread of jQuery?
Ok, it’s smaller, but if I have to be lightweight I will design a library ad hoc. Instread, if I’ve to design a “full” featured JS site, jQuery is the baseline of anything else…
Don’t take me wrong, I often “redesign” something just to grasp the inner soul of a problem so I completely understan this, I’m just asking if you – as the author – can see a real usage scenario. 🙂
Folletto,
The reasons I'd say are:
1) Lightweight (as you mentioned).
2) Fully modular. This means that you will only use what you need, with the option of adding on extra functionality or, more importantly, write your own module based upon the DOMAss functionality.
3) DOMAss is for core interaction with the DOM, returning regular DOM references and uses names in the same fashion as already existing DOM methods, making it very easy to understand and use. Basically, you don't need to learn how the library works, but instead, just start using it.
Hi,
isn't your library quite similar to the Microsoft Ajax Library??
Greetings
Stefan
[…] at your website Machine Tags: Tagging Revisited Interviewing 9rules – A Group Interview DOMAss – the DOM assistant How Blogging Really Started Collabor […]
My condolences to the latest victim of frameworkitis.
Stefan,
I have no idea, I've never seen it. I doubt it though, since Microsoft are/have been infamous for their poor script code. They might've changed, though, so I really don't know.
Nice! Seems very similar to MooTools though, maybe because you are inspired by the same sources?
[…] btrusive scripting are very easily thrown out of the window. (tags: JavaScript Toolkits) DOMAss – The DOM assistant provides a simple, consistent way to script against the DO […]
[…] ninguna falta. Robert Nyman ha publicado hace unos dÃÂas una pequeña y ligera librerÃÂa, DOMass en […]
Torkil,
I guess. Many JavaScript web developers nowadays seem to agree about what's best practices.
Hi Robert 🙂
As first point: good work, I like your tiny libs (expecially code inside them)
The second point is a little problem with hasClass function (same problem of EJ) … I suppose a class like "my-header-one" should be a problem with your RegExp, am I wrong ?
<code>DOMAss.hasClass = function (className){
return new RegExp(
"(^|s)".concat(className.replace(/-/g, "-"), "(s|$)"), "i"
).test(this.className);
};</code>
I hope this will be useful.
Regards.
Andrea,
Thank you!
No, it works just fine. The RegExp doesn't look for any certain characters surrounding the class name, other than a space or a start/end of string
For instance, this code works fine;
<code>$("the-header").hasClass("my-header-one");</code>
Cool name…
did you know that in dutch the word 'dom' actually means dumb?
Very nice! Maybe you can compare the functionality with mootools one. Mootools v1.0 is out now. The code-notation seems very similiar.
ciao André
cow,
No, didn't know that. 🙂
André,
Thank you, and thanks for the tip!
Hm, interesting. Will check this out more in-depth! 🙂
But, as others have said, I think it would be a good idea to introduce at least aliases to getElementsByAttribute and getElementsByClassName. I see your argument on keeping with the name conventions of DOM methods, but, you are already "breaking" that by using the $() method which is basically an alias for getElementById. So, how about the aliases $A and $C for getting elements by attribute and class? Obviously not terribly intuitive for newcomers, but that's why I suggest them as aliases, and it would certainly save the advanced users quite a bit of typing.
Of course, it's not that hard to add $A = DOMAss.getElementsByAttribute myself 🙂
Frode,
Yeah, I get the point. But in the end, many people are used to seeing <code>$</code> in other libraries, as opposed to short versions of the other ones.
What you can do is add your own tiny module with your own short names. 🙂
I ported a simple page to your lib to try it out. Works great in firefox but IE6&7 keep giving me an object unsupported method error on the arrowed line because it can't find the addEvent call I'm guessing. Any ideas? Or know if IE has a REAL javascript debugger as Microsoft Script Debugger is next to useless without a view of the DOM tree.
<code>
window.onload = function() {
var aColor = $('colorOpt').getElementsByClassName('color');
for( var i=0; i aColor[i].addEvent('mouseover', colorMouseover);
<code>
— aColor[i].addEvent('mouseover', colorMouseover); —-
aColor[i].addEvent('mouseout', colorMouseout);
aColor[i].addEvent('click', colorClick);
}</code>
Rest of code got clipped for some reason.
Brandon,
The idea is that you always need to call the <code>$</code> method, which in turn will apply all methods to the element in question (if it doesn't already have them).
So, your code should be like this:
<code> $(aColor[i]).addEvent('click', colorClick);</code>
This is due to the fact that it's not possible to dynamically add methods to all elements in a web page in Internet Explorer.
[…] our photoshop document to a CSS in less than 30 seconds CSS Tools and Services DOMAss – The DOM assistant CSS Documentation Shortcut CSS Type Ajax, Javascript […]
Great job, Robert!
I found a little bug (?): $('container').firstChild.remove() won't works, if the firstChild is a text element (Firefox 2). If it's i.e. , there's no problem.
I suggest, to use htmlentities rather than completely delete non-enabled html tags from comments.
So "If it’s i.e. p , there’s no problem. "
I'm a little confused on using the "addEvent".
I know you call it like this:
$("divId").addEvent("click", functionName);
but can you pass parameters to the function like this:
$("divId").addEvent("click", functionName(param1, param2));
I see how to make the parameters issue work with by doing it with a function call as the second parameter like you've shown already:
$(â€ÂdivIdâ€Â).addEvent(â€Âclickâ€Â, function() {
functionName(param1,param2);
});
Joó,
The <code>remove</code> method will probably not work well on textnodes, no. And since IE doesn't even know what a text node is, I'd recommend just trying to remove HTML elements, to be consistent (otherwise you might end up with some weird results).
Also, maybe the <code>prev</code> and <code>next</code> can help ypu find the appropriate element.
Regarding comments: it's WordPress defaults, but as long as you escape it correctly, like this: <, for < it will look fine…
dale,
Yep, you need to use anonymous functions for that.
[…] hotoshop and image ready and that it will take about 30 seconds ? CSS Tools and Services DOMAss – The DOM assistant DOMAss is short for DOM Assistant, and the idea is to […]
Robert thank you so much for this excellent contribution! I find myself just as you do only doing stuff with the DOM. I haven't done any work with fancy effects or Ajax. This is why I plan to leave mootools for this framework. I've used your code before (getElementsByClassName I believe is what I came across from a link on Jon Snook's blog) so I very much look forward to using this and offering any help or plugins I can. Are you open to enhancements, new functionality from the community??
I do have one question though in regards to your $() function. I have a function that highlights a row that contains a focused field in a form. For example I wrap each form element with a div, so if I focus the cursor on an input element I dynamically add a class to the div (parent element) to add a bright background color. Because I'm using the event onclick and onfocus to achieve this, I use the this scope and the parentNode property to work my way up to the div tag so I can add the class. Can I pass an element to the $() so I have access to the other DOMAss functions??
…
fields[i].onfocus = function(){$(this.parentNode).addClass(cl)};
…
Is this doable in your DOMAss framework? Thanks again for your contribution! Looking forward to using it. I'm afraid I'll have to rename it though as I'm sure domass.js will be popular for all the wrong reasons. 🙂 Thanks!
[…] « links for 2007-02-12 links for 2007-02-13 DOMAss – The DOM assistant – Robert’s talk DOMAss is short for DOM Assistant, a […]
Javier,
I'm glad that you like it and find it useful! And yes, you can use DOMAss exactly as in your code example! If you pass an object reference to the <code>$</code> function, it will return that same element but with all the DOMAss methods applied.
Thanks Robert, I will be making a permanent switch to this framework as I only do stuff with the DOM! Although I do have a question you didn't answer but maybe I misunderstood how you are providing this framework. Are you providing DOMAss for all developers to take it as their own and modify it?? Or were you wanting to accept new enhancements for it as plugins (or updates to the already existing files)?? If so please let me know as I have many new DOM functions I'd like to add to DOMAss. Thanks again for all your hard work Robert!
Javier,
Sounds good!
To answer your question: basically, anyone can use it for what they want. If they want to alter it or enhance it, they're welcome to do that as well; the license is just there for me as the author of the code and to avoid anyone else marketing it as their own.
If you want to write more functions to add to it, I think the best way is to post about them here in a comment so anyone can see, or, if that's an option, write a blog post about it and pingback this post.
In the long run, I might add them to the existing modules or as new add-on modules (naturally, with the proper credits then).
[…] SharePoint 2007 CSS Reference Chart (tags: css sharepoint Moss2007 sharepoint2007 moss) DOMAss – The DOM assistant – Robert’s talk (tags: javascript DOM programming) […]
i know in the documentation it says "removeEvent" can only be used with actual functions and not anonymous ones. Is there any sort of work around to this issue?
dale,
Sorry, not as of now. If you’re interested in delving deeper, you might want to take a look at Mark Wubben’s Event Cache.
all it needs is $$ (getElementsbyCssselector ), as a module ? and it will be all i need for smaller projects 🙂
please i'd really appreciated it
and your ajax previewer is totally awesome!!!!
William,
Thank you!
I'm not too big of fan of using CSS selectors in script to access elements; to me, it feels awkward. But one can never tell what the future holds…
[…] arch 2nd 2007 If you like this code, I sincerely recommend that you take a look at the DOMAssistant JavaScript library. The web is littered with full-blown JavaScript […]
Hi Robert, thanks for this – been looking for a lightweight alternative to jQuery for a while now and this fits the bill nicely.. almost :).
Something I use fairly often is the jQuery <code>parents</code> function to find a specific container above a given element. I've tried to roll my own, but i'm no expert when it comes to JS. Here's what i've come up with so far, which I've added to the DOMAssistant.js file:
<code>
getParentByTagName : function(tag) {
var elm = this;
while (elm) {
if (elm.tagName.toLowerCase() == tag.toLowerCase()) {
return elm;
}
elm = elm.parentNode;
}
}
</code>
I'm sure one of you folks will be able to point out where my glaring errors are rather quickly!
Colin,
Interesting. I've only tried it briefly, but this should do the trick:
<code>
getParentByTagName : function(tag){
var elm = this;
var pattern = new RegExp(tag, "i");
while(elm.parentNode && !pattern.test(elm.nodeName) && !/body/i.test(elm.nodeName)){
elm = elm.parentNode;
}
return elm;
}
</code>
Hi Robert,
That works beautifully, I'm using to add classes to form element containers when required fields aren't filled out – it works like a charm.
Thanks for your help.
Colin
Colin,
I'm glad to hear that! 🙂
Thanks for this! Always nice to see another option.
I've been looking for something specific. Namly a script that would allow me to wrap HTML tags around a number of HTML tags that are of a specific class. For instance, I might have this:
[img class="test" /]
[img class="test" /]
[div class="testwrapper"]And would like to, via javascript, end up with this:
[div class="testwrapper"][img class="test" /][/div]
[div class="testwrapper"][img class="test" /][/div]
I see several libraries that allow one to insert HTML inside a tag (ala innerHTML) but finding ones that allow you to wrap HTML outside a tag seem harder to find. It was recommended to be to check out both jQuery and DomAssistant. I did find how to do it with jQuery, but it does involve using jQuery, which is a tad large for this one thing. Can DomAssistant to do this? Looking through the examples, I saw lots of examples of inner-HTML-esque options, but nothing that actually wrapped HTML.
Darrel,
Wow, interesting scenario…
This is just off the top of my head, but i think it will work:
var desiredElms = document.getElementsByClassName("test");
var elm;
var elmParent;
for(var i=0; i<desiredElms.length; i++){
elm = desiredElms[i];
elmParent = elm.parentNode;
var wrapper = $(elm).create("div", {
className : "testwrapper"
}, false, elm.cloneNode(true));
elmParent.insertBefore(wrapper, elm);
elmParent.removeChild(elm);
};
The idea is:
It finds the elements
Clones them
Creates the wrapper
Appends the clone to the new wrapper
Inserts the new wrapper into the DOM before the original element
Deletes the original element
[…] If you like this, you might also be interested in DOMAssistant. […]
@ Darrel,
I had success with something similar by simply changing an element's <code>parentNode</code>. You might try something like the following (untested) bit of code. The first half is the same as Robert's suggestion.
<code>
var testImgs = document.getElementsByClassName("test");
var elem;
for(var i=0; elem=testImgs[i], i<testImgs.length; i++){
var wrapper = elem.create("div", { className: "wrapper" }, false);
wrapper.parentNode = elem.parentNode;
elem.parentNode = wrapper;
}
</code>
@ Robert,
First of all, thanks for sharing DOMAssistant.
I changed <code>getElementsByAttribute</code> a little bit because I needed partial matching of the attribute values. Here's the code, in case you find it interesting/useful:
<code>
getElementsByAttribute : function (attr, attrVal, tag, partialMatch){
var elms = ((!tag || tag == "*") && this.all)? this.all : this.getElementsByTagName(tag || "*");
partialMatch = (partialMatch ? ".*" : "");
var returnElms = [];
if(typeof attrVal != "undefined"){
var attrVal = new RegExp((partialMatch || "(^|s)") + attrVal + (partialMatch || "(s|$)"));
}
…
// the rest of the method is not changed.
}
</code>
Needless to say, this could give you way too many matches, but I thought it wouldn't hurt to share.
Alejandro,
Thanks for sharing! It's always good to have different versions for possible alternate scenarios.
[…] DOMAss – The DOM assistant DOMAss is short for DOM Assistant, and the idea is to provide a simpler and more consistent way to script against the Document Object Model (DOM) in web browsers. […]
know in the documentation it says “removeEvent†can only be used with actual functions and not anonymous ones. Is there any sort of work around to this issue?
Katalog,
No, sorry. This is due to the default behavior and implementation of events in web browsers. Please see my comment above for an alternate solution.
DOMAssistant.DOMReady(addEvents);
function addEvents() {
if($("formContact")) { alert('q'); }
$("formContact").addEvent("submit", validateContact);
}
——-
Why is the onsubmit event is not added to "formContact" ?
Peter,
It seems like you have used an invalid character for apostrophes in your code (or the WordPress commenting system mangled it). Either way, this code below works fine:
DOMAssistant.DOMReady(addEvents);
function addEvents() {
if($("formContact")) {
alert('q');
}
$("formContact").addEvent("submit", validateContact);
}
function validateContact(){
alert("Validate");
}
[…] 25th 2007, I released something I fondly nicknamed DOMAss, which step by step evolved into the today full-fledged DOMAssistant. Today, it is time to let it […]