views:

109

answers:

2

I am making a DOM builder which I have working succesfully but now I am trying to assign some shorthand functions so that div() -> e("div")

Here is my code:

//assign these objects to a namespace, defaults to window
(function(parent) {

/**
* Creates string of element
* @param tag The element to add
* @param options An object of attributes to add
* @param child ... n Child elements to nest
* @return HTML string to use with innerHTML
*/
var e = function(tag, options) {
    var html = '<'+tag;
    var children = Array.prototype.slice.apply(arguments, [(typeof options === "string") ? 1 : 2]);

    if(options && typeof options !== "string") {
        for(var option in options) {
            html += ' '+option+'="'+options[option]+'"';
        }
    }

    html += '>';
    for(var child in children) {
        html += children[child];
    }
    html += '</'+tag+'>';
    return html;
}

//array of tags as shorthand for e(<tag>) THIS PART NOT WORKING
var tags = "div span strong cite em li ul ol table th tr td input form textarea".split(" "), i=0;
for(; i < tags.length; i++) {
    (function(el) { //create closure to keep EL in scope
        parent[el] = function() {
            var args = Array.prototype.slice.call(arguments);
            console.log(args);
            args[0] = el; //make the first argument the shorthand tag
            return e.apply(e,args);
        };
    })(tags[i]);
}

//assign e to parent
parent.e = e;
})(window);

What's currently happening is the args array is getting modified each time I call one of the shorthand functions and I assume what needs to happen is a closure somewhere so the args array I created does not get affected each time it is called. Here is the output of the unit tests:

div( div( span("Content")), span()) expected: <div><div><span>Content</span></div><span></span></div> result: <div><span></span></div>

div( div( span( e("b", e("b", e("b")))), span())) expected: <div><div><span><b><b><b></b></b></b></span><span></span></div></div> result: <div></div>

+1  A: 

Though this doesn't directly answer your question,

for(var el in tags) {

is not entirely correct. tags is an array, not an object, so its properties cannot be enumerated using for (... in ...). Try

for(var el = 0; el < tags.length; el++) {

This can make a huge difference towards the interpreter's understanding of your code... and the correct execution of your algorithm.

MvanGeest
Oh thanks, I guess I'm used to `for each`.
Louis
@Louis - there is a `for each` too in a recent version of JavaScript. It is used to enumerate through object values, and can be used with arrays if you don't care about order. Try `for each(var v in {a:1, b:2, c:3}) console.log(v);` in Firefox.
Anurag
A: 

Blonde moment, I was overwriting the first element when I meant to use args.unshift(el);

Louis