// JAVASCRIPT BROWSER v2.0
// Encapsulates all the things you want to know about your browser (width, height, version)
// Automates the image rollovers
// Allows you to add to the laod event

// Fix mNewMouse
// Fix use of Min
// Ensure resize occurs after all other resize events


// -----------------------------------------------------------------------------------------------------------------------
// Methods that safely allow developers to add funcions to onload and onresize without overwriting what's already there
// Can't use addEventListener or attachEvent since that messes around with the ordering of events - load MUST fire before resize
function addLoadEvent(func) {
	// Add to OnLoad (but don't kill what's already in OnLoad)
	if (typeof window.onload != 'function') {
		window.onload = func;
	} else {
		var holdonload = window.onload;
		window.onload = function() { holdonload(); func(); }
	}
}

function addResizeEvent(func) {
	if (typeof window.onresize != 'function') {
		window.onresize = func;
	} else {
		var holdonresize = window.onresize;
		window.onresize = function() { holdonresize(); func();  }
		// doesn't appear to matter whether you do "holdonresize(); func();" or "func(); holdonresize();", first thing added always fires first
	}
}

function findPos(obj) {
	var curleft = curtop = 0;
	if (obj.offsetParent) {
		do {
			curleft += obj.offsetLeft;
			curtop += obj.offsetTop;
		} while (obj = obj.offsetParent);
	}
	return [curleft,curtop];
}

// -----------------------------------------------------------------------------------------------------------------------
// Browser to capture position of Mouse X & Y - eventually incorporate offset?

function Browser() {
	this.mouseX = 0; this.mouseY = 0; this.mouseDown = false; this.mouseDownFlag = false;   // controlled by events defined outside of this class
   // outside people check AND RESET this.mouseDownFlag so no MouseDown is missed

	this.width = 0; this.height = 0;
	// this.width = parseInt(screen.availWidth / 2); this.height = parseInt(screen.availHeight / 2);
	// this.widthmin = 1024 - 121; this.heightmin = 768 - 180; // don't allow window to ever be smaller than 1024 x 768 (need to take into scrollbars, address bars etc.)
	this.widthmin = 749; this.heightmin = 500; // don't allow window to ever be smaller than 1024 x 768 (need to take into scrollbars, address bars etc.)
	this.ratioX = 1; this.ratioY = 1;

	this.name = ""; this.version = 0; this.os = "";
	this.keys = new Array(255);

	this.pageWidth = 0; this.pageHeight = 0;
	this.pageTagExcludes = null; this.pageTagIncludes = null;   // Either a list of Tags to Include OR Exclude (can never be both). MUST BE LOWER CASE!!!
	this.pageIdExcludes = null; this.pageIdIncludes = null;
	this.TempLeft = null; this.TempWidth = null;
	this.TempTop = null; this.TempHeight = null;
	this.TempSuccess = false; this.TempHold = 0; this.TempIndex = 0;
}

// Instantiate the Browser object (badly encapsulates everything)
var gBrowser = new Browser();

