/*=============================================================================================================================================
                                                               JUNE    FRAMEWORK    v 2.0                                                      
=============================================================================================================================================*/

/*==================================================================================
    Copyright (c) 2008 Costin Trifan                        http://www.june-js.com/ 
                                                                                    
    Permission is hereby granted, free of charge, to any person obtaining a copy    
    of this software and associated documentation files (the "Software"), to deal   
    in the Software without restriction, including without limitation the rights    
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell       
    copies of the Software, and to permit persons to whom the Software is           
    furnished to do so, subject to the following conditions:                        
                                                                                    
    The above copyright notice and this permission notice shall be included in      
    all copies or substantial portions of the Software.                             
                                                                                    
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR      
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,        
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE     
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER          
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,   
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN       
    THE SOFTWARE.                                                                   
                                                                                    
==================================================================================*/

/*==============================================================
        Description:                                            
            This is the Framework's main library.               
        version: 2.0                                            
        Package: JUNE FRAMEWORK                                 
        Last Edited: Nov 05, 2008                               
==============================================================*/

var JUNE = (function() {
///<summary>The Framework's main Namespace.</summary>
///<returns type="Object" />

    var _version = '2.0';
    
    return {
        start : function(runnable)
        {
        ///<summary>
        ///     This method simply sets up the init method of the script you pass it as an event listener for the load event of the window object.
        ///     This function will be called ONLY AFTER all the page content is loaded.
        ///</summary>
        ///<param name="runnable" type="Object" optional="false">(Required). The name of the Object to call when page loads.</param>
            return JUNE.Event.addHandler(window, "load", runnable.init);
        },
        getVersion : function()
        {
        ///<summary>Gets the version of this framework.</summary>
        ///<returns type="String" />
            return _version;
        }
    }
})();


JUNE.Event = (function()
{
        /* W3C DOM 2 Events Model */
    if (document.addEventListener)
    {
        var addHandler = function(domElement, type, handler) { domElement.addEventListener(type, handler, false); };
        var removeHandler = function(domElement, type, handler) { domElement.removeEventListener(type, handler, false); };
        var preventDefault = function(event) { return event.preventDefault(); };
        var stopPropagation = function(event) { return event.stopPropagation(); };
        var addHandlers = function(domElements, events, handler)
        {
            if ( !JUNE.Util.isArray(domElements) ) {throw new Error(JUNE.Exception.generalError('JUNE.Event.addHandlers', 'The argument < domElements > must be an Array!'));}
            if ( !JUNE.Util.isArray(events) ) {throw new Error(JUNE.Exception.generalError('JUNE.Event.addHandlers', 'The argument < events > must be an Array!'));}

            for (var i=0; i < domElements.length; i++)
            {
                for (var e=0; e < events.length; e++)
                {
                    addHandler(domElements[i], events[e], handler);
                }
            }
        };

        var removeHandlers = function(domElements, events, handler)
        {
            if ( !JUNE.Util.isArray(domElements) ) {throw new Error(JUNE.Exception.generalError('JUNE.Event.addHandlers', 'The argument < domElements > must be an Array!'));}
            if ( !JUNE.Util.isArray(events) ) {throw new Error(JUNE.Exception.generalError('JUNE.Event.addHandlers', 'The argument < events > must be an Array!'));}

            for (var i=0; i < domElements.length; i++)
            {
                for (var e=0; e < events.length; e++)
                {
                    removeHandler(domElements[i], events[e], handler);
                }
            }
        };
    }
        /* Internet Explorer Events Model */
    else if (document.attachEvent)
    {
        var addHandler = function(domElement, type, handler)
        {
                /* Prevent adding the same handler twice, since DOM 2 Events */
                /* ignores duplicates like this. */
            if (_findHandler(domElement,type,handler) != -1) {return;}

                /* handler2 calls handler as a method of domElement in one of two */
                /* ways, depending on what this version of IE supports, and */
                /* passes it the global event as an argument. */
            var handler2 = function() {
                var event = window.event;

                if (Function.prototype.call) { handler.call(domElement, event); }
                else {
                    domElement._currentListener = handler;
                    domElement._currentListener(event);
                    domElement._currentListener = null;
                }
            };

                /* Add handler2 using IE's attachEvent method. */
            domElement.attachEvent("on" + type, handler2);

                /* Create an object describing this handler so we can clean it up later. */
            var handlerRecord = {
                domElement: domElement,
                type: type,
                handler: handler,
                handler2: handler2
            };

                /* Get a reference to the window object containing domElement. */
            var targetDocument  = domElement.document || domElement;
            var targetWindow    = targetDocument.parentWindow;

                /* Create a unique ID for this handler. */
            var handlerId = "1" + _handlerCounter++;

                /* Store the record of this handler in the window object */
            if (!targetWindow._allHandlers) {targetWindow._allHandlers = {};}
            targetWindow._allHandlers[handlerId] = handlerRecord;

                /* Store this handler's id in domElement */
            if (!domElement._handlers) {domElement._handlers = [];}
            domElement._handlers[domElement._handlers.length] = handlerId;

                /* Set up _removeAllHandlers to clean up all handlers on unload */
            if (!targetWindow._unloadHandlerAdded) {
                targetWindow._unloadHandlerAdded = true;
                targetWindow.attachEvent("onunload", _removeAllHandlers);
            }
        };

        var removeHandler = function(domElement, type, handler)
        {
                /* Find out if the handler was actually added to domElement. */
            var handlerIndex = _findHandler(domElement, type, handler);
            if (handlerIndex == -1) {return;}

                /* Get a reference to the window object containing domElement. */
            var targetDocument = domElement.document || domElement;
            var targetWindow = targetDocument.parentWindow;

                /* Obtain the record of the handler from the window object. */
            var handlerId = domElement._handlers[handlerIndex];
            var handlerRecord = targetWindow._allHandlers[handlerId];

                /* Remove the handler and remove its ID from domElement */
            domElement.detachEvent("on" + type, handlerRecord.handler2);
            domElement._handlers.splice(handlerIndex, 1);

                /* Remove the record of the handler from the window object. */
            delete targetWindow._allHandlers[handlerId];
        };

        var _findHandler = function(domElement, type, handler)
        {
    ///<summary>(Private method). Finds a handler that was previously set to a DOM element.</summary>
    ///<param name="domElement" type="Object" optional="false">(Required). The reference to the DOM element.</param>
    ///<param name="type" type="String" optional="false">(Required). The type of the event.</param>
    ///<param name="handler" type="Function" optional="false">(Required). The name of the handler function.</param>

                /* Get the array of handler IDs added to domElement */
            var handlers = domElement._handlers;
            if (!handlers) {return -1;}

                /* Get a reference to the window object containing domElement */
            var targetDocument = domElement.document || domElement;
            var targetWindow = targetDocument.parentWindow;

                /* Searching backward to (speed up onunload processing), find the handler. */
            for (var i = handlers.length -1; i >= 0; i--) {
                    /* Get the handler's ID from domElement. */
                var handlerId = handlers[i];

                    /* Get the record of the handler from the window object */
                var handlerRecord = targetWindow._allHandlers[handlerId];

                    /* Compare type and handler with the retrieved record */
                if (handlerRecord.type == type && handlerRecord.handler == handler) {return i;}
            }
            return -1;
        };

        var _removeAllHandlers = function()
        {
        ///<summary>(Private method).
        /// Called automatically on page unload;
        /// it removes all handlers that was set while the page was loaded to prevent memory leakage.
        ///</summary>
            var targetWindow = this;
            for (id in targetWindow._allHandlers) {
                var handlerRecord = targetWindow._allHandlers[id];
                    handlerRecord.domElement.detachEvent("on" + handlerRecord.type, handlerRecord.handler2);
                delete targetWindow._allHandlers[id];
            }
        };


        var addHandlers = function(domElements, events, handler)
        {
            if ( !JUNE.Util.isArray(domElements) ) {throw new Error(JUNE.Exception.generalError('JUNE.Event.addHandlers', 'The argument < domElements > must be an Array!'));}
            if ( !JUNE.Util.isArray(events) ) {throw new Error(JUNE.Exception.generalError('JUNE.Event.addHandlers', 'The argument < events > must be an Array!'));}

            for (var i=0; i < domElements.length; i++)
            {
                for (var e=0; e < events.length; e++)
                {
                    addHandler(domElements[i], events[e], handler);
                }
            }
        };

        var removeHandlers = function(domElements, events, handler)
        {
            if ( !JUNE.Util.isArray(domElements) ) {throw new Error(JUNE.Exception.generalError('JUNE.Event.addHandlers', 'The argument < domElements > must be an Array!'));}
            if ( !JUNE.Util.isArray(events) ) {throw new Error(JUNE.Exception.generalError('JUNE.Event.addHandlers', 'The argument < events > must be an Array!'));}

            for (var i=0; i < domElements.length; i++)
            {
                for (var e=0; e < events.length; e++)
                {
                    removeHandler(domElements[i], events[e], handler);
                }
            }
        };

        _handlerCounter = 0;

        var preventDefault = function(event) { return event.returnValue = false; };
        var stopPropagation = function(event) { return event.cancelBubble = true; };
    }


    return {

        addHandler : function(domElement, type, handler)
        {
        ///<summary>This method sets up an event handler function for a particular event type on a particular element.</summary>
        ///<param name="domElement" type="Object" optional="false">(Required). The reference to the DOM element.</param>
        ///<param name="type" type="String" optional="false">(Required). The event type.</param>
        ///<param name="handler" type="Function" optional="false">(Required). The handler function.</param>
            return addHandler(domElement, type, handler);
        },
        removeHandler : function(domElement, type, handler)
        {
        ///<summary>This method removes an event handler that was previously set to an element.</summary>
        ///<param name="domElement" type="Object" optional="false">(Required). The reference to the DOM element.</param>
        ///<param name="type" type="String" optional="false">(Required). The event type.</param>
        ///<param name="handler" type="Function" optional="false">(Required). The handler function.</param>
            return removeHandler(domElement, type, handler);
        },
        addHandlers : function(domElements, events, handler)
        {
        ///<summary>Add an event handler for multiple events to an element.</summary>
        ///<param name="domElements" type="Array" optional="false">(Required). Array holding the references to each of the elements to which a handler will be attached.</param>
        ///<param name="events" type="Array" optional="false">(Required). The list of events.</param>
        ///<param name="handler" type="Function" optional="false">(Required). The handler function.</param>
            return addHandlers(domElements, events, handler);
        },
        removeHandlers : function (domElements, events, handler)
        {
        ///<summary>This method removes the event handlers that were previously set for an element.</summary>
        ///<param name="domElements" type="Array" optional="false">(Required). Array holding the references to each of the elements from which the handler will be removed.</param>
        ///<param name="events" type="Array" optional="false">(Required). A list of events.</param>
        ///<param name="handler" type="Function" optional="false">(Required). The handler function.</param>
            return removeHandlers(domElements, events, handler);
        },
        preventDefault : function(event)
        {
        ///<summary>This method prevents the default action associated with an event from occuring.</summary>
        ///<param name="event" type="Object" optional="false">(Required). The event object.</param>
            return preventDefault(event);
        },
        stopPropagation : function(event)
        {
        ///<summary>This method stops the event from propagating further, and potentially triggering event handlers asigned to ancestors of the element to which the current event handler is assigned.</summary>
        ///<param name="event" type="Object" optional="false">(Required). The event object.</param>
            return stopPropagation(event);
        }
    } /* End return */
})();



