/*
 * Name:
 *	global_functions.js
 *
 * Description:
 *	Defines global javascript functions
 *
 * Pre-conditions:
 *	None
 *
 * Post-conditions:
 *	Defines the following functions:
 *
 * Log:
 *	Shaunak Kashyap		11/21/2005
 *	- Creation
 *	Doug Mears			4/28/2006
 *	- added functions:
 *		getBrowser, getOS, checkUserAgent, bVer, makeSream, changeStreamReload
 *	Toan Nguyen-Dinh	5/11/2006
 *	- added function:
 *		embedFlash
 *	Li Zheng			02/13/2007
 *	 - Merge functions from 
 * 		event_handler.js, tran_frame.js ,html_element_search.js
 */

//Set global variables to be used by more than one function
//needs to be set within script
//delay, numelements depend on  php elements

var delay = new Array();
var numElements = new Array();
var index = new Array();
var timeOutID = new Array();
var isRunning = new Array();



/*
 * Name:
 *	getElement
 *
 * Description:
 *	Returns an element searched by name or id
 *
 * Pre-conditions:
 *	elName		REQUIRED	Id or name of element
 *
 * Post-conditions:
 *	The element is returned
 *
 * Log:
 *	Shaunak Kashyap		11/21/2005
 *	- Creation
 *
 */

function getElement(elName) {

	if (document.getElementByName) {
		
		return document.getElementByName(elName);
		
	} else if (document.getElementById) {
		
		return document.getElementById(elName);
		
	} else {
		
		return false;
		
	} 
	
} // END function - getElement

/*
==================================================================
ltrim(string) : Returns a copy of a string without leading spaces.
==================================================================
*/
function ltrim(str)
/*
   PURPOSE: Remove leading blanks from our string.
   IN: str - the string we want to ltrim
*/
{
   var whitespace = new String(" \t\n\r");

   var s = new String(str);

   if (whitespace.indexOf(s.charAt(0)) != -1) {
      // We have a string with leading blank(s)...

      var j=0, i = s.length;

      // Iterate from the far left of string until we
      // don't have any more whitespace...
      while (j < i && whitespace.indexOf(s.charAt(j)) != -1)
         j++;

      // Get the substring from the first non-whitespace
      // character to the end of the string...
      s = s.substring(j, i);
   }
   return s;
}

/*
==================================================================
rtrim(string) : Returns a copy of a string without trailing spaces.
==================================================================
*/
function rtrim(str)
/*
   PURPOSE: Remove trailing blanks from our string.
   IN: str - the string we want to rtrim

*/
{
   // We don't want to trip JUST spaces, but also tabs,
   // line feeds, etc.  Add anything else you want to
   // "trim" here in Whitespace
   var whitespace = new String(" \t\n\r");

   var s = new String(str);

   if (whitespace.indexOf(s.charAt(s.length-1)) != -1) {
      // We have a string with trailing blank(s)...

      var i = s.length - 1;       // Get length of string

      // Iterate from the far right of string until we
      // don't have any more whitespace...
      while (i >= 0 && whitespace.indexOf(s.charAt(i)) != -1)
         i--;


      // Get the substring from the front of the string to
      // where the last non-whitespace character is...
      s = s.substring(0, i+1);
   }

   return s;
}

/*
=============================================================
trim(string) : Returns a copy of a string without leading or trailing spaces
=============================================================
*/
function trim(str)
/*
   PURPOSE: Remove trailing and leading blanks from our string.
   IN: str - the string we want to trim

   RETVAL: A trimmed string!
*/
{
   return rtrim(ltrim(str));
}


/*
 * Name:
 *	getBrowser
 *
 * Description:
 *	gets and returns a string representing the user's browser
 *
 * Pre-conditions:
 *
 * Post-conditions:
 *
 * Author:
 *		Doug Mears		4/28/06
 *
 * Updates:
 *
 */

function getBrowser()
{
	
	var browser;
	
	//begin if checks for browser
	if (checkUserAgent('konqueror'))
	{
		browser = "Konqueror";
	}
	else if (checkUserAgent('safari')) browser = "Safari";
	else if (checkUserAgent('omniweb')) browser = "OmniWeb";
	else if (checkUserAgent('opera')) browser = "Opera";
	else if (checkUserAgent('webtv')) browser = "WebTV";
	else if (checkUserAgent('icab')) browser = "iCab";
	else if (checkUserAgent('msie')) browser = "IE"
	else if (checkUserAgent('firefox')) browser = "Firefox";
	else if (!checkUserAgent('compatible'))
	{
		browser = "Netscape"
	}
	else browser = "unknown";
	
	//return browser string
	return browser;
} //END function getBrowser

