﻿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()
    {
        /// <summary>
        /// Get the XMLHttpRequest object.
        /// </summary>
        /// <returns>The XMLHttpRequest object.</param>
        this.GetRequestObject = function()
        {
            var request = null;
                                        
            if(window.XMLHttpRequest)
            {
                try
                {
                    request = new XMLHttpRequest();
                }
                catch(e)
                {
                    request = false;
                }
            }
            else if(window.ActiveXObject)
            {
                try
                {
                    request = new ActiveXObject("Msxml2.XMLHTTP");
                }
                catch(e)
                {
                    try
                    {
                        request = new ActiveXObject("Microsoft.XMLHTTP");
                    }
                    catch(e)
                    {
                        request = false;
                    }
                }
            }

            return request;
        }
        
        /// <summary>
        /// Show a waiting panel on top of the targeted object.
        /// </summary>
        /// <param name="target">The targeted object to be covered with wait panel.</param>
        this.ShowWaitPanel = function(target)
        {
            var panel = document.createElement("div");
            var icon = document.createElement("div");
            
            target.__waitPanel = panel;
            
            panel.style.top = icon.style.top = Daedalus.Utility.TopPosition(target) + "px";
            panel.style.left = icon.style.left = Daedalus.Utility.LeftPosition(target) + "px";
            
            panel.style.width = icon.style.width = target.offsetWidth + "px";
            panel.style.height = icon.style.height = target.offsetHeight + "px";
            
            panel.style.position = icon.style.position = "absolute";

            panel.className = "WaitPanel";
            icon.className = "WaitPanel_Icon";
            
            panel.__iconPanel = icon;
            
            Daedalus.GraphicEffects.ApplyOpacity(panel, 80);

            Daedalus.Utility.GetBodyTag().appendChild(panel);
            Daedalus.Utility.GetBodyTag().appendChild(icon);
        }
        
        /// <summary>
        /// Hide a waiting panel on top of the targeted object.
        /// </summary>
        /// <param name="target">The targeted object covered by the wait panel.</param>
        this.HideWaitPanel = function(target)
        {
            if(target.__waitPanel != null)
            {
                Daedalus.Utility.GetBodyTag().removeChild(target.__waitPanel);
                Daedalus.Utility.GetBodyTag().removeChild(target.__waitPanel.__iconPanel);
                target.__waitPanel = null;
            }
        }
    }

    /// <summary>
    /// Provides utility functions for other objects.
    /// </summary>
    function __Utility()
    {
        /// <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 - obj.offsetWidth) / 2;
            var y = (winHeight - obj.offsetHeight) / 2;

            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.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>
        this.FadeIn = function(object, startOpacity, endOpacity, opacityIncrement, timeout)
        {
            var SetOpacity = this.ApplyOpacity;
            
            SetOpacity(object, startOpacity);
            
            var currentOpacity = startOpacity;
            
            function doAnimation()
            {
                currentOpacity += opacityIncrement;
                
                if(currentOpacity > endOpacity)
                {
                    SetOpacity(object, endOpacity);
                }
                else
                {
                    SetOpacity(object, currentOpacity);
                    setTimeout(doAnimation, timeout);
                }
            }
            
            doAnimation();
        }

        /// <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>
        this.FadeOut = function(object, startOpacity, endOpacity, opacityDecrement, timeout)
        {
            var SetOpacity = this.ApplyOpacity;
            
            SetOpacity(object, startOpacity);
            
            var currentOpacity = startOpacity;
            
            function doAnimation()
            {
                currentOpacity -= opacityDecrement;
                
                if(currentOpacity < endOpacity)
                {
                    SetOpacity(object, endOpacity);
                }
                else
                {
                    SetOpacity(object, currentOpacity);
                    setTimeout(doAnimation, timeout);
                }
            }
            
            doAnimation();
        }
    }
}

/// <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;
    }
}