HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Tiny DOM builder

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
builderdomtiny

Problem

My goal was to create a tiny DOM builder library that made creating element trees less gross.

This is the syntax I decided on:

var foo = Builder.create('div', function(){
    //set attributes
    this.id = "foo-div";
    this.title = "Foo Div";

    //append a child node
    this.create('button', function(){

        //append a text node
        this.text('Click Me!');

        this.on('click', function(){
            this.parentNode.style.backgroundColor = 'red';
        });
    });
 });

 document.body.appendChild(foo);


The builder factory also binds the created element to the function so you can also work with the element without all of the magic:

Builder.create('div', function(element){
    element.style.color = '#ffffff';
});


Here is the implementation:

```
var Builder = function(el){
//set root and element shortcuts
this.root = el;

//create a new element
this.create = function(tag, func){
var builder, property, obj = {};
var el = document.createElement(tag);

//setup new builder
builder = new Builder(el);

if(func != undefined){
obj = new (this.attach(builder, func))(el);
}

//apply attributes
for (property in obj){
if (obj.hasOwnProperty(property)) {

//set name and value
builder.set(property, obj[property]);
}
}

return this.append(el);
};

//set attribute
this.set = function(name, value){

//try setAttribute (from jquery source)
if (typeof this.root.setAttribute !== "undefined") {
if (value === false) {
this.root.removeAttribute(name);
} else {
this.root.setAttribute(name, value === true ? name : value);
}
}else{
this.root[name] = value;
}

return this;
}

//attach prototypes
this.attach = function(builder

Solution

Interesting,

I agree with your assessment that mentioned the way I bind the methods to the function feels gross.

I forked your demo here : http://jsfiddle.net/konijn_gmail_com/hz62smvp/
and replaced

if(func != undefined){
       obj = new (this.attach(builder, func))(new_element);
    }


with

if(func != undefined){
       obj = func.bind(builder)(new_element) ;
    }


and it seems to work fine, negating the need for attach altogether.

Furthermore, you should consider adding functions to the prototype of Builder instead of to the instances of builder, this should reduce your memory foot-print.

Other than that:

  • Run this through JsHint in JSFiddle, there are a few missing semicolons and a few dirty comparisons to null and undefined.



  • Consider adding 'use strict' at the start of Builder



-
Just a thought, but I would default el to document.body if it is not provided

this.root = el || document.body;


  • In the same vein, in append I would expect an error if el is not set, instead you make silently the provided parameter the root. The name of that function does not match what it does



Everything else looks good and maintainable.

Code Snippets

if(func != undefined){
       obj = new (this.attach(builder, func))(new_element);
    }
if(func != undefined){
       obj = func.bind(builder)(new_element) ;
    }
this.root = el || document.body;

Context

StackExchange Code Review Q#61050, answer score: 2

Revisions (0)

No revisions yet.