﻿// Navigation.js
// javascript in this file is related to the applicant-side navigation.
//
// Change Log
// [Date]: [who] - [what was done]
//

var SaveAsDraftURL = '99draft.aspx';

//### Navigation - a JSON Object to represent the state of the application in terms of pages and navigation.
Navigation = {
    // PageId should match the 1st page that PageController is returning.  If this ever changes, recommend using a global preference.
    CurrentPage: { ScriptLocation: "<%=DefaultScriptLocation%>", PageId: -11 }, 
    OnNextLoadAction: "",
    Timeout: 30000, //length in milliseconds
    TimeoutDefault: 30000, //reset after each load
    ListOfPages: [],
    NextTargetPage: {},
    LastLoadedPage: {},
    CallingPage: {},
    IsDataPageLoaded: true,
    InErrorState: false,
    OnFirstPage: function() {
        return Navigation.CurrentPage.ScriptLocation.toLowerCase() == Navigation.ListOfPages[0].ScriptLocation.toLowerCase();
    },
    OnLastPage: function() {
        return Navigation.CurrentPage.ScriptLocation.toLowerCase() == Navigation.ListOfPages[Navigation.ListOfPages.length - 1].ScriptLocation.toLowerCase()
    },
    OnSaveAsDraft: function() {
        return Navigation.CurrentPage.ScriptLocation.toLowerCase() == SaveAsDraftURL.toLowerCase();
    },
    DisableAll: function() {
        this.DisablePageNavigation();
        this.DisableTabNavigation();
        this.DisableSaveAsDraft();
        this.DisablePrevPage();
        this.DisableNextPage();
        this.DisableFinishAndSubmit();
    },
    EnableAll: function() {
        this.EnablePageNavigation();
        this.EnableTabNavigation();
        this.EnableSaveAsDraft();
        this.EnablePrevPage();
        this.EnableNextPage();
        this.EnableFinishAndSubmit();
    },
    DisablePageNavigation: function() { $get('VeilPageNavigation').style.display = 'block'; },
    EnablePageNavigation: function() { $get('VeilPageNavigation').style.display = 'none'; },
    DisableTabNavigation: function() { Trace("*** Disable Tab ***"); $get('VeilTabs').style.display = 'block'; },
    EnableTabNavigation: function() { $get('VeilTabs').style.display = 'none'; },
    DisableSaveAsDraft: function() { this.DisableButton('SaveAsDraftBG', 'LinkSaveAsDraft'); },
    EnableSaveAsDraft: function() { this.EnableButton('SaveAsDraftBG', 'LinkSaveAsDraft'); },
    DisablePrevPage: function() { this.DisableButton('PrevPageBG', 'LinkPrevPage'); },
    EnablePrevPage: function() { this.EnableButton('PrevPageBG', 'LinkPrevPage'); },
    DisableNextPage: function() { this.DisableButton('NextPageBG', 'LinkNextPage'); },
    EnableNextPage: function() { this.EnableButton('NextPageBG', 'LinkNextPage'); },
    DisableFinishAndSubmit: function() { this.DisableButton('FinishAndSubmitBG', 'LinkFinishAndSubmit'); },
    EnableFinishAndSubmit: function() { this.EnableButton('FinishAndSubmitBG', 'LinkFinishAndSubmit'); },
    DisableButton: function(eltId, linkId) {
        $get('Veil' + eltId).style.display = 'block';
    },
    EnableButton: function(eltId, linkId) {
        $get('Veil' + eltId).style.display = 'none';
    },
    LogOut: function() {
        parent.location.replace('_LogOut.aspx?action=autoclose');
    }
};
//### End Navigation JSON Object

// error handling (see /* Error Handling Section */ below)
var errTimer = null;
var errCnt = 0;
var cancelNav = false;

// called when the 'onload' event is fired on the 'AppDataPage' iFrame in _application
// TODO [CleanUp] - this function doesn't do anything other than send debug info; see onload on the AppDataPage iframe.
// the intent is to check for "AppliTrack" pages within the iFrame.  If it is not an "AppliTrack" page then it must be ~ 500 error (IIS page/Server error).
function iFrameLoaded() {
    if (AppDataPage.AppliTrackPage) {
        Trace('iFrameLoaded(): AppDataPage ready');
    } else {
        Trace('iFrameLoaded(): AppliTrackPage ABSENT');
    }
}

