MooTools-Like Element Creation in jQuery

By  on  

I really dislike jQuery's element creation syntax. It's basically the same as typing out HTML but within a JavaScript string...ugly! Luckily Basil Goldman has created a jQuery plugin that allows you to create elements using MooTools-like syntax.

Standard jQuery Element Creation

var newDiv = $('<div class="my-class"></div>');

Looks exactly like writing out the HTML...blah.

The jQuery .create Method

/* plugin */
jQuery.create = function() {
    if (arguments.length == 0) return [];
    var args = arguments[0] || {}, elem = null, elements = null;
    var siblings = null;

    // In case someone passes in a null object,
    // assume that they want an empty string.
    if (args == null) args = "";
    if (args.constructor == String) {
        if (arguments.length > 1) {
            var attributes = arguments[1];
                if (attributes.constructor == String) {
                            elem = document.createTextNode(args);
                            elements = [];
                            elements.push(elem);
                            siblings =
        jQuery.create.apply(null, Array.prototype.slice.call(arguments, 1));
                            elements = elements.concat(siblings);
                            return elements;

                    } else {
                            elem = document.createElement(args);

                            // Set element attributes.
                            var attributes = arguments[1];
                            for (var attr in attributes)
                                jQuery(elem).attr(attr, attributes[attr]);

                            // Add children of this element.
                            var children = arguments[2];
                            children = jQuery.create.apply(null, children);
                            jQuery(elem).append(children);

                            // If there are more siblings, render those too.
                            if (arguments.length > 3) {
                                    siblings =
        jQuery.create.apply(null, Array.prototype.slice.call(arguments, 3));
                                    return [elem].concat(siblings);
                            }
                            return elem;
                    }
            } else return document.createTextNode(args);
      } else {
              elements = [];
              elements.push(args);
              siblings =
        jQuery.create.apply(null, (Array.prototype.slice.call(arguments, 1)));
              elements = elements.concat(siblings);
              return elements;
      }
};

This class was taken from Basil Goldman's blog post. The code isn't beautiful but its functionality is.

The Usage

/* usage */
$(document).ready(function() {
	var element = $.create('li',{
		id: 'item',
		'class': 'custom-class'
	},['This is a new LI element']);
	$(document.body).append(element);
});

You provide three arguments: the element type, element attributes, and an array containing the text within the element or child elements. OK, so it's not quite as wonderful as MooTools' element creation but it's a step in the right direction!

Recent Features

  • By
    CSS @supports

    Feature detection via JavaScript is a client side best practice and for all the right reasons, but unfortunately that same functionality hasn't been available within CSS.  What we end up doing is repeating the same properties multiple times with each browser prefix.  Yuck.  Another thing we...

  • By
    5 Awesome New Mozilla Technologies You&#8217;ve Never Heard Of

    My trip to Mozilla Summit 2013 was incredible.  I've spent so much time focusing on my project that I had lost sight of all of the great work Mozillians were putting out.  MozSummit provided the perfect reminder of how brilliant my colleagues are and how much...

Incredible Demos

  • By
    MooTools Window Object Dumping

    Ever want to see all of the information stored within the window property of your browser? Here's your chance. The XHTML We need a wrapper DIV that we'll consider a console. The CSS I like making this look like a command-line console. The MooTools JavaScript Depending on what you have loaded...

  • By
    Check All/None Checkboxes Using MooTools

    There's nothing worse than having to click every checkbox in a list. Why not allow users to click one item and every checkbox becomes checked? Here's how to do just that with MooTools 1.2. The XHTML Note the image with the ucuc ID -- that...