function Browser_PageWidthHeight(pNode) {
	var e = window.document.getElementById("textlast");
	gBrowser.pageWidth = gBrowser.width; gBrowser.pageHeight = parseInt(e.style.top) + parseInt(e.offsetHeight);
	return


	// 0. User needs to decide if they want this. I needed it for the Invaders. Heavy function. Fills out .pageWidth and .pageHeight
   // 1. Consider creating an OnLoad that flags an element as eligible (has a left,top,width,height - isn't excluded)
   //    Create a Browser_Refresh to go with it, so user can get this recalculated. load & refresh call private refresh
   // 2. Consider passing in the elements as a string.
	// 3. DIVs that have width & height, MAY have a height of 0 if they contain other DIVs. Don't know if this is a problem
	var Node = pNode;	// preserve copy of the reference (ensure it's passed by value, I'm simply not sure)

	// traverse every single element in this browser
	if (Node.childNodes) {
		for (var index=0; index < Node.childNodes.length; index++) {
			Browser_PageWidthHeight(Node.childNodes[index]);
		}
	}

	gBrowser.TempHold = findPos(Node);  // Can't just use style.left since it's only valid if filled out. offsetLeft requires traversing the tree!
	gBrowser.TempLeft = gBrowser.TempHold[0]; gBrowser.TempWidth = Node.offsetWidth;
	gBrowser.TempTop = gBrowser.TempHold[1]; gBrowser.TempHeight = Node.offsetHeight;

	if ((gBrowser.TempLeft >= 0) && (gBrowser.TempTop >= 0) && (gBrowser.TempWidth > 0) && (gBrowser.TempHeight > 0)) {		
		gBrowser.TempSuccess = true;   // this element has everything we need, so let's get down to bidness.

		// Exclude FIRST (exclude trumps include)
		if ((Node.tagName) && (gBrowser.pageTagExcludes != null) && (gBrowser.TempSuccess)) {
			gBrowser.TempHold = Node.tagName.toLowerCase();	// want to avoid this expensive operation if nothing is included/excluded
			for (gBrowser.TempIndex = 0; gBrowser.TempIndex < gBrowser.pageTagExcludes.length; gBrowser.TempIndex++) { if (gBrowser.pageTagExcludes[gBrowser.TempIndex] == gBrowser.TempHold) { gBrowser.TempSuccess = false; } }
		}
		if ((Node.id) && (gBrowser.pageIdExcludes != null) && (gBrowser.TempSuccess)) {
			gBrowser.TempHold = Node.id.toLowerCase();
			for (gBrowser.TempIndex = 0; gBrowser.TempIndex < gBrowser.pageIdExcludes.length; gBrowser.TempIndex++) { if (gBrowser.pageIdExcludes[gBrowser.TempIndex] == gBrowser.TempHold) { gBrowser.TempSuccess = false; } }
		}

		if (gBrowser.TempSuccess) {

			if ((gBrowser.pageTagIncludes != null) || (gBrowser.pageIdIncludes != null)) {
				// Includes NEXT
				gBrowser.TempSuccess = false;
	
				if ((Node.tagName) && (gBrowser.pageTagIncludes != null) && (!gBrowser.TempSuccess)) {
					gBrowser.TempHold = Node.tagName.toLowerCase();	
					for (gBrowser.TempIndex = 0; gBrowser.TempIndex < gBrowser.pageTagIncludes.length; gBrowser.TempIndex++) { if (gBrowser.pageTagIncludes[gBrowser.TempIndex] == gBrowser.TempHold) { gBrowser.TempSuccess = true; } }
				}
				if ((Node.id) && (gBrowser.pageIdIncludes != null) && (!gBrowser.TempSuccess)) {
					gBrowser.TempHold = Node.id.toLowerCase();
					for (gBrowser.TempIndex = 0; gBrowser.TempIndex < gBrowser.pageIdIncludes.length; gBrowser.TempIndex++) { if (gBrowser.pageIdIncludes[gBrowser.TempIndex] == gBrowser.TempHold) { gBrowser.TempSuccess = true; } }
				}
			}

			if (gBrowser.TempSuccess) {
				gBrowser.TempHold = parseInt(gBrowser.TempLeft) + parseInt(gBrowser.TempWidth);
				if (gBrowser.TempHold > gBrowser.pageWidth) { gBrowser.pageWidth = gBrowser.TempHold; }
				gBrowser.TempHold = parseInt(gBrowser.TempTop) + parseInt(gBrowser.TempHeight);
				if (gBrowser.TempHold > gBrowser.pageHeight) { gBrowser.pageHeight = gBrowser.TempHold; }
			}
		}
	}

	// working code: if (Node.id) { ShowAllHtml += Node.id + "\n"; }
	// working code: alert("count! : " + document.getElementsByTagName("body")[0].childNodes.length);
	// if (parseInt(gBrowser.TempLeft) + gBrowser.TempWidth >= 1000) {
	//		alert("2. " + typeof(Node) + ":" + Node.tagName + ":" + Node.id + " -  " + gBrowser.TempLeft + "," + gBrowser.TempTop + "   " + gBrowser.TempWidth + "," + gBrowser.TempHeight);
	// }
}

// -----------------------------------------------------------------------------------------------------------------------
// Capture the size of the browser (taking into account user resize) and store in .width and .height
// If this page scrolls (it's bigger than the browser), this function ignores that and just returns the width/height of the BROWSER
function Browser_onresize() {
	gBrowser.width = 0; gBrowser.height = 0;

	// happens BEFORE all the other resize events have been processed (they need it)
	// Get actual gBrowser width & height (not the screen)
	if( typeof( window.innerWidth ) == 'number' ) {
		//Non-IE
		gBrowser.width  = window.innerWidth;
		gBrowser.height = window.innerHeight;
	} else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
		//IE 6+ in 'standards compliant mode'
		gBrowser.width = document.documentElement.clientWidth;
		gBrowser.height = document.documentElement.clientHeight;
	} else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
		//IE 4 compatible
		gBrowser.width = document.body.clientWidth;
		gBrowser.height = document.body.clientHeight;
	}

	if (gBrowser.width <= gBrowser.widthmin) { gBrowser.width = gBrowser.widthmin; gBrowser.ratioX = 1;} else { gBrowser.ratioX = gBrowser.width / gBrowser.widthmin; }
	if (gBrowser.height <= gBrowser.heightmin) { gBrowser.height = gBrowser.heightmin; gBrowser.ratioY = 1;} else { gBrowser.ratioY = gBrowser.height / gBrowser.heightmin; }
}