function RefreshNavigation(onCompleteFunction) {   
    // if no function was passed in, set the onCompleteFunction to the default - OnPageListLoaded
    if (onCompleteFunction == null) onCompleteFunction = OnPageListLoaded;
    
    // asp.net ajax call to the GetPages() webmethod in _application.aspx.vb
    // on success, call onCompleteFunction passing in data returned from the function.
    // on failure, call OnPageListLoadFailed
    PageMethods.GetPages(CurrentUser.AppNo, onCompleteFunction, OnPageListLoadFailed);
}

var NavigationContainerHTML = '<div class="NavLeft_BGActive"><div class="NavLeft_LeftActive"><div class="NavLeft_RightActive"><div class="NavLeft_TopActive"><div class="NavLeft_BottomActive"><div class="NavLeft_TopLeftActive"><div class="NavLeft_TopRightActive"><div class="NavLeft_BottomLeftActive"><div class="NavLeft_BottomRightActive"><div class="NavLeft_TextActive">{TEXT}</div></div></div></div></div></div></div></div></div></div>'
function OnPageListLoaded(result) {
    // result is the List(Of SetupPages) returned from GetPages <WebMethod()> in _application.aspx.vb.
    Navigation.ListOfPages = result; 

    // ensure nothing is done if on the first or last page and a previous or next was requested (respectively).
    // if the buttons are correctly disabled in DataPageLoaded(), this is not necessary.  Good as a safety measure. 
    if (Navigation.OnFirstPage() && Navigation.OnNextLoadAction == "loadPrev") {
        Navigation.OnNextLoadAction = ""; //reload the current page when going prev on first
    }
    if (Navigation.OnLastPage() && Navigation.OnNextLoadAction == "loadNext") {
        Navigation.OnNextLoadAction = ""; //reload the current page when going next on last
    }
    
    //get next Current Page
    var strOut = new Sys.StringBuilder;
    var TargetPage;
    // loop thru the pages returned
    Trace("--- OnPageListLoaded: " + Navigation.CurrentPage.ScriptLocation + ", " + Navigation.CurrentPage.PageId);
    for (i = 0; i < Navigation.ListOfPages.length; i++) {
        // until we find the current page
        if (Navigation.ListOfPages[i].PageId == Navigation.CurrentPage.PageId) {
        
            // determine the current page's next action
            switch (Navigation.OnNextLoadAction) {
                case "":
                    // stay on the same page
                    TargetPage = Navigation.ListOfPages[i];
                    break;
                case "loadNext":
                    // go to the next page in the list
                    TargetPage = Navigation.ListOfPages[i + 1];
                    break;
                case "loadPrev":
                    // go to the previous page in the list
                    TargetPage = Navigation.ListOfPages[i - 1];
                    break;
                case "loadTarget":
                    // go to a specific page.  
                    // the OnNextLoadAction is set to 'loadTarget' on a OnNavLinkClicked, an error (to stay on the same page)
                    // or in situations when we are bypassing the navigation page list (for instance, when importing an application).
                    Trace("--- loadTarget: " + Navigation.NextTargetPage.ScriptLocation);
                    TargetPage = Navigation.NextTargetPage;
                    break;
                case "saveAsDraft":
                    Trace('--- saveAsDraft: ');
                    TargetPage = { ScriptLocation: SaveAsDraftURL, QueryString: "", PageId: Navigation.CallingPage.PageId };
                    break;
            }
        }
    }
    //If we have no TargetPage...
    //Use the NextTarget if it is declared
    if (Navigation.NextTargetPage && Navigation.NextTargetPage.InjectTarget) {
        
        Navigation.OnNextLoadAction == "loadTarget";
        Navigation.NextTargetPage.InjectTarget = null;
        TargetPage = Navigation.NextTargetPage;
    }
    else if (!TargetPage && result.length > 0) {
        //Or, use the first in list
        TargetPage = result[0];
    }
    else if (!TargetPage && !result.length) {
        //uh-oh - don't know the target and GetPages returned nothing.  Error.
        Trace('Navigation Error!');
        TraceDump(result);

        // show the draft page
        TargetPage = { ScriptLocation: SaveAsDraftURL, QueryString: "", PageId: Navigation.CallingPage.PageId };
    }

    // now that we know the page, navigate to it!
    Navigation.CurrentPage = TargetPage;
    var targetLocation = TargetPage.ScriptLocation + '?';
    if (TargetPage.QueryString && TargetPage.QueryString.length > 0) {
        targetLocation += TargetPage.QueryString + '&';
    }
    targetLocation += 'AppNo=' + CurrentUser.AppNo + "&PageID=" + TargetPage.PageId + "&y=" + (Math.random() * 500);
    Trace("--- AppDataPage Replace() - " + targetLocation);
    AppDataPage.location.replace(targetLocation);

    //update the display
    var PageNbr = 1
    for (i = 0; i < result.length; i++) {
        var NavigationItemHTML = ''
        NavigationItemHTML = "<table border='0'><tr><td align='right' valign='top' style='width: 22px;'>" + PageNbr + ".</td><td>" + Navigation.ListOfPages[i].PageTitle + "</td></tr></table>"

        strOut.append("<div class='NavLeft_Item' onclick=\"OnNavLinkClicked(" + i + ")\" id='NavItem" + PageNbr + "' ")
        PageNbr++

        if (TargetPage.PageId == Navigation.ListOfPages[i].PageId) {

            // the current page's navigation item will be "Active" unless this is a "saveAsDraft" action
            var NavHTMLOut = NavigationContainerHTML.replace("{TEXT}", NavigationItemHTML)
            
            // this is tightly coupled to save as draft as a temporary solution.
            if (Navigation.OnNextLoadAction == "saveAsDraft") {
                NavHTMLOut = NavHTMLOut.replace(/Active/g, "Hover")
            }
            strOut.append(" onmouseover='' onmouseout=''>" + NavHTMLOut);

        } else {
            strOut.append(" onmouseover='ChangeLeftNavOver(this,\"Off\",\"Hover\")' onmouseout='ChangeLeftNavOver(this,\"Hover\",\"Off\")'>" + NavigationContainerHTML.replace("{TEXT}", NavigationItemHTML).replace(/Active/g, "Off"))
        }

        strOut.append("</div>");
    }

    Navigation.OnNextLoadAction = "";
    //Sys.Debug.trace(strOut.toString());

    $get("NavLeft_Contents").innerHTML = strOut.toString();

    //Do other things to the rest of the page...

}

