//*************************************************************************************
//* Debugging routines                            
//* Include in the header of all KME JavaScript Apps                      
//* Written by Knowledge Management, Inc. 2001, all rights reserved       
//*************************************************************************************                                                                       

//***** GLOBAL VARIABLES

	var debug_started = false;
	var load_complete = false;
	var func_ctr   	= 0;
	var func_a 		= new Array();
	func_a[func_ctr]= "";

	var stackfunc  	= "<p> <b> The function/event execution call stack was:</b> <p>";
	
	var debug_f, subdocd, eventsd, debugd, traced, showd, messagesd, errorsd	= false;        //* main debug flags
	
	var w			= null;         //* debug window variable
	var ws			= null;
	var we			= null;
	var d			= null;         //* debug document variable
	var u			= document.URL; //* URL variable
	var crDoc		= "";
    var idx			= null;
	var divCtr		= 0;	

//***** END GLOBAL VARIABLES                     																																																					

//***** DETERMINE DEBUG ENVIRONMENT		
//	InitDebug();
//************************************************************
//* Function:InitDebug() Populate all debug vars, get args, open window 
//************************************************************	
//	function InitDebug()
//	{
	
//	w = (window.opener) ? window.opener.w : top.w;
//	d = (window.opener) ? window.opener.d : top.d;
//	ws = (window.opener) ? window.opener.ws : top.ws;
//	we = (window.opener) ? window.opener.we : top.we;
//  debug_started = (window.opener) ? window.opener.debug_started : top.debug_started;

	w				= top.w;						//* point to top window's w variable.
	d				= top.d;
	ws				= top.ws;
	we				= top.we;
	debug_started = top.debug_started;
//	if (window.opener) w = window.opener.w;	
 	debug_f		= (window.opener) ? window.opener.debug_f : top.debug_f;
	
	subdocd		= (window.opener) ? window.opener.subdocd : top.subdocd;
	eventsd		= (window.opener) ? window.opener.eventsd : top.eventsd;
	traced		= (window.opener) ? window.opener.traced	: top.traced;
	debugd		= (window.opener) ? window.opener.debugd	: top.debugd;
	showd		= (window.opener) ? window.opener.showd	: top.showd;
	messagesd	= (window.opener) ? window.opener.messagesd : top.messagesd;
	errorsd		= (window.opener) ? window.opener.errorsd : top.errorsd;  	
  	
	args = GetArgs();  	    
   	for (i in args)  window[i] = args[i];       //* add query parms to window object as properties
 
  	
   	idx = (u.lastIndexOf('\\') != -1) ? u.lastIndexOf('\\') : u.lastIndexOf('/');
 	
 	crDoc = u.substring(idx + 1);               //* file name of current document
//    alert ("crDoc = " + crDoc);
    if (top.subdocd == crDoc) debug_f = true;    //* debug on for just this document
   	
    if (debug_f == true)
  		if (debug_started == false) 
//        if ((window.top == self) && ((w == null) || (w.closed)) && (top.debug_started == false))
        { 
        	debug_started = true;
//        	alert ("Opening debug window from: " + crDoc);
        	OpenWindow(); 
        		
		}

//	}
//***** END DETERMINE DEBUG ENVIRONMENT


//***** DEBUGGING ROUTINES
//************************************************************
//* Function: GetArgs() Create an args object to hold all debug and command line query parameters
//************************************************************	
	function GetArgs()
	{
    	var args = new Object();
    	var query = location.search.substring(1);  		// Get query string.
    	var pairs = query.split(",");              		// Break at comma.
    	for(var i = 0; i < pairs.length; i++)
    	{
			var pos = pairs[i].indexOf('=');       		// Look for "name=value".
			if (pos == -1) continue;               		// If not found, skip.
			var argname = pairs[i].substring(0,pos);  	// Extract the name.
			var value = pairs[i].substring(pos+1); 		// Extract the value.  tjw.. with no second parm, must go to end of string.  Makes sense.
			if (value == "true") value = 1;
			if (value == "false") value = 0;
			args[argname] = unescape(value);          	// Store as a property.
        }
    	args[args] = query;
    	return args;                               		// Return the object.
	}


