﻿var Daedalus = new __Daedalus();

/// <summary>
/// Daedalus platform javascript.
/// </summary>
function __Daedalus()
{
    this.Ajax = new __Ajax();
    this.Utility = new __Utility();
    this.GraphicEffects = new __GraphicEffects();

    /// <summary>
    /// Provides ajax functions.
    /// </summary>
    function __Ajax()
    {
    }
    
    (function()
    {
        var LOADING_MESSAGE_TIMER = null;
        
        __Ajax.prototype.RequestLimit = 3;
        __Ajax.prototype.RequestPool = new Array();

        /// <summary>
        /// Open an AJAX connection.
        /// </summary>
        /// <param name="requestObject">The request object to be released.</param>
        /// <returns>The XMLHttpRequest object.</returns>
        __Ajax.prototype.OpenConnection = function(method, url, data, callback)
        {
            // Make HTTP request
            var request = this.GetRequestObject();
            var object = this;

            if(request != null)
            {
                request.onreadystatechange = function()
                {
                    if(request.readyState == 4)  // COMPLETED
                    {
                        if(request.status == 200)  // HTTP Status Code - 200 OK
                        {
                            var xmlDoc = request.responseXML;
                            object.ReleaseRequestObject(request);
                            if(typeof callback == "function") callback(xmlDoc);
                        }
                    }
                }

                request.open(method, url, true);
                request.send(data);
            }
        }
        
        /// <summary>
        /// Release an XMLHttpRequest object back into pool.
        /// </summary>
        /// <param name="requestObject">The request object to be released.</param>
        /// <returns>The XMLHttpRequest object.</returns>
        __Ajax.prototype.ReleaseRequestObject = function(requestObject)
        {
            for(var i=0; i<this.RequestPool.length; i++)
            {
                if(requestObject == this.RequestPool[i])
                {
                    this.RequestPool.splice(i, 1);
                }
            }
        }
        
        /// <summary>
        /// Get an XMLHttpRequest object.
        /// </summary>
        /// <returns>The XMLHttpRequest object.</returns>
        __Ajax.prototype.GetRequestObject = function()
        {
            var request = null;
            
            // Create new request object if pool is not full
            if(request == null && this.RequestPool.length < this.RequestLimit)
            {
                if(window.XMLHttpRequest)
                {
                    try
                    {
                        request = new XMLHttpRequest();
                    }
                    catch(e)
                    {
                        request = null;
                    }
                }
                else if(window.ActiveXObject)
                {
                    try
                    {
                        request = new ActiveXObject("Msxml2.XMLHTTP");
                    }
                    catch(e)
                    {
                        try
                        {
                            request = new ActiveXObject("Microsoft.XMLHTTP");
                        }
                        catch(e)
                        {
                            request = null;
                        }
                    }
                }
                this.RequestPool.push(request);
            }

            return request;
        }
        
        /// <summary>
        /// Show a loading panel on top of the targeted object.
        /// </summary>
        __Ajax.prototype.ShowLoadingPanel = function()
        {
            if(Daedalus.Utility.GetObject("LoadingPanel")) return;
            
            var panel = document.createElement("div");
            
            panel.id = "LoadingPanel";
            panel.innerHTML = "Working on it...";
            
            panel.style.visibility = "hidden";

            Daedalus.Utility.GetBodyTag().appendChild(panel);
            
            if(document.body.style.maxHeight != null)
            {
                panel.style.position = "fixed";
                panel.style.top = "0px";
                Daedalus.Utility.HorizontalCenterObjectOnScreen(panel);
            }
            else
            {
                panel.style.position = "absolute";
                panel.style.top = Daedalus.Utility.GetScrollY() + "px";
                Daedalus.Utility.HorizontalCenterObjectOnScreen(panel);
                panel.style.left = (Daedalus.Utility.GetScrollX() + parseInt(panel.style.left.replace("px", ""))) + "px";

                LOADING_MESSAGE_TIMER = setInterval(dynamicPosition, 500);
            }

            panel.style.visibility = "";

            function dynamicPosition()
            {
                panel.style.top = Daedalus.Utility.GetScrollY() + "px";
            }
        }
        
        /// <summary>
        /// Hide a loading panel on top of the targeted object.
        /// </summary>
        /// <param name="target">The targeted object covered by the wait panel.</param>
        __Ajax.prototype.HideLoadingPanel = function()
        {
            var panel = document.getElementById("LoadingPanel");
            
            if(panel != null) Daedalus.Utility.GetBodyTag().removeChild(panel);
            clearInterval(LOADING_MESSAGE_TIMER);
        }

        /// <summary>
        /// Select a single node in the XML document base on the xpath.
        /// </summary>
        /// <returns>The reference to the node specified in the xpath.</returns>
        __Ajax.prototype.SelectSingleNode = function(xmlDoc, xPath)
        {
            return (xmlDoc.evaluate ? xmlDoc.evaluate(xPath, xmlDoc, null, 0, null).iterateNext() : xmlDoc.selectSingleNode(xPath));
        }

        /// <summary>
        /// Select a single node in the XML document base on the xpath.
        /// </summary>
        /// <returns>The reference to the node specified in the xpath.</returns>
        __Ajax.prototype.SelectNodes = function(xmlDoc, xPath)
        {
            var result = new Array();
            
            if(xmlDoc.evaluate)
            {
                var snapShotList = xmlDoc.evaluate(xPath, xmlDoc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
                for(var i=0 ; i<snapShotList.snapshotLength; i++)
                {
                    result.push(nodesSnapshot.snapshotItem(i));
                }
                
                return result;
            }
            else if(xmlDoc.selectNodes)
            {
                return xmlDoc.selectSingleNode(xPath);
            }
        }
    })();

    /// <summary>
    /// Provides utility functions for other objects.
    /// </summary>
    function __Utility()
    {
        /// <summary>
        /// URL encode a string.
        /// </summary>
        /// <param name="input">The input string to encode.</param>
        /// <returns>The encoded string.</returns>
        this.UrlEncode = function(input)
        {
            return escape(input).replace(new RegExp("\\+", "g"), "%2B");
        }
        
        /// <summary>
        /// Set maximum character limit to a text box control.
        /// </summary>
        /// <param name="textbox">The text box control to set maximum character limit to.</param>
        /// <param name="maxLength">The maximum number of characters allowed.</param>
        this.SetMaxLength = function(textbox, maxLength)
        {
            function keydownEvent(e)
            {
                var chr = null;
                
                if(window.event)
                {
                    chr = window.event.keyCode;
                }
                else if(e)
                {
                    chr = e.which;
                }
                
                if(chr)
                {
                    var length = this.value.length;
                    
                    if(length >= maxLength)
                    {
                        if(length > maxLength) this.value = this.value.substring(0, maxLength);
                        return (chr == 46 || chr == 8 || chr == 37 || chr == 38 || chr == 39 || chr == 40);
                    }
                }
            }
            
            textbox.onkeydown = keydownEvent;
        }

        /// <summary>
        /// Get the horizontal scroll offset.
        /// </summary>
        /// <param name="html">The HTML code to encode.</param>
        /// <returns>The horizontal scroll offset.</returns>
        this.HtmlEncode = function(html)
        {
            var div = document.createElement("div");
            var text = document.createTextNode(html);
            
            div.appendChild(text);
            return div.innerHTML;
        }
        
        /// <summary>
        /// Get the horizontal scroll offset.
        /// </summary>
        /// <returns>The horizontal scroll offset.</returns>
        this.GetScrollX = function()
        {
            var x = 0;
            
            if(typeof(window.pageYOffset) == "number")
            {
                //Netscape compliant
                x = window.pageXOffset;
            }
            else if(document.body && (document.body.scrollLeft || document.body.scrollTop))
            {
                //DOM compliant
                x = document.body.scrollLeft;
            }
            else if(document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop))
            {
                //IE6 standards compliant mode
                x = document.documentElement.scrollLeft;
            }
            return x;
        }

        /// <summary>
        /// Get the vertical scroll offset.
        /// </summary>
        /// <returns>The vertical scroll offset.</returns>
        this.GetScrollY = function()
        {
            var y = 0;

            if(typeof(window.pageYOffset) == "number")
            {
                //Netscape compliant
                y = window.pageYOffset;
            }
            else if(document.body && (document.body.scrollLeft || document.body.scrollTop))
            {
                //DOM compliant
                y = document.body.scrollTop;
            }
            else if(document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop))
            {
                //IE6 standards compliant mode
                y = document.documentElement.scrollTop;
            }

            return y;
        }

        /// <summary>
        /// Get the width of the window.
        /// </summary>
        /// <returns>The width of the window.</returns>
        this.GetWindowWidth = function()
        {
            var width = 0;

            if(typeof(window.innerWidth) == "number")
            {
                //Non-IE
                width = window.innerWidth;
            }
            else if(document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight))
            {
                //IE 6+ in 'standards compliant mode'
                width = document.documentElement.clientWidth;
            }
            else if(document.body && (document.body.clientWidth || document.body.clientHeight))
            {
                //IE 4 compatible
                width = document.body.clientWidth;
            }

            return width;
        }

        /// <summary>
        /// Get the height of the window.
        /// </summary>
        /// <returns>The height of the window.</returns>
        this.GetWindowHeight = function()
        {
            var height = 0;

            if(typeof(window.innerWidth) == "number")
            {
                //Non-IE
                height = window.innerHeight;
            }
            else if(document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight))
            {
                //IE 6+ in 'standards compliant mode'
                height = document.documentElement.clientHeight;
            }
            else if(document.body && (document.body.clientWidth || document.body.clientHeight))
            {
                //IE 4 compatible
                height = document.body.clientHeight;
            }
            
            return height;
        }

        /// <summary>
        /// Get an object in the page.
        /// </summary>
        /// <param name="id">The object ID.</param>
        /// <returns>The reference to the object element.</returns>
        this.GetObject = function(id)
        {
            return document.getElementById(id);
        }
        
        /// <summary>
        /// Get body tag element of the page.
        /// </summary>
        /// <returns>The reference to the body tag element.</returns>
        this.GetBodyTag = function()
        {
            return document.getElementsByTagName("body").item(0);
        }
        
        /// <summary>
        /// Add a style class to an object.
        /// </summary>
        /// <param name="obj">An object on the screen.</param>
        /// <param name="className">The name of the style class to add.</param>
        this.AddClass = function(obj, className)
        {
            var lower = className.toLowerCase();
            var classList = (obj.className.toLowerCase()).split(" ");
            
            for(var i=0; i<classList.length; i++)
            {
                if(classList[i] == lower) return;
            }
            
            obj.className += " " + className;
        }

        /// <summary>
        /// Remove a style class to an object.
        /// </summary>
        /// <param name="obj">An object on the screen.</param>
        /// <param name="className">The name of the style class to remove.</param>
        this.RemoveClass = function(obj, className)
        {
            var lower = className.toLowerCase();
            var classList = obj.className.split(" ");
            var newList = new Array();
            
            for(var i=0; i<classList.length; i++)
            {
                if(classList[i].toLowerCase() != lower) newList.push(classList[i]);
            }
            
            obj.className = newList.join(" ");
        }

        /// <summary>
        /// Gets the absolute top position of any object on the browser screen.
        /// </summary>
        /// <param name="obj">An object on the screen.</param>
        /// <return>The top position of the object.</return>
        this.TopPosition = function(obj)
        {
            var top = obj.offsetTop;
            var container = obj.offsetParent;
            
            while(container)
            {
                top += container.offsetTop;
                container = container.offsetParent;
            }
            
            return top;
        }

        /// <summary>
        /// Gets the absolute bottom position of any object on the browser screen.
        /// </summary>
        /// <param name="obj">An object on the screen.</param>
        /// <return>The bottom position of the object.</return>
        this.BottomPosition = function(obj)
        {
            var top = obj.offsetTop;
            var container = obj.offsetParent;
            
            while(container)
            {
                top += container.offsetTop;
                container = container.offsetParent;
            }
            
            return (top + obj.offsetHeight);
        }

        /// <summary>
        /// Gets the absolute left position of any object on the browser screen.
        /// </summary>
        /// <param name="obj">An object on the screen.</param>
        /// <return>The left position of the object.</return>
        this.LeftPosition = function(obj)
        {
            var left = obj.offsetLeft;
            var container = obj.offsetParent;
            
            while(container)
            {
                left += container.offsetLeft;
                container = container.offsetParent;
            }
            
            return left;
        }

        /// <summary>
        /// Gets the absolute right position of any object on the browser screen.
        /// </summary>
        /// <param name="obj">An object on the screen.</param>
        /// <return>The right position of the object.</return>
        this.RightPosition = function(obj)
        {
            var left = obj.offsetLeft;
            var container = obj.offsetParent;
            
            while(container)
            {
                left += container.offsetLeft;
                container = container.offsetParent;
            }
            
            return (left + obj.offsetWidth);
        }

        /// <summary>
        /// Make an object visible on screen.
        /// </summary>
        /// <param name="obj">An object on the screen.</param>
        this.ShowObject = function(obj)
        {
            obj.style.visibility = "visible";
            obj.style.display = "";
        }

        /// <summary>
        /// Make an object invisible on screen.
        /// </summary>
        /// <param name="obj">An object on the screen.</param>
        this.HideObject = function(obj)
        {
            obj.style.visibility = "hidden";
            obj.style.display = "none";
        }

        /// <summary>
        /// Toggle the visibility of an object.
        /// </summary>
        /// <param name="obj">An object on the screen.</param>
        this.ToggleVisibility = function(obj)
        {
            (obj.style.visibility == "hidden") ? ShowObject(obj) : HideObject(obj);
        }

        /// <summary>
        /// Move an object's top to the specified location.
        /// </summary>
        /// <param name="x">The vertical position.</param>
        /// <param name="y">The horizontal position.</param>
        /// <param name="obj">An object on the screen.</param>
        this.MoveObject = function(x, y, obj)
        {
            obj.style.left = x + "px";
            obj.style.top = y + "px";
        }

        /// <summary>
        /// Move an object to the center of the browser screen.
        /// </summary>
        /// <param name="obj">An object on the screen.</param>
        this.CenterObject = function(obj)
        {
            var winHeight = (window.innerHeight ? window.innerHeight : Math.max(document.body.clientHeight, (document.documentElement ? document.documentElement.clientHeight : 0)));
            var winWidth = (window.innerWidth ? window.innerWidth : Math.max(document.body.clientWidth, (document.documentElement ? document.documentElement.clientWidth : 0)));

            var x = (winWidth + this.GetScrollX() - obj.offsetWidth) / 2;
            var y = (winHeight + this.GetScrollY() - obj.offsetHeight) / 2;

            this.MoveObject(x, y, obj);
        }

        /// <summary>
        /// Middle align an object on screen horizontally.
        /// </summary>
        /// <param name="obj">An object on the screen.</param>
        this.HorizontalCenterObjectOnScreen = function(obj)
        {
            var winWidth = (window.innerWidth ? window.innerWidth : Math.max(document.body.clientWidth, (document.documentElement ? document.documentElement.clientWidth : 0)));

            var x = (winWidth - obj.offsetWidth) / 2;

            obj.style.left = x + "px";
        }

        /// <summary>
        /// Middle align an object on screen vertically.
        /// </summary>
        /// <param name="obj">An object on the screen.</param>
        this.VerticalCenterObjectOnScreen = function(obj)
        {
            var winHeight = (window.innerHeight ? window.innerHeight : Math.max(document.body.clientHeight, (document.documentElement ? document.documentElement.clientHeight : 0)));

            var y = (winHeight - obj.offsetHeight) / 2;

            obj.style.top = y + "px";
        }

        /// <summary>
        /// Trim all space on the left side of the string.
        /// </summary>
        /// <param name="str">The string to trim.</param>
        /// <returns>The new string with all space on the left removed.</returns>
        this.LTrim = function(str) 
        {
            var index = -1;

            for(var i=0; i<str.length; i++)
            {
                if(str.charAt(i) != ' ' && str.charAt(i) != '\n' && str.charAt(i) != '\t' && str.charAt(i) != '\r') break;
                index = i;
            }

            return str.substring(index+1, str.length);
        }

        /// <summary>
        /// Trim all space on the right side of the string.
        /// </summary>
        /// <param name="str">The string to trim.</param>
        /// <returns>The new string with all space on the right removed.</returns>
        this.RTrim = function(str) 
        {
            var index = str.length;

            for(var i=str.length-1; i>0; i--)
            {
                if(str.charAt(i) != ' ' && str.charAt(i) != '\n' && str.charAt(i) != '\t' && str.charAt(i) != '\r') break;
                index = i;
            }

            return str.substring(0, index);
        }
        
        /// <summary>
        /// Trim all space on both side of the string.
        /// </summary>
        /// <param name="str">The string to trim.</param>
        /// <returns>The new string with all space on both sides removed.</returns>
        this.Trim = function(str)
        {
            return this.RTrim(this.LTrim(str));
        }
        
        /// <summary>
        /// Display a popup window on screen.
        /// </summary>
        /// <param name="url">The url of the popup page.</param>
        /// <param name="width">The width of the popup page.</param>
        /// <param name="height">The height of the popup page.</param>
        /// <param name="center">Center the popup window on screen if true. Default is false.</param>
        this.PopupWindow = function(url, width, height, center)
        {
            var x = (window.screen.availWidth - width) / 2;
            var y = (window.screen.availHeight - height) / 2;

            var popup = window.open(url, "Popup", "toolbar=0,scrollbars=1,location=0,statusbar=0,menubar=0,resizable=0,width=" + width + ",height=" + height + ",left=" + x + ",top=" + y);
            popup.focus();
        }
    }

    /// <summary>
    /// Provides graphical effect functions.
    /// </summary>
    function __GraphicEffects()
    {
        /// <summary>
        /// Apply opacity to object.
        /// </summary>
        /// <param name="object">The targeted object to apply opacity to.</param>
        /// <param name="opacity">The opacity setting (0 - 100).</param>
        this.ApplyOpacity = function(object, opacity)
        {
            var opaVal = 0;
            
            try
            {
                opaVal = parseInt(opacity);
            }
            catch(e)
            {
                opaVal = 100;
            }
            
            
            if(opaVal > 100)
                opaVal = 100;
            else if(opaVal < 0)
                opaVal = 0;
            
            if(object.style.MozOpacity != null)
            {
                object.style.MozOpacity = opaVal / 100;
            }
            if(object.style.opacity != null)
            {
                object.style.opacity = opaVal / 100;
            }
            if(object.style.filter != null)
            {
                object.style.zoom = 1;
                object.style.filter = "alpha(opacity=" + opaVal + ")";
            }
        }
        
        /// <summary>
        /// Apply shadow to object.
        /// </summary>
        /// <param name="object">The targeted object to apply shadow to.</param>
        /// <param name="color">The color of the shadow.</param>
        /// <param name="shadowDirection">The direction of the shadow.</param>
        /// <param name="shadowStrength">The strength of the shadow.</param>
        this.ApplyShadow = function(object, color, shadowDirection, shadowStrength)
        {
            if(object.style.filter != null)
            {
                object.style.filter = "shadow(color:" + color + ",direction:" + shadowDirection + ",strength:" + shadowStrength + ")";
            }
        }
        
        /// <summary>
        /// Apply fade in effect to an object.
        /// </summary>
        /// <param name="object">The targeted object to apply fade in effect to.</param>
        /// <param name="startOpacity">The starting opacity setting (0 - 100).</param>
        /// <param name="endOpacity">The ending opacity setting (0 - 100).</param>
        /// <param name="opacityIncrement">The opacity increment amount for each frame.</param>
        /// <param name="timeout">Time delay between each frame in milliseconds.</param>
        /// <param name="callback">The function that will be called after the fade animation is completed.</param>
        this.FadeIn = function(object, startOpacity, endOpacity, opacityIncrement, timeout, callback)
        {
            var SetOpacity = this.ApplyOpacity;
            
            SetOpacity(object, startOpacity);
            
            var currentOpacity = startOpacity;
            
            function doAnimation()
            {
                currentOpacity += opacityIncrement;
                
                if(currentOpacity > endOpacity)
                {
                    SetOpacity(object, endOpacity);
                    if(callback) callback();
                    
                    clearInterval(evnt);
                }
                else
                {
                    SetOpacity(object, currentOpacity);
                }
            }
            
            var evnt = setInterval(doAnimation, timeout);
        }

        /// <summary>
        /// Apply fade in effect to an object.
        /// </summary>
        /// <param name="object">The targeted object to apply fade in effect to.</param>
        /// <param name="startOpacity">The starting opacity setti?g (0 - 100).</param>
        /// <param name="endOpacity">The ending opacity setting (0 - 100).</param>
        /// <param name="opacityDecrement">The opacity decrement amount for each frame.</param>
        /// <param name="timeout">Time delay between each frame in milliseconds.</param>
        /// <param name="callback">The function that will be called after the fade animation is completed.</param>
        this.FadeOut = function(object, startOpacity, endOpacity, opacityDecrement, timeout, callback)
        {
            var SetOpacity = this.ApplyOpacity;
            
            SetOpacity(object, startOpacity);
            
            var currentOpacity = startOpacity;
            
            function doAnimation()
            {
                currentOpacity -= opacityDecrement;
                
                if(currentOpacity < endOpacity)
                {
                    SetOpacity(object, endOpacity);
                    if(callback) callback();
                    
                    clearInterval(evnt);
                }
                else
                {
                    SetOpacity(object, currentOpacity);
                }
            }
            
            var evnt = setInterval(doAnimation, timeout);
        }
        
        /// <summary>
        /// Apply move animation to an object.
        /// </summary>
        /// <param name="object">The targeted object to apply fade in effect to.</param>
        /// <param name="startLocation">The starting location.</param>
        /// <param name="distance">The distance to move.</param>
        /// <param name="speed">The distance in pixels to move for each frame.</param>
        /// <param name="direction">The opacity decrement amount for each frame.</param>
        /// <param name="timeout">Time delay between each frame in milliseconds.</param>
        /// <param name="callback">The function that will be called after the animation is completed.</param>
        this.Move = function(object, startLocation, distance, speed, direction, timeout, callback)
        {
            direction = direction.toLowerCase();
            
            if(direction == "left" || direction == "right")
                object.style.left = startLocation;
            else if(direction == "up" || direction == "down")
                object.style.top = startLocation;
            
            var currentLocation = startLocation;
            var distanceLeft = distance
            
            function doAnimation()
            {
                if(direction == "left" || direction == "up")
                    currentLocation -= speed;
                else if(direction == "right" || direction == "down")
                    currentLocation += speed;
                
                distanceLeft -= speed;
                
                if(distanceLeft > 0)
                {
                    if(direction == "left" || direction == "right")
                        object.style.left = currentLocation + "px";
                    else if(direction == "up" || direction == "down")
                        object.style.top = currentLocation + "px";
                }
                else
                {
                    if(direction == "left" || direction == "up")
                        object.style.left = (startLocation - distance) + "px";
                    else if(direction == "right" || direction == "down")
                        object.style.top = (startLocation + distance) + "px";
                    
                    if(callback) callback();
                    clearInterval(evnt);
                }
            }
            
            var evnt = setInterval(doAnimation, timeout);
        }
        
        this.Expand = function(object, initialSize, targetSize, speed, timeout, callback)
        {
            object.style.width = initialSize.Width + "px";
            object.style.height = initialSize.Height + "px";
            
            var currentSize = initialSize;
            
            function doAnimation()
            {
                if(currentSize.Width < targetSize.Width || currentSize.Height < targetSize.Height)
                {
                    if(currentSize.Width < targetSize.Height) currentSize.Width += Math.ceil((targetSize.Width - currentSize.Width) * (speed / 100));
                    if(currentSize.Height < targetSize.Height) currentSize.Height += Math.ceil((targetSize.Height - currentSize.Height) * (speed / 100));
                    
                    object.style.width = currentSize.Width + "px";
                    object.style.height = currentSize.Height + "px";
                }
                else
                {
                    object.style.width = targetSize.Width + "px";
                    object.style.height = targetSize.Height + "px";
                    if(callback) callback();
                    
                    clearInterval(evnt);
                }
            }
            
            var evnt = setInterval(doAnimation, timeout);
        }
    }
}

/// <summary>
/// Add on method to javascript functions, allows inheritance of another class.
/// </summary>
/// <param name="parent">The parent class to inherit from.</param>
Function.prototype.Inherits = function(parent)
{
    if(parent.constructor == Function) 
    {
        // Inherits a normal class
        this.prototype = new parent;
        this.prototype.constructor = this;
        this.prototype.BaseClass = parent.prototype;
    }
    else
    {
        // Inherits an abstract class
        this.prototype = parent;
        this.prototype.constructor = this;
        this.prototype.BaseClass = parent;
    }
}

/// <summary>
/// Add on method to javascript Array object, allows indexOf function for IE.
/// </summary>
/// <param name="element">The element to search for.</param>
/// <param name="beginIndex">The starting position.</param>
/// <returns>The position of the element in the array, if exist; otherwise, -1.</returns>
Array.prototype.indexOf = function(element, beginIndex)
{
	var start = (beginIndex < 0 ? this.length + beginIndex : beginIndex || 0);
	
	for(i=start; i<this.length; i++)
	{
		if(element === this[i]) return i;
	}
	
	return -1;
}