New in Prototype trunk: DOM builder

by Mislav | May 12th, 2007

There is no rest for the Prototype core team. Immediately after we pushed version 1.5.1 out, great changes continue to incubate in our experimental SVN branches, and some of those have recently made their way into trunk. Here's a look at one such change that will make creating DOM nodes simpler in the next release of Prototype.

Recently the DOM part of the framework has received much love from Tobie Langel, who hacked around the DOM branch a lot to provide us with great new features for the next release.

Today's highlight is that now you can create a new HTML element like this:

var form = new Element('form', {
                         action: "/user/create",
                         method': "post"
                       });
//-> <form action="/user/create" method="post">

That's right -- you can specify both the element and its attributes in a single call! So, you've got your own minimal DOM builder right here. Naturally, this is entirely cross-browser since it maps the attributes to correct properties internally. You can even do this in IE without tears:

new Element('input', { name: "user", disabled: true });
//-> <input name="user" disabled="disabled" />

Experienced coders will remember that Internet Explorer doesn't allow the name attribute to be set in a normal way. Well, we worked around that, too. This also demonstrates how boolean true as an attribute value results in repeating its name inside the value (disabled="disabled"), which is a convention of XHTML.

The Element constructor demonstrated here sets attributes by using a method that's also new: Element#writeAttributes. We should also mention that the constructor is optimized for speed when creating multiple instances of the same type. Using document.createElement() a lot to create nodes you will later manipulate with Prototype? You should use the Element constructor instead.

This, folks, is currently in the trunk, but you can check it out with SVN (instructions) and use anytime. You can also download this development build if you want to skip the SVN process. Big thanks to Martin Ström and Tom Gregory for inspiring this and helping it happen. Also thanks everyone participating in the discussion for helping us make Prototype a better library!

