/* * * * * * * * * * * * * * * * * * * * * * * * *
 *	 Seir Anphin JavaScript Utility Library	     *
 * Copyright Darrel Grant unless otherwise noted *
 *			  http://www.anphin.com	             *
 * * * * * * * * * * * * * * * * * * * * * * * * */

// Provide getElementById shorthand
function $(id) {
	if (!document.getElementById) {
		document.getElementById = function(id) {
			if (document.all) {
				return document.all[id];
			} else if (document.layers) {
				return document.layers[id];
			}
		}
	} else {
		return document.getElementById(id);
	}
}



function UserAgent() {
	this.agent = navigator.userAgent.toLowerCase();
	this.isIE = ((this.agent.indexOf("msie") != -1) && (this.agent.indexOf("opera") == -1) && (this.agent.indexOf("webtv") == -1));
	this.ieVersion = parseFloat(this.agent.substring(this.agent.indexOf('msie ') + 5));
	this.isGecko = (this.agent.indexOf("gecko") != -1);
	this.isSafari = (this.agent.indexOf("safari") != -1);
	this.isKonqueror = (this.agent.indexOf("konqueror") != -1);
	
	// Opera has an option to send an incorrect user-agent string,
	// so we check for a unique object instead
	this.isOpera = (typeof(window.opera) != 'undefined') ? true : false;
	this.isNetscape = (this.agent.indexOf("netscape") != -1);
	this.netscapeVersion = parseFloat(this.agent.substring(this.agent.lastIndexOf('/') + 1));
	
	this.get_webkit_version = function() {
		try{
			var regObj = new RegExp("\\(.*\\) AppleWebKit/(.*) \\((.*)");
			var agent = regObj.exec(navigator.userAgent);
			if (agent) {
				var version = this.parse_webkit_version(agent[1])
			} else {
				return null;
			}
			return {
				// Appears to be valid JSON, but Firefox frequently 
				// flags it as the cause of completely unrelated errors...
				/*
				major : version['major'],
				minor : version['minor'],
				is_nightly : version['is_nightly']
				*/
			};
		} catch(e) {
			alert("Could not get webkit version. " + e);
		}		
	};	

	this.parse_webkit_version = function(agent_string) {
		try {
			var agent_array = agent_string.split(".");
			var nightly = (agent_string[agent_string.length - 1] == "+");
			if (nightly) {
				var minor = "+";
			} else {
				var minor = parseInt(agent_array[1]);
				if (isNaN(minor)) {
					minor = "";
				}
			}
			return {
				/*
				major : parseInt(agent_array[0]),
				minor : minor,
				is_nightly : nightly
				*/
			}
		} catch(e) {
			alert("Could not parse webkit version." + e);
		}
	};

	this.webkitVersion = this.get_webkit_version();
	this.webkitVersion = this.webkitVersion ? this.webkitVersion=this.webkitVersion["major"] : this.webkitVersion=null;
	
	// Never used, because konqueror doesn't support anything
	konquerorVersion : parseFloat(this.agent.substring(this.agent.indexOf('konqueror/')+10))	
}

ua = new UserAgent;


/*
	Developed by Robert Nyman, http://www.robertnyman.com
	Code/licensing: http://code.google.com/p/getelementsbyclassname/
*/
var getElementsByClassName = function (className, tag, elm){
	if (document.getElementsByClassName) {
		getElementsByClassName = function (className, tag, elm) {
			elm = elm || document;
			var elements = elm.getElementsByClassName(className),
				nodeName = (tag)? new RegExp("\\b" + tag + "\\b", "i") : null,
				returnElements = [],
				current;
			for(var i=0, il=elements.length; i<il; i+=1){
				current = elements[i];
				if(!nodeName || nodeName.test(current.nodeName)) {
					returnElements.push(current);
				}
			}
			return returnElements;
		};
	}
	else if (document.evaluate) {
		getElementsByClassName = function (className, tag, elm) {
			tag = tag || "*";
			elm = elm || document;
			var classes = className.split(" "),
				classesToCheck = "",
				xhtmlNamespace = "http://www.w3.org/1999/xhtml",
				namespaceResolver = (document.documentElement.namespaceURI === xhtmlNamespace)? xhtmlNamespace : null,
				returnElements = [],
				elements,
				node;
			for(var j=0, jl=classes.length; j<jl; j+=1){
				classesToCheck += "[contains(concat(' ', @class, ' '), ' " + classes[j] + " ')]";
			}
			try	{
				elements = document.evaluate(".//" + tag + classesToCheck, elm, namespaceResolver, 0, null);
			}
			catch (e) {
				elements = document.evaluate(".//" + tag + classesToCheck, elm, null, 0, null);
			}
			while ((node = elements.iterateNext())) {
				returnElements.push(node);
			}
			return returnElements;
		};
	}
	else {
		getElementsByClassName = function (className, tag, elm) {
			tag = tag || "*";
			elm = elm || document;
			var classes = className.split(" "),
				classesToCheck = [],
				elements = (tag === "*" && elm.all)? elm.all : elm.getElementsByTagName(tag),
				current,
				returnElements = [],
				match;
			for(var k=0, kl=classes.length; k<kl; k+=1){
				classesToCheck.push(new RegExp("(^|\\s)" + classes[k] + "(\\s|$)"));
			}
			for(var l=0, ll=elements.length; l<ll; l+=1){
				current = elements[l];
				match = false;
				for(var m=0, ml=classesToCheck.length; m<ml; m+=1){
					match = classesToCheck[m].test(current.className);
					if (!match) {
						break;
					}
				}
				if (match) {
					returnElements.push(current);
				}
			}
			return returnElements;
		};
	}
	return getElementsByClassName(className, tag, elm);
};