/*
 * Name:
 *	getOS
 *
 * Description:
 *	gets and returns a string representing the user's operating system
 *
 * Pre-conditions:
 *
 * Post-conditions:
 *
 * Author:
 *		Doug Mears		4/28/06
 *
 * Updates:
 *
 */
function getOS()
{
	var OS;
	
	//begin if checks to get the operating system
	if (checkUserAgent('konqueror'))
	{
		OS = "Linux";
	}
	else if (checkUserAgent('linux')) OS = "Linux";
	else if (checkUserAgent('x11')) OS = "Unix";
	else if (checkUserAgent('mac')) OS = "Mac"
	else if (checkUserAgent('win')) OS = "Windows"
	else OS = "unknown";

	//return the operating system string
	return OS;
} //END function getOS

/*
 * Name:
 *	checkUserAgent
 *
 * Description:
 *	figures out if the given string is in the navigator.userAgentString
 *	used to detect browser..and os info
 *
 * Pre-conditions:
 *
 * Post-conditions:
 *   return value > 0 means there was a match
 * Author:
 *		Doug Mears		4/28/06
 *
 * Updates:
 *
 */

function checkUserAgent(string)
{
	//return 1 or more (true) if userAgent contains input string
	return (navigator.userAgent.toLowerCase().indexOf(string) + 1);
}

/*
 * Name:
 *	bVer
 *
 * Description:
 *	gets the browser version
 *
 * Pre-conditions:
 *
 * Post-conditions:
 *   returns a float representation of the navigator's version
 * Author:
 *		Doug Mears		4/28/06
 *
 * Updates:
 *
 */

function bVer() {
  // return version number (e.g., 4.03)
  return parseFloat(navigator.appVersion)
} //END function bVer

/*
 * Name:
 *	makeStream
 *
 * Description:
 *	makeStream is an object contructor whose data holds the url and name
 *	usage: new makeStream('myfile.asx', 'Episode 1');
 *
 * Pre-conditions:
 *
 * Post-conditions:
 *  sets and creates an object with the property values url and name
 * Author:
 *		Doug Mears		4/28/06
 *
 * Updates:
 *
 */
function makeStream(url, name) {
	this.url = url;
	this.name = name;
} //END function - make stream

/*
 * Name:
 *	changeStreamReload
 *
 * Description:
 *	changes the current stream for Windows Internet Explorer users
 *	reloads the page for other users
 *
 * Pre-conditions:
 *		url					path to php/asx file to use in the stream
 *		episodeName			name of episode
 *		episodeDescription	description of episode
 *		reloadQuery			contains string with episode ID to reload with
 * Post-conditions:
 *   either changes video stream or reloads the page with a query 
 *	 with the episode id
 * Author:
 *		Doug Mears		4/28/06
 *
 * Updates:
 *
 */
function changeStreamReload(url, episodeName, episodeDescription, reloadQuery)
{
	var versionCode = bVer();
	var mac = (navigator.userAgent.indexOf("Mac")!=-1);
	var activeX = (getBrowser() == 'IE' && versionCode >= 4.0) ? true : false; 

	//if user is using Internet Explorer for Windows and has activeX controls installed
	if (activeX && !mac) //for IE
	{
		
		//insert episodeName and episodeDescription into respective divs
		getElement('episodeNameDiv').innerHTML = episodeName;
		getElement('episodeDescriptionDiv').innerHTML = episodeDescription;
		mediaPlayer.autoStart = true;
   		mediaPlayer.URL = url;

	} //END if user is using Internet Explorer for Windows and has activeX controls installed
	//else reload window
  	else
  	{
  		window.location.href = reloadQuery;
  	} //END else reload window
} //END function changeStreamReload

/*
 * Name:
 *	embedFlash
 * 
 * Description:
 *	prints out the HTML code using javascript instead of embedding the Flash object directly into
 *	the HTML code. This is a workaround for the ActiveX issue in IE that needs the ActiveX content
 *	to be activated before it can be used. The workaround removes the need for activation
 *
 * Pre-conditions:
 *		embedString			String containing all tags holding the Flash object in the HTML page
 *								i.e. "<object ...><param1...><param2...><embed...></embed></object>"
 *
 * Post-conditions:
 *	The Flash object is embedded in the webpage while avoiding the ActiveX issue
 *
 * Functions:
 *	None
 *
 * Log:
 *	Toan Nguyen-Dinh		5/11/2006
 *		- Creation
 * 
 */
