var Util = new function()
{

    this.Trim = function(stringToTrim) {
        return stringToTrim.replace(/^\s+|\s+$/g,"");
    };
    
    this.LeftTrim = function (stringToTrim) {
        return stringToTrim.replace(/^\s+/,"");
    };
 
    this.RightTrim = function(stringToTrim) {
        return stringToTrim.replace(/\s+$/,"");
    };
 
    this.GetChildNamed = function(node, name)
    {
        var children = node.childNodes;
        var len = children.length;
        var upperName = name.toUpperCase();
        
        for (var i = 0; i < len; i++)
        {
            var child = children[i];
            if (child.nodeType == 1)
            {
                if (child.nodeName.toUpperCase() == upperName)
                {
                   return child;
                }
            }
        }
        return null;
    };
};


function XmlHttpRequest()
{

	var xmlHttp;
	
	function Init()
	{
		try { xmlHttp = new XMLHttpRequest(); return xmlHttp; } catch (ex) {}
		try { xmlHttp = new ActiveXObject("Msxml2.XMLHTTP.4.0"); return xmlHttp; } catch (ex) {}
		try { xmlHttp = new ActiveXObject("MSXML2.XMLHTTP"); return xmlHttp; } catch (ex){}
		try { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); return xmlHttp; } catch (ex) {}
		return null;
	}
	
	Init();
	if (xmlHttp == null)
	{
		throw "Can't create XmlHttp object";
	}
	
	this.Open = function(method, url, async)
	{
		xmlHttp.open(method, url, async);
	}
	
	this.Send = function(body, callback)
	{
		xmlHttp.onreadystatechange = function()
		{
			if (xmlHttp.readyState == 4) //READY_STATE_COMPLETED
			{
				callback(xmlHttp);
			}
		};
		xmlHttp.send(body);
	}
	
	this.SetContentHeader = function(header, value)
	{
		xmlHttp.setRequestHeader(header, value);
	}

}

function WebService(url)
{

	this.Call = function(method, params, callback)
	{
		var xmlHttp = new XmlHttpRequest();

		var completeUrl = url + "/" + method;
		var body = "";
		if (params)
		{
			for (var p in params)
			{
				if (body != "")
				{
					body += "&";
				}
				body += encodeURIComponent(p) + "=" + encodeURIComponent(params[p]);
			}
		}
		xmlHttp.Open("POST", completeUrl, true);
		xmlHttp.SetContentHeader("Content-Type", "application/x-www-form-urlencoded");
		xmlHttp.SetContentHeader("x-s-r-f", "1");
		xmlHttp.Send(body, callback);
	}
	
}

// Utilities:

var NullFunction = function() {};

var AlwaysTrue = function() { return true; }

function GetQueryValue(key, length)
{
    var search = document.location.search;
    var pos = search.indexOf(key);
    if (pos != -1)
    {
        var start = pos + key.length + 1;
        return search.substring(start, start + length);
    }
}

function SafeInsertBefore(parent, child, reference)
{
    if (reference)
    {
        parent.insertBefore(child, reference);
    }
    else
    {
        parent.appendChild(child);
    }
}

function AddClass(el, className)
{
    var classes = el.className.split(" ");
    if (!FindFirst(classes, function(c) { return className == c; }))
    {
        el.className += (" " + className);
    }
}

function RemoveClass(el, className)
{
    var classes = el.className.split(" ");
    var i = -1;
    if (FindFirst(classes, function(c) { i++; return className == c; }))
    {
        classes.splice(i, 1);
    }
    el.className = classes.join(" ");
}

function ContainsClass(el, className)
{
    var classes = el.className.split(" ");
    return FindFirst(classes, function(c) { return className == c; }) != null;
}

function FindFirst(_this, pred)
{
    var len = _this.length;
    for (var i = 0; i < len; i++)
    {
        if (pred(_this[i]))
        {
            return _this[i];
        }
    }
    return null;
}

function ForEach(_this, action)
{
    var len = _this.length;
    for (var i = 0; i < len; i++)
    {
        action(_this[i]);
    }
}

//supports volatile collections
function ForEachEx(_this, action)
{
    for (var i = 0; i < _this.length; i++)
    {
        action(_this[i]);
    }
}

function Filter(_this, predicate)
{
    var len = _this.length;
    var arr = new Array();
    for (var i = 0; i < len; i++)
    {
        var el = _this[i];
        if (predicate(el))
        {
            arr.push(el);
        }
    }
    return arr;
}

function GetOuterXml (node) {
    var xmlSerializer = new XMLSerializer();
    // serialize
    var markup = xmlSerializer.serializeToString(node);
    return markup;
}

function GetChildNamed(node, name)
{
    if (node)
    {
        var children = node.childNodes;
        var len = children.length;
        var upperName = name.toUpperCase();
        
        for (var i = 0; i < len; i++)
        {
            var child = children[i];
            if (child.nodeType == NODE_TYPE_ELEMENT)
            {
                if (child.nodeName.toUpperCase() == upperName)
                {
                    return child;
                }
            }
        }
    }        
    return null;
}

function cap(parent, tag) { var el = document.createElement(tag); parent.appendChild(el); return el; }

function capd(doc, parent, tag) { var el = doc.createElement(tag); parent.appendChild(el); return el; }
