/* ------------------------------------------------------------------------ *
 * SAS Institute, Inc.                                                      *
 *                                                                          *
 * Copyright (c) 2002-2008 SAS Institute, Inc.  All rights reserved.             *
 *                                                                          *
 * Contains general functions used throughout the Citation Web application  *
 *                                                                          *
 * Dependencies: citation_events.js, citation_dialogUtils                   *
 *               this file should be loaded first, however.                 *
 *               dojo library must be loaded before this file               *
 *                                                                          *
 * ------------------------------------------------------------------------ */

// globals
var g_wrsVersion          = 4.2;
var g_console             = null;
var g_consoleWindowName   = "DebugConsole";
var g_consoleWindowOpenProperties = "width=200px,height=200px,left=40px,top=32px,toolbar,menubar,resizable,scrollbars=yes";
var g_showDebugMsgs       = false;
var g_showDebugMsgsVerbosity = 1;
var g_showEventDebugMsgs  = false;
var g_closeWindowOnError  = false;
var g_helpDocDialog       = null;
var g_step4CheckAll       = false;
var g_pageLoaded          = false;
var g_openTOC             = 'open';
// indicates the wizard step page number if in wizard
var g_wizardStep          = null;

// In 4.2 themed world, IMAGE_DIR is NOT a constant, but 
// is "overriden" by header.jsp or dialogLayout.jsp. It is
// retained only for use in places where we are not yet able to
// to make images fully theme-able.  In general, it should NOT be used:
var IMAGE_DIR = 'images/';  // Dummy setting, not a constant.
var SCRIPT_DIR = 'scripts/';
// TABLE_IMAGE_DIR and EDIT_IMAGE_DIR are no longer used.
var MENU_END_SPACER_WIDTH = 15;

/*
Hides or shows the given block-level html element based on the value of the 'show' parameter.
The htmlElement will be made visible if the show parameter is true and invisible
if false.  
*/
function wrsShowElement(htmlElement, show) {
    if ( htmlElement == null || show == null) {
        return;
    }
    var displayVal = show ? "block" : "none"; // Assume
    if (show && !isBrowserIE()) {   // Browser supports CSS spec?
        switch (htmlElement.tagName) {
            case "TABLE": displayVal="table"; break;
            case "TR": displayVal = "table-row"; break;
            case "TD": displayVal = "table-cell"; break;
            case "TH": displayVal = "table-cell"; break;
        }
    }
    htmlElement.style.display = displayVal;
}

// a difference between findDOM and dojo.byId is that existing code relies on 
// findDOM returning null, and not undefined when the object doesn't exist.
function findDOM(objectID)
{
    var returnObj = dojo.byId(objectID);
    return (undefined == returnObj ? null : returnObj);
}
function findDOMStyle(id)
{
    var style = null;
    var obj = findDOM(id);
    if (obj != null) {
        style = obj.style;
    }
    return style;
}
// ------------------------------------------------------------------
// Return the DOM element object with the given unique ID attribute
// (if idObj is not a string, just return idObj, assumed to be the
// element already).
// ------------------------------------------------------------------
function getElement(idObj)
{
   return (typeof idObj == "string")? findDOM(idObj): idObj;
}
// ------------------------------------------------------------------
// Return {x,y} values for the left and top values of a static 
// (non-absolutely positioned) element, relative to the document.
// ------------------------------------------------------------------
function getElementOffset(idObj)
{
   return( dojo.style.getAbsolutePosition(idObj, true) );
}
// returns true if is IE 5.5 or later
function isBrowserIE() {
    return (undefined != window.createPopup)
}

function isBrowserFirefox() {
    var agent = navigator.userAgent.toLowerCase();
    return (agent.indexOf("firefox") >= 0);
}

// Returns true on if is IE version 7
function isBrowserIE7() {
    return (isBrowserIE() && document.documentElement && typeof document.documentElement.style.maxHeight!="undefined");
}

// Remove the given style property name (e.g., 'color') from the given element or element ID
function removeStyleProperty(elementOrId, propName) {
    var elem = dojo.byId(elementOrId);
    if (elem) {
        if (isBrowserIE()) {
            elem.style.removeAttribute(propName);
        }
        else {
            elem.style.removeProperty(propName);
        }
    }
}