/*=============================================================================================================================================
                                                                JUNE.Browser                                                                   
=============================================================================================================================================*/

JUNE.Browser = (function()
{
    var UA = window.navigator.userAgent.toLowerCase();
    return {
        isIE : function(version)
        {
        ///<summary>Detects the Internet Explorer browser.</summary>
        ///<param name="version" type="Number" optional="true">(Optional). The version of IE browser to detect.</param>
        ///<returns type="Boolean" />
            if (JUNE.Browser.isOpera()) { return false; }
            switch (version)
            {
                case  6  : {return UA.indexOf("msie 6") >= 0;};
                case  7  : {return UA.indexOf("msie 7") >= 0;};
                case  8  : {return UA.indexOf("msie 8") >= 0;};
                default  : {return UA.indexOf("msie")   >= 0;};
            }
        },

        isOpera : function()
        {
        ///<summary>Detects the Opera browser.</summary>
        ///<returns type="Boolean" />
            return (UA.indexOf("opera") >= 0);
        },
        isMozilla : function()
        {
        ///<summary>Detects if the browser is a Mozilla-based browser(Firefox, Flock, Safari).</summary>
        ///<returns type="Boolean" />
            return (UA.indexOf("gecko") >= 0);
        },
        isFlock : function()
        {
        ///<summary>Detects the Flock browser.</summary>
        ///<returns type="Boolean" />
            return (UA.indexOf("flock") >= 0);
        },
        isSafari : function()
        {
        ///<summary>Detects the Safari browser.</summary>
        ///<returns type="Boolean" />
            return (UA.indexOf("safari") >= 0);
        },
        isFirefox : function()
        {
        ///<summary>Detects the Firefox browser.</summary>
        ///<returns type="Boolean" />
            if ( JUNE.Browser.isFlock() || JUNE.Browser.isSafari() ) {
                return false;
            }
            else { return (UA.indexOf("firefox") >= 0) ? true : false; }
        },
        isCSS1Compat : function()
        {
        ///<summary>Detects if the browser is CSS1 Compatible.</summary>
        ///<returns type="Boolean" />
            return document.compatMode == "CSS1Compat";
        },
        createImagePreview : function(images, closeWithParent, windowFeatures)
        {
        ///<summary>Opens a popup window to display a selected image.</summary>
        ///<param name="images" type="Array" optional="false">(Required). The reference to each image.</param>
        ///<param name="closeWithParent" type="Boolean" optional="true">(Optional). Whether the popup window should be closed when the parent window is closed. Default value: true</param>
        ///<param name="windowFeatures" type="String" optional="true">(Optional). 
        ///     A list of comma delimited values to define which features should be available.
        ///</param>
            if (!images) {throw new Error(JUNE.Exception.missingArgument("JUNE.Browser.createImagePreview", "images"));}
            if (!JUNE.Util.isArray(images)) {throw new Error(JUNE.Exception.generalError("JUNE.Browser.createImagePreview", "The < images > argument must be an Array."));}
            
            for (var i = 0; i < images.length; i++)
            {
                var image = images[i];
                JUNE.Event.addHandler(image, 'click', function(event)
                {
                    var imageSrc = this.getAttribute("src");
                    if (!imageSrc) {
                        throw new Error(JUNE.Exception.generalError("JUNE.Browser.createImagePreview", "The source of the image is missing."));
                    }
                    windowFeatures = windowFeatures || "width=400, height=200";
                    window.popWin = window.open(imageSrc, 'ImagePreviewWindow', windowFeatures);
                    window.popWin.focus();
                });
            }

            if ( closeWithParent == null ) {
                // close the popup when the parent window is closed
                JUNE.Event.addHandler(window, 'unload', function(event)
                {
                    try {
                        if ( !window.popWin.closed ) {
                            window.popWin.close();
                        }
                    }catch(e) {}
                });
            }
            
        },
        detectPopupBlocker : function()
        {
        ///<summary>Detects if a popup blocker is active.</summary>
        ///<returns type="Boolean" />
            var  url = 'http://june-js.com/'
                ,title = 'test'
                ,features = 'width=10, height=10'
                ,testWindow = window.open(url, title, features);

            try { testWindow.close(); return false; } catch(ex) { return; }
            return true;
        },

        refresh : function()
        {
        ///<summary>Forces the current window to refresh itself.</summary>
            return window.location.href = unescape(window.location.pathname);
        },

        redirect : function(location)
        {
        ///<summary>Redirects the browser to a specific location.</summary>
        ///<param name="url" type="String" optional="false">(Required). The location of the page to navigate to.</param>
            if (location) { return window.location.href = location; }
            else { throw new Error(JUNE.Exception.missingArgument("JUNE.Browser.redirect", "location")); }
        },

        addToFavorites : function(pageTitle, pageUrl)
        {
        ///<summary>Adds the current viewed page to favorites.</summary>
        ///<param name="pageTitle" type="String" optional="true">(Optional). The title of the page that will be added to the favorites.</param>
        ///<param name="pageUrl" type="String" optional="true">(Optional). The url of the page that will be added to the favorites.</param>
            if (!pageTitle) { pageTitle = document.title || "DefaultDocument"; }
            if (!pageUrl) { pageUrl = document.URL; }

            try {
                if (document.all) { window.external.AddFavorite(pageUrl, pageTitle); }
                else if (window.sidebar) { window.sidebar.addPanel(pageTitle, pageUrl, ""); }
                else { throw new Error(JUNE.Exception.generalError("JUNE.Browser.addToFavorites", "The operation could not be completed.")); }
            }
            catch(ex) { alert(ex.message); }
        },

        setAsHomePage : function(domElement, pageUrl)
        {
        ///<summary>Sets as Home Page the selected page.</summary>
        ///<param name="domElement" type="Object" optional="false">(Required). The reference to the DOM element that will set the page as homepage.</param>
        ///<param name="pageUrl" type="String" optional="true">(Optional). The url of the page that will be set as homepage.</param>

            if (!domElement) { JUNE.Exception.missingArgument("JUNE.Browser.setAsHomePage", "domElement"); }
            var url = pageUrl || window.location.href;

            try {
                domElement.style.behavior = "url(#default#homepage)";
                domElement.setHomePage(url);
            }
            catch(ex) {throw new Error(JUNE.Exception.generalError("JUNE.Browser.setAsHomePage", "The operation is not supported by this browser."));}
        },

        parseQueryString : function(keyName)
        {
        ///<summary>Gets the data contained in a given QueryString.</summary>
        ///<param name="keyName" type="String" optional="false">(Required). The name of the parameter to retrieve from querystring.</param>
        ///<returns type="String" />
        ///<remarks></remarks>
            if (!keyName) { throw new Error(JUNE.Exception.missingArgument("JUNE.Browser.parseQueryString", "keyName")); }

            var qs = window.location.search.substring(1);
            // If there is a QueryString.
            if (qs) {
                var qvars = qs.split("&");
                for (var i = 0; i < qvars.length; i++) {
                    var qvar = qvars[i].split("=");
                    if (keyName == qvar[0]) {
                        return qvar[1];
                    }
                }
            }
            else {return "";}
        },
        getWindowWidth : function()
        {
        ///<summary>Gets the value of the browser's width.</summary>
        ///<returns type="Number" />
            var Width = 0;
            if (typeof(window.innerWidth) == 'number') {
                return Width = window.innerWidth;
            }
            else if (document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
                return Width = document.documentElement.clientWidth;
            }
            else if (document.body && (document.body.clientWidth || document.body.clientHeight)) {
                return Width = document.body.clientWidth;
            }
            return Width;
        },
        getWindowHeight : function()
        {
        ///<summary>Gets the value of the browser's height.</summary>
        ///<returns type="Number" />
            var Height = 0;
            if (typeof(window.innerWidth) == 'number') {
                return Height = window.innerHeight;
            }
            else if (document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
                return Height = document.documentElement.clientHeight;
            }
            else if (document.body && (document.body.clientWidth || document.body.clientHeight)) {
                return Height = document.body.clientHeight;
            }
            return Height;
        }
    }
})();






