patternjavascriptMinor
Tiny DOM builder
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:
The builder factory also binds the created element to the function so you can also work with the element without all of the magic:
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
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
with
and it seems to work fine, negating the need for
Furthermore, you should consider adding functions to the prototype of
Other than that:
-
Just a thought, but I would default
Everything else looks good and maintainable.
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
nullandundefined.
- Consider adding
'use strict'at the start ofBuilder
-
Just a thought, but I would default
el to document.body if it is not providedthis.root = el || document.body;- In the same vein, in
appendI would expect an error ifelis 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.