function OnPageListLoadFailed() {
    Trace('OnPageListLoadFailed()');
    Navigation.DisableAll();
    VeilError.Show();
}

// OnNextPageClicked - the next page action attempts to call the AppDataPage's validation routine before saving the current page and navigating.
function OnNextPageClicked() {
    var initScrollTop = winScrollTop(AppDataPage);
    var wHeight = winHeight(AppDataPage);
    var dHeight = winBodyHeight(AppDataPage);

    if ( initScrollTop >= (dHeight - wHeight - scrollSlack)) {
        NextPageNav();
    } else {
        aniScrollTop(AppDataPage.document, initScrollTop + wHeight, 5);
    }
}

function NextPageNav() {
    if (Navigation.IsDataPageLoaded) {
        Navigation.OnNextLoadAction = "loadNext";
        // call the page's javascript validation
        if (AppDataPage && AppDataPage.PageValidate) {
            if (AppDataPage.PageValidate()) {
                SaveAndNavigate();
            } else {
                //page validation failed - alerts are expected to be thrown byt he AppDataPage.
                Trace('OnNextPageClicked(): Page Validation failed - abort navigation');
            } //
        } else {
            //no validation exists, save & navigate
            SaveAndNavigate();
        }
    } else {
        Trace('OnNextPageClicked(): IsDataPageLoaded is false - RefreshNavigation');
        RefreshNavigation();
    }
}


// OnPrevPageClicked - the previous page action saves the current page and then navigates.
function OnPrevPageClicked() {
    var initScrollTop = winScrollTop(AppDataPage);
    var wHeight = winHeight(AppDataPage);
    var dHeight = winBodyHeight(AppDataPage);

    if (initScrollTop <= scrollSlack) {
        PrevPageNav();
    } else {
        aniScrollTop(AppDataPage.document, initScrollTop - wHeight, -5);
    }
}