// =================================================================================
// Debug Console Window
// taken from O'Reilly JavaScript 4th Edition, pg 234
// =================================================================================
function showDebugMsgs(where,msg,verboseLevel) 
{
    if (!window.g_showDebugMsgs) {
      return;
    }
    if (verboseLevel && !(window.g_showDebugMsgsVerbosity >= verboseLevel)) {
      return;
    }
    if (window.console && !window.console.isStubForNoFirebug ) {
        console.log(" ", where, ":", (msg ? msg : ""));
        return;
    }
    try {
        // open new window, first time this function is called
        if ( !window.g_console || (g_console.closed)) {
            // no default URL supplied
            g_console = window.open("", g_consoleWindowName, g_consoleWindowOpenProperties, false);         
            g_console.document.write("<pre style='font:8pt Consolas'>\nBegin Log........................."  + where
                                     + "\n==================================" 
                                     + "\n title:    " + (document ? document.title : "no title") 
                                     + "\n href:     " + window.location.href 
                                     + "\n pathname: " + window.location.pathname
                                     + "\n==================================\n" );
        }
        var text = null;
        if (msg) {
            text = where + ': ' + msg;
        } else {
            text = 'DEBUG: ' + where;
}
        var node = g_console.document.writeln(dojo.string.escape("html",text));
        // always scroll to end so last line is visible
        g_console.scrollTo(0,1000000);
    } catch (e) {
        window.status = 'Exception caught writing to debug window.';
    }
    
    // status = text;  don't do this...it generates confusion and interferes with status line defects
    // do not call close but leave window open
}
// ===============================================================
// Allow for Firebug console API to be used with Firefox but still 
// be handled in IE in some fashion.
// ===============================================================
if (!window.console) {
    window.console = new Object();
    window.console.isStubForNoFirebug = true;
    window.console.output = function (level, arg1, arg2) { showDebugMsgs(level,  arg1 + " " + (arg2 ? arg2 : " ")); };    
    window.console.log = function (arg1, arg2, arg3) { console.output("LOG", arg1, arg2); };
    window.console.info = function (arg1, arg2, arg3) { console.output("INFO", arg1, arg2); };
    window.console.debug = function (arg1, arg2, arg3) { console.output("DEBUG", arg1, arg2); };
    window.console.warn = function (arg1, arg2, arg3) { console.output("WARN", arg1, arg2); };
    window.console.error = function (arg1, arg2, arg3) { console.output("ERROR", arg1, arg2); };
    window.console.assert = function (expr) { if (!expr) {console.error("Assertion failed.")}; };
    window.console.dir = function () { console.info("console.dir not implemented"); };
    window.console.dirxml = function () { console.info("<dir> console.dirxml not implemented </dir>"); };
    window.console.group = function (title) { showDebugMsgs("START " + title, "========================================================"); };
    window.console.groupEnd = function (title) { showDebugMsgs("END " + title, "========================================================"); };
    window.console.trace = function () { return true; };
    window.console.time = function () { window.console.singletonTime = new Date(); console.info("time start: " + console.singletonTime); };
    window.console.timeEnd = function () { var end = new Date(); console.info("elapsed time: " + (end.getTime() - console.singletonTime.getTime() )); console.singletonTime = null; };
    window.console.profile = function (title) { console.info("console.profile not implemented");  };
    window.console.profileEnd = function () { console.info("console.dir not implemented");  };
    window.console.count = function (title) { console.info("console.dir not implemented");  };
}

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// +++++++++++++++++++++++    require/provide/exist functions     +++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// token provided and required must be the same as the file name minus .js extension.
// e.g. wrsProvide("citation_debug");
function wrsProvide(token)
{
   if (wrsExists(token))
   {
      alert("Duplicate wrsProvide of element: " + token);
      showDebugMsgs("INCLUDE ERROR", "Duplicate wrsProvide of element: " + token);
      return;
   }
   showDebugMsgs("NOTE", "wrsProvide element [" + token + "]");
   try {
      sas.provides(token);  
   } catch (e) {
      showDebugMsgs("ERROR in wrsProvide:",   token + ":" + e);
   }   
}
// e.g. wrsRequire("citation", "scripts/", "myJsFile.js");
function wrsRequire(token, loc, requiredFromWhere)
{
   try {
      if (!wrsExists(token)) {
         showDebugMsgs("NOTE", 
              "wrsRequire loading ---->>>> " + token + ", for " + requiredFromWhere);
         var loadLoc = loc ? loc : SCRIPT_DIR;
         sas.requires(token, loadLoc);
      } else {
         // showDebugMsgs("NOTE", "wrsRequire skipped ---- " + token);
      }        
   } catch (e) {
      showDebugMsgs("ERROR in wrsRequire of", 
                        token + " from:" + requiredFromWhere +", error:" + e);
   }
}
function wrsExists(token)
{
   try {
      if (!sas.isProvided(token)) {
         return false;
      } 
   } catch (e) {
      showDebugMsgs("ERROR in wrsExists", token + " error:" + e);
      return false;
   }
   return true;
}

// ++++++++++++++++++++++++++ end require/provide/exist +++++++++++++++++++++

// -----------------------------------------------------------
// This handler should be registered on every page load in
// a header tile or layout tile
// -----------------------------------------------------------
function cwOnPageLoad(evt) {
    // set variable that indicates the page has been fully loaded
    g_pageLoaded = true;
    registerActionTriggerIndicatorForReportLinks();
}