/*=============================================================================================================================================
                                                                JUNE.Cookie                                                                    
=============================================================================================================================================*/

JUNE.Cookie = (function()
{
    return {
        cookiesEnabled: function()
        {
        ///<summary>Checks the client browser for cookies support.</summary>
        ///<returns type="Boolean" />
            return navigator.cookieEnabled;
        },

        setCookie: function(cookieName, value, expiresAfter, path, domain, secure)
        {
        ///<summary>Creates a cookie file on a client computer.</summary>
        ///<param name="cookieName" type="String" optional="false">(Required). The name of the cookie.</param>
        ///<param name="value" type="Object" optional="true">(Optional). The value to store in the cookie.</param>
        ///<param name="expiresAfter" type="Number" optional="true">(Optional). Specifies the number of days before cookie expires. By default, a session cookie will be set</param>
        ///<param name="path" type="String" optional="true">(Optional). The location where the cookie will be active.</param>
        ///<param name="domain" type="String" optional="true">(Optional). The name of the domain.</param>
        ///<param name="secure" type="Boolean" optional="true">(Optional). Whether the https channel should be used in order to access the cookie.</param>
        ///<remarks>http://www.quirksmode.org/js/cookies.html</remarks>
            if (!JUNE.Cookie.cookiesEnabled()) { return null; }
            if (!cookieName) { throw new Error(JUNE.Exception.missingArgument('JUNE.Cookie.setCookie', 'cookieName')); }
            var expires = '';
            if (expiresAfter)
            {
                var date = new Date(),
                    time = date.getTime(),
                    period = (expiresAfter * 24 * 60 * 60 * 1000);
                date.setTime(time + period);
                expires = '; expires=' + date.toGMTString();
            }
            var optionals = ((path) ? ('; path=' + path) : '') + ((domain) ? ('; domain=' + domain) : '') + ((secure) ? ('; secure') : '');
            document.cookie = cookieName + "=" + escape(value) + expires + optionals;
        },

        getCookie: function(cookieName)
        {
        ///<summary>Reads a cookie file from the client computer.</summary>
        ///<param name="cookieName" type="String" optional="false">(Required). The name of the cookie.</param>
        ///<returns type="String" />
        ///<remarks>http://www.quirksmode.org/js/cookies.html</remarks>

            if (!JUNE.Cookie.cookiesEnabled()) { return null; }
            if (!cookieName) { throw new Error(JUNE.Exception.missingArgument('JUNE.Cookie.getCookie', 'cookieName')); }
                var  ckName = cookieName + "="
                    ,cookies = document.cookie.split(';')
                    ,_c = null;
            for(var i = 0; i < cookies.length; i++) {
                _c = cookies[i];
                while (_c.charAt(0) == ' ') {
                    _c = _c.substring(1, _c.length);
                }
                if (_c.indexOf(ckName) == 0) {
                    return unescape(_c.substring(ckName.length, _c.length));
                }
            }
            return null;
        },

        deleteCookie: function(cookieName, path, domain)
        {
        ///<summary>Deletes a cookie file from the client computer.</summary>
        ///<param name="cookieName" type="String" optional="false">(Required). The name of the cookie.</param>
        ///<param name="path" type="String" optional="true">(Optional). The location where the cookie is stored.</param>
        ///<param name="domain" type="String" optional="true">(Optional). The name of the domain.</param>
        ///<remarks>http://www.quirksmode.org/js/cookies.html</remarks>
            try {
                if (!JUNE.Cookie.cookiesEnabled()) { return null; }
                if (!cookieName) { throw new Error(JUNE.Exception.missingArgument('JUNE.Cookie.deleteCookie', 'cookieName')); }
                var optionals = ((path) ? ('; path=' + path) : '') + ((domain) ? ('; domain=' + domain) : '');
                JUNE.Cookie.setCookie(cookieName, '', -7, optionals);
            } catch(ex){ return; }
        }
    }
})();