function PrevPageNav() {
    if (Navigation.IsDataPageLoaded) {
        Navigation.OnNextLoadAction = "loadPrev";
        SaveAndNavigate();
    } else {
        Trace('OnPrevPageClicked():IsDataPageLoaded is false - RefreshNavigation');
        RefreshNavigation();
    }
}

function OnSaveAsDraftClicked() {
    Trace('OnSaveAsDraftClicked()');
    //if on home tab, switch to employment application tab.
    if (Tabs.currentTab == 1) {
        setTimeout("Tabs.show(2)", 1);
        switchAppTab(2);
    }
    Navigation.OnNextLoadAction = "saveAsDraft";
    SaveAndNavigate();
}

function OnDraftContinue() {
    cancelNav = false;
    RefreshNavigation();
}

function OnFinishAndSubmitClicked() {
    Navigation.OnNextLoadAction = "loadTarget";
    Navigation.NextTargetPage = Navigation.ListOfPages[Navigation.ListOfPages.length - 1];
    SaveAndNavigate();
}

function OnNavLinkClicked(index) {
    Navigation.OnNextLoadAction = "loadTarget";
    Navigation.NextTargetPage = Navigation.ListOfPages[index];
    SaveAndNavigate();
}

function OnImportApplicationClicked() {
    Navigation.OnNextLoadAction = "loadTarget";
    Navigation.NextTargetPage = { ScriptLocation: '1importfile1.asp', QueryString: "", PageId: -10 };
    Navigation.Timeout = 45000 //the import may take up to 45 seconds
    SaveAndNavigate();
    setTimeout("Tabs.show(2)", 1);
    switchAppTab(2);
}

function OnScheduleInterviewsClicked() {
    setTimeout("Tabs.show(3)", 1);
    switchAppTab(3);
}

function OnLogOffClicked() {
    Navigation.OnNextLoadAction = "loadTarget";
    Navigation.NextTargetPage = Navigation.ListOfPages[index];
    SaveAndNavigate();
}

var LoadingTimeout;
//validation is done previously (on next only), assumed OK to submit now
function SaveAndNavigate() {
    Trace("SaveAndNavigate(): callee " + (arguments.callee && arguments.callee.name ? arguments.callee.name : 'unknown'));
    Trace("Navigation.OnNextLoadAction: " + Navigation.OnNextLoadAction);
    Trace("Navigation.NextTargetPage.ScriptLocation: " + Navigation.NextTargetPage.ScriptLocation);

    if (VeilLoading) {
    //show veil
    VeilLoading.ResizeAnimations();
    VeilLoading.Show();

    // disable navigation
    Navigation.DisableAll();

    Trace("*** Calling Page: " + Navigation.CurrentPage.ScriptLocation);
    Navigation.CallingPage = Navigation.CurrentPage;

    // set the timer before loading a page.  The page will call DataPageLoaded() and the error will be cleared.
    Trace('-- set timer');
    if (Navigation.Timeout != -1) { errTimer = setTimeout("watchForErrors()", Navigation.Timeout); }
    Navigation.IsDataPageLoaded = false;
    Navigation.InErrorState = false;

    var submitJS;
    if (AppDataPage && AppDataPage.Submit) {
        // the page has a Submit function
        submitJS = "AppDataPage.Submit()";
    } else if (AppDataPage && AppDataPage.document && AppDataPage.document.thisForm) {
        // no custom Submit function exists -- just submit the form
        submitJS = "AppDataPage.document.thisForm.resp.value = 'Save';"
        submitJS += "AppDataPage.document.thisForm.submit();"
    } else {
        submitJS = "Trace('Received SaveAndNavigate() from page with no form to save.');";
    }

    //submit after a 1/10 of a second (show the "saving message")
    LoadingTimeout = setTimeout(submitJS, 100);
    }
}