function showErrors(msgs) {
    if (msgs != null) {
        alert(msgs);
    }
}

function setSelectionCursor(elem) {
    if (elem != null && elem.style != null && elem.style.cursor != null)
    {
        elem.style.cursor = 'pointer';  // Note: not 'hand', which only works in IE
    }
}

// Select the 'auto' cursor (that is, it changes automatically
// under the browser's control).  This is not the same as setting it to
// 'default' cursor (which would be a non-changing diagonal pointing arrow in IE and Firefox)
function setAutoCursor(elem) {
    if (elem && elem.style && elem.style.cursor != null)
    {
        elem.style.cursor = 'auto';
    }
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Convenience method that sets the style of the cursor for current document's
// body to the given style. Calling this method is equivalent to calling
// setElementCursorStyle(document.body, style);
// @param style - cursor style to set for document
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function setDocumentCursorStyle(style) {
    setElementCursorStyle(document.body, style);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Sets the style of the elements cursor to the given style
// @param element - element whose cursor style is to be set
// @param style - cursort style to set for document
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function setElementCursorStyle(element, style) {
    element.style.cursor = style;
}

// If keypress is Escape key, close dialog (if isDialog is true), or
// return to previous URL if isDialog is false.
// Lets all other key events proceed normally.
function handleKeyPress(event, isDialog)
{
    var allowEvent = true;
    if (event.keyCode == 27) {  // escape key was pressed (both IE and Firefox use event.keyCode)?
        // always stop progress if progress exists
        var foundProgress = false;
        var progress = findDOM('progressIndicatorDialog');
        if (progress != null) {
            if (progress.style.visibility == 'visible') {
                foundProgress = true;
            }
        } else {
            progress = findDOM('progressIndicator');
            if (progress != null) {
                if (progress.style.visibility == 'visible') {
                    foundProgress = true;
                }
            }
        }
        // only call cancel progress when progress is visible
        // because it has the side affect of closing the dialog
        // or in main window going back to previous URLs
        if (foundProgress && cancelProgress != null) {
            cancelProgress(isDialog);
        } else if (isDialog) {
            self.close();
        } else {
            // if current page is errors page then close it
            if (window.closeErrorsWindow != null) {
                closeErrorsWindow();
            }
            // always make sure all popup menus are closed
            dojo.event.topic.publish('Components.ClosePopups');
        }
        // stop bubbling and prevent default
        dojo.event.browser.stopEvent(event);    
        allowEvent = false;
    }
    return allowEvent;
}

// Stop onkeypress event processing if is ASCII key and
// does not match the given regular expression
function allowKeypress(event, regExp) {
   // IE does not have an onkeypress event for editing keys like arrow  
   // and delete, but Firefox does (and backspace is considered an ascii key)
    var ok = (undefined != event.which && (0 == event.which || 8 == event.which));  // true only for Firefox non-graphic key
    if (! ok) { // Not just an editing key?
        var key = (event.which) ? event.which : event.keyCode;
        ok = String.fromCharCode(key).match(regExp);
        if (! ok) {
            dojo.event.browser.stopEvent(event);
        }
    }
    return ok;
}

// Stop onkeypress event processing if is ASCII key and
// matches the given regular expression
function disallowKeypress(event, regExp) {
    var ok = (undefined != event.which && (0 == event.which || 8 == event.which));
    if (! ok) {
        var key = (event.which) ? event.which : event.keyCode;
        ok = (! String.fromCharCode(key).match(regExp));
        if (! ok) {
            dojo.event.browser.stopEvent(event);
        }
    }
    return ok;
}

// For onkeypress only
function allowNumericOnly(event) {
    return allowKeypress(event, /\d/);
        }

// For onkeypress only
function allowDecimalNumericOnly(event) { // allows 0 - 9, deimal points and minus signs
    return allowKeypress(event, /[0-9.-]/);
    }
    
// For onkeypress only
// function allowInternationalNumericOnly(event) { // allows 0 - 9, decimal point, minus sign, commas and blanks
//  return allowKeypress(event, /[0-9 ,.-]/);
//    }    
    
// For onkeypress only
function allowInternationalNumericOnly(event, decimalSeparator, groupingSeparator) 
{   // Allows 0 - 9, the user's decimal separator, the user's grouping separator and minus sign
    // note the lack of slashes in regExpString this was necessary for this to be turned into a 
    // regular expression. leaving them in made them escaped and nothing was allowed to be entered.
    // If the grouping separator is a space character then it must be converted to \x20 which is the
    // hex representation of the ASCII space.
    if(!event) event = window.event;
    // if(groupingSeparator == "%20")
    //     groupingSeparator = '\x20';
    var regExpString = "[0-9" + decimalSeparator + groupingSeparator + "-]";
    showDebugMsgs("allowInternationalNumericOnly", "regExpString = " + regExpString);
    var regularExpression = new RegExp(regExpString, "gi");
    return allowKeypress(event, regularExpression);
}       

// For onkeypress only
function allowNoQuotes(event) {
    return disallowKeypress(event, /'"/);
}

// For onkeypress only
function allowNoBlanks(event) {
    return disallowKeypress(event, / /);
        }
// Note: For WRS 4.2, images in CitationButtons can only be themed by
// changing the actual image files.  Cannot change the file name or location.
// For theme-based image changes. (Maybe not acutally used in 4.2 WRS?)
function changeImageState(elem, baseName, suffix) {
    if (elem && elem.src && elem.src.length > 0) {
        var iSlash = elem.src.lastIndexOf("/");
        if (iSlash > 0) {
            var imageDir = elem.src.slice(0, iSlash);
            var imageSrc = imageDir + baseName + suffix;
            if (imageSrc != '')
               elem.src = imageDir + baseName + suffix;
        }
    }
}

function changeImageInactive(id, baseName) {
    var doc = findDOM(id);
    if (doc != null) {
        changeImageState(doc, baseName, '_inactive.gif');  // See note above
        doc.style.cursor = 'text';
    }
}
function changeImageActive(id, baseName) {
    var doc = findDOM(id);
    if (doc != null) {
        changeImageState(doc, baseName, '_default.gif');        
        doc.style.cursor = 'text';
    }
}
function changeImageRollover(id, baseName) {
    var doc = findDOM(id);
    if (doc != null) {
        changeImageState(doc, baseName, '_rollover.gif');        
        setSelectionCursor(doc);
    }
}
// added by xxx to support application branding
// This functions changes the applied image to one in a static location instead
// of the standard image directories
function changeImageStatic(id, imagePath) {
    var doc = findDOM(id);
    if (doc != null) {
        doc.src = imagePath;
        setSelectionCursor(doc);
    }
}
function changeTableImageActive(id, baseName) {
    var doc = findDOM(id);
    if (doc != null) {
        changeImageState(doc, baseName, '-default.gif');                
        doc.style.cursor = 'text';
    }
}
function changeTableImageRollover(id, baseName) {
    var doc = findDOM(id);
    if (doc != null) {
        changeImageState(doc, baseName, '-rollover.gif');                        
        setSelectionCursor(doc);
    }
}

// browser-independent way to get the text of an object
function getObjectText(obj) { 
    if (obj.innerText) { // IE; 
        return obj.innerText; 
    } 
    else { 
        if (obj.textContent) { 
            return obj.textContent; 
        } 
        else {
            return 'undefined';
        } 
    }
}

// Replace the first text node (excluding nodes that are just whitespace)
// of the given DOM element (or ID of desired element) or its children.
// Example of how to replace IE-only code with call to this function:
//    findDOM("myElementId").innerText = "New label";   // WRONG! IE only, do not use
//    replaceFirstTextNode('myElementId', "New label"); // RIGHT
function replaceFirstTextNode(elemOrId, text) {
    if (elemOrId) {
        var elem =  ("string" == typeof elemOrId) ? document.getElementById(elemOrId) : elemOrId;
        if (elem) {
            var textNode = getFirstTextNode(elem, /\S/);    // Find first text node that is not just whitespace
            if (textNode) {
                textNode.nodeValue = text;
                return true;
            }
        }
    }
    return false;
}

// Walk subtree of given DOM object elem, and return its first text node
// that matches the given regular expression (may be null to match any
// text, including just whitespace).
function getFirstTextNode(elem, regExp) {
    if (elem) {
        if (isTextNode(elem, regExp)) {
            return elem;
        }
        else {
            for(var iNode=0; iNode < elem.childNodes.length; iNode++) {
                var childNode = elem.childNodes[iNode];
                if (isTextNode(childNode, regExp)) {
                    return childNode;
                }
                childNode = getFirstTextNode(childNode, regExp); // recursive call
                if (childNode) {
                    return childNode;
                }
            }
        }
    }
    return null;
}

// Returns true if given DOM object is a text node,
// optionally matching given regular expression.
function isTextNode(node, regExp) {
    if (node && (3 == node.nodeType)) {
        if (regExp) {
            return (null != node.nodeValue.match(regExp));
        }
        else {  // Any text node will do (including whitespace)
            return true;
        }
    }
    return false;
}

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++  Progress Indicator ++++++++++++++++++++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
isGUICancelInProgress = false;
cancelButtonWasSuppressed = false;

function progressIndicatorStart()
{
    var foundDialog = false;
    var foundWIP = false;
    var progress = findDOM('progressIndicatorDialog');
    if (progress != null) {
        foundDialog = true;
    } else {
        progress = findDOM('progressIndicatorWIP');
        if (progress != null) {
            foundWIP = true;
        } else {
           progress = findDOM('progressIndicator');
           if (progress == null) {
               return;
           }
        }   
    }
    var progressIframe = findDOM('progressIndicatorIframe');
    if(progressIframe)
    {
        progressIframe.style.left = parseInt(progress.offsetLeft) + 1;
        progressIframe.style.top = parseInt(progress.offsetTop) + 1;
        if (parseInt(progress.offsetWidth) > 0) {
            progressIframe.style.width = parseInt(progress.offsetWidth) - 1;
        } else {
            progressIframe.style.width = dojo.html.getViewportWidth();
        }
        if (parseInt(progress.offsetHeight) > 0) {
            progressIframe.style.height = parseInt(progress.offsetHeight) - 1;
        } else {
            progressIframe.style.height = dojo.html.getViewportHeight();
        }   
        progressIframe.style.display = 'inline';
    }

    var yOrigin = 0;
    if (foundWIP) {
        yOrigin = 45;       // primary menu is 45px high for WIP banner
    } else if (! foundDialog) {
        yOrigin = 60;       // primary menu is 60px high
    }
    progress.style.top = yOrigin;
    progress.style.visibility = 'visible';
    if (foundDialog) {
        return;
    }

    content = findDOM('applicationLevelMenu');
    if (content != null) {
        content.style.visibility = 'hidden';
    }
    content = findDOM('applicationTabs');
    if (content != null) {
        content.style.visibility = 'hidden';
    }
    content = findDOM('reportLevelMenu');
    if (content != null) {
        content.style.visibility = 'hidden';
    }
    content = findDOM('welcome');
    if (content != null) {
        content.style.visibility = 'hidden';
    }
    
    window.scrollTo(0, 0);

    showDebugMsgs("progressIndicatorStart", "isGUICancelInProgress: " + isGUICancelInProgress);
    if(isGUICancelInProgress == true)
    {
        suppressCancelButtonAndChangeText();
        isGUICancelInProgress = false;
        cancelButtonWasSuppressed = true;
    }
    else
    {
        showDebugMsgs("progressIndicatorStart", "cancelButtonWasSuppressed: " + cancelButtonWasSuppressed);
        if(cancelButtonWasSuppressed == true)
        {
            enableCancelButtonAndChangeText();
            cancelButtonWasSuppressed = false;
        }
    }
}
function progressIndicatorStop() {
    window.status = '';
    var progress = findDOM('progressIndicatorDialog');
    if (progress != null) {
        progress.style.visibility = 'hidden';
        progressIframe = findDOM('progressIndicatorIframe');
        if (progressIframe != null) {
            progressIframe.style.display = 'none';
        }
        return;
    }
    progress = findDOM('progressIndicator');
    if (progress != null) {
        progress.style.visibility = 'hidden';
    }
    
    progress = findDOM('progressIndicatorWIP');
    if (progress != null) {
        progress.style.visibility = 'hidden';
    }

    progressIframe = findDOM('progressIndicatorIframe');
    if (progressIframe != null) {
        progressIframe.style.display = 'none';
    }
    var content = findDOM('applicationLevelMenu');
    if (content != null) {
        content.style.visibility = 'visible';
    }
    content = findDOM('applicationTabs');
    if (content != null) {
        content.style.visibility = 'visible';
    }
    content = findDOM('reportLevelMenu');
    if (content != null) {
        content.style.visibility = 'visible';
    }
    content = findDOM('welcome');
    if (content != null) {
        content.style.visibility = 'visible';
    }
}
function changeLabel(labelID, text) {
    var doc = findDOM(labelID);
    if (doc != null) {
        var kids = doc.childNodes;
        var numKids = kids.length;
        if (numKids > 0) {
            var kids2 = kids[0].childNodes;
            if (kids2 != null) {
                var numKids2 = kids2.length;
                if (numKids2 > 0) {
                    kids2[0].data = text;
                } else {
                    kids[0].data = text;
                }
            } else {
                kids[0].data = text;
            }
        }
    }
}
function getLabel(labelID) {
    var label = '';
    var doc = findDOM(labelID);
    if (doc != null) {
        var kids = doc.childNodes;
        var numKids = kids.length;
        if (numKids > 0) {
            label = kids[0].data;
        }
    }
    return label;
}
// IMPORTANT: This function should be called in response to a keyup event in a text field.
// If you call this in response to a keydown event then a newly typed character will not
// have been appended to the the text fields value yet when the onkeydown handler is
// invoked. I assume it could also be called in response to a keypress event but
// unfortunately IE 5+ doesn't recognize the backspace character correctly.
function checkLogon(usernameID, minUsernameLen, passwordID, minPasswordLen, logonButtonID) {
    if (findDOM(usernameID) != null
        && findDOM(passwordID) != null
        && findDOM(logonButtonID) != null) {

        var username  = findDOM(usernameID).value;
        var password  = findDOM(passwordID).value;

        //alert( 'username.length = ' + username.length + ',\npassword.length = ' + password.length );
        if (username.length >= minUsernameLen
            && password.length >= minPasswordLen) {
            // enable the button by changing the default images
            //  and allowing onClick, onMouseOver, and onMOuseOut
            findDOM(logonButtonID).disabled = false;
        } else {
            findDOM(logonButtonID).disabled = true;
        }
    }
}

//==============================================================================
// Functions to open and manage specific dialogs within the app
//==============================================================================
//
// requires citation_dialogUtils.js
function openSaveDialog(onDlgClosing, onDlgClosed)
{
    var odClosing = onDlgClosing != null ? onDlgClosing : null;
    var odClosed  = onDlgClosed != null ? onDlgClosed : null;
    cwDialogManager.openDialog(
                        "saveReport.do?dialogCommand=openDialog", //dlgUrl
                        cwDialogManager.SAVE_OPTIONS, //dlgName
                        cwDialogManager.SAVE_OPTIONS, //dlgFeatures
                        true, //bReplaceUrl
                        true, //bModal
                        false, //bReplaceIfOpen
                        odClosing,
                        odClosed
                    );
}
function closeHelpDocDialog()
{
    if (g_helpDocDialog != null) {
        if (!g_helpDocDialog.closed) {
            g_helpDocDialog.close();
        }
        g_helpDocDialog = null;
    }
}

// Note: This function replaces openHelpDocDialog(...) because that name collied
// with another function of the same name in SASDoc_window.js 
function cwOpenHelpDocDialog(event, helpPath)
{
	if (openSASDocWindow) {
		openSASDocWindow(helpPath); 
	}
	// No longer used for 4.2 with WebDoc help:
    //var windowName = null;
    // nav.jsp is used for Table Of Contents and Index
    //if ( helpPath.indexOf( "nav.jsp" ) != -1 ) {
    //    windowName = "SASHelpNavV";
    //} else {
    //    windowName = "SASHelpV";
    //}
    //g_helpDocDialog = window.open(helpPath,
    //    windowName,
    //    'width=800px,height=475px,left=20px,top=20px,resizable=yes');
    //g_helpDocDialog.focus();
}

function openGenericDialog(name,page)
{
    cwDialogManager.openDialog(
                        page, //dlgUrl
                        name, //dlgName
                        cwDialogManager.STD_DLG_FEATURES, //dlgFeatures
                        true, //bReplaceUrl
                        false, //modal
                        false //bReplaceIfOpen
                    );
}
function openHelpWebPageDialog(name,page)
{
    cwDialogManager.openDialog(
                        page, //dlgUrl
                        name, //dlgName
                        cwDialogManager.HELP_DLG, //dlgFeatures
                        true, //bReplaceUrl
                        false, //modal
                        false //bReplaceIfOpen
                    );
}
function openAboutDialog(dlgUrl)
{
    cwDialogManager.openDialog(
                        dlgUrl,  //dlgUrl
                        cwDialogManager.HELP_ABOUT,   //dlgName
                        cwDialogManager.HELP_ABOUT,   //dlgFeatures
                        true, //bReplaceUrl
                        true, //bModal (S0513257)
                        false //bReplaceIfOpen
                    );
}
function cwPrintReport(reportUrl)
{
    var dlgUrl = "openViewReportPrintOptions.do?dialogCommand=openDialog";
    if (reportUrl != null) {
        dlgUrl = "openViewReportPrintOptions.do?REPORT_ID=" + encodeURIComponent(reportUrl) + "&dialogCommand=openDialog";
    }
    openPrintDialog(dlgUrl);
}
function openPrintDialog(dlgUrl)
{
    cwDialogManager.openDialog(
                        dlgUrl,  //dlgUrl
                        cwDialogManager.PRINT_OPTIONS,   //dlgName
                        cwDialogManager.PRINT_OPTIONS,   //dlgFeatures
                        true, //bReplaceUrl
                        true, //bModal
                        false //bReplaceIfOpen
                    );
}

// Note: class RemoveInvalidSecurityChars was here, is no longer used.  
// See ProhibitedCharacterListener in citation_events.js.

//------------------------------------------------------------------------------
// CLASS: RemoveInvalidFilterChars
// Retained for backward compatibility only.  Use ProhibitedCharacterListener class directly instead.
// @param textInputField - the "textarea" element whose input is to be restricted
// the "textarea"
//------------------------------------------------------------------------------
function RemoveInvalidFilterChars(textInputField)
{
    this.prohibited = new ProhibitedCharacterListener(textInputField, g_regExpInvalidFilterChars);
}

RemoveInvalidFilterChars.prototype.initialize = function ()
{
    // Does nothing; for backward compatibility only
}

// ---- End of Class RemoveInvalidFilterChars ----

//--------------------------------------------------------------------------------
// @param reportName - name should be escaped appropriately before calling
//---------------------------------------------------------------------------------
function redrawReportName(reportName) {
    var reportNameLabel = findDOM('reportName');
    if (reportNameLabel != null) {
        changeLabel('reportName', reportName);
    }
    reportNameLabel = findDOM('bantitle2');
    if (reportNameLabel != null) {
        changeLabel('bantitle2', reportName);
        if (findDOM('banbullet') != null) {
            if (reportName != null && ! reportName.match(/^$/)) {
                findDOM('banbullet').style.visibility = 'visible';
            } else {
                findDOM('banbullet').style.visibility = 'hidden';
            }
        }
    }
}
function closeErrorsWindow()
{
    var rootAppWindow = cwDialogManager._getRootApplicationWindow(window);
    // Special override:
    // To the dialog manager, print window appears to be a main window.
    // the global variable override allows an unusual window, such as the
    // print output window, which acts like a top-level window but is not a dialog,
    // to designate behavior when it's close button is pressed after an
    // error in printing.
    // showDebugMsgs("closeErrorsWindow" , window.name + " rootAppWin: " + rootAppWindow.name);
    if (g_closeWindowOnError)
    {
        window.close();
    }
    // Root window
    //
    // Third case: from portal, not viewer (WRS), not a secondary window
    // start up WRS app from portal, no requested report, go to manage/open and
    // try to render a report that fails.  Currently this is closing the window
    // even though it should revert to portal.  Usually the above would catch
    // a WRS main page situation because g_closeWindowOnError is set specially
    // to true ONLY when it's the print preview window.
    else if (window == rootAppWindow)
    {
        // showDebugMsgs("closeErrorsWindow", "window is root with no opener");
        window.location.href = 'recoveryTransaction.do';
        return;
    }
    else
    {
        // anything else other than the root window mandates that we shut the window
        // that would go for any dialog window, or any auxiliary window, such as the
        // print preview results.
        window.close();
    }
}

var linksToExclude = new Array();

function addLinkToExclude( elementToExclude )
{
    linksToExclude[linksToExclude.length] = elementToExclude;
}

function excludeLink( elementToLookFor )
{
    for( var index = 0; index < linksToExclude.length; index++ )
    {
        if( linksToExclude[index] == elementToLookFor )
        {
            return true;
        }
    }
    return false;
}

var wrsMapLayer = false;
var wrsZoomLayer = false;

function registerActionTriggerIndicatorForReportLinks()
{
    for( index = 0; index < document.links.length; index++ )
    {
        var linkElement = document.links[index];
        if( linkElement.href != null && linkElement.href.indexOf('javascript') == -1
         && linkElement.href.indexOf('#') == -1
         && linkElement.target != '_blank' && excludeLink(linkElement) == false)
        {
            if( registerEventHandler != null )
            {
                registerEventHandler( linkElement, 'click', onLeavePage, false );
            }
        }
    }

    // see if there is an ESRI map zoom layer available
    if(wrsZoomLayer)
    {   // register click events on the zoom layer catches zoom in/out
        registerEventHandler( wrsZoomLayer, 'mouseup', onLeavePage, false );
    }
}

function onLeavePage()
{
    progressIndicatorStart();
    if(typeof g_msgPleaseWait != "undefined")
        window.status = g_msgPleaseWait;
    var progressIndicatorElement = findDOM('progressIndicator');
    var progressIndicatorElementWIP = findDOM('progressIndicatorWIP');

    if(progressIndicatorElement != null)
    {
        progressIndicatorElement.style.height = dojo.html.getViewportHeight();
    }
    else if (progressIndicatorElementWIP != null)
    {
       progressIndicatorElementWIP.style.height = dojo.html.getViewportHeight();
    }

    reloadAnimatedImage('progressIndicatorImage');
}

// After the progress indicator has been hidden if it is made visible the animated spinning coin image no longer spun.
// Found this trick on the Net to reload the image simply by finding it in the DOM, saving the name,
// setting it to an empty string and then restoring the same name. This reloads the image and gets it spinning again.

function reloadAnimatedImage(imageId)
{
    var imageString = '';
    var imageElement = findDOM(imageId);
    if( imageElement != null )
    {
        showDebugMsgs('reloadAnimatedImage', 'Found the target image to reload');
        imageString = imageElement.src;
        //CAUTION it has been determined that the statement below 
        //causes an undesired HTTP request to be fired to the resource
        //pointed to by the base tag's href attribute (See S0408407)
        //imageElement.src = ''; 
        if (imageString != '')
           imageElement.src = imageString;
    }
}

// var originalMapOnClick = window.sas_mapOnClick;
// var wrsMapOnClick = function(esriMapObjId)
// {
//     debugger;
//     wrsMapOnClick.originalMapOnClick(esriMapObjId);
//     var esriMapObject = eval(esriMapObjId);
//     if(esriMapObject != undefined)
//     {
//         if(esriMapObject.mode != 6) // if esri map and the identify action has been selected skip wait
//         {
//             onLeavePage();
//         }
//     }
// }
// wrsMapOnClick.originalMapOnClick = originalMapOnClick; //add
// window.sas_mapOnClick = wrsMapOnClick;


// Return the iChild'th (0-relative) immediate child element
// of the given element (excluding text or other child node types), or null if not found.
function cw_findChildElement(elem, iChild) {    // (S0348464)
    var iChildElem = -1;
    for(var iNode=0; iNode < elem.childNodes.length; iNode++) {
        if (1 == elem.childNodes[iNode].nodeType) { // Is an element
            iChildElem++;
            if (iChild == iChildElem) {
                return elem.childNodes[iNode];
            }
        }
    }
    return null;    // Not found
}
//------------------------------------------------------------------------------
// Function to check whether browser is adequate for the WRS job.
// Shows an alert to user if not.  Does not prevent user from using the 
// page, just annoys him.
//------------------------------------------------------------------------------

function cwCheckBrowserSupport(alertMessage)
{
    var browser = new Object();
    browser.isMicrosoft = false;
    browser.isFirefox = false;
    browser.versionMajor = parseInt(navigator.appVersion);
    browser.versionInside = 0;
    if (navigator.appVersion.indexOf("MSIE")!=-1)
    {
        temp = navigator.appVersion.split("MSIE")
        browser.versionInside = parseFloat(temp[1])
    }
    if (navigator.appName.indexOf('Microsoft') != -1)
    {
        browser.isMicrosoft = true;
    }
    if (navigator.appName.indexOf("Netscape") != -1
        && navigator.userAgent.indexOf("Firefox") != -1)
    {
        browser.versionMajor = 5;
        browser.isFirefox = true;
        showDebugMsgs("browser check:", "FF=" + browser.isFirefox + "  MS:" + browser.isMicrosoft);
    }
    if (!((browser.isMicrosoft == true && browser.versionMajor >= 4 && browser.versionInside >= 5.5)
           || (browser.isFirefox == true)) )
    {
        alert(alertMessage);
    }
    return browser;
}


function noScrollIE()
{
    document.body.scroll="no";
}

function noScrollMozilla()
{
    document.width= window.innerWidth;
    document.height=window.innerHeight;
}

function wrsRemoveScrollBars(evt)
{
   if (isBrowserIE() || isBrowserIE7())
   {
      noScrollIE();
   }
   else 
   {
      noScrollMozilla();
   }
}

function handleSessionTimeout(data, event)
{
   showDebugMsgs("handleSessionTimeout", "Check for timeout.");
   var timeoutFound = false;
   
   startTime = new Date().getTime(); 

   try 
   {
      if (data && data.indexOf("sas.sessionExpired") > -1) 
      {
         eval(data);
         if (sas.sessionExpired) 
         {
            showDebugMsgs("handleSessionTimeout", "Session timeout!");
            if (sas.sessionExpired.message)
               alert(sas.sessionExpired.message);
            if (sas.sessionExpired.forwardLocation)
               window.location.href = sas.sessionExpired.forwardLocation;

            sas.sessionExpired = false; 
            
            timeoutFound = true;
         }   
      }   
   } 
   catch (e)  
   {
      // Received no timeout error from server. Continue normally.
   }   
   

   try 
   {
      if (!timeoutFound)
      {
        if( typeof sas_framework_updateTimeout !="undefined")
        {
           sas_framework_updateTimeout();
        }
        if (window.opener) 
        { 
          if (typeof window.opener.sas_framework_updateTimeout != 'undefined') 
          {
             window.opener.sas_framework_updateTimeout();
          }
        }
      }

   } 
   catch (e)  
   {
      // Reset timer failed. Continue normally.
   }   

   endTime = (new Date().getTime() - startTime); 
   showDebugMsgs("handleSessionTimeout", "Time it took to check for timeout = "+endTime+ " miliseconds");
   
   return timeoutFound;
}

function openPDFWindow(targetUrl)
{
   var dlgUrl = "viewPDF.do?TARGET_URL=" + encodeURIComponent(targetUrl);
   window.open( dlgUrl, "viewPDFWindow", "", true );
}
    
function cwOpenCommentManagerDialog(reportUrl)
{
	var dlgUrl = "commentManager.do?dialogCommand=openDialog";
	
	if(reportUrl != null)
		dlgUrl += "&reportUrl=" + encodeURIComponent(reportUrl);
	
    cwDialogManager.openDialog(
    		            dlgUrl, //dlgUrl
                        cwDialogManager.COMMENT_MANAGER,   //dlgName
                        cwDialogManager.COMMENT_MANAGER,   //dlgFeatures
                        true, //bReplaceUrl
                        true, //bModal
                        false //bReplaceIfOpen
                    );
}    

function isNumber(n) 
{ 
	return !isNaN(parseFloat(n)) && isFinite(n); 
} 


// -----------------------
wrsProvide("citation");
// -----------------------

