function QBuilder(nodeName, options, children)
{
	if(nodeName == 'input' || nodeName == 'textarea' || nodeName == 'select')
	{
		//ie cant build inputs normally so we have to jump through hoops
		return QInputBuilder(nodeName, options, children);
	}
	var el = document.createElement(nodeName);
	if(!children && typeof options != 'object')
	{
		children = options;
	}
	else
	{
		for(nom in options)
		{
			if(nom == 'className')
			{
				el.className = options.className;
			}
			else if(nom == 'id')
			{
				el.id = options.id;
			}
			else if(nom == 'name')
			{
				el.name= options.name;
			}
			else if(nom.substring(0, 2) == 'on')
			{
				el[nom] = Function(options[nom]);
			}
			else if(nom == 'checked')
			{
				el.defaultChecked = true;
				el.setAttribute('checked','checked');
			}
			else if(nom == 'htmlFor')
			{
				el.htmlFor = options[nom];
				el.setAttribute('for', options[nom]);
			}
			else
			{
				//try{ //these trys really slow things down so only put them in if there is a problem
					el.setAttribute(nom, options[nom]);
				//}catch(e){
				//	alert(nodeName+' '+nom+' '+options)
				//}
			}
		}
	}

	if(children)
	{
		if(typeof children === 'object')
		{
			if(children.length)
			{
				for(var i=0, len=children.length; i<len; ++i)
				{
					var ch = children[i];
					if(ch === undefined)
					{
						ch = 'undefined';
					}
					if(typeof ch=='string' || typeof ch=='number')
					{
						el.appendChild(document.createTextNode(ch));
					}
					else
					{
						//check to see if its a real dom node
						if(ch.nodeType)
						{
							el.appendChild(ch);
						}
						else
						{
							//something weird is going on so just put what ever the results of String is.
							el.appendChild(document.createTextNode(String(ch)));
						}
					}
				}
			}
		}
		else
		{
			var node;
			if(typeof children=='string' || typeof children=='number')
			{
				node = document.createTextNode(children);
			}
			else
			{
				node = children;
			}
			el.appendChild(node);
		}
	}
	return el;
}

function QInputBuilder(nodeName, options, children)
{
	var attr = '';
	for(nom in options)
	{
		var val = options[nom];
		var key = '';
		switch(nom)
		{
			case 'className':
				key = 'class';
			break;
			case 'id':
				key = 'id';
			break;
			case 'checked':
				key = 'checked';
			break;
			case 'htmlFor':
				key = 'for'
			break;
			default:
				key = nom;
		}
		attr += key+'="'+val+'" ';
	}
	var parent = QBuilder('div');
	parent.innerHTML = '<'+nodeName+' '+attr+' />';
	var el = parent.firstChild.cloneNode(true);
	removeElement(parent);//clear the memory leak

	if(children)
	{
		var type = typeof children;
		if(type === 'object')
		{
			for(var i=0, len=children.length; i<len; ++i)
			{
				var ch = children[i];
				var node;
				if(typeof ch=='string' || typeof ch=='number')
				{
					node = document.createTextNode(ch);
				}
				else
				{
					node = ch;
				}
				el.appendChild(node);
			}
		}
		else if(type=='string' || type=='number')
		{
			el.appendChild(document.createTextNode(children));
		}
	}
	return el;
}

/** will take a string and parse out the html entities **/
function QEntity(str, mode) {
	str = (str) ? str : "";
	mode = (mode) ? mode : "string";

	var e = document.createElement("div");
	e.innerHTML = str;

	if (mode == "numeric") {
		return "&#" + e.innerHTML.charCodeAt(0) + ";";
	}
	else if (mode == "utf16") {
		var un = e.innerHTML.charCodeAt(0).toString(16);
		while (un.length < 4) un = "0" + un;
		return "\\u" + un;
	}
	else return e.innerHTML;
}
