/*
JSON-HTML Utility (1.0)
Author: Miles Jackson
Utility used for generating legitimate DOM nodes from json of a specific format. Meant to be used
with the sister PHP library.

Functions:

jsonToHTML(json), jsonToDOM(json), jsonToNodes(json)
	Takes an object generated from json with the JSON PHP backend and returns an array representation of DOM nodes.
	The provided object should look like the following: 
		type : div, input, p, table, etc
		attributes: id:'the_id', name:'the_name', readonly:'readonly', etc
		children: an array of objects like this
		text: the text of a text node
		
putJSON(json, target, injectionType)
	Calls jsonToHTML on the json parameter and injects the resulting array of nodes into the target node.
	json = the json from which the html should be generated
	target = the target node. can be an id string or an actual dom object
	injectionType = 'replace', 'append'
*/


function jsonToHTML(json) {
	
	if (_JSONUtil.isArray(json)) {
		var returnNodes = [];
		for (var i = 0; i < json.length; i++) returnNodes.push(_JSONUtil.jsonToNode(json[i]));
		return returnNodes;
	}
	else return [_JSONUtil.jsonToNode(json)];
}


var jsonToDOM = jsonToHTML;


var jsonToNodes = jsonToHTML;


function putJSON(json, target, injectionType) {
	
	if (typeof(target) == 'string') target = document.getElementById(target);
	injectionType = _JSONUtil.defined(injectionType) ? injectionType : "replace";
	
	var nodes = jsonToHTML(json);
	
	switch (injectionType) {
		case 'replace':
			if (target.hasChildNodes()) {
				while (target.childNodes.length > 0) target.removeChild(target.firstChild);       
			}
			for (var i = 0; i < nodes.length; i++) target.appendChild(nodes[i]);
			break;
		
		case 'append':
			for (var i = 0; i < nodes.length; i++) target.appendChild(nodes[i]);
			break;
	}
	
	//force browser redraw
	var oldDisplay = target.style.display;
	target.style.display = "none";
	var redrawFix = target.offsetHeight;
	target.style.display = oldDisplay;
}


var _JSONUtil = {

	defined : function(obj) {
		return (typeof(obj) != 'undefined' && typeof(obj) != 'null');
	},

	isArray : function(obj) {
		//return (obj && !(obj.propertyIsEnumerable('length')) && typeof obj === 'object' && typeof obj.length === 'number');
		return (obj.constructor == Array);
	},

	jsonToNode : function(json) {
		
		if (!_JSONUtil.defined(json.type)) {
			alert("jsonToHTML error: node does not have a type property defined!");
			return "";
		}
			
		if (json.type == 'text') return document.createTextNode(json.text);
		
		if (json.type == 'script' && (json.attributes.type == 'text/javascript' || json.attributes.type == 'text\/javascript')) {
			if (json.children.length > 0) {
				eval(json.children[0].text);
				return false;
			}
		}
		
		var element = '';
		
		if (json.type == 'object') {
			element = document.createElement('div');
			element.innerHTML = _JSONUtil.jsonToString(json);
			element = element.childNodes[0];
		}
		else {
			element = document.createElement(json.type);
		}
		
		if (_JSONUtil.defined(json.attributes)) {
			
			if (json.type == 'input' && (json.attributes.type == 'radio' || json.attributes.type == 'checkbox')) {
				try {
					var radioStr = (json.attributes.type == 'radio') ? "<input type='radio' " : "<input type='checkbox' ";
					if (_JSONUtil.defined(json.attributes.name)) radioStr += " name='"+json.attributes.name+"' ";
					if (_JSONUtil.defined(json.attributes.checked)) radioStr += " checked='"+json.attributes.checked+"' ";
					radioStr += " />";
					element = document.createElement(radioStr);
				} catch (err) {
					// not IE
				}
			}
			
			for (var i in json.attributes) {
				
				switch (i) {
					
					case 'id':			element.id = json.attributes[i]; break;
					case 'name':		element.name = json.attributes[i]; break;
					case 'class':		element.className = json.attributes[i]; break;
					case 'value':		element.value = json.attributes[i]; break;
					case 'type':		element.type = json.attributes[i]; break;
					case 'checked':		element.checked = json.attributes[i]; break;
					case 'selected':	element.selected = json.attributes[i]; break;
					
					case 'href':		case 'title':		case 'colspan':		case 'rowspan':				case 'src':
					case 'alt':			case 'disabled':	case 'readonly':	case 'allowscriptaccess':	case 'allowfullscreen':
					case 'width':		case 'height':		case 'target':
										element.setAttribute(i, json.attributes[i]); break;
					
					case 'onabort':		case 'onblur':		case 'onchange':	case 'onclick':		case 'ondblclick':
					case 'onerror':		case 'onfocus':		case 'onkeydown':	case 'onkeypress':	case 'onkeyup':
					case 'onload':		case 'onmousedown':	case 'onmousemove':	case 'onmouseout':	case 'onmouseover':
					case 'onmouseup':	case 'onreset':		case 'onresize':	case 'onselect':	case 'onsubmit':	case 'onunload':
										var evalCode = "element."+i+" = function() { "+json.attributes[i]+" };";
										eval(evalCode);
										break;
						
					default:			break; //element.setAttribute(i, json.attributes[i]); break;
				}
			}
		}
		
		//if (json.type == 'object') return element;
		
		if (_JSONUtil.defined(json.children)) {
			for (var i = 0; i < json.children.length; i++) {
				
				if (json.type != 'object') {
					
					var child = _JSONUtil.jsonToNode(json.children[i]);
					if (child) element.appendChild(child);
				}
			}
		}
		
		return element;
	},
	
	jsonToString : function(json) {
		
		if (!_JSONUtil.defined(json.type)) {
			alert("jsonToHTML error: node does not have a type property defined!");
			return "";
		}
			
		if (json.type == 'text') return json.text;
		
		var htmlString = '<'+json.type+' ';
		
		if (_JSONUtil.defined(json.attributes)) {
			for (var i in json.attributes) 
				htmlString += i+'="'+json.attributes[i]+'" ';
		}
		
		htmlString += '>';
		
		if (_JSONUtil.defined(json.children)) {
			for (var i = 0; i < json.children.length; i++)
				htmlString += _JSONUtil.jsonToString(json.children[i]);
		}
		
		htmlString += '</'+json.type+'>';
		
		return htmlString;
	}
	
	
};