sa2 = {
	// Holds an element ID to be set as "off" when using ajax menues
	oldLinkId : null,
	
	events : new Array(),

	// Add a function to be run when the current page has finished rendering
	onLoad : function(func) {
		var oldonload = window.onload;
		if (typeof window.onload != 'function') {
			window.onload = func;
		} else {
			window.onload = function() {
				// All functions previously set to execute at window.onload
				// will do so before this one.
				oldonload();
				func();
			}
		}
	},

	// A true cross-browser event handler, for when you really need events
	// to work anywhere, and don't care about small, unimportant things
	// like memory leaks. 
	
	// It may be a bad idea to use this with mousemove, as those
	// fire with a very high frequency. 

	// Problem: "this" cannot be used, so how to acquire the calling object?	
	// For now, use closures. Even though they leak on IE. Nobody cares about IE.
	addEvent : function(element, eventType, callback) {

		// No listeners here, just basic property manipulation
		var other = (element["on" + eventType]) ? element["on" + eventType] : function() {};
		element["on" + eventType] = function() { other(); callback(); }
		
		// Save a copy of this event as a global, so it can be removed 
		// by removeEvent, without also removing all other events on element
		
		// The only real problem with this implementation would arise when 
		// there is a need to frequently remove event listeners from an 
		// element which has many events in it. Is there ever a need for that?
		sa2.events[element] = callback;
	},
	
	eventHandler : function(ev) {
		// Get the event
		var target = dom.getTarget(ev);
	},
	
	// Todo: Add support for removing just one specific event while keeping the rest
	removeEvent : function(element, eventType, callback) {
		// Works by clearing all events of eventType from element,
		// then re-adding all of them except callback
		element["on" + eventType] = null;
		
		/*
		// Delete this event from the ghetto registry
		delete sa2.events[element];
		
		for (var old_element in sa2.events) {
			sa2.addEvent(element, sa2.events[old_element]);
		}
		*/
	},
	
	array_search : function(needle, haystack) {
		for (var key in haystack){
			if(haystack[key] == needle) {
				return key;
			}
	    	return false;
		}
	},
 
	copyInnerHTML : function(layerFrom, layerTo, linkId) {
		if (linkId != null) {
			if (this.oldLinkId != null) {
				this.setClassName(this.oldLinkId, 'menu_item_off');
			}
			this.setClassName($(linkId), 'menu_item_on');
			this.oldLinkId = linkId;
		}

		src = dom.getElm(layerFrom);
		dst = dom.getElm(layerTo);
		dst.innerHTML = src.innerHTML;
	},
	
	swapInnerHTML : function(layer1, layer2) {
		src = $(layer1);
		dst = $(layer2);
		tmp = '';
		tmp = dst.innerHTML;
		dst.innerHTML = src.innerHTML;
		src.innerHTML = tmp;
	},

	checkClassName : function(id, className) {
		return new RegExp('\\b'+className+'\\b').test(dom.getElm(id).className);		
	},

	// Checks if the element id exists and sets the classname
	setClassName : function(obj, className) {
		try {
			dom.getElm(obj).className = className;
		} catch(e) {
			alert("Could not set classname on object: " + obj + ". " + e);
		}
	},
	
	// Appends a classname, ensuring there are no leading or trailing spaces
	appendClassName : function(id, newClassName) {
		var element = dom.getElm(id);
		if (element.className != '') {
			element.className += " " + newClassName;
		} else {
			element.className = newClassName;
		}
		//dom.dumpProps(element);
		//alert("element " + element + "'s classname is " + element.className);
	},
	
	removeClassName : function(id, thisClassName) {
		var element = dom.getElm(id);
		try {
			if (element.className == thisClassName) {
				element.className = '';
			} else {
				element.className  = element.className.replace(' ' + thisClassName, '');
			}
		} catch(e) {
			alert("Could not find a classname for element " + id);
		}
	},

	// Add support for popup menus where CSS :hover pseudo selectors
	// aren't supported (looking at you IE)
	init_menus : function() {
		dom.addEvent($('admin_menu'), 'mouseover', sa2.menuhandler)		
	},
	
	menuhandler : function(e) {
		var target = dom.getTarget(e);
		try {
			if (target.className == 'popup_menu') {
				var menu = target.nextSibling.nextSibling;
				if (menu.className == 'popupclass') {
					menu.className = '';
				} else {
					menu.className = 'popupclass';
				}
			}
		} catch (err) {
			alert("Failed to make the menu visible. Error: " + err);
		}		
	}
}

//sa2.onLoad(sa2.init_menus);