Discussion

  1. psalmi

    I don’t know if this is a step in a right direction. To me, mootools element creation has always been too heavyweight and I’ve resorted into using String.substitute and set(‘html’) -combo.

    Manual element creation has also been a major performance penalty with IE and tables, if I remember correctly instead of creating everything from a string.

    Having said that, I don’t like jQuery syntax anymore than you do, I’ve had enough of that when porting FancyBox into mootools syntax.

  2. I can’t say that I agree with this idea, this is the fastest jquery way to parse something into the DOM. You just add a not needed JS layer.

    The jQuery syntax is something you really like or you just hate I think, if you don’t like it, you better use directly mootools :P

  3. “The jQuery syntax is something you really like or you just hate I think, if you don’t like it, you better use directly mootools”

    I disagree. If I inherit an old website I cannot simply switch their entire website to MooTools.

  4. ewwww. Not sure if that’s a good thing.

  5. @Rick: I am. :)

  6. @Cedric Dugas: Creating an Element isn’t the same thing as parsing a string to DOM-Elements. So mootools doesn’t add an extra JS Layer, it uses a completely different (more robust, semantic and object-oriented) way via document.createElement. While jQuery passes the string over to .innerHTML.
    I think you can’t compare this two methods directly.

    @psalmi: You’re right it’s a little clunky. I think you will love mootools 2.0. It will allow you to create elements by passing a selector. Something like: var div = new Element('div.my-class');

    This said I think you can guess which way I prefer. :) (moo rocks)

  7. Well this is a special case, most of your time is probably spent on new sites.

    Anyway as far as I am concern, I rarely work on old websites with technologies my company do not work with.

  8. @Walsh hahaha. yes. you are.

  9. Definitely a good idea – jQuery’s weird syntax really does put me off.

  10. Jeffrey Schrab

    There’s a time and a place for both techniques. I like the Mootools way when I want to create an element AND assign event handlers to it all in one go.

    More complicated element structures are a bit of a pain to do with the new Element() method. The innerHTML method works out better for me in that case, even if I have to assign event handlers after the fact.

  11. I still prefer jquery syntax:

    $(function() {
    $("")
      .id('item')
      .addClass('custom-class')
      .html('This a new LI element').appendTo('body');
    })
    

    vs

    $(document).ready(function() {
    	var element = $.create('li',{
    		id: 'item',
    		'class': 'custom-class'
    	},['This is a new LI element']);
    	$(document.body).append(element);
    });
    
  12. @Ethan: $(“”) should be $(“<li>”)

  13. This is an interesting plugin. Normally I would recommend learning the “normal” syntax of whatever tool you’re using, but syntactic sugar like this can definitely help smooth out the learning curve for new users.

    If the goal is to avoid the html literal, as opposed to explicitly imitating Mootools, you could also do this the “jQuery way” like this…

    var $el =$('el').attr({
        id : 'item',
        class : 'custom-class'
    }).text('This is a new LI element');
    
    $(document.body).append($el);
    

    It’s worth noting, though, that in some cases using a literal string is actually more performant…

  14. Oops – in my example, “class : ‘custom=class'” should be “className : ‘custom-class'”. Class is a special case: http://docs.jquery.com/Attributes/attr#properties.

  15. Edit #2: $(‘el’) should also be $(‘li’). Must be monday….

  16. Steve Calvert

    Ya I’m not sure I’m agreeing with this either. I used to love mootools, but now since I’ve been using jQuery I find the syntax quite easy to work with. I do agree that having strings in your code is less than ideal, but it almost fits in with jQuery’s expressive nature. I’m gonna let this one slide…

  17. @thomasd, hold on a sec! You’re claiming that the “innerHTML” technique is flawed (or not as “robust” as MooTools’ technique) and that it adds another “JS layer” (by which I assume you mean “abstraction”) yet you’re promoting a new technique with a much higher level of abstraction. Using a CSS selector to create HTML elements in production code is a very bad idea. The performance hit isn’t worth it. jQuery is built for speed; delegating element creation to the browser’s parsing mechanism is the fastest way to create elements (there’s no contest).

    @marc, how is it weird? What could be a more natural way of creating HTML elements than writing HTML syntax?

    It might also be worth discussing the suitability of creating elements with JavaScript at all. In most situations, a primative templating system is better than either jQuery’s or MooTools’ techniques – it would allow a more maintainable means to dynamically add HTML.

    “The code isn’t beautiful”

    I agree.

  18. Looks like reinventing the wheel. I don`t see why this method is better than writing:

    $('').attr('id', 'myid').css('opacity', '0.5').appendTo("#wrap");
    
  19. seems like some tags are stripped …

  20. I, too, prefer writing HTML as a string instead of this object representation, but I can see the allure in it (despite its performance overhead).

    Here’s a little snippet I’ve used a lot when desiring this object-y style:

     /* Return a DOM element with tag name `elem` and attributes {attrs}. */
    function DOM(elem, attrs) {
      var elem = document.createElement(elem);
      for (var attr in attrs) {
        elem[attr] = attrs[attr];
      }
      return elem;
    }
    

    It provides nearly exactly the same API as the above code (though probably not as full-featured)… As an example:

    	var element = DOM('li',{
    		id: 'item',
    		'className': 'custom-class',
                    'innerHTML': 'This is a new LI element'
    	});
    

    Also, (moreso from the comments on Basil’s post..) I wanted to point out that throwing jQuery a big string of HTML is faster than using all the methods…

    So:

    $('#wrapper").append('hello world');
    

    is faster than

    jQuery(" " ).attr( "id", "wrapper-header").addClass( "header" ).html( "hello world").appendTo( jQuery( "#wrapper" ) );
    

    Cheers

  21. @james: you’re totally right, nothing is as fast as innerHTML, that’s what browsers are best in, parsing HTML-text to HTML in the DOM. What I tried to say is, that there isn’t a jQuery or a mootools way of creating elements. It’s parsing (innerHTML) on the one side and object-oriented creating of elements (document.createElement) on the other side and you can’t compare them directly. Two different ways of doing the same.

    I didn’t say innerHTML adds another JS-layer. What I said was mootools doesn’t add another JS layer it uses the object-oriented way. Not better or bader just different.

    For me using CSS selectors to create elements is something between this two methods. Expressive strings to make it a little easier to read and write, but still be objected-oriented. Still not better or bader but definitly slower than innerHTML, I agree with you. But JS-engines become faster and faster and speed isn’t always the most importing thing.

    Still…mootools rocks :)
    Oh and sorry for my bad English, it isn’t my native language.

  22. Mootools doesn’t do overloading: getStyle(rule), setStyle(rule, val), setStyles(obj), etc.. With jQuery everything is overloaded – a single css() does all of the above depending on whether 1 or 2 params are passed and whether they are objects or strings.

    So it totally makes sense to do $(‘li’) to find all the LI’s in a page, and $(”) to create a new LI.

    I came from a Mootools background to a huge jQuery project – first thing I did was port over a bunch of Mootools goodies: bind and pass (which look to be coming in the next version of jQuery) and Array, String and Number helpers… but the goal is understanding the tools you are given. It is the difference between someone who is a year in another country and everytime they speak think “how would I say this in English” and then translate – vs – someone who is 10 years in another country and just speaks the language fluently. $.create() is not increasing your toolbox, it’s rewriting a piece of a foreign language in English.

  23. Steve Calvert

    @Aeron – well said.

  24. Would be nice if you could stick to the css syntax instead

    .create('li#item.custom-class', 'content of the element here');
  25. I find the mootools element creation clunky so I use the string substitution that was mentioned in the comments too, it’s quick and easy, plus I get a bunch of elements quick.

    That said, I can see how it would be nice to map a comfortable syntax to an uncomfortable one in situations where there is no other remedy.

  26. hello,

    this is a good idea, but my function is easier than your:

    (function($){
        $.fn.create = function(element, attributes){
            return $(document.createElement(element)).attr(attributes).prependTo(this);
        };
    })(jQuery);
    

    usage:

    $('body').create('div', {'id':'sampleId', 'class':'normal'}).text('sample');
    
  27. @mits: AWESOME! I love it!

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!