/**
 * mkEl(doc, tagname, attributes, children)
 * 	create an HTML element with the specified attributes and children
 *
 * The attributes argument is a Javascript object: the names and values of its
 * properties are taken as the names and values of the attributes to set.
 * If attributes is null and hildren is an array or a string the attributes 
 * can be omitted altogether and the children passed as the second argument
 *
 * The children argument is normally an array of children to be added to
 * the created element. If there are no children, this argument can be 
 * omitted. If there is only a single child, it can be passed directly
 * instead of being enclosed in an array. (But if the child is not a string
 * and no attributes are specified, an array must be used.)
 *
 * Example: mkEl("p", ["This is a ", mkEl("b", "bold"), " word."]);
 *
 * Inspired by the Mochikit library (http://Mochikit.com) by Rob Ippoloto
 * */

function mkEl(doc, tagname, attributes, children)
{
	// If invoked with two arguments, the attributes argument is  an array 
	// or a string, it should really be the children argument.
	if (arguments.length == 3 && 
		(attributes instanceof Array || typeof attributes == "string")) {
		children = attributes;
		attributes = null;
	}
	
	// Create the element
	var e = doc.createElement(tagname);
	
	// Set attributes
	if (attributes != null) {
		for (var name in attributes) e.setAttribute(name, attributes[name]);
	}
	
	// Add children, if any where specified
	if (children != null) {
		if (children instanceof Array) { // If it really is an array
			for (var i=0; i<children.length; i++) {
				var child = children[i];
				if (typeof child == "string") // Handle text nodes
					child = doc.createTextNode(child);
				e.appendChild(child);  // Assume anything else in a node
			}
		}
		else if (typeof children == "string") {// Handle single text child
			e.appendChild(doc.createTextNode(children));
		}
		else {
			e.appendChild(children);  // Handle any other single child
		}
	}
	
	// Finally, return the element

	return e;
}

/**
 * maker(tagname): return  function that calls mkEL() for the specified tag.
* Example: var table = maker("table"), tr = maker("tr"), td = maker("td");
*/
function maker(tag)
{
	return function(doc, attributes, children) {
		if (arguments.length == 2) return mkEl(doc, tag, attributes);
		else return mkEl(doc, tag, attributes, children);
	}
}

var mkA = maker("a");
var mkBlockquote = maker("blockquote");
var mkBody = maker("body");
var mkBr = maker("br");
var mkButton = maker("button");
var mkCaption = maker("caption");
var mkDiv = maker("div");
var mkForm = maker("form");
var mkH1 = maker("h1");
var mkH2 = maker("h2");
var mkH3 = maker("h3");
var mkH4 = maker("h4");
var mkH5 = maker("h5");
var mkH6 = maker("h6");
var mkHtml = maker("html");
var mkImg = maker("img");
var mkInput = maker("input");
var mkLi = maker("li");
var mkLink = maker("link");
var mkObject = maker("object");
var mkOl = maker("ol");
var mkOptgroup = maker("optgroup");
var mkOption = maker("option");
var mkP = maker("p");
var mkScript = maker("script");
var mkSpan = maker("span");
var mkStrong = maker("strong");
var mkStyle = maker("style");
var mkTable = maker("table");
var mkTbody = maker("tbody");
var mkTfoot = maker("tfoot");
var mkThead = maker("thead");
var mkTd = maker("td");
var mkTh = maker("th");
var mkTr = maker("tr");
var mkUl = maker("ul");