//Count of arguments might be:
//  zero - navigate as normal
//  one (type: bool) - if false, remove veil and do not navigate
//  two (bool, type: SetupPage) - inject as next page
//  three (bool, SetupPage, type: Applicant) - inject as next page & set as current applicant
function DataPageSaved() {
    Trace("DataPageSaved(" + arguments + "): callee " + (arguments.callee && arguments.callee.name ? arguments.callee.name : 'unknown'));

    if (arguments && arguments.length) {

        if (arguments.length > 1 && arguments[1].ScriptLocation) {
            //Accept a parameter of SetupPage, push into Navigation.NextTargetPage().  
            //This will be picked-up by the OnPageListLoaded
            arguments[1].InjectTarget = true;
            Navigation.NextTargetPage = arguments[1];
        }

        if (arguments.length > 2 && arguments[2].AppNo) {
            //Accept a parameter of Applicant, push into CurrentUser
            CurrentUser.FirstName = arguments[2].FirstName;
            CurrentUser.LastName = arguments[2].LastName;
            CurrentUser.AppNo = arguments[2].AppNo;
            CurrentUser.Update();
        }

        if (!arguments[0]) {
            //Accept non-SetupPage param as a signal to abort navigation
            //hide veil
            VeilLoading.Hide();
            VeilError.Hide();
            //exit
            return false;
        }
    }
    if (!cancelNav) {
        RefreshNavigation();
    }
}

function DataPageLoaded() {
    // clear errors
    Trace("DataPageLoaded() - OnFirstPage: " + Navigation.OnFirstPage() + ", OnLastPage: " + Navigation.OnLastPage());
    Trace("OnNextAction: " + Navigation.OnNextLoadAction);
    Trace("LastLoaded NextAction: " + Navigation.LastLoadedPage.OnNextLoadAction);
    Trace("Caller Page: " + Navigation.CallingPage.ScriptLocation);
    Trace('DataPageLoaded - ' + Navigation.CurrentPage.ScriptLocation);

    // enable all navigation elements.  disable below, as appropriate.
    Navigation.EnableAll();

    // when on the first page, disable "Prev Page" button. else, enable.
    if (Navigation.OnFirstPage()) Navigation.DisablePrevPage();

    // when on the last page, disable "Next Page" and "Finish and Submit" buttons. 
    if (Navigation.OnLastPage()) {
        Navigation.DisableNextPage();
        Navigation.DisableFinishAndSubmit();        
    }

    // when on the first AND on the last page (starting)  
    if (Navigation.OnFirstPage() && Navigation.OnLastPage()) {
        Navigation.DisableAll();
        Navigation.EnableNextPage(); // disabled above when OnLastPage.
        Navigation.EnableTabNavigation(); // can still go back to 'Home' or 'Login to Existing Application'
    }
    
    // when on Save as Draft, disable Save as Draft
    if (Navigation.OnSaveAsDraft()) {
        parent.Navigation.DisableSaveAsDraft();
    }
    
    Trace('-- clear timer');
    clearTimeout(errTimer);
    Navigation.Timeout = Navigation.TimeoutDefault  //reset the timeout (the default is 10 seconds)
    // reset err cnt
    errCnt = 0;
    VeilLoading.Hide();
    Navigation.IsDataPageLoaded = true;
    Navigation.LastLoadedPage = Navigation.CurrentPage;

}

function AppDataPageLoaded() {
    RefreshNavigation();
}

function OnErrorCmdGoBack() { //to the last page you were on
    Trace('OnErrorCmdGoBack():  Nav back to ' + Navigation.LastLoadedPage);
    VeilError.Hide();
    Navigation.EnableAll();
    VeilLoading.Show();
    Navigation.OnNextLoadAction = "loadTarget";
    Navigation.NextTargetPage = Navigation.LastLoadedPage;
    Trace('-- set timer');
    errTimer = setTimeout("watchForErrors()", 10000);
    Navigation.IsDataPageLoaded = false;
    Navigation.InErrorState = false;

    RefreshNavigation();
}

function Trace(msg) {
    if (debugFlag) Sys.Debug.trace(msg);
}

function OnErrorCmdTryAgain() {
    Trace('OnErrorCmdTryAgain()');
    VeilError.Hide();
    Navigation.EnableAll();
    VeilLoading.Show(); 

    Navigation.OnNextLoadAction = "";

    Trace('-- set timer');
    errTimer = setTimeout("watchForErrors()", 10000);
    Navigation.IsDataPageLoaded = false;
    Navigation.InErrorState = false;

    RefreshNavigation();
}

