//Remember to include the IPCore.js file before this file in the pages where necessary.
//--- Namespace
IPCore.Dom = {};

//--- ANIMATOR --------------------------------------------------------------------------------------------------------------
IPCore.Dom.Animator = function(timerLength, defaultSlideSpeed, defaultElementDisplayStyle)
{
    //http://www.harrymaugans.com/2007/03/06/how-to-create-an-animated-sliding-collapsible-div-with-javascript-and-css/

    var timerLen = (timerLength ? timerLength : 5);
    var defSlideSpeed = (defaultSlideSpeed ? defaultSlideSpeed : 250);
    var elementDisplayStyle = (defaultElementDisplayStyle ? defaultElementDisplayStyle : 'inline');

    var timerID = new Array();
    var startTime = new Array();
    var obj = new Array();
    var endHeight = new Array();
    var endWidth = new Array();
    var moving = new Array();
    var dir = new Array();
    var slideAniLen = new Array();

    this.SlideUp = function(element, slideSpeed)
    {
        if (element)
        {
            if (moving[element.id])
            {
                return; // already busy with animation
            }

            if (element.style.display == 'none')
            {
                return; // cannot slide up something that is already hidden
            }

            moving[element.id] = true;
            dir[element.id] = 'up';
            slideAniLen[element.id] = (slideSpeed ? slideSpeed : defaultSlideSpeed);
            this.StartSlide(element);
        }

        return true;
    }

    this.SlideDown = function(element, slideSpeed)
    {
        if (element)
        {
            if (moving[element.id])
            {
                return; // already busy with animation
            }

            if (element.style.display != 'none')
            {
                return; // cannot slide down something that is already visible
            }

            moving[element.id] = true;
            dir[element.id] = 'down';
            slideAniLen[element.id] = (slideSpeed ? slideSpeed : defaultSlideSpeed);
            this.StartSlide(element);
        }

        return true;
    }

    this.SlideLeft = function(element, slideSpeed)
    {
        if (element)
        {
            if (moving[element.id])
            {
                return; // already busy with animation
            }

            if (element.style.display == 'none')
            {
                return; // cannot slide up something that is already hidden
            }

            moving[element.id] = true;
            dir[element.id] = 'left';
            slideAniLen[element.id] = (slideSpeed ? slideSpeed : defaultSlideSpeed);
            this.StartSlide(element);
        }

        return true;
    }

    this.SlideRight = function(element, slideSpeed)
    {
        if (element)
        {
            if (moving[element.id])
            {
                return; // already busy with animation
            }

            if (element.style.display != 'none')
            {
                return; // cannot slide up something that is already hidden
            }

            moving[element.id] = true;
            dir[element.id] = 'right';
            slideAniLen[element.id] = (slideSpeed ? slideSpeed : defaultSlideSpeed);
            this.StartSlide(element);
        }

        return true;
    }

    this.SlideIn = function(element, slideSpeed)
    {
        if (element)
        {
            if (moving[element.id])
            {
                return; // already busy with animation
            }

            if (element.style.display == 'none')
            {
                return; // cannot slide up something that is already hidden
            }

            moving[element.id] = true;
            dir[element.id] = 'upleft';
            slideAniLen[element.id] = (slideSpeed ? slideSpeed : defaultSlideSpeed);
            this.StartSlide(element);
        }

        return true;
    }

    this.SlideOut = function(element, slideSpeed)
    {
        if (element)
        {
            if (moving[element.id])
            {
                return; // already busy with animation
            }

            if (element.style.display != 'none')
            {
                return; // cannot slide up something that is already hidden
            }

            moving[element.id] = true;
            dir[element.id] = 'downright';
            slideAniLen[element.id] = (slideSpeed ? slideSpeed : defaultSlideSpeed);
            this.StartSlide(element);
        }

        return true;
    }

    this.StartSlide = function(element)
    {
        if (element)
        {
            obj[element.id] = element;

            element.style.overflow = 'hidden';
            if (isNaN(parseFloat(element.style.height)))
            {
                element.style.height = element.scrollHeight;
            }
            else if (element.style.height.indexOf('%') != -1)
            {
                element.style.height = parseFloat(element.clientHeight);
            }
            if (isNaN(parseFloat(element.style.width)))
            {
                element.style.width = element.scrollWidth;
            }
            else if (element.style.width.indexOf('%') != -1)
            {
                element.style.width = parseFloat(element.clientWidth);
            }

            endHeight[element.id] = element.style.height;
            endWidth[element.id] = element.style.width;
            startTime[element.id] = (new Date()).getTime();

            if (dir[element.id].indexOf('down') != -1)
            {
                element.style.height = '1px';
            }
            if (dir[element.id].indexOf('right') != -1)
            {
                element.style.width = '1px';
            }

            element.style.display = elementDisplayStyle;
            var instance = this;
            timerID[element.id] = setInterval(function() { instance.SlideTick(element.id); }, timerLen);
        }

        return true;
    }

    this.SlideTick = function(elementId)
    {
        var elapsed = (new Date()).getTime() - startTime[elementId];

        if (elapsed > slideAniLen[elementId])
        {
            this.EndSlide(elementId)
        }
        else
        {
            if ((dir[elementId].indexOf('up') != -1) || (dir[elementId].indexOf('down') != -1))
            {
                var hd = Math.round(elapsed / slideAniLen[elementId] * parseFloat(endHeight[elementId]));
                if (dir[elementId].indexOf('up') != -1)
                {
                    hd = parseFloat(endHeight[elementId]) - hd;
                }

                if (hd == 0)
                {
                    hd = 1;
                }
                obj[elementId].style.height = hd + 'px';
            }

            if ((dir[elementId].indexOf('left') != -1) || (dir[elementId].indexOf('right') != -1))
            {
                var wd = Math.round(elapsed / slideAniLen[elementId] * parseFloat(endWidth[elementId]));
                if (dir[elementId].indexOf('left') != -1)
                {
                    wd = parseFloat(endWidth[elementId]) - wd;
                }

                if (wd == 0)
                {
                    wd = 1;
                }
                obj[elementId].style.width = wd + 'px';
            }
        }

        return true;
    }

    this.EndSlide = function(elementId)
    {
        if (elementId)
        {
            clearInterval(timerID[elementId]);

            if ((dir[elementId].indexOf('up') != -1) || (dir[elementId].indexOf('left') != -1))
            {
                obj[elementId].style.display = 'none';
            }

            obj[elementId].style.height = parseFloat(endHeight[elementId]) + 'px';
            obj[elementId].style.width = parseFloat(endWidth[elementId]) + 'px';

            delete (moving[elementId]);
            delete (timerID[elementId]);
            delete (startTime[elementId]);
            delete (endHeight[elementId]);
            delete (endWidth[elementId]);
            delete (obj[elementId]);
            delete (dir[elementId]);
            delete (slideAniLen[elementId]);

            return true;
        }
    }
}

