graft() allows us to build chunks of DOM documents using really simple object notation. Graft() will feel very familiar to anyone who makes extensive use of the JSON format.
I’ll dive right into an example here and show graft in its simplest use. Suppose we have a DOM element somewhere in our document that we want to insert stuff into:
<div id="mycontentdiv"></div>
If we wanted to insert a button into the above div element, we could use standard DOM in the following manner:
var mydiv = document.getElementById("mycontentdiv");
var btn = document.createElement("input");
btn.type = "button";
btn.value = "click me";
btn.onclick = function(){this.value="i have been clicked!";};
mydiv.appendChild(btn);
The above button example becomes the following using graft():
graft(
document.getElementById("mycontentdiv"),
["input",
{
value:'click me',
type:'button',
onclick:'this.value="i have been clicked!";'
}
]
);
// graft() function
// Originally by Sean M. Burke from interglacial.com
// Closure support added by Maciek Adwent
function graft (parent, t, doc) {
// Usage: graft( somenode, [ "I like ", ['em',
// { 'class':"stuff" },"stuff"], " oboy!"] )
doc = (doc || parent.ownerDocument || document);
var e;
if(t == undefined) {
throw complaining( "Can't graft an undefined value");
} else if(t.constructor == String) {
e = doc.createTextNode( t );
} else if(t.length == 0) {
e = doc.createElement( "span" );
e.setAttribute( "class", "fromEmptyLOL" );
} else {
for(var i = 0; i < t.length; i++) {
if( i == 0 && t[i].constructor == String ) {
var snared;
snared = t[i].match( /^([a-z][a-z0-9]*)\.([^\s\.]+)$/i );
if( snared ) {
e = doc.createElement( snared[1] );
e.setAttribute( 'class', snared[2] );
continue;
}
snared = t[i].match( /^([a-z][a-z0-9]*)$/i );
if( snared ) {
e = doc.createElement( snared[1] ); // but no class
continue;
}
// Otherwise:
e = doc.createElement( "span" );
e.setAttribute( "class", "namelessFromLOL" );
}
if( t[i] == undefined ) {
throw complaining("Can't graft an undefined value in a list!");
} else if( t[i].constructor == String ||
t[i].constructor == Array ) {
graft( e, t[i], doc );
} else if( t[i].constructor == Number ) {
graft( e, t[i].toString(), doc );
} else if( t[i].constructor == Object ) {
// hash's properties => element's attributes
for(var k in t[i]) {
// support for attaching closures to DOM objects
if(typeof(t[i][k])=='function'){
e[k] = t[i][k];
} else {
e.setAttribute( k, t[i][k] );
}
}
} else {
throw complaining( "Object " + t[i] +
" is inscrutable as an graft arglet." );
}
}
}
parent.appendChild( e );
return e; // return the topmost created node
}
function complaining (s) { alert(s); return new Error(s); }