function embedFlash(embedString)
{
	//echo the string into the page
	document.write(embedString);
}




/*
 * Name:
 *	registerEvent
 *
 * Description:
 *	Attaches a JavaScript event to the given HTML DOM element. In event models that support
 *	both options, events are fired in the bubbling phase by this function, not the capturing
 *	phase. Note that, under some schemes, multiple events (even duplicates) may be assigned to
 *	an object, and all will fire, so be sure to unregister any unneeded events!
 *
 * Pre-conditions:
 *	obj				REQUIRED	The DOM object to which the given event should be attached.
 *	eventName		REQUIRED	The name of the event as a string. May optionally include the on- prefix.
 *	handler			REQUIRED	A callback for the handler function. (NOT a string, NO parentheses!)
 *
 * Post-conditions:
 *	Returns true on successful event attachment, false otherwise.
 *
 * Log:
 *	Randall Betta		08/25/2006
 *		- Creation
 *
 */
function registerEvent(obj, eventName, handler) {
	
	var eventWithOn;
	var eventWithoutOn;
	
	// Define two forms of the event name: one with a leading on- prefix, the other without it.
	eventWithOn = (eventName.match(/^on/)) ? eventName : 'on' + eventName;
	eventWithoutOn = eventName.replace(/^on/, '');
	
	// Determine if the browser supports the Microsoft model or the W3C model for event attachment.
	
	if (obj.addEventListener) { // If: the W3C addEventListener method is defined.
		
		//
		// Use the W3C model.
		//
		
		// The event names should be lowercase without the on- prefix in W3C-compliant implementations.
		eventName = eventWithoutOn.toLowerCase();
		// Fire events during the bubbling phase; this must match the detachment function!
		obj.addEventListener(eventName, handler, false);
		return true;
	}
	else if (obj.attachEvent) { // Else if: the Microsoft attachEvent method is defined.
		
		//
		// Use the Microsoft model.
		//
		
		// The event names should be lowercase with the on- prefix in Microsoft's implementation.
		eventName = eventWithOn.toLowerCase();	
		obj.attachEvent(eventName, handler);
		return true;
	}
	else { // Else: fall back on the traditional model.
		
		//
		// Use the traditional event registration model.
		//
		
		// The event names should be lowercase with the on- prefix in the traditional implementation.
		eventName = eventWithOn.toLowerCase();
		obj[eventName] = handler;
		return true;
	} // End else: use the traditional model.
	
} // End function: registerEvent








/*
 * Name:
 *	unregisterEvent
 *
 * Description:
 *	Detaches a JavaScript event from the given HTML DOM element.
 *
 * Pre-conditions:
 *	obj				REQUIRED	The DOM object from which to remove the given event.
 *	eventName		REQUIRED	The name of the event as a string. May optionally include the on- prefix.
 *	handler			REQUIRED	A callback for the handler function. (NOT a string, NO parentheses!)
 *
 * Post-conditions:
 *	Returns true on successful event detachment, false otherwise.
 *
 * Log:
 *	Randall Betta		08/25/2006
 *		- Creation
 *
 */
function unregisterEvent (obj, eventName, handler) {
	
	// Define two forms of the event name: one with a leading on- prefix, the other without it.
	eventWithOn = (eventName.match(/^on/)) ? eventName : 'on' + eventName;
	eventWithoutOn = eventName.replace(/^on/, '');
	
	// Determine if the browser supports the Microsoft model or the W3C model for event detachment.
	if (obj.removeEventListener) { // If: the W3C model is supported.
		
		//
		// Use the W3C event detachment model.
		//
		
		// The event names should be lowercase without the on- prefix in the W3C implementation.
		eventName = eventWithoutOn.toLowerCase();
		// The original attachment function is presumed here to have 
		// specified that events fire during the bubbling phase. This must
		// match the actual value used during event attachment!
		obj.removeEventListener(eventName, handler, false);
		return true;
		
	}
	else if (obj.detachEvent) { // Else if: the Microsoft model is supported.
		
		//
		// Use the Microsoft event detachment model.
		//	
		
		// The event names should be lowercase with the on- prefix in the Microsoft implementation.
		eventName = eventWithOn.toLowerCase();
		obj.detachEvent(eventName, handler);
		return true;
	}
	else { // Fall back on the traditional event model.
		
		//
		// Use the traditional model.
		//
		
		// The event names should be lowercase with the on- prefix in the traditional implementation.
		eventName = eventWithOn.toLowerCase();
		obj[eventName] = null;
		return true;
	} // End else: use the traditional model.
	
} // End function: unregisterEvent