function NavigateToPreviousPage() {
    VeilError.Hide();
    Navigation.EnableAll();
    VeilLoading.Show();
    Navigation.OnNextLoadAction = "loadTarget";
    Navigation.NextTargetPage = Navigation.CallingPage;
    Trace('-- set timer');
    errTimer = setTimeout("watchForErrors()", 10000);
    Navigation.IsDataPageLoaded = false;
    Navigation.InErrorState = false;
    RefreshNavigation();
}

// called from SaveAndNavigate() function
function watchForErrors() {
    Trace('-- watchForErrors() started, caller: ' + watchForErrors.caller);
    Trace('         errCnt: ' + errCnt);
    clearTimeout(errTimer);
    
    Navigation.InErrorState = true;
    //disable navigation and show error
    if (errCnt < 3) {
        ShowErrorVeil();
    } else {
        // if errors continue to happen without being cleared
        if (confirm('Application Error:\n\nMultiple errors have occurred while processing your application.\n\nClick OK to reload your application. If this problem continues, please\ncontact technical support by using the link on the main page.')) {
            parent.location = ('_application.aspx?r=' + (Math.random() * 500));
        } else {
            ShowErrorVeil()
        }
    } // end if
    errCnt += 1;
}

function ShowErrorVeil() {
    VeilLoading.Hide();
    Navigation.DisableAll();
    VeilError.Show();
}

//Image roll overs
function newImage(arg) {
    if (document.images) {
        rslt = new Image();
        rslt.src = arg;
        return rslt;
    }
}

function changeImages() {
    if (document.images && (preloadFlag == true)) {
        for (var i = 0; i < changeImages.arguments.length; i += 2) {
            document[changeImages.arguments[i]].src = changeImages.arguments[i + 1];
        }
    }
}

function changeBG(elID, color) {
    $get(elID).style.backgroundColor = color
}

var preloadFlag = false;
function preloadImages() {
    if (document.images) {
        LogoLock_over = newImage("images/LogoLock-over.jpg");
        SaveAsDraft_over = newImage("images/SaveAsDraft-over.jpg");
        FinishAndSubmit_over = newImage("images/FinishAndSubmit-over.jpg");
        PrevPage_over = newImage("images/PrevPage-over.jpg");
        NextPage_over = newImage("images/NextPage-over.jpg");
        preloadFlag = true;
    }
}

function switchAppTab(target) {
    Trace('switchAppTab() - target: ' + target + ', callee:' + switchAppTab.caller);
    
    switch (target) {
        case 1:
            $get("TopLevel_AppMain").style.display = "none";
            $get("TopLevel_Home").style.display = "block";
            if ($get("TopLevel_Interviews")) { $get("TopLevel_Interviews").style.display = "none"; }

            // if we have a current applicant
            if (CurrentUser.AppNo != 0) {
                switch (Navigation.LastLoadedPage.ScriptLocation) {
                    //post any changes back to the server except for the following pages 
                    case "1importfile1.asp":
                    case "1importfile2.asp":
                        break;
                    default:
                        Navigation.OnNextLoadAction = "loadTarget";
                        Navigation.NextTargetPage = Navigation.LastLoadedPage;
                        SaveAndNavigate();
                }
            }
            break;
        case 2:
            $get("TopLevel_AppMain").style.display = "block";
            $get("TopLevel_Home").style.display = "none";
            if ($get("TopLevel_Interviews")) { $get("TopLevel_Interviews").style.display = "none"; }
            
            $get("TopLevel_Bottom").style.backgroundColor = "red";
            break;
        case 3:
            $get("TopLevel_AppMain").style.display = "none";
            $get("TopLevel_Home").style.display = "none";
            if ($get("TopLevel_Interviews")) { $get("TopLevel_Interviews").style.display = "block"; }
            
    }
}

function ChangeLeftNavOver(el, sourceClass, targetClass) {
    ChangeChildDivs(el, sourceClass, targetClass)
}

function ChangeChildDivs(el, sourceClass, targetClass) {
    if (el.className.indexOf(sourceClass) != -1) {
        el.className = el.className.replace(sourceClass, targetClass)
    }
    for (e = 0; e < el.childNodes.length; e++) {
        newEl = el.childNodes[e]
        if (newEl.childNodes.length > 0) {
            ChangeChildDivs(newEl, sourceClass, targetClass)
        }
    }
}
