/************************************
 *
 * Core Component
 * vutil.js
 * Utility Library
 * Provides general JavaScript Utilities

VLog 2.x - Multi-user ASP powered weblogging/content management system
Copyright (C) 2006-2008  Robert Vesse
rvesse@vdesign-studios.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

 *
 * Code is self executing to force the Namespace to be created and the Functions made available as part of it
 *
 * Portions of Code (the Mozilla Type Browser sections) used in the Textbox Manipulation Section were taken (and adapted) from the following URL
 * http://bmearns.net/wwk/view/Insert_text_into_textarea_with_Javascript
 *
 * The GetElementPosition function is taken from an article at the following URL and was written by Peter-Paul Koch
 * http://www.quirksmode.org/js/findpos.html
 *
 ************************************/

(function() {

    if (!window.VLog) window['VLog'] = {};

    if (!window.VLog.Utilities) {
        window.VLog.Utilities = {};
    } else {
        //Utilities Namespace already Loaded!
        return;
    }

    //Mouse Tracking
    window.VLog.Utilities.GetMouseX = function(event) {
        //Tracks the X Position of the Mouse
        try {
            if (event.clientX) {
                return event.clientX;
            } else if (event.screenX) {
                return event.screenX;
            } else {
                return 0;
            }
        } catch (e) {
            try {
                if (event.screenX) {
                    return event.screenX;
                } else {
                    return 0;
                }
            } catch (e2) {
                try {
                    if (event.pageX) {
                        return event.pageX;
                    } else {
                        return 0;
                    }
                } catch (e3) {
                    return 0;
                }
            }
        }
    }

    window.VLog.Utilities.GetMouseY = function(event) {
        //Tracks the Y Position of the Mouse
        try {
            if (event.clientY) {
                return event.clientY;
            } else if (event.screenY) {
                return event.screenY;
            } else {
                return 0;
            }
        } catch (e) {
            try {
                if (event.screenY) {
                    return event.screenY;
                } else {
                    return 0;
                }
            } catch (e2) {
                try {
                    if (event.pageY) {
                        return event.pageY;
                    } else {
                        return 0;
                    }
                } catch (e3) {
                    return 0;
                }
            }
        }
    }

    //Calculating Page Properties

    window.VLog.Utilities.GetCentreX = function(width) {
        var x;
        try {
            x = (screen.width - width) / 2;
        } catch (e) {
            x = 0;
        }

        return x;
    }

    window.VLog.Utilities.GetCentreY = function(height) {
        var y;
        try {
            y = (screen.height - height) / 2;
            y += window.pageYOffset - (height);
        } catch (e) {
            y = 0;
        }

        return y;
    }

    window.VLog.Utilities.GetPageHeight = function() {
        var h;
        try {
            h = screen.height;
        } catch (e) {
            h = 600;
        }

        return h;
    }

    window.VLog.Utilities.GetPageWidth = function() {
        var w;
        try {
            w = screen.width;
        } catch (e) {
            w = 800;
        }

        return w;
    }

    //Get Elements, Children and Delete Elements

    window.VLog.Utilities.GetElement = function(id) {
        var el;

        if (document.getElementById) {
            el = document.getElementById(id);
        } else if (document.all) {
            el = document.all[id];
        } else if (document.layers) {
            el = document.layers[id];
        } else {
            el = false;
        }

        return el;
    }

    window.VLog.Utilities.GetElementPosition = function(obj) {
        //This Function is from an article at the following URL and written by Peter-Paul Koch
        //http://www.quirksmode.org/js/findpos.html

        var currLeft = currTop = 0;

        if (obj.offsetParent) {
            do {
                currLeft += obj.offsetLeft;
                currTop += obj.offsetTop;
            } while (obj = obj.offsetParent);

            return [currLeft, currTop];
        } else {
            return [0, 0];
        }
    }

    window.VLog.Utilities.GetChildElements = function(id) {
        var el = window.VLog.Utilities.GetElement(id);
        if (el) {
            return el.childNodes;
        } else {
            return [];
        }
    }

    window.VLog.Utilities.DeleteElement = function(id) {
        var el, parent;
        el = window.VLog.Utilities.GetElement(id);
        if (el) {
            parent = el.parentNode;
            parent.removeChild(el);
        }
    }

    //Show and Hide Elements

    window.VLog.Utilities.HideElement = function(id) {
        var el = window.VLog.Utilities.GetElement(id);
        if (el) {
            el.style.display = 'none';
        }
    }

    window.VLog.Utilities.ShowElement = function(id) {
        var el = window.VLog.Utilities.GetElement(id);
        if (el) {
            el.style.display = 'block';
        }
    }

    window.VLog.Utilities.ShowElementInline = function(id) {
        var el = window.VLog.Utilities.GetElement(id);
        if (el) {
            el.style.display = 'inline';
        }
    }

    //Apply Functions over Elements or Children

    window.VLog.Utilities.Apply = function(id, callback) {
        var el = window.VLog.Utilities.GetElement(id);
        if (el) {
            callback(el);
        }
    }

    window.VLog.Utilities.ApplyToChildren = function(id, callback) {
        var children = window.VLog.Utilities.GetChildElements(id);
        for (var i = 0; i < children.length; i++) {
            if (children[i].nodeType == 1) {
                callback(children[i]);
            }
        }
    }

    //Adjust Style Properties of Elements

    window.VLog.Utilities.AdjustStyle = function(id, styleAttr, styleValue) {
        var el = window.VLog.Utilities.GetElement(id);
        if (el) {
            eval('el.style.' + styleAttr + ' = \'' + styleValue + '\';');
        }
    }

    window.VLog.Utilities.ChangeClass = function(id, className) {
        var el = window.VLog.Utilities.GetElement(id);
        if (el) {
            el.setAttribute('class', className);
        }
    }

    //Create Popups

    if (!window.VLog.Utilities.Overflow) window.VLog.Utilities.Overflow = {};
    window.VLog.Utilities.Overflow.Visible = 'visible';
    window.VLog.Utilities.Overflow.Hidden = 'hidden';
    window.VLog.Utilities.Overflow.Auto = 'auto';
    window.VLog.Utilities.Overflow.Scroll = 'scroll';

    window.VLog.Utilities.NoFormatting = function(obj) {
        return;
    }

    window.VLog.Utilities.AddPadding = function(obj, p) {
        obj.style.padding = p + "px";
    }

    window.VLog.Utilities.AddPadding1px = function(obj) {
        window.VLog.Utilities.AddPadding(obj, 1);
    }

    window.VLog.Utilities.AddPadding3px = function(obj) {
        window.VLog.Utilities.AddPadding(obj, 3);
    }

    window.VLog.Utilities.AddPadding5px = function(obj) {
        window.VLog.Utilities.AddPadding(obj, 5);
    }


    window.VLog.Utilities.AllowDragDrop = function(obj) {
        obj.posX = parseInt(obj.style.left);
        obj.posY = parseInt(obj.style.top);

        obj.onmousedown = function(event) {
            obj.dragMode = true;
            obj.offsetX = obj.posX - window.VLog.Utilities.GetMouseX(event);
            obj.offsetY = obj.posY - window.VLog.Utilities.GetMouseY(event);
        }

        obj.onmouseup = function(event) {
            obj.dragMode = false;
        }

        obj.onmousemove = function(event) {
            if (obj.dragMode) {
                obj.posX = window.VLog.Utilities.GetMouseX(event) + obj.offsetX;
                obj.posY = window.VLog.Utilities.GetMouseY(event) + obj.offsetY;
                obj.style.left = obj.posX + "px";
                obj.style.top = obj.posY + "px";
            }
        }

    }

    window.VLog.Utilities.CreatePopup = function(id, x, y, w, h, className, overflow, zIndex, htmlContent, formatFunction, deleteOnClose) {
        var el;

        //Check doesn't exist already
        if (window.VLog.Utilities.GetElement(id)) {
            el = window.VLog.Utilities.GetElement(id);
        } else {
            el = document.createElement('div');
            el.setAttribute('id', id);
        }

        el.setAttribute('class', className);
        el.style.position = 'absolute';
        el.style.zIndex = zIndex;
        el.style.left = x + "px";
        el.style.top = y + "px";
        el.style.width = w + "px";
        el.style.height = h + "px";
        el.style.overflow = overflow;
        el.innerHTML = htmlContent;

        formatFunction(el);

        document.body.appendChild(el);

        addPopupCloseLink(el, deleteOnClose);
    }

    window.VLog.Utilities.InsertPopup = function(id, rx, ry, w, h, className, overflow, htmlContent, formatFunction, deleteOnClose, parentId) {
        var el, parent;

        //Check doesn't exist already
        if (window.VLog.Utilities.GetElement(id)) {
            //alert('Error: Cannot insert an Existing Element!');
            return;
        } else {
            el = document.createElement('div');
            el.setAttribute('id', id);
        }

        el.setAttribute('class', className);
        el.style.position = 'relative';
        el.style.left = rx + "px";
        el.style.top = ry + "px";
        el.style.width = w + "px";
        el.style.height = h + "px";
        el.style.overflow = overflow;
        el.innerHTML = htmlContent;

        formatFunction(el);

        parent = window.VLog.Utilities.GetElement(parentId);
        if (parent) {
            parent.appendChild(el);
        } else {
            //alert('Error: Cannot insert Element to a non-existent Parent!');
            return;
        }

        addPopupCloseLink(el, deleteOnClose);
    }

    window.VLog.Utilities.LightboxPopup = function(id, w, h, className, overflow, htmlContent, formatFunction) {
        var lightEl, el;

        //Check doesn't exist already
        if (window.VLog.Utilities.GetElement(id)) {
            return;
        }

        //Create the Lightbox Effect
        lightEl = document.createElement('div');
        lightEl.setAttribute('id', 'lboxOverlay_' + id);
        lightEl.setAttribute('style', 'opacity: 0.5; -moz-opacity:0.5; -khtml-opacity:0.5; filter: alpha(opacity=50);');
        lightEl.style.position = 'absolute';
        lightEl.style.zIndex = 999;
        lightEl.style.left = 0;
        lightEl.style.top = 0;
        lightEl.style.width = window.VLog.Utilities.GetPageWidth() + 'px';
        lightEl.style.height = window.VLog.Utilities.GetPageHeight() + 'px';
        lightEl.style.background = '#000000';

        //Create the Popup
        el = document.createElement('div');
        el.setAttribute('id', id);
        el.setAttribute('class', className);
        el.style.position = 'absolute';
        el.style.zIndex = 1000;
        el.style.left = window.VLog.Utilities.GetCentreX(w) + "px";
        el.style.top = window.VLog.Utilities.GetCentreY(h) + "px";
        el.style.width = w + "px";
        el.style.height = h + "px";
        el.style.overflow = overflow;
        el.innerHTML = htmlContent;

        formatFunction(el);
        addLightboxPopupCloseLink(el, lightEl);

        document.body.appendChild(lightEl);
        document.body.appendChild(el);
    }

    function addPopupCloseLink(el, deleteOnClose) {
        var cl, clp;

        if (window.VLog.Utilities.GetElement(el.id + '_close')) {
            clp = window.VLog.Utilities.GetElement(el.id + '_close');
        } else {
            clp = document.createElement('p');
        }
        clp.setAttribute('class', 'small');

        cl = document.createElement('a');
        if (deleteOnClose) {
            cl.setAttribute('href', 'javascript:window.VLog.Utilities.DeleteElement(\'' + el.id + '\');');
        } else {
            cl.setAttribute('href', 'javascript:window.VLog.Utilities.HideElement(\'' + el.id + '\');');
        }
        cl.innerHTML = 'Close';
        clp.appendChild(cl);

        el.appendChild(clp);
    }

    function addLightboxPopupCloseLink(el, lightEl) {
        var cl, clp;

        if (window.VLog.Utilities.GetElement(el.id + '_close')) {
            clp = window.VLog.Utilities.GetElement(el.id + '_close');
        } else {
            clp = document.createElement('p');
        }
        clp.setAttribute('class', 'small');

        cl = document.createElement('a');
        cl.setAttribute('href', 'javascript:window.VLog.Utilities.DeleteElement(\'' + lightEl.id + '\');window.VLog.Utilities.DeleteElement(\'' + el.id + '\');');
        cl.innerHTML = 'Close';
        clp.appendChild(cl);

        el.appendChild(clp);
    }

    //Menu Popups

    if (!window.VLog.Utilities.MenuOpenModes) window.VLog.Utilities.MenuOpenModes = {};
    window.VLog.Utilities.MenuOpenModes.Hover = 1;
    window.VLog.Utilities.MenuOpenModes.Click = 2;
    window.VLog.Utilities.MenuOpenModes.Manual = 3;

    window.VLog.Utilities.AttachMenu = function(menuid, sourceid, w, h, className, overflow, openMode, menuContents) {
        var el, source;

        try {
            if (!window.VLog.Utilities.GetElement(sourceid)) {
                alert('Error: Cannot attach a Menu to a non-existent Element!');
                return;
            } else {
                source = window.VLog.Utilities.GetElement(sourceid);
            }
            if (window.VLog.Utilities.GetElement(menuid)) {
                //Menu is already attached to the relevant Element
                return;
            }
        } catch (ex) {
            //Quit on errors
            return;
        }

        //Try to find the Object Position
        var realPos = window.VLog.Utilities.GetElementPosition(source);
        if (!isNaN(parseInt(source.style.width))) realPos[0] += parseInt(source.style.width);
        if (!isNaN(parseInt(source.style.height))) realPos[1] += parseInt(source.style.height);

        //Create the Menu
        el = document.createElement('div');
        el.setAttribute('id', menuid);
        el.setAttribute('class', className);
        el.style.position = 'absolute';
        el.style.display = 'none';
        el.style.zIndex = (source.style.zIndex + 10);
        el.style.left = realPos[0] + "px";
        el.style.top = realPos[1] + "px";
        el.style.width = w + "px";
        el.style.height = h + "px";
        el.style.overflow = overflow;
        el.innerHTML = menuContents;
        el.timerValue = '';

        document.body.appendChild(el);
        addPopupCloseLink(el, false);

        //Attach to the Source Element with appropriate Mouse Handlers
        if (openMode == window.VLog.Utilities.MenuOpenModes.Hover) {
            //Add Auto-Open for Hover Open Mode
            source.onmouseover = function(event) {
                window.VLog.Utilities.ShowElement(menuid);
                if (el.timerValue != '') {
                    clearTimeout(el.timerValue);
                }
            }
            el.onmouseover = function(event) {
                if (el.timerValue != '') {
                    clearTimeout(el.timerValue);
                }
            }

        } else if (openMode == window.VLog.Utilities.MenuOpenModes.Click) {
            //Add Open for Click Open Mode
            if (document.all) {
                //IE Compatability fix for IE being stupid!
                source.onmousedown = function(event) {
                    window.VLog.Utilities.ShowElement(menuid);
                    if (el.timerValue != '') {
                        clearTimeout(el.timerValue);
                    }
                    //Need to have the return false to stop the link/button being activated normally
                    return false;
                }
            } else {
                //Normal browsers
                source.onclick = function(event) {
                    window.VLog.Utilities.ShowElement(menuid);
                    if (el.timerValue != '') {
                        clearTimeout(el.timerValue);
                    }
                    //Need to have the return false to stop the link/button being activated normally
                    return false;
                }
            }
            el.onclick = function(event) {
                window.VLog.Utilities.ShowElement(menuid);
                if (el.timerValue != '') {
                    clearTimeout(el.timerValue);
                }
            }
            source.onmousemove = function(event) {
                if (el.timerValue != '') {
                    clearTimeout(el.timerValue);
                }
            }
            el.onmousemove = function(event) {
                if (el.timerValue != '') {
                    clearTimeout(el.timerValue);
                }
            }
        }

        if (openMode != window.VLog.Utilities.MenuOpenModes.Manual) {
            //Add Auto-Closing Handlers if not Manual Open Mode
            source.onmouseout = function(event) {
                el.timerValue = setTimeout(function() { window.VLog.Utilities.HideElement(menuid); }, 2000);
            }
            el.onmouseout = function(event) {
                el.timerValue = setTimeout(function() { window.VLog.Utilities.HideElement(menuid); }, 2000);
            }

            //Add Keep Open Handlers to all Child Elements
            addChildElementMenuOpenHandlers(el, el);
        }
    }

    function addChildElementMenuOpenHandlers(menuEl, el) {
        var children = el.childNodes;
        for (var i = 0; i < children.length; i++) {
            //Add the Handler
            try {
                children[i].onmouseover = function(event) {
                    if (menuEl.timerValue != '') {
                        clearTimeout(menuEl.timerValue);
                    }
                }

                //Recurse
                addChildElementMenuOpenHandlers(menuEl, children[i]);
            } catch (ex) {
                //Don't bother trying
                //This fixes a weird issue with IE
            }
        }
    }

    window.VLog.Utilities.ShowMenu = function(menuid) {
        var el = window.VLog.Utilities.GetElement(menuid);
        if (el) {
            window.VLog.Utilities.ShowElement(menuid);
            if (el.timerValue != '') {
                clearTimeout(el.timerValue);
            }
        }
    }

    window.VLog.Utilities.HideMenu = function(menuid) {
        var el = window.VLog.Utilities.GetElement(menuid);
        if (el) {
            if (el.timerValue != '') {
                clearTimeout(el.timerValue);
            }
            window.VLog.Utilities.HideElement(menuid);
        }
    }


    //Form Input Manipulation

    window.VLog.Utilities.InsertToTextbox = function(obj, text, replaceSelection) {
        try {
            //This approach should work for Mozilla Type Browsers

            //Get the selection bounds
            var start = obj.selectionStart;
            var end = obj.selectionEnd;

            //Break up the text by selection
            var currText = obj.value;
            var pre = String.substring(currText, 0, start);
            var sel = String.substring(currText, start, end);
            var post = String.substring(currText, end);

            //Insert the text at the beginning of the selection
            if (!replaceSelection) {
                currText = pre + text + sel + post;
            } else {
                currText = pre + text + post;
            }

            //Put the text in the textobj
            obj.value = currText;

            //Re-establish the selection, adjusted for the added characters.
            if (!replaceSelection) {
                obj.selectionStart = start + text.length;
                obj.selectionEnd = end + text.length;
            } else {
                obj.selectionEnd = start + text.length;
            }

        } catch (e) {
            try {
                //This approach should work for IE Type Browsers

                //Create a Text Range on the Textbox if possible
                if (obj.createTextRange) {
                    obj.caretPos = document.selection.createRange().duplicate();
                }
                //Alter the Value of this Text Range (if it exists) or simply append to End of Text
                if (obj.createTextRange && obj.caretPos.text != '') {
                    var currText = obj.caretPos.text;
                    if (!replaceSelection) {
                        currText = text + currText;
                    } else {
                        currText = text;
                    }
                    obj.caretPos.text = currText;
                } else {
                    obj.value = obj.value + startText + endText;
                }

            } catch (e2) {
                //Do the simplistic add to end of Textbox as a Fallback

                obj.value = obj.value + text;
            }
        }
    }

    window.VLog.Utilities.InsertToTextboxAroundSelection = function(obj, startText, endText) {
        try {
            //This approach should work for Mozilla Type Browsers

            //Get the selection bounds
            var start = obj.selectionStart;
            var end = obj.selectionEnd;

            //Break up the text by selection
            var currText = obj.value;
            var pre = String.substring(currText, 0, start);
            var sel = String.substring(currText, start, end);
            var post = String.substring(currText, end);

            //Insert the text at the beginning of the selection
            currText = pre + startText + sel + endText + post;

            //Put the text in the textobj
            obj.value = currText;

            //Re-establish the selection, adjusted for the added characters.
            obj.selectionStart = start + startText.length;
            obj.selectionEnd = end + startText.length;

        } catch (e) {
            try {
                //This approach should work for IE Type Browsers

                //Create a Text Range on the Textbox if possible
                if (obj.createTextRange) {
                    obj.caretPos = document.selection.createRange().duplicate();
                }
                //Alter the Value of this Text Range (if it exists) or simply append to end of Text
                if (obj.createTextRange && obj.caretPos.text != '') {
                    var currText = obj.caretPos.text;
                    currText = startText + currText + endText;
                    obj.caretPos.text = currText;
                } else {
                    obj.value = obj.value + startText + ' ' + endText;
                }

            } catch (e2) {
                //Do the simplistic add to end of Textbox as a Fallback

                obj.value = obj.value + startText + ' ' + endText;
            }
        }
    }



})();