addLoadEvent(Browser_onresize);
addResizeEvent(Browser_onresize);


// -----------------------------------------------------------------------------------------------------------------------
// Capture the Mouse and dump it into .mouseX and .mouseY
function Browser_onmousemove(e) {
	if( !e ) {
		if( window.event ) {
			//DOM
			e = window.event;
		} else {
			//TOTAL FAILURE, WE HAVE NO WAY OF REFERENCING THE EVENT
			window.status = "Error: Can't capture mouse!";
			return;
		}
	}

	if( typeof( e.pageX ) == 'number' ) {
		//NS 4, NS 6+, Mozilla 0.9+
		var xcoord = e.pageX;
		var ycoord = e.pageY;
	} else {
		if( typeof( e.clientX ) == 'number' ) {
			//IE, Opera, NS 6+, Mozilla 0.9+
			//except that NS 6+ and Mozilla 0.9+ did pageX ...
			var xcoord = e.clientX;
			var ycoord = e.clientY;
			if( !( ( window.navigator.userAgent.indexOf( 'Opera' ) + 1 ) ||
			( window.ScriptEngine && ScriptEngine().indexOf( 'InScript' ) + 1 ) ||
			window.navigator.vendor == 'KDE' ) ) {
				if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
					//IE 4, 5 & 6 (in non-standards compliant mode)
					xcoord += document.body.scrollLeft;
					ycoord += document.body.scrollTop;
				} else if( document.documentElement &&
				( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
					//IE 6 (in standards compliant mode)
					xcoord += document.documentElement.scrollLeft;
					ycoord += document.documentElement.scrollTop;
				}
			}
		} else {
			//TOTAL FAILURE, WE HAVE NO WAY OF OBTAINING THE
			//MOUSE COORDINATES
			return;
		}
	}
	gBrowser.mouseX = parseInt(xcoord); gBrowser.mouseY = parseInt(ycoord);
}

function Browser_onmousedown() { gBrowser.mouseDown = true; gBrowser.mouseDownFlag = true;}

function Browser_onmouseup() { gBrowser.mouseDown = false; }

// strangely, you can hook up to the events even though document should not exist at this point (try getting document.offsetWidth)
if( document.captureEvents ) {
    //non IE
    if( Event.KEYUP ) {
        //NS 4, NS 6+, Mozilla 0.9+
		document.captureEvents( Event.MOUSEMOVE );
		document.captureEvents( Event.MOUSEDOWN );
		document.captureEvents( Event.MOUSEUP );
    }
}
document.onmousedown = Browser_onmousedown; // can't call / link to methods of an object
document.onmouseup = Browser_onmouseup;
document.onmousemove = Browser_onmousemove;	


// -----------------------------------------------------------------------------------------------------------------------
// Keyboard
if( document.captureEvents ) {
    //non IE
    if( Event.KEYUP ) {
        //NS 4, NS 6+, Mozilla 0.9+
        document.captureEvents( Event.KEYDOWN );
		document.captureEvents( Event.KEYUP );
    }
}
document.onkeydown = Browser_keydown;
document.onkeyup = Browser_keyup;
		
function Browser_keycode(e) {
    if( !e ) {
        //if the browser did not pass the event information to the
        //function, we will have to obtain it from the event register
        if( window.event ) {
            //DOM
            e = window.event;
        } else {
            //TOTAL FAILURE, WE HAVE NO WAY OF REFERENCING THE EVENT
            return;
        }
    }
    if( typeof( e.which ) == 'number' ) {
        //NS 4, NS 6+, Mozilla 0.9+, Opera
        e = e.which;
    } else if( typeof( e.keyCode ) == 'number'  ) {
        //IE, NS 6+, Mozilla 0.9+
        e = e.keyCode;
    } else if( typeof( e.charCode ) == 'number'  ) {
        //also NS 6+, Mozilla 0.9+
        e = e.charCode;
    } else {
        //TOTAL FAILURE, WE HAVE NO WAY OF OBTAINING THE KEY CODE
        return;
    }
    return parseInt(e); // window.status = 'The key pressed has keycode ' + e + ' and is key ' + String.fromCharCode( e );
}
	