/*=============================================================================================================================================
                                                                JUNE.Dom                                                                       
=============================================================================================================================================*/
JUNE.Dom = (function()
{
    return {
        find : function(domElement)
        {
        ///<summary>Selects one or more Elements by ID or by reference.</summary>
        ///<param name="domElement" type="Object" optional="false">(Required). The reference to the DOM element(s) to select.</param>
        ///<returns type="Object;Array" />

            var args = arguments;
            var Elements = [];

            if (args.length >= 2)
            {
                for (var i = 0; i < args.length; i++)
                {
                    var _element = args[i];
                    if(typeof _element == 'string')
                    {
                        if (document.getElementById) { _element = document.getElementById(_element); Elements.push(_element);}
                        else if (document.all) { _element = document.all[_element]; Elements.push(_element); }
                        else if (document.layers) { _element = document.layers[_element]; Elements.push(_element); }
                    }
                    else { Elements.push(_element); }
                }
                return Elements;
            }
            else {
                if(typeof domElement == 'string')
                {
                    if (document.getElementById) { return document.getElementById(domElement);}
                    else if (document.all) { return document.all[domElement];}
                    else if (document.layers) { return document.layers[domElement];}
                }
                return domElement;
            }
        },

        getByClass : function(theClassName, parentContainer)
        {
        ///<summary>Returns an array of all DOM elements having the specified css class(es).</summary>
        ///<param name="theClassName" type="String" optional="false">(Required). The name of the css class(es) that act as selector.</param>
        ///<param name="parentContainer" type="Object" optional="true">
        ///     (Optional). 
        ///     The parent element where to search for the elements having the specified css class(es).
        ///     If not specified, the 'document' object will be used as parent element.
        ///</param>
        ///<returns type="Array" />
            if (!theClassName) { throw new Error(JUNE.Exception.missingArgument("JUNE.Dom.getByClass", "theClassName")); }

            var resultArray = [] , element = null , elements = null , _class = null;


            if ( JUNE.Util.isArray(theClassName) )
            {
                elements = parentContainer ? JUNE.Dom.getByTags('*', parentContainer) : JUNE.Dom.getByTags('*');

                for (var e=0; e < elements.length; e++)
                {
                    element = elements[e];
                    for ( var i = 0; i < theClassName.length; i++)
                    {
                        _class = theClassName[i];
                        if (JUNE.Dom.hasClass(element, _class))
                        {
                            resultArray.push(element);
                        }
                    }
                }
                return resultArray;

            }
            else if ( !JUNE.Util.isArray(theClassName) )
            {
                elements = parentContainer ? JUNE.Dom.getByTags('*', parentContainer) : JUNE.Dom.getByTags('*');

                for (var e=0; e < elements.length; e++)
                {
                    element = elements[e];
                    if (JUNE.Dom.hasClass(element, theClassName))
                    {
                        resultArray.push(element);
                    }
                }
                return resultArray;
            }
        },

        hasClass : function(domElement, theClassName)
        {
        ///<summary>Returns a boolean value whether an element has a specific css class or not.</summary>
        ///<param name="domElement" type="Object" optional="false">(Required). The reference to the DOM element.</param>
        ///<param name="theClassName" type="String" optional="false">(Required). The name of the css class.</param>
        ///<returns type="Boolean" />
            if (!domElement) { throw new Error(JUNE.Exception.missingArgument("JUNE.Dom.hasClass", "domElement")); }
            if (!theClassName) { throw new Error(JUNE.Exception.missingArgument("JUNE.Dom.hasClass", "theClassName")); }
            var pattern = new RegExp("(^| )" + theClassName + "( |$)");
            if (pattern.test(domElement.className)) { return true };
            return false;
        },

        addClass : function(domElement, theClassName)
        {
        ///<summary>Adds a css class to a specified DOM element.</summary>
        ///<param name="domElement" type="Object" optional="false">(Required). The reference to the DOM element.</param>
        ///<param name="theClassName" type="String" optional="false">(Required). The name of the css class to add.</param>
        ///<returns type="String" />
            if (!domElement) { throw new Error(JUNE.Exception.missingArgument("JUNE.Dom.addClass", "domElement")); }
            if (!theClassName) { throw new Error(JUNE.Exception.missingArgument("JUNE.Dom.addClass", "theClassName")); }
            if (!JUNE.Dom.hasClass(domElement, theClassName)) {
                if (domElement.className == "") {
                    domElement.className = theClassName;
                }
                else { domElement.className += " " + theClassName; }
            }
        },

        removeClass : function(domElement, theClassName)
        {
        ///<summary>Removes a css class from a specified DOM element.</summary>
        ///<param name="domElement" type="Object" optional="false">(Required). The reference to the DOM element.</param>
        ///<param name="theClassName" type="String" optional="false">(Required). The name of the css class to remove.</param>
        ///<returns type="String" />
            if (!domElement) { throw new Error(JUNE.Exception.missingArgument("JUNE.Dom.removeClass", "domElement")); }
            if (!theClassName) { throw new Error(JUNE.Exception.missingArgument("JUNE.Dom.removeClass", "theClassName")); }
            var pattern = new RegExp("(^| )" + theClassName + "( |$)");
            domElement.className = domElement.className.replace(pattern, "$1");
            domElement.className = domElement.className.replace(/ $/, "");
        },

        getComputedStyle : function(domElement, styleProperty)
        {
        ///<summary>Returns the value of the specified style property of a DOM element.</summary>
        ///<param name="domElement" type="Object" optional="false">(Required). The reference to the DOM element.</param>
        ///<param name="styleProperty" optional="false">(Required). The name of the style property.</param>
        ///<returns type="String" />
            if (!domElement) { throw new Error(JUNE.Exception.missingArgument("JUNE.Dom.getComputedStyle", "domElement")); }
            if (!styleProperty) { throw new Error(JUNE.Exception.missingArgument("JUNE.Dom.getComputedStyle", "styleProperty")); }

            var computedStyle = '';
            if (typeof (domElement.currentStyle) != "undefined") {
                computedStyle = domElement.currentStyle[styleProperty];
            }
            else { computedStyle = document.defaultView.getComputedStyle(domElement, null).getPropertyValue(styleProperty); }
            return computedStyle;
        },

        showCentered : function(domElement)
        {
        ///<summary>Displays an element centered on screen(absolute positioned).</summary>
        ///<param name="domElement" type="Object" optional="false">(Required). The reference to the DOM element.</param>

            if (!domElement) { throw new Error(JUNE.Exception.missingArgument("JUNE.Dom.showCentered", "domElement"));}

            // verify the position style attribute
            var pos = JUNE.Dom.getComputedStyle(domElement, "position");
            if ( !pos || pos != 'absolute') { pos = 'absolute'; domElement.style.position = pos;}

            var  elementWidth = 0
                ,elementHeight = 0;

            elementWidth = parseInt(JUNE.Dom.getComputedStyle(domElement, "width"), 10);
            elementHeight = parseInt(JUNE.Dom.getComputedStyle(domElement, "height"), 10);

            var  windowWidth = JUNE.Browser.getWindowWidth()
                ,windowHeight = JUNE.Browser.getWindowHeight()
                ,Left = Math.round((windowWidth-elementWidth)/2)
                ,Top = Math.round((windowHeight-elementHeight)/2);

            domElement.style.left = Left + "px";
            domElement.style.top = Top + "px";
        },

        toggleClass : function(domElement, defaultClass, newClass)
        {
        ///<summary>Toggles the css class of an element with another.</summary>
        ///<param name="domElement" type="Object" optional="false">(Required). The reference to the DOM element.</param>
        ///<param name="defaultClass" type="String" optional="false">(Required). The name of the default css class applied to the element.</param>
        ///<param name="newClass" type="String" optional="false">(Required). The name of the new css class that will be used to replace the default css class.</param>

            if (!domElement) { throw new Error(JUNE.Exception.missingArgument("JUNE.Dom.toggleClass", "domElement")); }
            if (!defaultClass) { throw new Error(JUNE.Exception.missingArgument("JUNE.Dom.toggleClass", "defaultClass")); }
            if (!newClass) { throw new Error(JUNE.Exception.missingArgument("JUNE.Dom.setStyles", "newClass")); }

            if (!JUNE.Dom.hasClass(domElement, newClass)) {
                JUNE.Dom.addClass(domElement, newClass);
                JUNE.Dom.removeClass(domElement, defaultClass);
            }
            else {
                JUNE.Dom.removeClass(domElement, newClass);
                JUNE.Dom.addClass(domElement, defaultClass);
            }
        },

        toggleState : function(domElement, defaultState, newState)
        {
        ///<summary>Toggles an element's display state.</summary>
        ///<param name="domElement" type="Object" optional="false">(Required). The reference to the DOM element.</param>
        ///<param name="defaultState" type="String" optional="true">(Optional). 
        ///     The display state that is currently set to the element.
        ///     If no value is set, the default value will be used instead (which is 'block').
        ///</param>
        ///<param name="newState" type="String" optional="true">(Optional).
        ///     The new display state that will be applyed to element.
        ///     If no value is set, the default value will be used instead (which is 'none').
        ///</param>

            if (!domElement) { throw new Error(JUNE.Exception.missingArgument("JUNE.Dom.toggleState", "domElement")); }

            if ( !defaultState ) { defaultState = 'block'; }
            if ( !newState ) { newState = 'none'; }

            var  originalState = JUNE.Dom.getComputedStyle(domElement, 'display');

            if (originalState == defaultState) {
                return domElement.style.display = (domElement.style.display != newState) ? newState : defaultState;
            }
            else {
                return domElement.style.display = (domElement.style.display != defaultState) ? defaultState : newState;
            }
        },

        removeChild : function(domElement)
        {
        ///<summary>Removes the selected child node from the DOM tree.</summary>
        ///<param name="domElement" type="Object" optional="false">(Required). The reference to the DOM element to be removed.</param>

            if (!domElement) { throw new Error(JUNE.Exception.missingArgument("JUNE.Dom.removeChild", "domElement")); }
            var parent = domElement.parentNode;
            try { parent.removeChild(domElement); }
            catch(ex) { return; }

        },

        removeAllChildren : function(parentContainer)
        {
        ///<summary>Removes all child nodes from the selected parent element.</summary>
        ///<param name="parentContainer" type="Object" optional="false">(Required). The reference to the DOM element from which to remove all child nodes.</param>

            if (!parentContainer) { throw new Error(JUNE.Exception.missingArgument("JUNE.Dom.removeAllChildren", "parentContainer")); }
            while (parentContainer.hasChildNodes()) {
	            var child = parentContainer.firstChild;
	            parentContainer.removeChild(child);
            }
        },
        
        insertBefore : function(parentContainer, referenceNode, nodeToInsert)
        {
        ///<summary>Inserts a new created element before an existing one.</summary>
        ///<param name="parentContainer" type="Object" optional="false">(Required). The reference to the DOM element that will append the new created node.</param>
        ///<param name="referenceNode" type="Object" optional="false">(Required). The reference node</param>
        ///<param name="nodeToInsert" type="Object" optional="false">(Required). The node to insert.</param>
            if (!parentContainer) { throw new Error(JUNE.Exception.missingArgument("JUNE.Dom.insertBefore", "parentContainer")); }
            if (!referenceNode) { throw new Error(JUNE.Exception.missingArgument("JUNE.Dom.insertBefore", "referenceNode")); }
            if (!nodeToInsert) { throw new Error(JUNE.Exception.missingArgument("JUNE.Dom.insertBefore", "nodeToInsert")); }
            return parentContainer.insertBefore(nodeToInsert, referenceNode);
        },

        insertAfter : function(parentContainer, referenceNode, nodeToInsert) {
        ///<summary>Inserts a new created element after an existing one.</summary>
        ///<param name="parentContainer" type="Object" optional="false">(Required). The reference to the DOM element that will append the new created node.</param>
        ///<param name="referenceNode" type="Object" optional="false">(Required). The reference node</param>
        ///<param name="nodeToInsert" type="Object" optional="false">(Required). The node to insert.</param>
            return parentContainer.insertBefore(nodeToInsert, referenceNode.nextSibling);
        },

        getNextSibling : function(referenceNode) {
        ///<summary>Returns a reference to the next element of the specified element.</summary>
        ///<param name="referenceNode" type="Object" optional="false">(Required). The reference to the node to start search for its next sibling.</param>
            var next_Sibling = referenceNode.nextSibling;
            while (next_Sibling.nodeType != 1) { next_Sibling = next_Sibling.nextSibling; }
            return next_Sibling;
        },

        getPreviousSibling : function(referenceNode) {
        ///<summary>Returns a reference to the previous element of the specified element.</summary>
        ///<param name="referenceNode" type="Object" optional="false">(Required). The reference to the node to start search for its previous sibling.</param>

            var prevSibling = referenceNode.previousSibling;
            while (prevSibling.nodeType != 1) { prevSibling = prevSibling.previousSibling; }
            return prevSibling;
        },

        setStyles : function(targetElements, styles)
        {
        ///<summary>Apply multiple style properties to one or multiple objects at once</summary>
        ///<param name="targetElements" type="Object;Array" optional="false">(Required). The reference to specified DOM elements.</param>
        ///<param name="styles" type="Object literal" optional="false">(Required). The css styles to apply to each of the elements of the array.</param>
        ///<remarks>Pro JavaScript Design Patterns book</remarks>
            if (!targetElements) { throw new Error(JUNE.Exception.missingArgument("JUNE.Dom.setStyles", "targetElements")); }
            if (!styles) { throw new Error(JUNE.Exception.missingArgument("JUNE.Dom.setStyles", "styles")); }

            var setStyle = function(targetElements, prop, val)
            {
                if (JUNE.Util.isArray(targetElements))
                {
                    var _length = targetElements.length;
                    for (var i = 0; i < _length; i++) {
                        targetElements[i].style[prop] = val;
                    }
                }
                else { return targetElements.style[prop] = val; }
            };
            /* Apply styles. */
            for (var prop in styles) {
                if (styles.hasOwnProperty(prop)) {
                    setStyle(targetElements, prop, styles[prop]);
                }
            }
        },

        getByTags : function(tags, parentContainer)
        {
        ///<summary>
        ///     Returns an array of DOM elements selected by their tag name.
        ///</summary>
        ///<param name="tags" type="String;Array" optional="false">(Required). The name of the tags that act as selectors.</param>
        ///<param name="parentContainer" type="Object" optional="true">(Optional). 
        ///     The parent element where to search for the specified tags.
        ///     If not specified the 'document' object will be used as parent element.
        ///</param>
        ///<returns type="Array" />
            if (!tags) { throw new Error(JUNE.Exception.missingArgument('JUNE.Dom.getByTags', 'tags')); }

            var elements=[], tempTags = null, tempTagsLength = null;

            if (JUNE.Util.isArray(tags))
            {
            
                for (var a=0;a<tags.length;a++) {
                    var element = tags[a];

                    tempTags = (parentContainer) ? parentContainer.getElementsByTagName(element) : document.getElementsByTagName(_element);

                    tempTagsLength = tempTags.length;
                    for(var i=0;i<tempTagsLength;i++)
                    {
                        elements.push(tempTags[i]);
                    }
                }
                return elements;
            }
            else {
                tempTags = (parentContainer) ? parentContainer.getElementsByTagName(tags) : document.getElementsByTagName(tags);

                tempTagsLength = tempTags.length;
                for(i=0;i<tempTagsLength;i++)
                {
                    elements.push(tempTags[i]);
                }
                return elements;
            }
        },
        createElement : function (newElement, content, newElementID, cssClass, style, child_nodes)
        {
        ///<summary>Factory method for creating DOM elements.</summary>
        ///<param name="newElement" type="String" optional="false">(Required). The tag name of the element to create.</param>
        ///<param name="content" type="String" optional="true">(Optional). The HTML content of the new element.</param>
        ///<param name="newElementID" type="String" optional="true">(Optional). The ID attribute of the new element.</param>
        ///<param name="cssClass" type="String" optional="true">(Optional). The name of the css class of the new element.</param>
        ///<param name="style" type="String" optional="true">(Optional). The css styles to apply to the new element.</param>
        ///<param name="child_nodes" type="Array" optional="true">(Optional). The collection of child nodes to append to the new element.</param>

            if (!newElement) {throw new Error(JUNE.Exception.missingArgument("JUNE.Dom.Create.element", "newElement"));}

            var element = document.createElement(newElement);
            
            if (content)        { element.innerHTML = content; }
            if (newElementID)   { element.id = newElementID; }
            if (cssClass)       { element.className = cssClass; }
            if (style)          { element.setAttribute("style", style); }
            if (child_nodes && JUNE.Util.isArray(child_nodes) && child_nodes.length > 0)
            {
                for (var i = 0; i < child_nodes.length; i++) {
                    element.appendChild(child_nodes[i]);
                }
            }

            return element;
        },

        getByAttribute : function (attributeName, attributeValues, parentContainer)
        {
        ///<summary>Search for elements having a specific attribute inside a parent container and retrieve the result as an Array.</summary>
        ///<param name="attributeName" type="String" optional="false">
        ///     (Required). The name of the attribute that act as selector.
        ///</param>
        ///<param name="attributeValues" type="String;List" optional="false">
        ///     (Required). A comma delimited list of values of the attribute.
        ///</param>
        ///<param name="parentContainer" type="Object" optional="true">
        ///     (Optional). 
        ///     The parent element where to search for the elements having the specified attribute.
        ///     If not specified, the 'document' object will be used as parent element.
        ///</param>
        ///<returns type="Array">

            var DomElements = parentContainer ? parentContainer.getElementsByTagName('*') : document.getElementsByTagName('*');
            var Elements = [];
            
            if (attributeValues.indexOf(',') >= 0)
            {
                var ValuesList = attributeValues;
                if (ValuesList.indexOf(' ') >= 0)
                {
                    ValuesList = ValuesList.replace(' ', '');
                }
                ValuesList = ValuesList.split(',');
                
                for (var i=0; i < ValuesList.length; i++)
                {
                    var value = ValuesList[i];
                    
                    for (var j=0; j < DomElements.length; j++)
                    {
                        var ctl = DomElements[j];
                        if (ctl.getAttribute(attributeName))
                        {
                            var pattern = new RegExp("(^| )" + value + "( |$)");
                            if (pattern.test(ctl.getAttribute(attributeName))) { Elements.push(ctl); }
                        }
                    }
                }
            }
            else
            {
                for (var j=0; j < DomElements.length; j++)
                {
                    var ctl = DomElements[j];
                    if (ctl.getAttribute(attributeName))
                    {
                        var pattern = new RegExp("(^| )" + attributeValues + "( |$)");
                        if (pattern.test(ctl.getAttribute(attributeName))) { Elements.push(ctl); }
                    }
                }
            }
            return Elements;
        }
    }
})();