//************************************************************
//* Function: OpenWindow() Open Debug Window  
//************************************************************	
	function OpenWindow()
	{
//	 	top.debug_started = true;
//	 	alert ("opening window");
//	 	alert ( " *****************************************************************************" + 
//	           	"\n\n 	    OPENING DEBUG WINDOW \n\n "+ 
//	            " *****************************************************************************");
	 	
	 	var dSess = "";
	 	
	 	w = top.window.open ("", "Debug", "resizable,  left=415, top=0, width=600, height=716, scrollbars, menubar");
     	    	     	
     	d = w.document;    					//* shorthand to refer to window.document as simply d
	 	dSess = "DEBUG Window - KMI: " + new Date();


       	d.write ('<HEAD> <TITLE> ' + dSess + '</TITLE> </HEAD>');
	   	ewSize = 0; 
	    if (eventsd == true) ewSize = 200; //* inactivated second frame for now
//;        else ewSize = 0;
 
        d.write ('<FRAMESET id="fsDebug" rows="*,', ewSize , '">',
        		 '<FRAME NAME="frDebugd" SRC="" SCROLLING="YES">',
        		 '<FRAME NAME="frEventsd" SCROLLING="YES">',
        		 '</FRAMESET>');
        ws = w.frDebugd;
        we = w.frEventsd;
     	d = ws.document;		 	 
     	d.write('<HEAD> <TITLE> ', dSess, '</TITLE> </HEAD>',
     			'<STYLE> BODY  {font-size: 10 pt; font-family: "arial"; color: #800000;} </STYLE>'); 
        d.write('<div align=left>');  
     	d.write('<hr size=4 width=100%>');
     	d.write('<font size=2 color=teal face="helvetica"><b>')
     	d.write('Debug Session: ' + new Date() + ' Document: ' + crDoc + '<br> </b> </font>');
     	d.write('<hr size=4 width=100%>'); 


	}

//************************************************************
//* Function: fname get name of current function 
//************************************************************	
	function fname(f)
	{
//*    	var f = (arguments.caller.caller.callee) ? arguments.caller.caller.callee : "function !!Main";
    	var s = f.toString().match(/function (\w*)/)[1];
    	if ((s == null) || (s.length == 0)) return "anonymous";
    	return s;
	}

//************************************************************
//* Function: trace(p_name) write current function name 
//************************************************************	
	function trace (p_name)
	{ 
	if (debug_f == true)
	{
		if (traced == true)
		{
			var m_verb = "Load";
 			var m_adverb = "Begin ";
 			var f_name = "!Main";
 			if (arguments.caller) 
 				if (arguments.caller != arguments.caller.callee ) f_name = fname(arguments.caller.callee); //* netscape condition
 			p_name = (p_name) ? p_name : f_name;  //* could also accept a parameter
   			if (load_complete == true) m_verb = "Execute";
   			msg = "<br><nobr><b>TRACE: </b>Document: <b>" + crDoc + "</b> Function: <b>" + p_name + "</b> Action: <b>" + m_adverb + m_verb + "</b>";
 			debug(msg, true);
  		}
	}
	}
//************************************************************
//* Function: endtrace(p_name) write current function name 
//************************************************************	
	function endtrace (p_name)
	{ 
	if (debug_f == true)
	{
		if (traced == true)
		{
 			var m_verb = "Load";
 			var m_adverb = "End ";
 			var f_name = "!Main";
 			if (arguments.caller) 
 				if (arguments.caller != arguments.caller.callee ) f_name = fname(arguments.caller.callee); //* netscape condition
 			p_name = (p_name) ? p_name : f_name;  //* could also accept a parameter
			if (load_complete == true) m_verb = "Execute";
 			msg = "<br><nobr><b>TRACE: </b>Document: <b>" + crDoc + "</b> Area/Function: <b>" + p_name + "</b> Action: <b>" + m_adverb + m_verb + "</b>";
 			debug(msg, true);
 		}
	}
	}
