//
// From Sean M. Burke's teachings, "Higher-Order Javascript".
//

// Usage: graft( somenode, [ "I like ", ['em',
//               { 'class':"stuff" },"stuff"], " oboy!"] )
function graft (parent, t, doc)
{
	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! (did you forget a comma somewhere?)");
			}
			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])  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); }