/*=============================================================================================================================================
                                                                JUNE.Form                                                                      
=============================================================================================================================================*/

JUNE.Form = (function()
{
    return {
        getForm : function(theForm)
        {
        ///<summary>Returns a reference to the specified FORM element.</summary>
        ///<param name="theForm" type="Object" optional="false">(Required). The reference to the FORM element.</param>
        ///<returns type="Object" />
            if (!theForm) {throw new Error(JUNE.Exception.missingArgument('JUNE.Form.getForm', 'theForm')); }
            if (document.forms) {
                return theForm = document.forms[theForm];
            }
            else {
                return theForm = JUNE.Dom.find(theForm);
            }
        },
        
        hasElements : function(theForm)
        {
        ///<summary>Checks if the specified form has elements.</summary>
        ///<param name="theForm" type="Object" optional="false">(Required). The NAME or the ID of the form.</param>
        ///<returns type="Boolean" />
            if (!theForm) { throw new Error(JUNE.Exception.missingArgument("JUNE.Form.hasElements", "theForm")); }
            var childs = theForm.elements;
            return (childs.length > 0);
        },

        toggleInputFieldText : function(domElement)
        {
        ///<summary>Toggles the text value of a text control.</summary>
        ///<param name="domElement" type="Object" optional="false">
        ///     (Required). The reference to the FORM element.
        ///     The VALUE and the TITLE attributes have to be set and their values must match.
        ///</param>
            if (!domElement) {throw new Error(JUNE.Exception.missingArgument("JUNE.Form.toggleInputFieldText", "domElement"));}
            if (!domElement.title) {
                throw new Error(JUNE.Exception.generalError("JUNE.Form.toggleInputFieldText",
                            "The value and the title attributes have to be set and their values must match!"));
            }

            if (domElement.value == domElement.title) { /* fires onclick */
                return domElement.value = '';
            }
            if (domElement.value == null || domElement.value == '') { /* fires onblur */
                return domElement.value = domElement.title;
            }
        },

        clearElements : function(targetElements)
        {
        ///<summary>Removes the text from text inputs.</summary>
        ///<param name="targetElements" type="Array" optional="false">(Required). The reference to the FORM elements.</param>

            if (!targetElements) {throw new Error(JUNE.Exception.missingArgument("JUNE.Form.clearElements", "targetElements"));}
            if (!JUNE.Util.isArray(targetElements)) {throw new Error(JUNE.Exception.missingArgument("JUNE.Form.clearElements", "The 'targetElements' argument must be an Array."));}
            else{
                for (var i=0; i < targetElements.length; i++)
                {
                    if (targetElements[i].value) { targetElements[i].value = ''; }
                }
            }
        },

        disableElements : function(targetElements)
        {
        ///<summary>Disables the specified FORM elements.</summary>
        ///<param name="targetElements" type="Array" optional="false">(Required). The reference to the FORM elements.</param>

            if (!targetElements) {throw new Error(JUNE.Exception.missingArgument("JUNE.Form.disableElements", "targetElements"));}
            if (!JUNE.Util.isArray(targetElements)) {throw new Error(JUNE.Exception.missingArgument("JUNE.Form.disableElements", "The 'targetElements' argument must be an Array."));}
            else
            {
                for (var i=0; i < targetElements.length; i++)
                {
                    targetElements[i].blur();
                    targetElements[i].disabled = true;
                }
            }
        },

        enableElements : function(targetElements)
        {
        ///<summary>Enables the specified FORM element(s).</summary>
        ///<param name="targetElements" type="Array" optional="false">(Required). The reference to the FORM elements.</param>

            if (!targetElements) {throw new Error(JUNE.Exception.missingArgument("JUNE.Form.enableElement", "targetElements"));}
            if (JUNE.Util.isArray(targetElements)) {
                for (var i=0; i < targetElements.length; i++)
                {
                    targetElements[i].disabled = false;
                }
            }
        },

        isNullOrEmpty : function(domElement)
        {
        ///<summary>Indicates whether the specified Object is a null reference or an Empty string.</summary>
        ///<param name="domElement" type="Object" optional="false">(Required). The reference to the FORM element.</param>
        ///<returns type="Boolean" />
            if (arguments.length == 1) {
                return (domElement == null) || (domElement.value.length == 0);
            }
            else {throw new Error(JUNE.Exception.missingArgument("JUNE.Form.isNullOrEmpty", "domElement"));}
        },

        requiredField: function(domElement, friendlyTitle, defaultCssClass, errorCssClass, onValidate)
        {
        ///<summary>Marks as required the specified FORM elements.</summary>
        ///<param name="domElement" type="Object" optional="false">(Required). The reference to the FORM element.</param>
        ///<param name="friendlyTitle" type="String" optional="false">(Required). The title to display when the element is hovered.</param>
        ///<param name="defaultCssClass" type="String" optional="false">(Required). The default css class applied to the element.</param>
        ///<param name="errorCssClass" type="String" optional="false">(Required). The css class to be applied if the element didn't pass the validation.</param>
        ///<param name="onValidate" type="Function" optional="false">(Required). Callback to validate the control.</param>

            if (!domElement)        { throw new Error(JUNE.Exception.missingArgument("JUNE.Form.requiredField", "domElement")); }
            if (!friendlyTitle)     { throw new Error(JUNE.Exception.missingArgument("JUNE.Form.requiredField", "friendlyTitle")); }
            if (!defaultCssClass)   { throw new Error(JUNE.Exception.missingArgument("JUNE.Form.requiredField", "defaultCssClass")); }
            if (!errorCssClass)     { throw new Error(JUNE.Exception.missingArgument("JUNE.Form.requiredField", "errorCssClass")); }
            if (!onValidate)        { throw new Error(JUNE.Exception.missingArgument("JUNE.Form.requiredField", "onValidate")); }

            try{domElement.setAttribute('title', friendlyTitle);}catch(ex){}

            function onActivated(event) {
            /* Remove the errorCssClass if the selected control failed to pass validation and add the defaultCssClass */
                if (JUNE.Dom.hasClass(domElement, errorCssClass)) {
                    JUNE.Dom.removeClass(domElement, errorCssClass);
                    JUNE.Dom.addClass(domElement, defaultCssClass);
                }
            }
            JUNE.Event.addHandler(domElement, 'click', onActivated);
        }
    }
})();