Comments

  1. Pierre Quillery #

    Awesome ! Thanks a lot for everything, I’ve been using Prototype for a few weeks and I’m beginning to find PHP a little boring :p Can’t wait for that new final version to be released !

    May 12th, 2007 @ 04:22 PM
  2. anty #

    Great news! Until now I was using the scriptacolous Builder. I can’t wait to see this released officially!

    May 13th, 2007 @ 01:10 AM
  3. anty #

    How will you enable the use of the attributes “for” and “class”? script.acolo.us uses htmlFor and className as a alternative. Do you have a better solution, or will you do the same?

    May 13th, 2007 @ 01:21 AM
  4. Tobie Langel #

    anty,

    You can use either for or htmlFor, class or className.

    Here’s my suggestion:

    Use class (or for) when setting one attribute only, e.g.:

    $(element).writeAttribute('class', 'vcard');

    and use className (or htmlFor) when passing a hash of attributes:

    $(element).writeAttribute({
      className: 'vcard',
      title: 'My contact details.'
    });

    Note that you can still use class (or for) in that case, but you’ll have to surrround it with quotes like so (Safari will choke otherwise):

    $(element).writeAttribute({
      'class': 'vcard',
      title: 'My contact details.'
    });

    This obviously also applies for new Element(...).

    May 13th, 2007 @ 02:33 AM
  5. Eimantas #

    How will it differ from scrip.aculo.us Builder.node()?

    May 13th, 2007 @ 03:32 AM
  6. Kim Joar #

    Thanks!:) Have had my share of cross browser troubles on this before, so nice to see it become a part of Prototype. Looking forward to the new final version.

    May 13th, 2007 @ 09:18 AM
  7. Matt Alexander #

    This is just perfect! Can’t wait to see the polished product. You guys save me so much work.

    May 13th, 2007 @ 01:10 PM
  8. Jim #

    This also demonstrates how boolean true as an attribute value results in repeating its name inside the value (disabled=”disabled”), which is a convention of XHTML.

    May 14th, 2007 @ 12:46 PM
  9. Mislav #

    Jim: I stand corrected :)

    May 14th, 2007 @ 02:16 PM
  10. Mislav #

    (Forgot)

    Tobie: not only Safari chokes on unquoted keywords. IE does so, too.

    Eimantas: it is very much alike scrip.aculo.us Builder. The latter has 2 extra features: you can define children and you can dump the node methods in some scope so you can get DIV, SPAN and similar methods if you prefer that syntax.

    It would be fairly easy to add both features to Prototype. But, for now, this is only a minimal builder that covers two most critical features: creating nodes and setting attributes. Building an additional API on top of that would be a piece of cake (and possibly left to the user).

    May 14th, 2007 @ 02:27 PM
  11. Lakshan #

    I’m bit confused on how to set content for an Element ?

    In Scrip.taculo.us builder there was the way of passing a string which would be treated as the content of the tag. This method doesn’t seem to work in prototype Element.

    For example, new Element(‘p’, ‘test’); doesn’t seems to return :

    test

    May 14th, 2007 @ 03:54 PM
  12. Tobie Langel #

    Lakshan, use:

    new Element('p').update('text');

    to do so, or the more standard compliant:

    new Element('p').appendChild(
      document.createTextNode('text')
    );
    May 14th, 2007 @ 03:59 PM
  13. Lakshan #

    Thanks Tobie :)

    May 14th, 2007 @ 04:04 PM
  14. Tobie Langel #

    Note that if you are a web-standard freak you could imagine using Element.addMethods to create a short-cut for the example I posted above:

    Element.addMethods({
      appendText: function(element, text) {
        text = document.createTextNode(text);
        element.appendChild(text);
        return $(element);
      }
    });

    Which you could then use like so:

    new Element('p').appendText('test');
    // --> <p>test</p>
    May 14th, 2007 @ 04:09 PM
  15. Michael Daines #

    Been playing around with this:

    
    $w('p em').each(function(e) {
      window['$' + e] = function() {
        var text, attributes = {}, children = $A();
    
        for (var i = 0; i < arguments.length; i++) {
          var argument = arguments[i];
          if (typeof argument == 'string')
            children.push(document.createTextNode(argument));
          else if (argument.nodeType == 1)
            children.push(argument);
          else if (argument.constructor == Array)
            children = children.concat(argument);
          else if (typeof argument == 'object')
            attributes = argument;
        }
    
        var element = new Element(e, attributes);
        children.each(function(c) { element.appendChild(c); });
        return element;
      }
    });
    

    Sorry for the all the code, but…

    $p({'class': 'praise'}, "The DOM builder is ", $em("great!"))
    May 14th, 2007 @ 09:58 PM
  16. Michael Daines #

    Adding those methods (undollared) to a dollar shortcut and using “with” might also be useful. If you were adding all the XHTML tags, making “i” a function for only a short while is maybe a good compromise with adding a whole bunch of stuff to the window object.

    with($E) { var list = ul( li("foo"), li("bar") ); }
    May 14th, 2007 @ 10:10 PM
  17. kourge #

    There also seems to be a bunch of function manipulation sugar in this build, like currying, delaying, and wrapping. Sweet.

    May 14th, 2007 @ 10:30 PM
  18. Tobie Langel #

    Michael, the with keyword can really be a resource hog. I’d only recommend using it if you’re short on space and not too worried about processing speed.

    May 15th, 2007 @ 01:16 AM
  19. Michael Daines #

    Yes, and also it’s not so great semantically. (“Semantically” is the correct term, I hope?) But I do like how that line looks.

    May 15th, 2007 @ 01:54 AM
  20. Nathan Renard #

    Feels good this new addition to prototype, hope i can work with that soon!

    May 16th, 2007 @ 06:54 AM
  21. digitarald #

    That are nice new toys, its just sad that a reference to the original idea is missing.

    Mootools 1.1 was released 4 days before this new feature with exactly the same syntax. The Mootools develeopers always add to new features the source of their inspiration or code.

    But its good to see that you like the Mootools syntax.

    May 16th, 2007 @ 07:37 AM
  22. Tobie Langel #

    digiterald,

    Please note that this syntax was first discussed in the Prototype Core mailing list on the 5th of February 2007, which makes it about a week before it made its way into Mootools.

    Next time, please check your facts before posting insinuations which could bite you back.

    May 16th, 2007 @ 08:26 AM
  23. digitarald #

    Nice inquest, sorry for this insinuation then. Anyway, its glad to see prototype goes now faster, than ever.

    May 16th, 2007 @ 10:01 AM
  24. Tobie Langel #

    Apologies accepted!

    I’m happy we could clear that issue out.

    May 16th, 2007 @ 01:26 PM
  25. Inviz #

    That’s not true. Mootools has “new Element” from the very beginning.

    May 16th, 2007 @ 11:56 PM
  26. Inviz #

    Or wait, do we talk about that object? Ok, i’m not right. :)

    May 17th, 2007 @ 12:03 AM
  27. chris #

    I still prefer the syntax described here : http://mg.to/topics/programming/javascript/jquery

    May 24th, 2007 @ 07:39 AM
  28. Bertelle Nicolas #

    What an excellent idea, i thinked about like 2 nights ago dealing at this time with scriptaculous .js

    Excellent ;-)

    May 28th, 2007 @ 03:27 PM
  29. Mad Max #

    what are the stuff that I can pass to it? i want to know if we can add an onclick handler to it.

    May 29th, 2007 @ 11:08 AM
  30. novice #

    Well done! I especially like the form#request fixes, thumbs up :)

    keep up the good work

    June 10th, 2007 @ 12:54 PM
  31. Adi Azar #

    Well I agree with chris about jquery syntax.

    Thanks for the effort guys.

    June 10th, 2007 @ 04:08 PM
  32. RoR #

    Great idea and great work. Keep it up.

    We appreciate all your effort.

    Thanks

    June 11th, 2007 @ 12:14 PM
  33. Les #

    ... no problems so far with Prototype 1.5.1 and latest Scriptaculous on Safari 3 :)

    June 11th, 2007 @ 02:42 PM

Sorry, comments are closed for this article.

Search Blog


Search the prototype blog.

Subscribe to the blog

Akismet badge