
//constants
var FIRST_CHILD = 1;

//returns {myClass : [myElement1, ...], ... } of all named children of node
//invoke with 1 argument - getClassedNodes(node)
//node is element object
function getClassedNodes(node, classedNodes){
	if(arguments.length < 2)
	{classedNodes = new Object();}

	if(node.className != undefined)
	{
		if(classedNodes[node.className] == undefined)
		{classedNodes[node.className] = new Array();}
		classedNodes[node.className].push(node);
	}
	
	for(var i=0; i < node.childNodes.length; ++i)
	{getClassedNodes(node.childNodes[i], classedNodes);}
	
	return classedNodes;
}

//returns {myName : [myElement, ...], ... } of all named children of node
//invoke with 1 argument - getNamedChildren(node)
//node is string or element object
function getNamedChildren(node, namedChildren){
	if(typeof node == 'string') 
	{node = document.getElementById(node);}
	
	if(arguments.length < 2)
	{namedChildren = new Object();}
	
	for(var i=0; i < node.childNodes.length; ++i)
	{
		getNamedChildren(node.childNodes[i], namedChildren);
		
		if(typeof node.childNodes[i].name != 'undefined')
		{
			if(namedChildren[node.childNodes[i].name] == undefined)
			{namedChildren[node.childNodes[i].name] = new Array();}
			
			namedChildren[node.childNodes[i].name].push(node.childNodes[i]);
		}
	}
	
	return namedChildren;
}


/////////////////////////////
//BEGIN StaticControl Class//
/////////////////////////////

function StaticControl(node) //ctor
{
	if(arguments.length >= 1)
	{
		if(typeof node == 'string') 
		{node = document.getElementById(node);}

		this.classedNodes = getClassedNodes(node);

		for(className in this.classedNodes)
		{
			for(var i=0; i < this.classedNodes[className].length; ++i)
			{this.classedNodes[className][i].control = this;}
		}
	}
}


///////////////////////////
//END StaticControl Class//
///////////////////////////



///////////////////////////////
//BEGIN Class TemplateControl//
///////////////////////////////

//use an html template to create multiple instances of a control
//templateNodes first non text child becomes the root element of this control
//templateNode - string id of DOM element or DOM element
function TemplateControl(templateNode)
{
	this.superClass = StaticControl;

	if(arguments.length >= 1)
	{
		if(typeof templateNode == 'string')
		{templateNode = document.getElementById(templateNode);}

		var child = templateNode.firstChild;
		while(child.nodeName == '#text')
		{child = child.nextSibling;}
		
		this.rootNode = child.cloneNode(true);
		this.superClass(this.rootNode);
	}
}


//optionPosition - optional. Values: FIRST_CHILD - attach this controls root as first child of node
function TemplateControl_attachToNode(node, optionPosition)
{
	if(typeof node == 'string')
	{node = document.getElementById(node);}
	
	if(arguments.length > 1)
	{
		switch(optionPosition)
		{
			case FIRST_CHILD:
				if(node.hasChildNodes())
				{node.insertBefore(this.rootNode, node.firstChild);}
				else
				{node.appendChild(this.rootNode);}
				break;
		}
	}
	else
	{node.appendChild(this.rootNode);}
}
TemplateControl.prototype.attachToNode = TemplateControl_attachToNode;
/////////////////////////////
//END Class TemplateControl//
/////////////////////////////


//invokes subroutine designated by action on remote server, passing 
//parameters and returning result object of form:
// { value: myValueObject, error: myErrorString }
// where error is non null if an error occurs
// and value is the return value result of performing action
//url - full url of remote service
//action - string name of action (applicaiton defined)
//parameters - object - parameters to pass to url via json
function invokeRemote(url, action, parameters)
{
	var postData = {action: action, parameters: JSON.encode(parameters)};

	var response = jQuery.ajax(
		{
		  url: url,
		  type: 'POST',
		  cache: false,
		  async: false,
		  dataType: 'text',
		  data: postData,
		  processData: true
		});

	var error = null;
	var value = null;
	
	//alert(response.responseText);//debug
	
	if(typeof response.responseText == 'string')
	{
		try
		{value = JSON.decode(response.responseText);}
		catch(err)
		{error = "Unable to parse server response as json";}
	}
	else
	{error = "Bad response from server";}
	
	return {error: error, value: value};
}


