// Prototype Extensions

// Client class

var Client = {
    getWindowSize: function() {
        var w = window;
        var width = w.innerWidth || (w.document.documentElement.clientWidth || w.document.body.clientWidth);
        var height = w.innerHeight || (w.document.documentElement.clientHeight || w.document.body.clientHeight);
        return [width, height];
    },

    width: function() {
        var w = window;
        return w.innerWidth || (w.document.documentElement.clientWidth || w.document.body.clientWidth);
    },

    height: function() {
        var w = window;
        return w.innerHeight || (w.document.documentElement.clientHeight || w.document.body.clientHeight);
    },

    getScrollbarWidth: function() {
        var scr = null;
        var inn = null;
        var wNoScroll = 0;
        var wScroll = 0;

        // Outer scrolling div
        scr = document.createElement('div');
        scr.style.position = 'absolute';
        scr.style.top = '-1000px';
        scr.style.left = '-1000px';
        scr.style.width = '100px';
        scr.style.height = '50px';
        // Start with no scrollbar
        scr.style.overflow = 'hidden';

        // Inner content div
        inn = document.createElement('div');
        inn.style.width = '100%';
        inn.style.height = '200px';

        // Put the inner div in the scrolling div
        scr.appendChild(inn);
        // Append the scrolling div to the doc
        document.body.appendChild(scr);

        // Width of the inner div sans scrollbar
        wNoScroll = inn.offsetWidth;
        // Add the scrollbar
        scr.style.overflow = 'auto';
        // Width of the inner div width scrollbar
        wScroll = inn.offsetWidth;

        // Remove the scrolling div from the doc
        document.body.removeChild(document.body.lastChild);

        // Pixel width of the scroller
        return (wNoScroll - wScroll);
    }
}

// End Client

// FunctionX class
var FunctionX = {

    createDelegate: function(object, method) {
        return function() { method.apply(object, arguments); }
    }
}

// End FunctionX

// Element extensions
//Element.Methods.prototype.track = function(onClosed)
//{
//	ElementTrack.track(this, onClosed);
//}

var ElementTrack = {

    _mouseMove: null,
    _mouseUp: null,

    capture: function(MouseMove, MouseUp) {
        ElementTrack._mouseMove = MouseMove;
        ElementTrack._mouseUp = MouseUp;

        Event.observe(document, "mousemove", ElementTrack._mouseMove);
        Event.observe(document, "mouseup", ElementTrack._mouseUp);
    },

    release: function() {
        Event.stopObserving(document, "mousemove", ElementTrack._mouseMove);
        Event.stopObserving(document, "mouseup", ElementTrack._mouseUp);

        ElementTrack._mouseMove = null;
        ElementTrack._mouseUp = null;
    },

    isChildOf: function(parent, el) {
        while (el) {
            if (el.parentNode == parent)
                return true;
            el = el.parentNode;
        }
        return false;
    },

    mouseInElement: function(evt) {
        mouseX = Event.pointerX(evt);
        mouseY = Event.pointerY(evt);

        var trg = evt.target ? evt.target : evt.srcElement;

        if (trg != ElementTrack._element && !ElementTrack.isChildOf(ElementTrack._element, trg))
            return false;
        else
            return true;
    },

    _element: null,
    _closeElement: null,
    _onClosed: null,


    _mouseDown: function(event) {
        if (ElementTrack._element) {
            if (!ElementTrack.mouseInElement(event)) {
                ElementTrack.untrack();
                Event.stop(event);
                return false;
            }
        }
        return true;
    },

    track: function(el, onClosed, elClose) {
        ElementTrack._element = $(el);
        ElementTrack._closeElement = $(elClose);
        ElementTrack._onClosed = onClosed;

        Event.observe(document, "mousedown", ElementTrack._mouseDown);
    },

    untrack: function() {
        if (ElementTrack._element) {
			if (ElementTrack._closeElement)
				ElementTrack._closeElement.hide();
			else
				ElementTrack._element.hide();
				
            if (ElementTrack._onClosed)
                ElementTrack._onClosed();
                
            ElementTrack._element = null;
            ElementTrack._closeElement = null;
            ElementTrack._onClosed = null;
        }

        Event.stopObserving(document, "mousedown", ElementTrack._mouseDown);
    }

}

// End Element extensions

// Array

var ArrayX = {

	add: function( arr, obj )
	{
		arr.push( obj );
		return obj;
	},

	remove: function( arr, obj )
	{
		var index = ArrayX.find( arr, obj );
		if ( index != -1 )
		{
			arr.splice( index, 1 );
		}
	},

	removeId: function( arr, id )
	{
		var index = ArrayX.findId( arr, id );
		if ( index != -1 )
		{
			arr.splice( index, 1 );
		}
	},

	find: function( arr, obj )
	{
		for (var i = 0; i < arr.length; i++)
		{
			if ( obj == arr[i] )
				return i;
		}
		return -1;
	},

	findId: function( arr, id )
	{
		for (var i = 0; i < arr.length; i++)
		{
			if ( id == arr[i].id )
				return i;
		}
		return -1;
	}
};

// XML
var XML = {

	load: function(fileName)
	{
		var doc = null;
		
		try //Internet Explorer
		{
			doc = new ActiveXObject("Microsoft.XMLDOM");
			doc.async = false;
			doc.load(fileName);
		}
		catch (e) {
			try //Firefox, Mozilla, Opera, etc.
			{
				doc = document.implementation.createDocument("", "", null);
				doc.async = false;
				doc.load(fileName);
			}
			catch (e) {
				try //Google Chrome
				{
					var xmlhttp = new window.XMLHttpRequest();
					xmlhttp.open("GET", fileName, false);
					xmlhttp.send(null);
					doc = xmlhttp.responseXML; //.documentElement;
				}
				catch (e) {
					alert(e.Message);
				}
			}
		}
		return doc;
	},
	
	toString: function(xmlDoc)
	{
		var serialized;
		
		try {
			// XMLSerializer exists in current Mozilla browsers
			serializer = new XMLSerializer();
			serialized = serializer.serializeToString(xmlDoc);
		} 
		catch (e) {
			// Internet Explorer has a different approach to serializing XML
			serialized = xmlDoc.xml;
		}
		
		return serialized;
	},
	
	fromString: function(s)
	{
		var doc = null;
		if (window.DOMParser)
		{
			parser = new DOMParser();
			doc = parser.parseFromString(s, "text/xml");
		}
		else // Internet Explorer
		{
			doc = new ActiveXObject("Microsoft.XMLDOM");
			doc.async = "false";
			doc.loadXML(s);
		} 
		return doc;
  	}
};

// Debug

function trace(s, clear) {
	var tc = $("debugcont");
	if (tc)
		tc.show();
		
	var t = $("debug");
	if (t) {
		if (clear)
			t.innerHTML = s;
		else
			t.innerHTML += s;
		t.innerHTML += "<br/>";
	}
}

// Error

function showError(s) {
	var tc = $("errorcont");
	if (tc)
		tc.show();
		
	var t = $("error");
	if (t) {
		t.innerHTML = s;
	}
}

// Ajax Extensions
Ajax.Request.prototype.abort = function() {
    // prevent and state change callbacks from being issued
    this.transport.onreadystatechange = Prototype.emptyFunction;
    // abort the XHR
    this.transport.abort();
    // update the request counter
    Ajax.activeRequestCount = Math.max(0, Ajax.activeRequestCount--);
};