/*=============================================================================================================================================
                                                                JUNE.DateTime                                                                  
=============================================================================================================================================*/

JUNE.DateTime = (function()
{
    return {
        displayCurrentDate : function(domElement, separator)
        {
        ///<summary>Displays the current date.</summary>
        ///<param name="domElement" type="Object" optional="false">(Required). The reference to the element that will be used to display the date.</param>
        ///<param name="separator" type="String" optional="true>(Optional). The character used as a separator.</param>

            if (!domElement) { throw new Error(JUNE.Exception.missingArgument('JUNE.DateTime.displayCurrentDate', "domElement")); }
            if (!separator) { separator = '/';}

            var months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
                days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
                thisTime = new Date(),
                thisMonth = months[thisTime.getMonth()],
                thisDate = thisTime.getDate(),
                thisYear = thisTime.getFullYear();


            /* Outputs: Month(separator)Date(separator)Year  */
            if (domElement.tagName.toLowerCase() == 'input' || domElement.tagName.toLowerCase() == 'textarea') {
                domElement.value = thisMonth + separator + thisDate + separator + thisYear;
            }
            else {
                domElement.innerHTML = thisMonth + separator + thisDate + separator + thisYear;
            }
        },
        
        isLeapYear : function(year)
        {
        ///<summary>Checks whether a year is a leap year or not.</summary>
        ///<param name="year" type="Number" optional="false">(Required). The year to check.</param>
        ///<returns type="Boolean">
            if (!year) { throw new Error(JUNE.Exception.missingArgument('JUNE.DateTime.isLeapYear', "year")); }
            return !(year % 4) && (year % 100) || !(year % 400) ? true : false;
        }
    }
})();





