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

DOMAssistant 2.0 released!

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:

 

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.
Posted in Developing,DOMAssistant,JavaScript,Technology |

70 Comments

  • Dave Child says:

    Nice work Robert – looking forward to giving this a test drive!

  • That is by far the best name for a library ever! Ahaha ;-)

  • pollas says:

    I like that name!

  • Binny V A says:

    Now combine all the file into one file – you got the best library ever.

    Those names still haunt me.

  • Robert Nyman says:

    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).

  • Tobie Langel says:

    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" :D

  • Matt Sanders says:

    Thanks, Robert! I look forward to testing some of these out tonight.

    Great idea, by the way.

    Cheers!

  • Stefan Van Reeth says:

    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 :)!!!

  • Manuel Catez says:

    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 !

  • Robert Nyman says:

    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.

  • Scott N. says:

    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.

  • chris says:

    this looks great. are there any issues using this alongside prototype, since both make use of the "$" shortcut?

  • AlastairC says:

    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…

  • Robert Nyman says:

    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. :)

  • Robert Nyman says:

    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.

  • Stefan Walther says:

    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 [...]

  • Reinis says:

    My condolences to the latest victim of frameworkitis.

  • Robert Nyman says:

    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.

  • Torkil says:

    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 [...]

  • Robert Nyman says:

    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.

  • Robert Nyman says:

    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>

  • cow says:

    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é

  • Robert Nyman says:

    cow,

    No, didn't know that. :-)

  • Robert Nyman says:

    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 :)

  • Robert Nyman says:

    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. :-)

  • Brandon says:

    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);

  • Brandon says:

    <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.

  • Robert Nyman says:

    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 [...]

  • JoÃ&Aci says:

    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.

  • JoÃ&Aci says:

    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. "

  • dale tan says:

    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));

  • dale tan says:

    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);

    });

  • Robert Nyman says:

    JoÃÂ&sup3;,

    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: &lt;, 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 [...]

  • Javier Julio says:

    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 [...]

  • Robert Nyman says:

    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.

  • Javier Julio says:

    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!

  • Robert Nyman says:

    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) [...]

  • dale tan says:

    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?

  • Robert Nyman says:

    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!!!!

  • Robert Nyman says:

    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 [...]

  • Colin Mc Mahon says:

    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!

  • Robert Nyman says:

    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>

  • Colin Mc Mahon says:

    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

  • Robert Nyman says:

    Colin,

    I'm glad to hear that! :-)

  • Darrel says:

    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.

  • Robert Nyman says:

    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. [...]

  • Alejandro Moreno says:

    @ 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.

  • Robert Nyman says:

    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?

  • Robert Nyman says:

    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.

  • Peter says:

    DOMAssistant.DOMReady(addEvents);

    function addEvents() {

    if($("formContact")) { alert('q'); }

    $("formContact").addEvent("submit", validateContact);

    }

    ——-

    Why is the onsubmit event is not added to "formContact" ?

  • Robert Nyman says:

    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 [...]

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>