function Browser_keydown(e) {
	gBrowser.keys[Browser_keycode(e)] = true;
}

function Browser_keyup(e) {
	gBrowser.keys[Browser_keycode(e)] = false;
}


// -----------------------------------------------------------------------------------------------------------------------
// Browser detection (can do this right away, no need to wait for document to load)
// http://www.howtocreate.co.uk/tutorials/index.php?tut=0&part=16
// http://www.quirksmode.org/js/detect.html

var detect = navigator.userAgent.toLowerCase();
function Browser_checkIt(string)
{
	place = detect.indexOf(string) + 1;
	thestring = string;
	return place;
}

if (Browser_checkIt('konqueror'))
{
	gBrowser.name = "Konqueror";
	gBrowser.os = "Linux";
}
else if (Browser_checkIt('safari')) gBrowser.name = "Safari"
else if (Browser_checkIt('omniweb')) gBrowser.name = "OmniWeb"
else if (Browser_checkIt('opera')) gBrowser.name = "Opera"
else if (Browser_checkIt('webtv')) gBrowser.name = "WebTV";
else if (Browser_checkIt('icab')) gBrowser.name = "iCab"
else if (Browser_checkIt('msie')) gBrowser.name = "Internet Explorer"
else if (!Browser_checkIt('compatible'))
{
	gBrowser.name = "Netscape Navigator"
	gBrowser.version = detect.charAt(8);
}
else gBrowser.name = "An unknown gBrowser.name";

if (!gBrowser.version) gBrowser.version = detect.charAt(place + thestring.length);

if (!gBrowser.os)
{
	if (Browser_checkIt('linux')) gBrowser.os = "Linux";
	else if (Browser_checkIt('x11')) gBrowser.os = "Unix";
	else if (Browser_checkIt('mac')) gBrowser.os = "Mac"
	else if (Browser_checkIt('win')) gBrowser.os = "Windows"
	else gBrowser.os = "an unknown operating system";
}


// -----------------------------------------------------------------------------------------------------------------------
// Easy Image Rollover v1.0
var Browser_cache = new Array();

function Browser_rollover() {
  	var rollover_images = new Array();
  	var hold_images = new Array();
  	var index = -1;
	var hold = "";
	var href = "";
	
  	// Step 1. Create an array of images that require rollovers	
  	var hold_images = document.getElementsByTagName('img');
  	for (var i = 0; i < hold_images.length; i++) {
  		if ((hold_images[i].src.indexOf('_off.') != -1) && (!hold_images[i].onmouseover) && (!hold_images[i].onmouseout)) {
  			index = rollover_images.length; 
  			rollover_images[index] = hold_images[i];
  		}
  	}
  
  	var hold_images = document.getElementsByTagName('input');
  	for (var i = 0; i < hold_images.length; i++) {
  		if ((hold_images[i].src.indexOf('_off.') != -1) && (!hold_images[i].onmouseover) && (!hold_images[i].onmouseout)) {
  			index = rollover_images.length; 
  			rollover_images[index] = hold_images[i];
  		}
  	}
  	
  	for (var i = 0; i < rollover_images.length; i++)
  	{	
  		// Step 2: If we're on the page this image links to, and the user want it remembered, don't add mouseovers and keep the image on always
		href = "";
		if ((rollover_images[i].parentNode) && (rollover_images[i].parentNode.href)) { href = rollover_images[i].parentNode.href.toLowerCase(); }

		if (href == window.location.href.toLowerCase()) {
  			rollover_images[i].src = rollover_images[i].src.replace("_off.", "_on.");

  		} else if (href != "") {
  			// Step 3: Add the usual mouse rollover events to each image
  			rollover_images[i].onmouseover = function () { this.src = this.src.replace("_off.", "_rollover."); };
  			rollover_images[i].onmouseout = function () { this.src = this.src.replace("_rollover.", "_off."); };
  			
  			// Step 4: Cache the on states of the rollover images (off states already cached by IMG tag).
  			index = Browser_cache.length;
  			Browser_cache[index] = new Image();
  			Browser_cache[index].src = rollover_images[i].src.replace("_off.", "_rollover.");
  		}
  	}
}
addLoadEvent(Browser_rollover);