/*=============================================================================================================================================
                                                                JUNE.Util                                                                      
=============================================================================================================================================*/
JUNE.Util = (function()
{
    return {
        isArray : function(value)
        {
        ///<summary>Returns true if the argument (value) is an Array and false if it's not.</summary>
        ///<param name="value" type="Object" optional="false">(Required). The object to test.</param>
        ///<returns type="Boolean">
        ///<remarks>Douglas Crockford's is_array method.</remarks>
            return value &&
                typeof value === 'object' &&
                typeof value.length === 'number' &&
                typeof value.splice === 'function' &&
                !(value.propertyIsEnumerable('length'));
        },

        randomNumber : function(limitNumber)
        {
        ///<summary>Returns a random number between 0 and the specified limit.</summary>
        ///<param name="limitNumber" type="Number" optional="true">
        ///     (Optional). The maximum value the random number can have.
        ///     The default limit is 200.
        ///</param>
        ///<returns type="Number">
            if (limitNumber && !JUNE.Validate.Number(limitNumber)) {throw new Error(JUNE.Exception.generalError('JUNE.Util.randomNumber', 'The argument "limitNumber" has to be a valid Number!'));}
            if (!limitNumber) {limitNumber = '200';}
            return Math.floor(Math.random() * limitNumber);
        },

        preloadImages : function()
        {
        ///<summary>Preloads the images passed as arguments.</summary>
        ///<usage>JUNE.Dom.preloadImages("image1.ext", "image2.ext" [, n] );</usage>

            if (!arguments.length >= 1) {
                throw new Error(JUNE.Exception.generalError('JUNE.Util.preloadImages', 'At least one argument has to be provided!'));
            }
            if (document.images) {
                for (var i = 0; i < arguments.length; i++) {
                    var img = new Image();
                    img.src = arguments[i];
                }
            }
        },

        scrollTo : function(domElement)
        {
        ///<summary>Scrolls the window to the selected object.</summary>
        ///<param name="domElement" type="Object" optional="false">(Required). The reference to the DOM element to scroll to.</param>

            if (domElement) { domElement.scrollIntoView(); }
            else { throw new Error(JUNE.Exception.missingArgument('JUNE.Util.scrollTo', 'domElement')); }
        },

        escapeFromFrame : function()
        {
        ///<summary>Doesn't allow a specific page to be loaded in a frame.</summary>
            if (top != self) { top.location = location; }
        },

        toggleStyleSheet : function()
        {
        ///<summary>Toggles the selected StyleSheets' enabled state. The arguments must be the stylesheets' ID attribute.</summary>
            if ( !arguments.length > 0) {throw new Error(JUNE.Exception.generalError("JUNE.Util.toggleStyleSheet", "At least one argument must be provided!"));}
            var stylesheets = [] , stylesheet = null;

            for (var i=0; i < arguments.length; i++)
            {
                stylesheet = JUNE.Dom.find(arguments[i]);
                if ( stylesheet.getAttribute('type') && stylesheet.getAttribute('type').indexOf('text/css') >= 0 )
                {
                    stylesheets.push(stylesheet);
                }
            }
            for (var j=0; j < stylesheets.length; j++)
            {
                stylesheet = stylesheets[j];
                if (stylesheet.disabled == false) { stylesheet.disabled = true; }
                else { stylesheet.disabled = false; }
            }
            
        },

        disableStyleSheets : function(titleSelector)
        {
        ///<summary>Disables the selected SyleSheets(using their title attribute as a selector).</summary>
        ///<param name="titleSelector" type="String" optional="false">
        ///     (Required). 
        ///     The title of the stylesheet(s) to disable (full name or part of the name).
        ///     Case sensitive.
        ///</param>

            if (!titleSelector) { throw new Error(JUNE.Exception.missingArgument('JUNE.Util.disableStyleSheets', 'titleSelector')); }
            var  whichSheets = []
                ,pageHeader = JUNE.Dom.getByTags('head')[0]
                ,links = JUNE.Dom.getByTags('link', pageHeader);
            for (var i = 0; i < links.length; i++) {
                var temp = links[i];
                if (temp.rel.indexOf('stylesheet') >= 0 && temp.title.indexOf(titleSelector) >= 0) { whichSheets.push(temp); }
            }
            for (var j in whichSheets) { whichSheets[j].disabled = true; }
        },

        loadDependantFile : function(fileUrl, position, title)
        {
        ///<summary>Loads dinamically the provided StyleSheet files or JavaScript files.</summary>
        ///<param name="fileUrl" type="String" optional="false">
        ///     (Required). The location of the file to load.
        ///</param>
        ///<param name="position" type="Number" optional="true">
        ///     (Optional). The position in the HEAD tag where to insert the file.
        ///</param>
        ///<param name="title" type="String" optional="true">
        ///     (Optional). The title attribute of the StyleSheet file.
        ///</param>

            if (!fileUrl) { throw new Error(JUNE.Exception.missingArgument('JUNE.Util.LoadDependantFile', 'fileUrl')); }

            var  pageHeader = document.getElementsByTagName('head')[0];

            var FileExists = function(_fileUrl)
            {
            ///<summary>Check if the selected file to load wasn't already loaded.</summary>
                if (pageHeader)
                {
                    var files = JUNE.Dom.getByTags(['link', 'script'], pageHeader);
                    for (var i=0; i < files.length; i++)
                    {
                        var file = files[i];
                        if (file.tagName.toLowerCase() == 'link')
                        {
                            try { if (file.getAttribute('href').indexOf(_fileUrl) >= 0) { return true; } } catch(ex){}
                        }
                        else if (file.tagName.toLowerCase() == 'script')
                        {
                            try { if (file.getAttribute('src').indexOf(_fileUrl) >= 0) { return true; }} catch(ex){}
                        }
                    }
                }
                return false;
            };

            var LoadStyleSheet = function(fileUrl, position, title)
            {
            ///<summary>Load the selected css file.</summary>
                if (pageHeader && !FileExists(fileUrl))
                {
                    var link = document.createElement('link');
                        link.setAttribute('rel', 'stylesheet');
                        link.setAttribute('type', 'text/css');
                        link.setAttribute('href', fileUrl);
                    if (title) {link.setAttribute('title', title);}
                    if (position) {
                        return link = pageHeader.insertBefore(link, pageHeader.childNodes[position]);
                    }
                    else { return pageHeader.appendChild(link); }
                }
            };

            var LoadJavaScript = function(fileUrl, position, title)
            {
            ///<summary>Load the selected js file.</summary>
                if (pageHeader && !FileExists(fileUrl))
                {
                    var script = document.createElement('script');
                        script.setAttribute('type', 'text/javascript');
                        script.setAttribute('src', fileUrl);
                        script.text = '';
                    if (position) {
                        return script = pageHeader.insertBefore(script, pageHeader.childNodes[position]);
                    }
                    else { return pageHeader.appendChild(script); }
                }
            };

            var url = fileUrl.toLowerCase();
            if (url.indexOf('.css') >= 0) { return LoadStyleSheet(fileUrl, position, title); }
            else if (url.indexOf('.js') >= 0) { return LoadJavaScript(fileUrl, position); }
        },

        addMethodsTo : function(theObject, methods)
        {
        ///<summary>Adds new methods to an Object or Function.</summary>
        ///<param name="theObject" type="Object" optional="false">(Required). The reference to the Object to extend.</param>
        ///<param name="methods" type="Object" optional="false">(Required). The methods that will be added to that Object.</param>
        ///<returns type="Object" />

            try {
                if (!theObject) {throw new Error(JUNE.Exception.missingArgument("JUNE.Util.addMethodsTo", "theObject"));}
                if (!methods) {throw new Error(JUNE.Exception.missingArgument("JUNE.Util.addMethodsTo", "methods"));}

                for (var property in methods) {
                    theObject[property] = methods[property];
                }
            }
            catch(ex) {return;}
        },

        clone : function(instanceToClone)
        {
        ///<summary>Clones an existent Object or Function.</summary>
        ///<param name="instanceToClone" type="Object" optional="false">(Required). The name of the Object or Function to clone.</param>
        ///<returns type="Object" />

            if (!instanceToClone) {throw new Error(JUNE.Exception.missingArgument("JUNE.Util.clone", "instanceToClone"));}

            if (instanceToClone)
            {
                try {
                    if (typeof(instanceToClone) == 'object')
                    {
                        var Clone = {};
                        for (var method in instanceToClone)
                        {
                            Clone[method] = instanceToClone[method];
                        }
                        return Clone;
                    }
                    else { return instanceToClone; }
                }
                catch(ex) { if (Clone) { Clone = null; } }
            }
            else { throw new Error(JUNE.Exception.missingArgument('JUNE.Util.clone', 'instanceToClone')); }
        }
    }
})();






/*=============================================================================================================================================
                                                                JUNE.Keyboard                                                                  
=============================================================================================================================================*/
JUNE.Keyboard = (function()
{
    var Keys = {
        /* Keyboard constants;
         * based on: http://www.cambiaresearch.com/c4/702b8cd1-e5b0-42e6-83ac-25f0306e3e25/Javascript-Char-Codes-Key-Codes.aspx
         */
        KEY_RETURN : 13,
        KEY_ESCAPE : 27,
        KEY_TAB : 9,
        KEY_SPACEBAR : 32
    };

    return {

        isEnterKey : function(event)
        {
        ///<summary>Checks whether the enter key has been pressed.</summary>
        ///<param name="event" type="Object" optional="false">(Required). The event Object.</param>
        ///<returns type="Boolean" />
            if (event) {
                var keyCode = event.keyCode ? event.keyCode : event.which ? event.which : event.charCode;
                return keyCode == Keys.KEY_RETURN;
            }
        },

        getKeyName : function(event)
        {
        ///<summary>Returns the name of the key pressed.</summary>
        ///<param name="event" type="Object" optional="false">(Required). The event Object.</param>
        ///<returns type="String" />
            if (event) {
                return String.fromCharCode(event.charCode ? event.charCode : event.keyCode);
            }
        },

        getKeyNumber : function(event)
        {
        ///<summary>Returns the number of the key pressed.</summary>
        ///<param name="event" type="Object" optional="false">(Required). The event Object.</param>
        ///<returns type="Number" />
            if (event) {
                return event.keyCode ? event.keyCode : event.which ? event.which : event.charCode;
            }
        }
    }
})();







/*=============================================================================================================================================
                                                                JUNE.Effect                                                                   
=============================================================================================================================================*/

JUNE.Effect = (function()
{
    return {
        highlight : function(domElement, timeout)
        {
        ///<summary>Adds the YellowFade effect over an element.</summary>
        ///<param name="domElement" type="Object" optional="false">(Required). The reference to the dom element to which the highlight effect will be applied to.</param>
        ///<param name="timeout" type="Number" optional="false">(Required). In milliseconds, the amount of time the highlight effect should persist.</param>
        ///<remarks>http://peter.michaux.ca/article/2946</remarks>
            if (!domElement) { throw new Error(JUNE.Exception.missingArgument('JUNE.Effect.highlight', 'domElement')); }
            if(!timeout) {timeout = 60;}
            var b = 155;
            (function fade() {
                domElement.style.background = 'rgb(255,255,'+ (b+=4) +')';
                if (b < 255) { setTimeout(fade, timeout); }
                else { domElement.style.background = 'Transparent'; }
            })();
        }
    }
})();







/*=============================================================================================================================================
                                                            JUNE.EXCEPTION                                                                    
=============================================================================================================================================*/

