/* ------------------------------------------------------------------------ *
 * SAS Institute, Inc.                                                      *
 *                                                                          *
 * Copyright (c) 2002 SAS Institute, Inc.  All rights reserved.             *
 *                                                                          *
 *                                                                          *
 * Contains methods that support event handling and registration across     *
 * browsers (IE 5.5+ & NS 6.2+ ).                                           *
 *                                                                          *
 *                                                                          *
 * Dependencies: none                                                       *
 *                                                                          *
 *                                                                          *
 * @author Rick Evans (left SAS after v913)                                 *
 * @author Harry Maxwell (harry.maxwell@sas.com)                            *
 * ------------------------------------------------------------------------ */

/* --------------------------------------------------------------------------
    requires citation.js for functions:
        findDOM()
        showDebugMsgs()
        getEventSource()

    requires citation_button.js for functions:
        setButtonState()
        setButtonState.ROLLOVER
        setButtonState.ROLLOUT
        changeImageRollover()
* ---------------------------------------------------------------------------*/
// constants
var HOW_DO_I = "howDoI";
var OPTIONS = "options";
var LAYOUT = "layout";
var HELP = "help";
var SEPARATOR = "separator";
var POPUP_MENU_CLASS = "popupmenu";
var POPUP_MENU_ID = POPUP_MENU_CLASS;
var POPUP_MENU_ID_NAME = 'SAS_WebReportStudio_Popup_';
var POPUP_MENU_ID_FIRST_NAME = POPUP_MENU_ID_NAME + '1';
var POSITION_RIGHT = false;
var POSITION_LEFT = true;

// globals
var g_popupMenu = null;
var g_popupSource = null;
var g_popupDebug = 0;

