// Pelican Design & Development PHP Framework
// JavaScript core methods
// Created on 2009-10-18 by Arsène
// PPF is a proprietary software. Any non-authorized modification or distribution of the source code is strictly prohibited.

// Note: the distribution of *THIS* file is authorized as far as legal mentions remain and the code is not modified or all modifications are documented and the file is distributed for free.

if (!String.prototype.endsWith) {
    String.prototype.endsWith = function(suffix) {
        var startPos = this.length - suffix.length;
        if (startPos < 0) return false;
        return (this.lastIndexOf(suffix, startPos) == startPos);
    };
}

if (!Element.prototype.SetText) {
    Element.prototype.SetText = function(newText) {
        if (this.textContent) {
            this.textContent = newText;
        }
        else if (this.innerText) {
            this.innerText = newText;
        }
        else {
            throw 'Object text cannot be set on the current object.';
        }
    };
}

var PPF = {
    Version: '1.0.0.0',
    // Methods related to interface.
    Interface: {
        // Toolbox methods.
        Toolbox: {
            // Displays a toolbox when user clicks on tools button.
            Show: function() {
                var toolboxButton = $('ppfToolsButton');
                var toolboxItem = $('ppfToolbox');
                if (toolboxItem) {
                    if (toolboxItem.style.display != 'block') toolboxItem.style.display = 'block';
                }
                else {
                    // TODO: handle this error
                }
                if (toolboxButton) {
                    if (toolboxButton.style.display != 'none') toolboxButton.style.display = 'none';
                }
                else {
                    // TODO: handle this error
                }
            },
            // Displays a toolbox when user clicks on tools button.
            Hide: function() {
                var toolboxButton = $('ppfToolsButton');
                var toolboxItem = $('ppfToolbox');
                if (toolboxItem) {
                    if (toolboxItem.style.display != 'none') toolboxItem.style.display = 'none';
                }
                else {
                    // TODO: handle this error
                }
                if (toolboxButton) {
                    if (toolboxButton.style.display != 'block') toolboxButton.style.display = 'block';
                }
                else {
                    // TODO: handle this error
                }
            }
        },
        Trace: {
            // Displays a toolbox when user clicks on tools button.
            Show: function() {
                var traceItem = $('ppfFullScreenTrace');
                if (traceItem) {
                    if (traceItem.style.display != 'block') traceItem.style.display = 'block';
                }
                else {
                    // TODO: handle this error
                }
            },
            // Displays a toolbox when user clicks on tools button.
            Hide: function() {
                var traceItem = $('ppfFullScreenTrace');
                if (traceItem) {
                    if (traceItem.style.display != 'none') traceItem.style.display = 'none';
                }
                else {
                    // TODO: handle this error
                }
            },
            // Displays feedback form which can be used to feedback trace to a developer.
            ShowFeedbackForm: function() {
                var feedbackButton = $('ppfTraceFeedbackMailShow');
                var feedbackForm = $('ppfTraceFeedbackMailForm');
                if (feedbackButton && feedbackForm) {
                    feedbackForm.style.display = 'block';
                    feedbackButton.hide();
                }
                else {
                    // TODO: handle this error
                }
            },
            HideFeedbackForm: function() {
                var feedbackButton = $('ppfTraceFeedbackMailShow');
                var feedbackForm = $('ppfTraceFeedbackMailForm');
                if (feedbackButton && feedbackForm) {
                    feedbackForm.hide();
                    feedbackButton.show();
                }
                else {
                    // TODO: handle this error
                }
            },
            SendFeedback: function() {
                var PpfTraceFeedbackMail = $('ppfTraceFeedbackMail');
                var PpfTraceFeedbackDetails = $('ppfTraceFeedbackDetails');
                var PpfTraceList = $('ppfTraceList');
                var PpfAjaxUrlStart = $('ppfTraceFeedbackAjaxUrlStart');

                var FrameworkDirectoryUrl = '';
                if (PpfAjaxUrlStart.textContent) {
                    FrameworkDirectoryUrl = PpfAjaxUrlStart.textContent;
                }
                else if (PpfAjaxUrlStart.innerText) {
                    FrameworkDirectoryUrl = PpfAjaxUrlStart.innerText;
                }

                if (PpfTraceFeedbackMail && PpfTraceFeedbackDetails && PpfTraceList) {
                    document.body.style.cursor = 'wait';
                    new Ajax.Request(FrameworkDirectoryUrl + 'ppf.php?ppfmode=1&ppfc=savetrace', {
                        method: 'get',
                        onSuccess: function(transport) {
                            document.body.style.cursor = 'default';
                            if (transport.responseText.startsWith('ok:')) {
                                var newUrl = 'mailto:' + PpfTraceFeedbackMail.value + '?subject=[Feedback]%20Site trace&body=' + PpfTraceFeedbackDetails.value + '%0A%0A-----%0A%0A' + escape('You can find trace record at ' + transport.responseText.substring(3) + ' or load it with Criollo Developer Tools.');
                                window.location = newUrl;
                            }
                            else {
                                alert('Action failed with error: ' + transport.responseText.substring(4));
                            }
                        },
                        onFailure: function() {
                            document.body.style.cursor = 'default';
                            throw 'Ajax failed';
                        }
                    });

                }
            },
            // Displays a hint for mail field.
            ShowFeedbackMailHint: function() {
                var hintContainer = $('ppfTraceFeedbackHint');
                var hintBody = $('ppfTraceFeedbackHintBody');
                var mailHintBody = $('ppfTraceFeedbackMailHint');
                if (hintContainer && hintBody && mailHintBody) {
                    hintContainer.setStyle({ top: '35px' });
                    hintBody.innerHTML = mailHintBody.innerHTML;
                    hintContainer.show();
                }
            },
            // Displays a hint for mail field.
            ShowFeedbackDetailsHint: function() {
                var hintContainer = $('ppfTraceFeedbackHint');
                var hintBody = $('ppfTraceFeedbackHintBody');
                var detailsHintBody = $('ppfTraceFeedbackDetailsHint');
                if (hintContainer && hintBody && detailsHintBody) {
                    hintContainer.setStyle({ top: '90px' });
                    hintBody.innerHTML = detailsHintBody.innerHTML;
                    hintContainer.show();
                }
            },
            // Displays a hint for submit link.
            ShowFeedbackSubmitHint: function() {
                var hintContainer = $('ppfTraceFeedbackHint');
                var hintBody = $('ppfTraceFeedbackHintBody');
                var submitHintBody = $('ppfTraceFeedbackSubmitHint');
                if (hintContainer && hintBody && submitHintBody) {
                    hintContainer.setStyle({ top: '190px' });
                    hintBody.innerHTML = submitHintBody.innerHTML;
                    hintContainer.show();
                }
            }
        },
        CoverageStats: {
            // Displays a toolbox when user clicks on tools button.
            Show: function() {
                var coverageItem = $('ppfFullScreenCoverageStats');
                if (coverageItem) {
                    if (coverageItem.style.display != 'block') coverageItem.style.display = 'block';
                }
                else {
                    // TODO: handle this error
                }
            },
            // Displays a toolbox when user clicks on tools button.
            Hide: function() {
                var coverageItem = $('ppfFullScreenCoverageStats');
                if (coverageItem) {
                    if (coverageItem.style.display != 'none') coverageItem.style.display = 'none';
                }
                else {
                    // TODO: handle this error
                }
            }
        }
    },
    // Interactive objects.
    Interactivity: {
        Definitions: null,

        OnLoad: function() {
            var ElementsCounter = $('ppfToolboxCountElements');
            if (ElementsCounter) {
                ElementsCounter.SetText(document.getElementsByTagName('*').length);
            }
            for (var i = 0; i < PPF.Interactivity.Definitions.length; i++) {
                var definition = PPF.Interactivity.Definitions[i];
                switch (definition.type) {
                    case 'TextboxWithHint':
                        var concernedElement = $(definition.controlId);
                        if (concernedElement) {
                            var currentClassName = concernedElement.className;
                            var murderHint = function() {
                                if (concernedElement.className.match(/(?:^|\s)hint(?:$|\s)/im)) {
                                    concernedElement.value = '';
                                    concernedElement.className = currentClassName;
                                }
                            };
                            var resuscitateHint = function() {
                                if (concernedElement.className.match(/(?:^|\s)hint(?:$|\s)/im) != null || concernedElement.value == '') {
                                    concernedElement.value = definition.hint;
                                    concernedElement.className = currentClassName + ' hint';
                                    if (concernedElement.selectionStart) {
                                        concernedElement.selectionStart = 0;
                                        concernedElement.selectionEnd = 0;
                                    }
                                    else if (document.selection) {
                                        var sel = document.selection.createRange();
                                        // Move selection start and end to 0 position
                                        sel.moveStart('character', -concernedElement.value.length);
                                        sel.moveEnd('character', 0);
                                    }
                                }
                            };
                            var evaluateHint = function() {
                                if (concernedElement.className.match(/(?:^|\s)hint(?:$|\s)/im)) {
                                    // Hint class enabled
                                    if (concernedElement.value.startsWith(definition.hint)) {
                                        concernedElement.value = concernedElement.value.substring(definition.hint.length);
                                    }
                                    else if (concernedElement.value.endsWith(definition.hint)) {
                                        concernedElement.value = concernedElement.value.substring(0, concernedElement.value.length - definition.hint.length);
                                    }
                                    else {
                                    }
                                    concernedElement.className = currentClassName;
                                }
                                else {
                                    if (concernedElement.value == '') {
                                        concernedElement.value = definition.hint;
                                        concernedElement.className = currentClassName + ' hint';
                                        if (concernedElement.selectionStart) {
                                            concernedElement.selectionStart = 0;
                                            concernedElement.selectionEnd = 0;
                                        }
                                        else if (document.selection) {
                                            var sel = document.selection.createRange();
                                            // Move selection start and end to 0 position
                                            sel.moveStart('character', -concernedElement.value.length);
                                            sel.moveEnd('character', 0);
                                        }
                                    }
                                }
                            };
                            PPF.Core.Events.Add(concernedElement, 'focus', murderHint);
                            PPF.Core.Events.Add(concernedElement, 'blur', resuscitateHint);
                            PPF.Core.Events.Add(concernedElement, 'keyup', evaluateHint);
                            if (!concernedElement.value) {
                                concernedElement.className += ' hint';
                                concernedElement.value = definition.hint;
                            }
                        }
                        break;
                }
            }
        }
    },
    // Core methods.
    Core: {
        // Events handling for non-intrusive javascript.
        Events: {
            // Adds a new listener on a page element.
            Add: function(pageElement, eventType, response) {
                if (pageElement.addEventListener) {
                    pageElement.addEventListener(eventType, response, true);
                    return true;
                }
                else if (pageElement.attachEvent) {
                    var r = pageElement.attachEvent('on' + eventType, response);
                    return r;
                }
                else {
                    return false;
                }
            },
            AdjustLayout: function() {
                var PpfFSWhitePanels = $$('.ppfFSWhitePanel');
                if (PpfFSWhitePanels) {
                    var maxHeight = Math.max(document.viewport.getHeight(), document.body.clientHeight) + 'px';
                    for (var i = 0; i < PpfFSWhitePanels.length; i++) {
                        PpfFSWhitePanels[i].style.height = maxHeight;
                    }
                }
            },
            // Reserved for PPF framework. If you want to do something on page load, add your own listener.
            OnLoad: function() {
                PPF.Core.Events.Add(window, 'mousemove', PPF.Core.Events.OnMouseMove);
                PPF.Core.Events.Add(window, 'resize', PPF.Core.Events.OnResize);
                PPF.Core.Events.Add(window, 'click', PPF.Core.Events.OnClick);

                PPF.Core.Events.AdjustLayout();

                var PpfToolsButton = $('ppfToolsButton');
                if (PpfToolsButton) {
                    PPF.Core.Events.Add(PpfToolsButton, 'click', PPF.Interface.Toolbox.Show);
                    PPF.Core.Events.Add(PpfToolsButton, 'mouseover', function() { $('ppfToolsButton').className = 'ppf hover'; });
                    PPF.Core.Events.Add(PpfToolsButton, 'mouseout', function() { $('ppfToolsButton').className = 'ppf'; });
                    PpfToolsButton.onclick = null;
                }

                var PpfToolboxCloseButton = $('ppfToolboxClose');
                if (PpfToolboxCloseButton) {
                    PPF.Core.Events.Add(PpfToolboxCloseButton, 'click', PPF.Interface.Toolbox.Hide);
                    PpfToolboxCloseButton.onclick = null;
                }

                var PpfTraceOpenButton = $('ppfFullScreenTraceOpen');
                if (PpfTraceOpenButton) {
                    PPF.Core.Events.Add(PpfTraceOpenButton, 'click', PPF.Interface.Trace.Show);
                    PpfTraceOpenButton.onclick = null;
                }

                var PpfTraceCloseButton = $('ppfFullScreenTraceClose');
                if (PpfTraceCloseButton) {
                    PPF.Core.Events.Add(PpfTraceCloseButton, 'click', PPF.Interface.Trace.Hide);
                    PpfTraceCloseButton.onclick = null;
                }

                var PpfTraceFeedbackOpenButton = $('ppfTraceFeedbackMailShow');
                if (PpfTraceFeedbackOpenButton) {
                    PPF.Core.Events.Add(PpfTraceFeedbackOpenButton, 'click', PPF.Interface.Trace.ShowFeedbackForm);
                    PpfTraceFeedbackOpenButton.writeAttribute('href', null);
                }

                var PpfTraceFeedbackMail = $('ppfTraceFeedbackMail');
                if (PpfTraceFeedbackMail) {
                    PPF.Core.Events.Add(PpfTraceFeedbackMail, 'focus', PPF.Interface.Trace.ShowFeedbackMailHint);
                }

                var PpfTraceFeedbackDetails = $('ppfTraceFeedbackDetails');
                if (PpfTraceFeedbackDetails) {
                    PPF.Core.Events.Add(PpfTraceFeedbackDetails, 'focus', PPF.Interface.Trace.ShowFeedbackDetailsHint);
                }

                var PpfTraceFeedbackSubmit = $('ppfTraceFeedbackSubmit');
                if (PpfTraceFeedbackSubmit) {
                    PPF.Core.Events.Add(PpfTraceFeedbackSubmit, 'mouseover', PPF.Interface.Trace.ShowFeedbackSubmitHint);
                    PPF.Core.Events.Add(PpfTraceFeedbackSubmit, 'click', PPF.Interface.Trace.SendFeedback);
                    PPF.Core.Events.Add(PpfTraceFeedbackSubmit, 'click', PPF.Interface.Trace.HideFeedbackForm);
                    PpfTraceFeedbackSubmit.writeAttribute('href', null);
                }

                var PpfCoverageStatsOpenButton = $('ppfFullScreenCoverageStatsOpen');
                if (PpfCoverageStatsOpenButton) {
                    PPF.Core.Events.Add(PpfCoverageStatsOpenButton, 'click', PPF.Interface.CoverageStats.Show);
                    PpfCoverageStatsOpenButton.onclick = null;
                }

                var PpfCoverageStatsCloseButton = $('ppfFullScreenCoverageStatsClose');
                if (PpfCoverageStatsCloseButton) {
                    PPF.Core.Events.Add(PpfCoverageStatsCloseButton, 'click', PPF.Interface.CoverageStats.Hide);
                    PpfCoverageStatsCloseButton.onclick = null;
                }

                var PpfInteractiveObjects = $('ppfInteractiveObjects');
                if (PpfInteractiveObjects) {
                    PPF.Interactivity.Definitions = null;
                    if (PpfInteractiveObjects.textContent) {
                        eval('PPF.Interactivity.Definitions = ' + PpfInteractiveObjects.textContent);
                    }
                    else if (PpfInteractiveObjects.innerText) {
                        eval('PPF.Interactivity.Definitions = ' + PpfInteractiveObjects.innerText);
                    }

                    PPF.Interactivity.OnLoad();
                }
            },
            // Reserved for PPF framework. If you want to do something on page click, add your own listener.
            OnClick: function(event) {
            },
            // Reserved for PPF framework. If you want to do something on page mouse move, add your own listener.
            OnMouseMove: function(event) {
            },
            // Reserved for PPF framework. If you want to do something on page resize, add your own listener.
            OnResize: function(event) {
                PPF.Core.Events.AdjustLayout();
            }
        },
        Interactivity: {
            CursorPosition: function(mouseMoveEvent) {
                mouseMoveEvent = mouseMoveEvent || window.event;
                var cursor = { x: 0, y: 0 };
                if (mouseMoveEvent.pageX || mouseMoveEvent.pageY) {
                    cursor.x = mouseMoveEvent.pageX;
                    cursor.y = mouseMoveEvent.pageY;
                }
                else {
                    var doc = document.documentElement;
                    var body = document.body;
                    cursor.x = mouseMoveEvent.clientX + (doc.scrollLeft || body.scrollLeft) - (doc.clientLeft || 0);
                    cursor.y = mouseMoveEvent.clientY + (doc.scrollTop || body.scrollTop) - (doc.clientTop || 0);
                }
                return cursor;
            }
        }
    },
    // Ajax related methods. WARNING: because Prototype framework is now permanent, this method will be removed in further versions. Prototype must be used instead for AJAX calls.
    //   @Num: specifies an unique number to allow multiple ajax requests at the same time.
    Ajax: function(Num) {
        this.HttpRequest = null;
        this.AttachedData = null;

        try {
            this.HttpRequest = new XMLHttpRequest(); // Firefox, Opera 8.0+, Safari
        }
        catch (e) { // Internet Explorer
            try {
                this.HttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
            }
            catch (e) {
                this.HttpRequest = new ActiveXObject("Microsoft.XMLHTTP");
            }
        }

        this.AttachData = function(Data) {
            this.AttachedData = Data;
        }

        this.Get = function(Request, Target, AnimElement, Method, PostParams) {
            if (!Method) Method = 'GET';
            Method = Method.toUpperCase();
            if (Method != 'POST') Method = 'GET';

            if (this.AttachedData) this.HttpRequest.AttachedData = this.AttachedData;
            this.HttpRequest.Response = Target;
            this.HttpRequest.open(Method, Request, true);
            this.HttpRequest.onreadystatechange = this.OnReadyStateChange;

            if ($('AjaxProgress')) $('AjaxProgress').style.visibility = 'visible';
            /*AjaxInstancesCount++;
            if (AjaxInstancesCount == 1 && AnimElement) {
            AjaxAnimElement = AnimElement;
            AnimElement.style.visibility = 'visible';
            }*/

            if (Method == 'POST') {
                if (PostParams) {
                    this.HttpRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
                    this.HttpRequest.setRequestHeader("Content-length", PostParams.length);
                    this.HttpRequest.setRequestHeader("Connection", "close");
                }
            }
            if (!PostParams) PostParams = null;
            this.HttpRequest.send(PostParams);
        };

        this.OnReadyStateChange = function(e) {
            alert(e);
            Origin = e.target;
            if (Origin.readyState == 4) {
                if ($('AjaxProgress')) $('AjaxProgress').style.visibility = 'hidden';
                try {
                    if (Origin.status == 200) {
                        /*AjaxInstancesCount--;
                        if (AjaxInstancesCount == 0 && AjaxAnimElement) AjaxAnimElement.style.visibility = 'hidden';*/
                        Origin.Response(true, Origin.responseText, Origin.AttachedData);
                    }
                }
                catch (e) {
                    /*AjaxInstancesCount--;
                    if (AjaxInstancesCount == 0 && AjaxAnimElement) AjaxAnimElement.style.visibility = 'hidden';*/
                    Origin.Response(false, e.description);
                }
            }
        }
    }
}
// Reserved. Do not remove.
PPF.Core.Events.Add(window, 'load', PPF.Core.Events.OnLoad);