//************************************************************
//* Function: debug(p_msg)  to log debugging messages
//* Debug is called either directly by user function, or other debugging routines.
//************************************************************	
	function debug(p_msg, notByUser)
	{
    	if (debug_f == true)
   		{
       		if (!notByUser)                    //* debug routine WAS explicity called by user code 
      		{
      			if (debugd == true)            //* are debugging messaged turned on?
      			{	
      				f_name = "!Main";
 					if (arguments.caller) 
 					if (arguments.caller != arguments.caller.callee ) f_name = fname(arguments.caller.callee); //* netscape condition
                      				                                                                     
      				p_msg = "<nobr> <B> &nbsp;&nbsp; DEBUG: </B>" + crDoc + "~>" + f_name + "( ): <B>" + p_msg + "</B>";
      			}
      			
      			else                          
      				return;                     //* if not, saya nara
      		}	
        	linefeed = "<br>\n";
       		
 //     		if ((debug_started == false) || (w.closed == true))       		
     			if (w.closed == true)
     				OpenWindow();
 //                 InitDebug();
        		d.write(p_msg + linefeed);
        		ws.scrollBy(0,2000);     
      	}  
   }

//************************************************************
//* Function: show(p_name, p_value) function to display any kind of entity
//************************************************************	
	function show(p_name, p_value, html)
	{
   	if (debug_f == true)	
	{   		
   		if (showd == true)
   		{
     		
      		f_name = "!Main";
 			if (arguments.caller) 
 			if (arguments.caller != arguments.caller.callee ) f_name = fname(arguments.caller.callee); //* netscape condition
   			s = "<B> &nbsp;&nbsp; SHOW: </B>" + crDoc + "~>" + f_name + "( ): Variable: <b>" + p_name + " </b> is a";
   			
			if (html == "html")
			{
   				top.divCtr += 1;
   				divId = "myMsg" + top.divCtr;
   				s += "n HTML/XML string.  Value is: <b> <DIV id=" + divId + " STYLE='color:blue; font-size:8pt; position:relative;top:5px;left:20px'> </DIV></B>";
 				debug(s, true);
				p_array = p_value.split('>');
				p_str = "";
//*				alert (p_array.length);
				stack = new Array();
				stack_ctr = 0;
				for (i = 0; i <= p_array.length -2; i++)
				{
//*				 	p_array[i] += ">\n";
//*				 	start 	= p_array[i].indexOf("<") + 1;
//*				 	end		= ((p_array[i].indexOf(' '), start) != -1) ? p_array[i].indexOf(' ') - 1 : p_array[i].indexOf('>') - 1;
//*				 	tagName = p_array[i].substring(start, end);
//*				 	alert (tagName);
				 
				 
				 	p_str +=  p_array[i] + ">\n";
//*				 	p_str +=   ">\n";
				}
				
				d.all(divId).innerText = p_str;

   			}
   			else
   			{
   			switch (typeof p_value)
   			{
     			case 'number':
     			{
       				s+= "<b> Number</b>. <br><nobr>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Value is: <b>" + p_value + "</b>."; 
       				break;
     			}
      			case 'string':
     			{
       				s+= "<b> String</b>. <br><nobr>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Value is: " + '"<b>' + p_value + '</b>".'; 
       				break;
     			}
       			case 'boolean':
     			{
       				s+= "<b> Boolean</b>. <br><nobr>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Value is: " + '"<b>' + p_value + '</b>".'; 
       				break;
     			}
      			case 'object':
      			{
       				var n = 0;           
       				a = new Array();
	   				for (i in p_value)
	   				{
		 				str = i + ":" + p_value[i]; 
	     				a[n] = str;
	     				n += 1;
	   				}
	   	   			a.sort();	   
       				if ((p_value.length >= 0) != true)    // has no length property, it's an object, not an array
		  			{
             			s+= "n<b> object</b>. <br><nobr>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object has properties/values: <br>"; 
	   					for (n = 0 ; n < a.length ; n++) s+= "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" + a[n] + "<br>";
         			}
       				else                               // has a length property, it's an array
          			{
             			s+= "n<b> Array Object</b>. <br><nobr>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Array Object has properties/values: <br>"; 
             			for (i in p_value) s+=  "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" + p_name + "[" + i + "]: " + p_value[i] + "<br>"; 
          			}
       				break;
      			}
          
     			default:
     			{
      		 		s+= "n <b> unknown object type</b>. Value is:  <b>" + p_value + "</b>."; 
       				break; 
     			}
    		}
   			debug(s, true);
   			}
 		}
	}
	}