//---------------------------------------------------------------------------------------------------------------------------
IPCore.Dom.DomHelper = function() //concept from JQuery
{
    var Items = new Array();
    var filterIdx = 0;
    var filters = new Array();

    //Animation stuff
    this.SLIDE_SPEED_NONE = 1; //cannot be 0
    this.SLIDE_SPEED_SLOW = 1500;
    this.SLIDE_SPEED_MEDIUM = 750;
    this.SLIDE_SPEED_FAST = 500;
    this.SLIDE_SPEED_DEFAULT = this.SLIDE_SPEED_FAST;
    this.Animator = new IPCore.Dom.Animator(5, this.SLIDE_SPEED_DEFAULT);

    //Returns the number of entries in the items array.
    this.Count = function()
    {
        var count = 0;
        if (Items)
        {
            count = Items.length;
        }
        return count;
    };

    //Returns the DomHelper with items array populated with elements matching the tagName.
    this.Get = function(tagName)
    {
        if (String.IsNullOrEmpty(tagName))
        {
            throw new Error('Argument "tagName". No element tag name specified.');
        }

        if (document)
        {
            Items = document.getElementsByTagName(tagName);
        }
        else
        {
            Items = new Array();
        }
        return this;
    };

    //Returns the element matching the id.
    this.GetElement = function(id)
    {
        if (String.IsNullOrEmpty(id))
        {
            throw new Error('Argument "id". No element id specified.');
        }

        var element = null;
        if (document)
        {
            element = document.getElementById(id);
        }
        return element;
    };

    //Returns the DomHelpher with items array populated from the current items array matching the className.
    this.FilterByClassName = function(className)
    {
        //NOTE: Allow empty class name to filter all elements with no class name.

        filters[filterIdx] = new Array(Items)[0];
        if (this.Count() > 0)
        {
            var temp = new Array();
            var addedIdx = 0;
            for (var idx = 0; idx < Items.length; idx++)
            {
                if ((String.IsNullOrEmpty(Items[idx].className) && String.IsNullOrEmpty(className)) ||
                    ((!String.IsNullOrEmpty(Items[idx].className) && !String.IsNullOrEmpty(className)) && (Items[idx].className.toLowerCase() == className.toLowerCase()))
                    )
                {
                    temp[addedIdx++] = Items[idx];
                }
            }
            Items = temp;
        }
        else
        {
            Items = new Array();
        }
        filterIdx++;
        return this;
    };

    //Returns the DomHelpher with items array populated from the current items array matching the id.
    this.FilterById = function(id)
    {
        if (String.IsNullOrEmpty(id))
        {
            throw new Error('Argument "id". No element id specified.');
        }

        filters[filterIdx] = new Array(Items)[0];
        if (this.Count() > 0)
        {
            var temp = new Array();
            var addedIdx = 0;
            for (var idx = 0; idx < Items.length; idx++)
            {
                if (Items[idx].id && (Items[idx].id.toLowerCase() == id.toLowerCase()))
                {
                    temp[addedIdx++] = Items[idx];
                }
            }
            Items = temp;
        }
        else
        {
            Items = new Array();
        }
        filterIdx++;
        return this;
    };

    //Returns the DomHelpher with items array restored to the array before the last Filter call.
    this.EndFilter = function()
    {
        if (filters && (filterIdx > 0))
        {
            --filterIdx;
            Items = filters[filterIdx];
            delete (filters[filterIdx]);
        }
        return this;
    };

    //Returns the DomHelpher with items array populated from the current items array matching the tagName.
    this.Find = function(tagName)
    {
        if (String.IsNullOrEmpty(tagName))
        {
            throw new Error('Argument "tagName". No element tag name specified.');
        }

        filters[filterIdx] = new Array(Items)[0];
        if (this.Count() > 0)
        {
            var temp = new Array();
            var addedIdx = 0;
            var toAdd = null;
            for (var childIdx = 0; childIdx < Items.length; childIdx++)
            {
                toAdd = Items[childIdx].getElementsByTagName(tagName);
                if (toAdd && toAdd.length > 0)
                {
                    for (var idx = 0; idx < toAdd.length; idx++)
                    {
                        temp = temp.concat(toAdd[idx]);
                    }
                }
            }
            Items = temp;
        }
        else
        {
            Items = new Array();
        }
        filterIdx++;
        return this;
    };

    //Slides the element up at the specified speed.
    this.SlideUp = function(slideSpeed)
    {
        if (!slideSpeed)
        {
            slideSpeed = this.SLIDE_SPEED_DEFAULT;
        }

        if (this.Count() > 0)
        {
            for (var idx = 0; idx < Items.length; idx++)
            {
                if (Items[idx])
                {
                    this.Animator.SlideUp(Items[idx], slideSpeed);
                }
            }
        }
        return true;
    };
    //Slides the element up with no animation
    this.SlideUpInstant = function()
    {
        return this.SlideUp(this.SLIDE_SPEED_NONE);
    };
    //Slides the element up at a slow speed.
    this.SlideUpSlow = function()
    {
        return this.SlideUp(this.SLIDE_SPEED_SLOW);
    };
    //Slides the element up at a medium speed.
    this.SlideUpMedium = function()
    {
        return this.SlideUp(this.SLIDE_SPEED_MEDIUM);
    };
    //Slides the element up at a fast speed.
    this.SlideUpFast = function()
    {
        return this.SlideUp(this.SLIDE_SPEED_FAST);
    };

    //Slides the element down at the specified speed.
    this.SlideDown = function(slideSpeed)
    {
        if (!slideSpeed)
        {
            slideSpeed = this.SLIDE_SPEED_DEFAULT;
        }

        if (this.Count() > 0)
        {
            for (var idx = 0; idx < Items.length; idx++)
            {
                if (Items[idx])
                {
                    this.Animator.SlideDown(Items[idx], slideSpeed);
                }
            }
        }
        return true;
    };
    //Slides the element down with no animation
    this.SlideDownInstant = function()
    {
        return this.SlideDown(this.SLIDE_SPEED_NONE);
    };
    //Slides the element down at a slow speed.
    this.SlideDownSlow = function()
    {
        return this.SlideDown(this.SLIDE_SPEED_SLOW);
    };
    //Slides the element down at a medium speed.
    this.SlideDownMedium = function()
    {
        return this.SlideDown(this.SLIDE_SPEED_MEDIUM);
    };
    //Slides the element down at a fast speed.
    this.SlideDownFast = function()
    {
        return this.SlideDown(this.SLIDE_SPEED_FAST);
    };

    //Slides the element left at the specified speed.
    this.SlideLeft = function(slideSpeed)
    {
        if (!slideSpeed)
        {
            slideSpeed = this.SLIDE_SPEED_DEFAULT;
        }

        if (this.Count() > 0)
        {
            for (var idx = 0; idx < Items.length; idx++)
            {
                if (Items[idx])
                {
                    this.Animator.SlideLeft(Items[idx], slideSpeed);
                }
            }
        }
        return true;
    };
    //Slides the element left with no animation
    this.SlideLeftInstant = function()
    {
        return this.SlideLeft(this.SLIDE_SPEED_NONE);
    };
    //Slides the element left at a slow speed.
    this.SlideLeftSlow = function()
    {
        return this.SlideLeft(this.SLIDE_SPEED_SLOW);
    };
    //Slides the element left at a medium speed.
    this.SlideLeftMedium = function()
    {
        return this.SlideLeft(this.SLIDE_SPEED_MEDIUM);
    };
    //Slides the element left at a fast speed.
    this.SlideLeftFast = function()
    {
        return this.SlideLeft(this.SLIDE_SPEED_FAST);
    };

    //Slides the element right at the specified speed.
    this.SlideRight = function(slideSpeed)
    {
        if (!slideSpeed)
        {
            slideSpeed = this.SLIDE_SPEED_DEFAULT;
        }

        if (this.Count() > 0)
        {
            for (var idx = 0; idx < Items.length; idx++)
            {
                if (Items[idx])
                {
                    this.Animator.SlideRight(Items[idx], slideSpeed);
                }
            }
        }
        return true;
    };
    //Slides the element right with no animation
    this.SlideRightInstant = function()
    {
        return this.SlideRight(this.SLIDE_SPEED_NONE);
    };
    //Slides the element right at a slow speed.
    this.SlideRightSlow = function()
    {
        return this.SlideRight(this.SLIDE_SPEED_SLOW);
    };
    //Slides the element right at a medium speed.
    this.SlideRightMedium = function()
    {
        return this.SlideRight(this.SLIDE_SPEED_MEDIUM);
    };
    //Slides the element right at a fast speed.
    this.SlideRightFast = function()
    {
        return this.SlideRight(this.SLIDE_SPEED_FAST);
    };

    //Slides the element in at the specified speed.
    this.SlideIn = function(slideSpeed)
    {
        if (!slideSpeed)
        {
            slideSpeed = this.SLIDE_SPEED_DEFAULT;
        }

        if (this.Count() > 0)
        {
            for (var idx = 0; idx < Items.length; idx++)
            {
                if (Items[idx])
                {
                    this.Animator.SlideIn(Items[idx], slideSpeed);
                }
            }
        }
        return true;
    };
    //Slides the element in with no animation
    this.SlideInInstant = function()
    {
        return this.SlideIn(this.SLIDE_SPEED_NONE);
    };
    //Slides the element in at a slow speed.
    this.SlideInSlow = function()
    {
        return this.SlideIn(this.SLIDE_SPEED_SLOW);
    };
    //Slides the element in at a medium speed.
    this.SlideInMedium = function()
    {
        return this.SlideIn(this.SLIDE_SPEED_MEDIUM);
    };
    //Slides the element in at a fast speed.
    this.SlideInFast = function()
    {
        return this.SlideIn(this.SLIDE_SPEED_FAST);
    };

    //Slides the element out at the specified speed.
    this.SlideOut = function(slideSpeed)
    {
        if (!slideSpeed)
        {
            slideSpeed = this.SLIDE_SPEED_DEFAULT;
        }

        if (this.Count() > 0)
        {
            for (var idx = 0; idx < Items.length; idx++)
            {
                if (Items[idx])
                {
                    this.Animator.SlideOut(Items[idx], slideSpeed);
                }
            }
        }
        return true;
    };
    //Slides the element out with no animation
    this.SlideOutInstant = function()
    {
        return this.SlideOut(this.SLIDE_SPEED_NONE);
    };
    //Slides the element out at a slow speed.
    this.SlideOutSlow = function()
    {
        return this.SlideOut(this.SLIDE_SPEED_SLOW);
    };
    //Slides the element out at a medium speed.
    this.SlideOutMedium = function()
    {
        return this.SlideOut(this.SLIDE_SPEED_MEDIUM);
    };
    //Slides the element out at a fast speed.
    this.SlideOutFast = function()
    {
        return this.SlideOut(this.SLIDE_SPEED_FAST);
    };
}
var dom = new IPCore.Dom.DomHelper();