/*
    event - HTML event that triggered popup menu
    id - HTML element ID
    type - either HOW_DO_I or HELP or OPTIONS or LAYOUT
    labels - Array of labels to show for popup menu items;
        if one of the Array element values is SEPARATOR
        then that will cause a HR element to be displayed
    links - Array of onclick links that match one-to-one with labels Array
*/
function overCell(event, id, type, labels, links) {
    // only allow popup menu on the screen at one time
    if (g_popupSource != null) {
        return;
    }
    // HJM: this seems to be causing problems with little benefit.
    // cursor over the original button already was correct, why change?
    // var doc = findDOMStyle(id);
    // try {
        // Netscape cursor
        // doc.cursor = "pointer";
    //} catch (ex) {
        // IE cursor
      //  doc.cursor = "hand";
    // }
    var position = POSITION_LEFT;
    if (LAYOUT.match(type)) {
        position = POSITION_RIGHT;
    }
    //show transient pop-up as mouse moves over table cells
    _showPopup(event, id, type, labels, links, position);
    _hidePopupEvent("over", id, event, type);

    if (HOW_DO_I.match(type) || OPTIONS.match(type) || LAYOUT.match(type)) {
        setButtonState(event, id, setButtonState.ROLLOVER, 'reportLevel_menuButton');
        changeImageRollover('img_' + id + '_c', 'down_arrow');
    } else {
        setButtonState(event, id, setButtonState.ROLLOVER, 'appLevel_secondary_menuButton');
    }

    // show tool tip for text to help user know to click on text for pop-up
    if (g_popupMenu == null
        || g_popupMenu.style.visibility == "hidden") {
        //findDOM(id).title = TEXT_OPTIONS;
    }

    // put focus on first item in dropdown
    if (findDOM(POPUP_MENU_ID_FIRST_NAME) != null) {
        try {
            findDOM(POPUP_MENU_ID_FIRST_NAME).focus();
        } catch(e) {
        }
    }
}
function alterSubsequentProcessing(event, stopPropagation, allowNormalAction)
{
    if (event == null)
    {
        event = window.event; // IE
    }
    if (stopPropagation)
    {
	    // We've handled this event. Don't let anybody else see it.
	    if (event.stopPropagation)  // DOM Level 2
	    {
	        event.stopPropagation(  );
	    }
	    else // IE
	    {
	        event.cancelBubble = true;
	    }
    }
    // Now prevent any default action.
    if (!allowNormalAction)
    {
	    if (event.preventDefault) // DOM Level 2
	    {
	        event.preventDefault();
	    }
	    else  // IE
	    {
	        event.returnValue = false;
	    }
    }
    return allowNormalAction;
}
function processPopupKey(event, menuIndex, id, type, maxNumber)
{
    var keyCode = ( event.which != null ) ? event.which : event.keyCode;
    var stopPropagation = false;
    var allowNormalAction = true;
    showDebugMsgs("processPopupKey", "type " + event.type + " Keycode: " + keyCode);
    // down arrow key
    if (keyCode == "40")
    {
        // put focus on next item below current menu item in dropdown
        var nextItem = POPUP_MENU_ID_NAME + (menuIndex+1);
        if (findDOM(nextItem) != null) {
            try {
                findDOM(nextItem).focus();
            } catch(e) {
            }
            stopPropagation = true;
            allowNormalAction = false;
        // cycle back to first menu item
        } else {
            var nextItem = POPUP_MENU_ID_FIRST_NAME;
            if (findDOM(nextItem) != null)
            {
                try {
                    findDOM(nextItem).focus();
                } catch(e) {
                }
                stopPropagation = true;
                allowNormalAction = false;
            }
            else // if item does not exist then close the popup menu
            {
                _hidePopupMenu(event, id, type);
                stopPropagation = true;
                allowNormalAction = true;
            }
        }
    }
    // up arrow key
    else if (keyCode == "38")
    {
        // put focus on previous item below current menu item in dropdown
        var prevItem = POPUP_MENU_ID_NAME + (menuIndex-1);
        if (findDOM(prevItem) != null) {
            try {
                findDOM(prevItem).focus();
            } catch(e) {
            }
            stopPropagation = true;
            allowNormalAction = false;
        // cycle back to last menu item
        } else {
            var nextItem = POPUP_MENU_ID_NAME + maxNumber;
            if (findDOM(nextItem) != null) {
                try {
                    findDOM(nextItem).focus();
                } catch(e) {
                }
                stopPropagation = true;
                allowNormalAction = false;
            // if item does not exist then close the popup menu
            } else {
                _hidePopupMenu(event, id, type);
                stopPropagation = true;
                allowNormalAction = true;
            }
        }
    }
    // right arrow key
    else if (keyCode == "39")
    {
        _hidePopupMenu(event, id, type);
        stopPropagation = true;
    }
    // left arrow key
    else if (keyCode == "37")
    {
        _hidePopupMenu(event, id, type);
        stopPropagation = true;
    }
    // escape key
    else if (keyCode == "27")
    {
        _hidePopupMenu(event, id, type);
        stopPropagation = true;
        allowNormalAction = false;
    }
    // tab key
    else if (keyCode == "9")
    {
        _hidePopupMenu(event, id, type);
        allowNormalAction = true;
    }
    // get out of the way of other hot keys on the page
    else if (event.altKey == true)
    {
        // showDebugMsgs("popup ignoring hot key", keyCode);
        _hidePopupMenu(event, id, type);
        allowNormalAction = true;
    }

    // IE has different mechanism to cancel event processing
    showDebugMsgs("popup ends", type + "," + stopPropagation + "," + allowNormalAction);
    alterSubsequentProcessing(event, stopPropagation, allowNormalAction);
    return allowNormalAction;
}
/*
    event - HTML event that triggered popup menu
    id - HTML element ID
*/
function hidePopup(event, id, type) {
    var doc = findDOMStyle(id);
    if (doc != null) {
        _hidePopupEvent("hide", id, event, type);
    }
}
function hideAllPopups(event) {
    if (g_popupMenu
        && g_popupMenu.style.visibility == "visible") {
        _hidePopupMenu(event,null,HOW_DO_I);
        _hidePopupMenu(event,null,OPTIONS);
        _hidePopupMenu(event,null,LAYOUT);
    }
    // see if any sas_menubar.js popups need closing.
    // a hack, because it depends on knowing the names of the sas_menubar globals
    if (window.MenuBar_hidePop)
    {
        if (window.previousMenu && event)
        {
            MenuBar_hidePop(previousMenu, event);
        }
    }
}
function _showPopup(event, id, type, labels, links, positionToLeft) {

    showDebugMsgs("SHOW", "event="+event+", id="+id+", type="+type+", labels="+labels.toString()+", links="+links.toString());

    // see if any sas_menubar.js popups need closing.
    // a hack, because it depends on knowing the names of the sas_menubar globals
    if (window.MenuBar_hidePop)
    {
        if (window.previousMenu && event)
        {
            MenuBar_hidePop(previousMenu, event);
        }
    }
    _createPopup();
    _createPopupContents(id, type, labels, links);

    var doc = findDOM(id);
    // position menu to left of document element (include width of element)
    var xOrigin = 0;
    var yOrigin = doc.offsetHeight;
    var parent = doc;
    while (parent != null) {
        xOrigin += parent.offsetLeft;
        yOrigin += parent.offsetTop;
        // subtract scrolltop if not top-level
        if (parent.scrollTop != 0 && parent.offsetParent != null) {
          yOrigin -= parent.scrollTop;
        }
        parent = parent.offsetParent;
    }
    /*dbg
    status = "DOC-LOCATION: X="+xOrigin+", Y="+yOrigin;
    dbg*/

    // must disable tool tip for text or else it shows on top of pop-up menu
    doc.title = '';

    g_popupMenu.style.top = yOrigin;
    if (positionToLeft) {
        g_popupMenu.style.left = xOrigin - g_popupMenu.offsetWidth + doc.offsetWidth;
    } else {
        g_popupMenu.style.left = xOrigin;
    }
    g_popupMenu.style.visibility = "visible";
    g_popupSource = getEventSource("show", event);
}
function _hidePopupEvent(where, id, event, type) {
    if (g_popupMenu
        && event != null
        && g_popupMenu.style.visibility == "visible") {

        var notInSource = true;
        var doc = findDOM(id);

        // IE: event
        if (event.toElement) {
            // only hide when event goes out of popup menu or parent document
            var popupContainsEvent = g_popupMenu.contains(event.toElement);
            var documentContainsEvent = doc.contains(event.toElement);

            // showDebugMsgs("HIDE", type+"(id="+id+"), doc contains="+documentContainsEvent+", menu contains="+popupContainsEvent+", toID="+event.toElement.id+", fromID="+event.fromElement.id+", srcID="+event.srcElement.id+", popupSrcID="+g_popupSource);

            if (g_popupSource != null
                && event.toElement.id == g_popupSource.id)
            {
                notInSource = false;
            }
            if (notInSource
                && !documentContainsEvent
                && !popupContainsEvent)
            {
                _hidePopupMenu(event,id,type);
            }
        // Netscape: event
        }
        else if (event.curLevel)
        {
			/* BUG: popup menus cannot be selected on Netscape
			showDebugMsgs("HIDE", "doc="+doc.id+", docContains="+_containsNetscape(doc,event.currentTarget)
			+ ", popContains="+_containsNetscape(g_popupMenu,event.currentTarget)
			+ ", curID="+event.currentTarget.id+", target="+event.target.id
			+", popSrc="+g_popupSource.id);
			BUG: popup menus cannot be selected on Netscape*/

            if (g_popupSource != null
                && event.currentTarget.id == g_popupSource.id) {
                notInSource = false;
            }
            if (!_containsNetscape(doc, event.currentTarget)
                && !_containsNetscape(g_popupMenu, event.currentTarget)
                && notInSource) {
                _hidePopupMenu(event,id,type);
            }
        }
    }
}
function _containsNetscape(container, containee) {
    var isParent = false;
    if (containee == null) {
        return isParent;
    }
    do {
        if ((isParent = container == containee)) {
            break;
        }
    } while ((containee = containee.parentNode))
    return isParent;
}
function _hidePopupMenu(event,id,type)
{
    if (g_popupMenu)
    {
        g_popupMenu.style.top = '0px';
        g_popupMenu.style.right = '0px';
        g_popupMenu.style.visibility = "hidden";
        g_popupSource = null;

        // showDebugMsgs('HIDE-POPUP', 'pop-up menu=' + g_popupMenu);

        // reset original button state
        if (HOW_DO_I.match(type) || OPTIONS.match(type) || LAYOUT.match(type))
        {
            setButtonState(event, id, setButtonState.ROLLOUT, 'reportLevel_menuButton');
            changeImageActive('img_' + id + '_c', 'down_arrow');
        } else {
            setButtonState(event, id, setButtonState.ROLLOUT, 'appLevel_secondary_menuButton');
        }

        if (findDOM(id) != null) {
            findDOM(id).focus();
        }
    }
}
function _createPopup() {
    if (g_popupMenu == null) {
        g_popupMenu = document.createElement('div');
        document.body.appendChild(g_popupMenu);

        g_popupMenu.style.position = 'absolute';
        g_popupMenu.style.top = '0px';
        g_popupMenu.style.right = '0px';
        g_popupMenu.style.visibility = "hidden";
        g_popupMenu.style.zIndex = 10;

        // showDebugMsgs('CREATE-POPUP', 'created the pop-up menu='+g_popupMenu);

    }
}