//************************************************************
//* Function: message(p_name) write current function name 
//************************************************************	
	function message (type, data)
	{ 
	if (debug_f == true)
	{
		if (messagesd == true)
		{
        	f_name = "!Main";                        //* not in a function... called from main body
 			if (arguments.caller) 
 			if (arguments.caller != arguments.caller.callee ) f_name = fname(arguments.caller.callee); //* netscape condition
    		
    		if (type == "s")
      		{
      		 	type = "REQUEST";
      		 	data = unescape(document.URL.substring(0, document.URL.lastIndexOf('\\')+ 1)) + data;	
      			msg = "<B>&nbsp;&nbsp; MESSAGE: </B>" + crDoc + "~>" + f_name + "( ): <B>" + type + ": <BR>" 
 						+	"<BR><nobr><font STYLE='color:blue; font-size:8pt;'> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" + data + "<br></font></B>";
 				debug(msg, true);
			}
      		
      		if (type == "r") 
      		{
      			type = "RESPONSE"; 
      			top.divCtr += 1;
      			divId = "myMsg" + top.divCtr;
      			msg = "<B> &nbsp;&nbsp; MESSAGE: </B>" + crDoc + "~>" + f_name + "( ): <B>" + type + ": <BR>" 
 						+	"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <DIV id=" + divId + " STYLE='color:blue; font-size:8pt; position:relative;top:5px;left:20px'> </DIV></B>";
 				debug(msg, true);
				d.all(divId).innerText = data;
			//*	w.myMsg.innerText = "HELP";
  			}
                      				                                                                     
  		}
	}
	}


// Figure out whether this is Navigator or IE. Assume version 4.
var isNav = (navigator.appName.indexOf("Netscape") != -1);
var isIE = (navigator.appName.indexOf("Microsoft") != -1);
	
//************************************************************************
//*  function eventtrace(): Put in all event handler functions.
//************************************************************************	
	function eventtrace(p)
	{
//	 	alert (crDoc + " event trace: parm is: "  + p + " but event flag is: " + eventsd);
	 	if (debug_f == true)
	 	{
	 		if (eventsd == true) 
	 		{
	 			if (p == "add") addhandlers(document);
	 			else handler();
	 		}
		}	 	
	}
//************************************************************************
//*  function handler():  Capture and write out event details to event window
//************************************************************************	
	function handler(e)
 	{
//        if (we.closed == true)
//        { 
//        	OpenWindow();
//        	return;
//        }
       

 		if ((debug_started == false) || (w.closed == true))       		
       	{	
       		OpenWindow();
       		return;
        }
  		
  		var ew = we.document;        // Shorthand
  		
  		if (!handler.docopen) 
  		{   // If the document is not already open
      		ew.open("text/plain");     // ...open it as plain text.
      		handler.docopen = true;
      		ew.writeln("EVENT DEBUGGING WINDOW: ");
     		ew.writeln("======================  ")

  		}
  		// If we're in Navigator, report event details in this way.
  		if (isNav)
  		{
    		ew.writeln("Type: " + e.type);
    		if (e.target) d.writeln("Target: " + 
                            Object.prototype.toString.apply(e.target));
    		if (e.target.name) ew.writeln("Target name: " + e.target.name);
    		if (e.x || e.y) ew.writeln("X: " + e.x + " Y: " + e.y);
    		if (e.which) ew.writeln("which: " + e.which);
    		if (e.modifiers) ew.writeln("modifiers: " + e.modifiers);
  		}
  		// If we're in Internet Explorer, first copy the event from the 
  		// global event variable, then report its details. Finally, set
  		// the cancelBubble property so it doesn't bubble and get reported 
  		// multiple times.
  		if (isIE)
  		{
     		e = window.event;   // Grab the event.
     		len = 9 - e.type.length;
     		str = crDoc + "~> Event: " + e.type;
     		for (i = 0; i < 9 - e.type.length; i++)
     			str += " ";
     		if (e.srcElement && e.srcElement.tagName)
     		{
     			str +=  " | Tag: " + "<" + e.srcElement.tagName + ">" ;
     			for (i = 0; i < 5 - e.srcElement.tagName.length; i ++)
     				str += " "; 
			}
     		str += (e.srcElement && e.srcElement.name)		? " | Name: " + e.srcElement.name 				: "";
     		str += (e.srcElement && e.srcElement.id)		? " | Id: " + e.srcElement.id 					: "";
     		str += (e.button)								? " | button: " + e.button 						: "";
     		str += (e.keyCode)								? " | keyCode: " + e.keyCode 					: "";
     		str += (e.altKey)								? " | altKey " 									: "";
     		str += (e.ctrlKey)								? " | ctrlKey " 								: "";
     		str += (e.shiftKey)								? " | shiftKey " 								: "";
     		str += (e.clientX || e.clientY)					? " | X:" + e.clientX + " Y:" + e.clientY 	: "";
            ew.writeln(str);

     		// We've reported this event, and don't want our container to
     		// report it too, so don't let it bubble up any further.
     		e.cancelBubble = true;  
  		}
  		we.scrollBy(0,2000);     

  		// Arrange to close the document a second from now, resetting any timer
  		// set by a previous event.
  		if (handler.timeoutid) we.clearTimeout(handler.timeoutid);
  		handler.timeoutid = setTimeout("we.document.close(); handler.docopen=false;",1000);
	}