/*
 * Name:
 *	getEventTarget
 *
 * Description:
 *	Every event handler should take a single argument, which will either be made null by IE or set
 *	to an event object by W3C-compliant browsers. Given this object, this function returns a reference
 *	to the target element of the event.
 *
 * Pre-conditions:
 *	eventObj	REQUIRED	The implicit event object passed to an event handler (may possibly be null).
 *
 * Post-conditions:
 *	Returns a reference to the target of the event whose implicit event object is passed in as an argument.
 *	Returns false on failure.
 *
 * Log:
 *	Randall Betta		08/25/2006
 *		- Creation
 *
 */
function getEventTarget(eventObj) {
	
	var targetObj;
	
	//
	// Obtain a reference to the proper event-describing object.
	//
	
	// Under Internet Explorer, no implicit event object is passed to event handler. Instead, the
	// window.event object holds data for the last event to be raised.
	eventObj = (eventObj) ? eventObj : window.event;
	if (!eventObj) { // If: the event object can't be found.
		// Indicate failure.
		return false;
	} // End if: the event object can't be found.
	
	//
	// The event-describing object is known by this point. Obtain a reference to the DOM object that
	// was the original target of the event.
	//
	
	// W3C-compliant browsers call the event's object "target." IE calls it "srcElement."
	targetObj = (eventObj.target) ? eventObj.target : eventObj.srcElement;
	if (!targetObj) { // If: the target object can't be found.
		// Indicate failure.
		return false;
	} // End if: the target object can't be found.
	
	// Under Safari, a bug can cause events that fire on text element to store their target element
	// as the text node in the DOM, rather than its containing HTML node. Fix this.
	targetObj = (targetObj.nodeType == 3) ? targetObj.parentNode : targetObj;
	
	return targetObj;
	
} // End function: getEventTarget


/* Name:
 *	callTran
 *
 * Description:
 *	Executes a script in the tran frame
 *
 * Pre-conditions:
 *	scriptUrl			REQUIRED	Url of script
 *	scriptQueryString	OPTIONAL	Query string to pass to script
 *
 * Post-conditions:
 *	The script is loaded
 *
 * Log:
 *	Shaunak Kashyap		11/13/2005
 *	- Creation
 *  Atif Malik			12/23/2006
 *  - Changed by Atif Malik to allow click with iframes
 */

function callTran(scriptUrl, scriptQueryString) {
	
	//
	// Load url in tran frame
	//
	
	//window.top.tranFrame.location = "/tran_frame/" + scriptUrl + "?" + scriptQueryString;
	document.getElementById("tranFrame").src = "/tran_frame/" + scriptUrl + "?" + scriptQueryString;

	
} // END function - callTran




/*
* Name:
*	getAllFrames
*
* Description:
*	Returns an array of window elements of all (grand)child iframe and frame HTML elements 
*	in the given window, including itself. This function is recursive. Note that a window is 
*	the same as an (i)frame in JavaScript.
*	
* Pre-conditions:
*	windowObj		REQUIRED	The topmost window object to include in the array.
*
* Post-conditions:
*	An array of references to HTML (i)frame tags that exist inside the given window.
*
* Log:
*	Randall Betta		08/24/2006
*		- Creation
*
*/
function getAllFrames(windowObj) {

	var windowFrames;			// All frames in the current window object.
	var allWindows;				// An array of all framed window objects to return.
	var childFrames;			// All descendant (i)frames.
	var currentWindow;			// A temporary variable for storing an (i)frame's window object.
	var frameIndex;				// Counter variable.
	var childIndex;				// Counter variable.

	// Initialize the array that will store the windows of (i)frames.
	allWindows = new Array();

	// Determine if this document has any frames. If not, return an empty array.
	if ((windowObj.frames) ? windowObj.frames.length > 0 : false) { // If: this window has frames.
		// Obtain all iframe elements in this window using the javascript frames array. Note that 
		// this will include ordinary frames too, though this is not relevant for our purposes.
		windowFrames = windowObj.frames;

		// Iterate through (i)frames in this window.
		for (frameIndex = 0; frameIndex < windowFrames.length; frameIndex++) { // For: iterate through frames.
		
			// Store the current iframe's window object in this iteration.
			currentWindow = windowFrames[frameIndex];
			
			// Obtain an array of all descendant (i)frames inside the child (i)frame, plus itself.
			allWindows = allWindows.concat(getAllFrames(currentWindow));	

		} // End for: iterate through (i)frames.
		
	} // End if: this window contains (i)frames.
	
	// Store this window itself in the returned array of window objects.
	allWindows[allWindows.length] = windowObj;
	
	return allWindows;
	
} // End function: getAllFrames