// (brcarb 12/20/06 S0396661) Returns true if browser is IE 7
function isBrowserIE7() {
	return (document.documentElement
			&& typeof document.documentElement.style.maxHeight!="undefined");
}

// ----------------------------------------------
// _createPopupContents requires a link string Array
// where each link indicates the action to be taken
// when the corresponding label is selected.
// each link has a prefix that indicates how it
// should be generated.  These two are just for
// text values with no real action:
// "DISABLED|",
// "ACTIVE|",
// These indicate an action to be done onclick.
// "JAVASCRIPT|",
// "JSP|",  (or "SAME|")
// "WEBPAGE|"
// "DIALOG|"
// -----------------------------------------------
function _createPopupContents(id, type, labels, links) {
    if (labels == null
        || links == null) {
        alert("popup create: no menus supplied");
    } else if (labels.length != links.length) {
        alert("popup create: mismatch in labels ("+labels.length+") and links ("+links.length+")");
    } else {
        /*
        showDebugMsgs("popup create: labels={"+labels.toString()+"}\nlinks={"+links.toString()+"}");
        */
        var html = '<table border="0" summary="" cellpadding="0" cellspacing="0"'
          + ' id="'+POPUP_MENU_ID+'" class="'+POPUP_MENU_CLASS+'"'
          + ' onmouseout="javascript:hidePopup(event,\''+id+'\',\''+type+'\');">\n';
        html += '<tr><td class="linePadding">&nbsp;</td></tr>\n';
        if (g_popupDebug) {
            html += '<tr><td class="popupdebug" nowrap="nowrap">'+type+' Pop-up</td></tr>';
            html += '<tr><td class="linePadding">&nbsp;</td></tr>\n';
        }
        var activePopupIndex = 1;
        var maxLinks = 0;
        for (var i=0; i<labels.length; i++) {
            if (labels[i].match(SEPARATOR)) {
            } else {
                var tag = links[i].split("|",2);
                if ("ACTIVE".match(tag[0]))
                {
                } else if ("DISABLED".match(tag[0]))
                {
                } else
                {
                    maxLinks++;
                }
            }
            // this happens rarely, but stored processes can have <> and
            // they can be on the history list - S0311028
            labels[i] = labels[i].replace(/</, "&lt;");
            labels[i] = labels[i].replace(/>/, "&gt;");
        }
        for (var i=0; i<labels.length; i++)
        {
            if (labels[i].match(SEPARATOR))
            {
                html += '<tr><td align="center" ><hr class="popupmenuspacer"/></td></tr>\n';
            }
            else
            {
                html += '<tr><td align="left" <%MOUSEOVER%> nowrap="nowrap">';
                onclick = 'javascript:_hidePopupMenu(event,\''+id+'\',\''+type+'\');';

                var tag = links[i].split("|",2);
                if ("JAVASCRIPT".match(tag[0])
                		|| "CHECKEDRADIO".match(tag[0])
                		|| "UNCHECKEDRADIO".match(tag[0]))
                {
                    onclick += "location.href='javascript:" + tag[1] + "'";
                }
                else if ("JSP".match(tag[0]) || "SAME".match(tag[0]))
                {
					if (isBrowserIE7()) {	// (brcarb 12/20/06 S0396661)
						onclick += tag[1];
					}
					else {	// Is IE6
						onclick += "location.href='" + tag[1] + "'";
					}
                }
                else if ("DIALOG".match(tag[0]))
                {
                    onclick += " openGenericDialog('PopupDialog','" + tag[1] + "');";
                }
                else if ("WEBPAGE".match(tag[0]))
                {
                    onclick += " openHelpWebPageDialog('WebPage','" + tag[1] + "');";
                }
                else
                {
                    onclick += " openHelpDocDialog(event,'" + links[i] + "');";
                }

                if ("ACTIVE".match(tag[0]))
                {
                    html += '<span class="popup_active">'
                        + labels[i]
                        + '</span>';
                }
                else if ("DISABLED".match(tag[0]))
                {
					html = html.replace('<%MOUSEOVER%>', 'onmouseover="javascript:popupHighlightMenuItem(this);"');

                    html += '<span class="popup_disabled">'
                        + labels[i]
                        + '</span>';
                }
                // This is not really an html radio at all, but a pseudo-radio with a dot marker
                // in front of the selected option.  The checked one doesn't use it's link because
                // it's already selected.
                else if ("CHECKEDRADIO".match(tag[0]))
                {
                    name = POPUP_MENU_ID_NAME + activePopupIndex;
                    html += '<table border="0" summary="" cellpadding="1" cellspacing="0"><tr><td><img src="images/popup/dot_blue.gif"></td>';
                    html += '<td nowrap="nowrap"><span id="'+name+'" class="popup_selected" tabIndex="-1"'
                        + '>'
                        + labels[i]
                        + '</span></td></tr></table>';
                    // activePopupIndex++;
                }
                // This is really just an action with space for a dot selector
                // The unchecked radio is the one you can select, so it uses its link.
                else if ("UNCHECKEDRADIO".match(tag[0]))
                {
                    name = POPUP_MENU_ID_NAME + activePopupIndex;
                    html += '<table summary="" border="0" cellpadding="1" cellspacing="0"><tr><td class="marginPadding">&nbsp;</td>';
                    html += '<td nowrap="nowrap"><a id="' + name + '" class="hyperlink" tabIndex="-1"'
                        + ' onkeydown="javascript:processPopupKey(event,'
                        + activePopupIndex
                        + ',\'' + id + '\',\'' + type + '\','
                        + maxLinks
                        + ');"'
                        // Adds extra tooltip
                        // + ' title="' + labels[i] + '"'
                        + ' href="' + onclick + '">'
                        + labels[i]
                        + '</a></td></tr></table>';
                    activePopupIndex++;
                }
                // for graying out an element that is indented like a radio button
                else if ("DISABLEDRADIO".match(tag[0]))
                {
                	html += '<table summary="" border="0" cellpadding="1" cellspacing="0"><tr><td class="marginPadding">&nbsp;</td>';
                	 html += '<td><span class="popup_disabled">'
                        + labels[i]
                        + '</span></td></tr></table>';
                }
                // This is the normal menu action:
                else
                {
                    name = POPUP_MENU_ID_NAME + activePopupIndex;
                    html += '<a id="'+name+'" class="hyperlink menuItem" tabIndex="-1"'
                        + ' onkeydown="javascript:processPopupKey(event,'
                        + activePopupIndex
                        + ',\''+id+'\',\''+type+'\','
                        + maxLinks
                        + ');"'
                        + ' onfocus="javascript:popupHighlightMenuItem(this);"';
                        // adds extra tooltip
                        // + ' title="' + labels[i] + '"'
                    if (isBrowserIE7()) {	// (brcarb 12/20/06 S0396661) Is IE7?
                       	html += ' href="javascript:void(0)"'
                       	+ ' onclick="' + onclick + '">';
					}
					else {	// Is IE6
						html += ' href="' + onclick + '">';
					}
                    html += labels[i]
                        + '</a>';

					html = html.replace('<%MOUSEOVER%>', 'onmouseover="javascript:popupHighlightMenuItem(this);"');

                    activePopupIndex++;
                }
                html += '</td></tr>\n';

				html = html.replace("<%MOUSEOVER%>", "");
            }
        }
        html += '<tr><td class="linePadding">&nbsp;</td></tr></table>\n';

        /*
        showDebugMsgs("CREATE-POPUP-CONTENTS","HTML for id="+id+"\n"+html);
        */
        g_popupMenu.innerHTML = html;
    }
}