JUNE.Exception = (function()
{
    return {
        generalError : function(_function, _errorMessage)
        {
        ///<summary>Displays a general error message.</summary>
        ///<param name="_function" type="String" optional="true">(Optional). The name of the function.</param>
        ///<param name="_errorMessage" type="String" optional="true">(Optional). The error message.</param>
        ///<returns type="String" />

            if (!_function){_function='';}
            if (!_errorMessage){_errorMessage='';}
            return "Internal Error. \n\nFunction: " + _function + "\n\nError: " + _errorMessage;
        },
        missingArgument : function(_function, _argumentName)
        {
        ///<summary>Displays an argument missing exception message.</summary>
        ///<param name="_function" type="String" optional="true">(Optional). The name of the function.</param>
        ///<param name="_argumentName" type="String" optional="true">(Optional). The name of the missing argument.</param>
        ///<returns type="String" />

            if (!_function){_function='';}
            if (!_argumentName) { _argumentName = ''; }
            return "Internal Error. \n\nFunction: " + _function + "\n\nError: The argument "+_argumentName+" is required!";
        }
    }
})();




/*=============================================================================================================================================
                                                                JUNE.Validate                                                                  
=============================================================================================================================================*/
JUNE.Validate = (function()
{
    var isNumber = function(theNumberToTest)
    {
    ///<summary>Private Method. Checks whether the "theNumberToTest" is a number.</summary>
    ///<returns type="Boolean" />
        var numberPattern = new RegExp(/^-?[0-9]+$/);
        return numberPattern.test(theNumberToTest);
    };
    var isDecimal = function(number)
    {
    ///<summary>Private Method. Checks whether the "number" is a decimal number.</summary>
    ///<returns type="Boolean" />
        if (isNumber(number)) {return false;}
        var decimalNumberPattern = new RegExp(/^-?(\d+|(\d*[.,]\d+))$/);
        return decimalNumberPattern.test(number);
    };
    var isString = function(stringToValidate)
    {
    ///<summary>Private Method. Checks whether the "stringToValidate" is a valid string.</summary>
    ///<returns type="Boolean" />
        var stringPattern = new RegExp("^[a-z A-Z]+$");
        return stringPattern.test(stringToValidate);
    };

    return {
        email: function(emailToValidate)
        {
        ///<summary>Checks whether an email address is in the correct format.</summary>
        ///<param name="emailToValidate" type="String" optional="false">(Required). The email address to validate.</param>
        ///<returns type="Boolean" />
        ///<usage>JUNE.Validate.Email("an@email.address");</usage>
            try { if (!emailToValidate) { throw new Error(JUNE.Exception.missingArgument('JUNE.Validate.email', 'emailToValidate')); } }
            catch(ex) { return false; }

            var  emailPattern = new RegExp("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,6}$", "i")
                ,data = emailToValidate.toLowerCase();
            return emailPattern.test(data);
        },

        url: function(urlToValidate)
        {
        ///<summary>Checks whether an url address is in the correct format.</summary>
        ///<param name="urlToValidate" type="String" optional="false">(Required). The url address to validate(http, https, ftp).</param>
        ///<returns type="Boolean" />
        ///<usage>JUNE.Validate.Url("http://www.june-js.com");</usage>
        ///<usage>JUNE.Validate.Url("https://www.june-js.com");</usage>
        ///<usage>JUNE.Validate.Url("ftp://ftp.june-framework.com");</usage>
            try { if (!urlToValidate) { throw new Error(JUNE.Exception.missingArgument('JUNE.Validate.url', 'urlToValidate')); } }
            catch(ex) { return false; }

            var urlPattern = new RegExp("^(ftp|http|https)+://[A-Za-z0-9-_]+\\.[A-Za-z0-9-_%&\?\/.=]+$")
                ,data = urlToValidate.toLowerCase();
            return urlPattern.test(data);
        },

        zipCode: function(zipCodeToValidate, country)
        {
        ///<summary>Checks whether a specific zip code is in the correct format for the specified country.</summary>
        ///<param name="zipCodeToValidate" type="String" optional="false">(Required). The zip code to validate.</param>
        ///<param name="country" type="String" optional="true">(Optional). The country identifier. Case insensitive.</param>
        ///<returns type="Boolean" />
        ///<usage country="US">JUNE.Validate.ZipCode(12345);</usage>
        ///<usage country="US">JUNE.Validate.ZipCode(12345-6789);</usage>
            try {
                if (!zipCodeToValidate) { throw new Error(JUNE.Exception.missingArgument('JUNE.Validate.zipCode', 'zipCodeToValidate')); }
                if (!country) {country = 'US';}
            }
            catch(ex) { return false; }

            var usZipCodePattern = new RegExp(/(^\d{5}$)|(^\d{5}-\d{4}$)/);

            switch (country.toUpperCase())
            {
                case 'US'   : {return usZipCodePattern.test(zipCodeToValidate);}

                default     : {return usZipCodePattern.test(zipCodeToValidate);}
            }
        },

        number: function(numberToValidate, allowDecimals)
        {
        ///<summary>Checks whether the specified value is a valid(decimal, if specified) Number.</summary>
        ///<param name="numberToValidate" type="Number" optional="false">(Required). The number to validate.</param>
        ///<param name="allowDecimals" type="Boolean" optional="false">(Required). If specified, it will allow decimal numbers to be validated also.</param>
        ///<returns type="Boolean" />
        ///<usage>JUNE.Validate.Number(0.5, true)</usage>
        ///<usage>JUNE.Validate.Number('0,5', true)</usage>
        ///<usage>JUNE.Validate.Number(5)</usage>
            try { if (numberToValidate == null) { throw new Error(JUNE.Exception.missingArgument('JUNE.Validate.number', 'numberToValidate')); } }
            catch(ex) { return false; }
            return (allowDecimals) ? isDecimal(numberToValidate) : isNumber(numberToValidate);
        },

        range: function(numberToValidate, lowerBound, upperBound)
        {
        ///<summary>Checks whether a specific number is in a specified range of values.</summary>
        ///<param name="numberToValidate" type="Number" optional="false">(Required). The number to validate.</param>
        ///<param name="lowerBound" type="Number" optional="false">(Required). The upper bound limit.</param>
        ///<param name="upperBound" type="Number" optional="false">(Required). The lower bound limit.</param>
        ///<returns type="Boolean" />
        ///<usage>JUNE.Validate.Range(0.3, 0.5, 4);</usage>
        ///<usage>JUNE.Validate.Range('0,3', '0,5', 4);</usage>
        ///<usage>JUNE.Validate.Range(3, 0, 4);</usage>
            try {
                if (numberToValidate == null)   { throw new Error(JUNE.Exception.missingArgument('JUNE.Validate.range', 'numberToValidate')); }
                if (lowerBound == null)         { throw new Error(JUNE.Exception.missingArgument('JUNE.Validate.range', 'lowerBound')); }
                if (upperBound == null)         { throw new Error(JUNE.Exception.missingArgument('JUNE.Validate.range', 'upperBound')); }
            }
            catch(ex) { return false; }

            if (typeof(numberToValidate) == 'string') {
                if (numberToValidate.indexOf(',') >= 0) { numberToValidate = numberToValidate.replace(',','.'); }
            }
            if (typeof(lowerBound) == 'string') {
                if (lowerBound.indexOf(',') >= 0) { lowerBound = lowerBound.replace(',','.'); }
            }
            if (typeof(upperBound) == 'string') {
                if (upperBound.indexOf(',') >= 0) { upperBound = upperBound.replace(',','.'); }
            }

            return (numberToValidate >= lowerBound) && (numberToValidate <= upperBound);
        },

        valueMatch: function(dataToValidate, matchValue)
        {
        ///<summary>Checks whether a specified value matches a specific value.</summary>
        ///<param name="dataToValidate" type="String;Number" optional="false">(Required). Data to validate.</param>
        ///<param name="matchValue" type="String;Number" optional="false">(Required). The matching value.</param>
        ///<returns type="Boolean" />
        ///<usage>JUNE.Validate.ValueMatch(4, 4);</usage>
        ///<usage>JUNE.Validate.ValueMatch('a string', 'a string');</usage>
            try { if (dataToValidate == null) { throw new Error(JUNE.Exception.missingArgument('JUNE.Validate.valueMatch', 'dataToValidate')); }}
            catch(ex) { return false; }
            return matchValue == dataToValidate;
        },

        string: function(stringToValidate)
        {
        ///<summary>Validates a string.</summary>
        ///<param name="stringToValidate" type="String" optional="false">(Required). The string to validate.</param>
        ///<returns type="Boolean" />
        ///<usage>JUNE.Validate.String("Is this a valid string?");</usage>
            try { if (!stringToValidate) { throw new Error(JUNE.Exception.missingArgument('JUNE.Validate.string', 'stringToValidate')); }}
            catch(ex) { return false; }
            return isString(stringToValidate);
        }
    }
})();

//
JUNE.Widget = {};