// This function registers the event handler defined above on all possible
// event handlers for the specified object. Note that when using this 
// program as a diagnostic tool, you may find that you get too many
// annoying blur, focus, mouseover, and mouseout events. If so, simply
// comment those event handlers out here.
	function addhandlers(o)
	{
      	if (eventsd == true)
      	{
      		var aHndlr = new Array ("onabort", "onblur", "onchange", "onclick", "ondblclick", "onerror", "onfocus",
      							"onkeydown", "onkeypress", "onkeyup", "onload", "onmousedown", "onmouseout", 
      							"onmouseover", "onmouseup", "onmove", "onreset", "onresize", "onselect", 
      							"onsubmit", "onunload"); 
//			show("aHndlr: ", aHndlr);      	
     		for (i=0; i < aHndlr.length; i++)
    		{
				tHndlr = aHndlr[i];
				(o[tHndlr]) ? true : o[tHndlr] = handler;     			     
			}
		}
	}
   	function NewHandler(ohndlr)
   	{
    	debug("ohndlr: " + ohndlr);
    	var temphandler = ohndlr.toString();
//    	var temphandler = ohndlr;
    	temphandler = temphandler.replace(/{/,"{ \n handler();");
    	alert ("temphandler: " + temphandler);
//	   	fstart  = temphandler.substring(0, temphandler.indexOf('{') + 1);
//    	fend	= temphandler.substring(temphandler.indexOf('{') + 1);
//    	hndlrCode = window.handler;
//    	hndlrCode = hndlrCode;
//    	hStart = hndlrCode.indexOf('{'); 
//    	hEnd   = hndlrCode.lastIndexOf('}'); 
//    	debug("hndlrCode: " + hndlrCode);             
//   		debug("hStart: " + hStart);
//    	debug("hEnd: " + hEnd);
//    	hndlrCode = hndlrCode.substring(hStart + 1, hEnd);
//    	debug("hndlrCode: " + hndlrCode);  
    	
//    	temphandler = fstart + hndlrCode + fend; 
//    	temphandler = fstart +fend; 
		return(temphandler);
//     	document.onmouseover = temphandler;
	}




// Several functions are based on material from JavaScript: The Definitive Guide, 3rd Edition.
// That book and the base functions were Written by David Flanagan. They are Copyright (c) 1996, 1997, 1998 O'Reilly & Associates.

function stacktrace()
//* This function returns a string that contains a "stack trace."
{
    var s = "";  // This is the string we'll return.
    // Loop through the stack of functions, using the caller property of
    // one arguments object to refer to the next arguments object on the
    // stack.
    for(var a = arguments.caller; a != null; a = a.caller) {
        // Add the name of the current function to the return value.
        s += funcname(a.callee) + "<br>";

        // Because of a bug in Navigator 4.0, we need this line to break.
        // a.caller will equal a rather than null when we reach the end 
        // of the stack. The following line works around this.
        if (a.caller == a) break;
    }
    return s;
}

//***** END DEBUG ROUTINES