/*
* Name:
*	getRelatedElements
*
* Description:
*	Returns an array of all HTML elements of the same type whose class or id property matches
*	a given regex. This function will optionally search the entire iframe hierarchy up and down, 
*	including any pages not generated by Intertech functions.
*	
* Pre-conditions:
*	htmlElement		REQUIRED	Case-sensitive string of what kinds of HTML elements to search (e.g. "div").
*	pattern			REQUIRED	The regex to use to decide whether to return an element.
*	useId			REQUIRED	Boolean: if true, match the HTML id against the regex. If false, use class.
*	searchAllFrames	REQUIRED	Boolean: if true, traverse all (i)frames.
*
* Post-conditions:
*	An array of references to HTML tags whose id or class properties match the regex is returned.
*
* Log:
*	Randall Betta		08/23/2006
*		- Creation
*	Randall Betta		10/10/2006
*		- Fixed a bug that prevented searches confined to only one frame from working.
*
*/
function getRelatedElements(htmlElement, pattern, useId, searchAllFrames) { 

	var docObj;				// A temporary variable: HTML DOM "document" object.
	var winIndex;			// A counter for the current window.
	var htmlElts;			// An array of references to HTML elements.
	var elt;				// A temporary variable: reference to an HTML element.
	var eltIndex;			// A counter for the current elt.
	var matchingElts;		// The returned array of references to matching HTML elements.
	var eltText;			// The text of the HTML element property to compare against the pattern.
	var searchWindows;		// An array of all HTML DOM "window" objects to search.
	var thisDocFound;		// A boolean: used when 
	
	// Initialize the matching elements array.
	matchingElts = new Array();
	
	// Determine whether we need to search this document or all (i)framed documents.
	if (searchAllFrames) { // If: search all frames.
		// Obtain references to all frames.
		searchWindows = getAllFrames(top);		
	}
	else { // Else: search only this document.
		searchWindows = new Array();
		searchWindows[0] = window;
	} // End else: search only this document,
	
	
	// Iterate through all documents to be searched.
	for (winIndex = 0; winIndex < searchWindows.length; winIndex++) { // For: iterate through windows to search in.
		try {
			// Store a reference to the current document object.
			docObj = searchWindows[winIndex].document;
			// Obtain an array of all HTML elements of the desired type in the current document object.
			htmlElts = docObj.getElementsByTagName(htmlElement);
		}
		catch (exc) {
			// Permission will be denied to access elements on a page from a different domain.
			// Silently skip this document if this error occurs.
			continue;
		}
		
		// Iterate through the HTML elements.
		for (eltIndex = 0; eltIndex < htmlElts.length; eltIndex++) { // For: iterate through HTML elements.
			try {
				// Store a reference to the current HTML element.
				elt = htmlElts[eltIndex];
				// Determine if this element is part of the set we are looking for.
				if (useId) { // If: the match criterion is the HTML element ID property.
					eltText = (elt.id) ? elt.id.toString() : '';
				}
				else { // Else: the match criterion is the HTML element CSS class property.
					eltText = (elt.className) ? elt.className.toString() : '';
				} // End else: the match criterion is the HTML element CSS class property.
				
				// Test whether the class or ID property (as appropriate) matches the regex.
				if (eltText.match(pattern)) { // If: the property matches the regex.
					// Append this element to the array.
					matchingElts[matchingElts.length] = elt;
				} // End if: the property matches the regex.
			}
			catch (exc) {
				// Permission will be denied to access elements on a page from a different domain.
				// Silently skip this document if this error occurs.
				continue;
			}
			
		} // End for: iterate through HTML elements.
		
	} // End for: iterate through windows to search in.
	
	return matchingElts;

} // End function: getRelatedElements