// Activates the target element when the spacebar is pressed.
// The target element is activated by dispatching a click event
// to all of the target's onclick listeners.
function popupActivateListener(event) {
    var keyCode = ( event.which != null ) ? event.which : event.keyCode;
    // alert('ENTERING spaceBarActivateListener = ' + keyCode);
    if (keyCode == '40' || (String.fromCharCode(keyCode) == ' ') )
    {
        //space bar pressed while event target has focus
        var evtTrg = ( event.target != null ) ? event.target : event.srcElement;

        //dispatch a click event to the event target's click handlers
        eventNotify ( evtTrg, 'click', true );
    }
    //alert('EXITING spaceBarActivateListener');
}

 function popupHighlightMenuItem(element)
 {
	// incoming element could either be the anchor or the td that the anchor lives in.
	var anchor = null;
 	if(element.tagName=='A')
    {
		anchor= element;
    }
    // if TD passed in then find its internal anchor
	else if ( element.tagName=='TD' )
	{
		kids = element.childNodes;
		for (var i = 0; i < kids.length; i++)
		{
			if(kids[i].tagName=='A')  // is it the anchor
			{
				anchor = kids[i];
				break;
			}
		}
	}

	if(anchor!=null)
	{
		var menuItemRow = anchor.parentNode.parentNode;  // Menu Item TR
		var menuTable = menuItemRow.parentNode.parentNode;          // Menu Table
		var menuDiv = menuTable.parentNode;              // Menu container Div

		if(menuDiv!=null && menuDiv.style.display!='none')  // can happen in time span between clicking a menu item adn the menu closing itself
		{
			var highlightDiv = document.getElementById(menuDiv.id + "_highlightMenuItem");
			if( !highlightDiv )
			{
			        highlightDiv = document.createElement("DIV");
			        highlightDiv.id = menuDiv.id+"_highlightMenuItem";
					highlightDiv.className = "menuItemHighlight";
			        menuDiv.appendChild(highlightDiv);
			}

			// really should put some cross browser event dispatching code in sas_Common
			// at some point and use that instead of this.
			if(anchor.dispatchEvent) { // DOM2
				highlightDiv.onclick=function(event){anchor.dispatchEvent(event);};
            }
			else if (anchor.click)
			{
				// IE - could fireEvent but since IE supports click method lets just
				// call it on the anchor.
                // Get the function in scope so it won't go away before it gets called. [hjm]
                var clickHandler = anchor.click;
				highlightDiv.onclick=function(event){clickHandler();};
			    // highlightDiv.onclick=function(event){anchor.fireEvent(window.event.type, window.event);};
			}


			// we will now position the highlighting div over the top of
			// the menu items TR.
			menuDivCoords = new sas_Coordinates(menuDiv);
			anchorCoords = new sas_Coordinates(anchor);

			highlightDiv.style.top = anchorCoords.getY();
			highlightDiv.style.height = anchorCoords.getHeight();
			highlightDiv.style.left = menuDivCoords.getX()+3;
			highlightDiv.style.width = menuDivCoords.getWidth()-6;

			highlightDiv.style.display='block';
		}
	}
}