window.onload = function() {
	jojo.Common.pageLoad();
}
self.jojo = {};
jojo.Common = {
	
	pageLoad: function() {
		if (!document.getElementById || !document.getElementsByTagName) {
			return;
		}
		self.loadEvents.sort( function(a,b) {
			return a[1] < b[1] ? 1 : -1;
		} );
		for (var i = 0, j = self.loadEvents.length; i<j; i++) {
			self.loadEvents[i][0]();
		}
	},
	
	// find all image input elements and sets the mouseover and mouseout
	// handlers to swap the rollover images.
	// By convention all images in the html source must be of the form
	// *_off.* and there must exist a second image of the form
	// *_on.* in the same directory to swap it with.
	// NOTE for mozilla (firefox) this function attaches the event and
	// for IE it replaces any existing event.
	attachRollovers: function() {
		var inputElements = document.getElementsByTagName('input');
		
		for (var i = 0; i < inputElements.length; i++) {
			
			// is this a rollover button?
			if(jojo.Common.hasCssClass(inputElements[i], 'withRollover')) {
				
				// does the rollover button have an appropriately 
				// named image for the 'off' state?
				if (inputElements[i].src.indexOf('_off.') != -1) {

					// then save a copy of the image.					
					inputElements[i].offImage = new Image();
					inputElements[i].offImage.src = inputElements[i].src;
						
					// create and preload an image with the 'on' state src.
					inputElements[i].onImage = new Image();
					inputElements[i].onImage.src = inputElements[i].src.replace(/_off\./, '_on.');

					// attach/replace the actual rollover functions.
					jojo.Common.replaceEvent(inputElements[i],'mouseover', 						
						function () {
							jojo.Common.changeSrc(this, this.onImage.src);
						}
					);
					// attach/replace the actual rollover functions.
					jojo.Common.replaceEvent(inputElements[i],'mouseout', 
						function () {
							jojo.Common.changeSrc(this, this.offImage.src);
						}
					);
				}
			}
		}
	},
		
	hasCssClass: function(o, css_class) {
		return o.className.match(new RegExp("\\b" + css_class + "\\b")) == css_class;
	},
	addCssClass: function(o, css_class) {
        if (!o || typeof o != "object") {
            return false;
        }
        if (o.className == null) {
            return false;
        }
        if (this.hasCssClass(o, css_class)) {
            return false;
        }
        o.className = o.className.trim() + " " + css_class.trim();
        return true;
    },
    removeCssClass: function(o, css_class) {
        if (!o || typeof o != "object") {
            return false;
        }
        if (!o.className) {
            return false;
        }
        if (!this.hasCssClass(o, css_class)) {
            return false;
        }
        o.className = o.className.replace(css_class.trim(), "").trim();
        return true;
    },
    setCssClass: function(o, css_class) {
        if (!o || typeof o != "object") {
            return false;
        }
        if (!o.className) {
            return false;
        }
        o.className = css_class;
        return true;
    },
    getClientDimensions: function() {
        var x,y;
        if (self.innerHeight) {
                x = self.innerWidth;
                y = self.innerHeight;
        }
        else if (document.documentElement && document.documentElement.clientHeight) {
                x = document.documentElement.clientWidth;
                y = document.documentElement.clientHeight;
        }
        else if (document.body) {
                x = document.body.clientWidth;
                y = document.body.clientHeight;
        }
        return { "x":x, "y":y };
    },
    getVerticalScrollPosition: function() {
        var de = document.documentElement;
        return self.pageYOffset || (de && de.scrollTop) || document.body.scrollTop;
    },
	getAbsolutePosition: function(o, stop_at_element) {
        if (!o || typeof o != "object") {
            return false;
        }
        if (!o.offsetParent) {
            return false;
        }
        var position = new Object();
        position["left"] = parseInt(o.offsetLeft);
        position["top"] = parseInt(o.offsetTop);
        while (o = o.offsetParent) {
            if (o == stop_at_element) {
                break;
            }
            position["left"] += parseInt(o.offsetLeft);
            position["top"] += parseInt(o.offsetTop);
        }
        return position;
    },
    getParentNodeByTagName: function(o, parent_tag) {
        if (!o || typeof o != "object") {
            return false;
        }
        while (o = o.parentNode) {
            if (o.nodeType != 1) {
                continue;
            }
            if (o.tagName.toLowerCase() == parent_tag.toLowerCase()) {
                return o;
            }
        }
        return null;
    },
    getElementsByTagNames: function(o, list) {
        if (!o || typeof o != "object") {
            return false;
        }
        var tag_names = list.split(",");
        var results = new Array();
        for (var i=0; i<tag_names.length; i++) {
            var elements = o.getElementsByTagName(tag_names[i]);
            for (var j=0, k=elements.length; j<k; j++) {
                results.push(elements[j]);
            }
        }
        return results;
    },
    getElementsByTagNameClass: function(o, tag_name, css_class) {
        if (!o || typeof o != "object") {
            return false;
        }
        var child_elements = new Array();
        var elements = o.getElementsByTagName( tag_name );
        for (var i = 0, j = elements.length; i<j; i++) {
            if (this.hasCssClass(elements[i], css_class) || css_class == "" || css_class == null) {
                child_elements.push(elements[i]);
            }
        }
        return child_elements;
    },
    getElementsByTagNameSimilarClass: function(o, tag_name, css_class) {
        if (!o || typeof o != "object") {
            return false;
        }
        var child_elements = new Array();
        var elements = o.getElementsByTagName( tag_name );
        for (var i = 0, j = elements.length; i<j; i++) {
            if (elements[i].className.indexOf(css_class) != -1) {
                child_elements.push(elements[i]);
            }
        }
        return child_elements;
    },
    getParentByStyleProperty: function(o, property, value) {
        if (!o || typeof o != "object") {
            return false;
        }
        while (o = o.parentNode) {
            if (this.getComputedStyle(o, property) == value) {
                return o;
            }
        }
        return null;
    },
    getComputedStyle: function(o, property) {
        if (!o || typeof o != "object") {
            return false;
        }
        var property_value = null;
        if (o.currentStyle) {
            property_value = o.currentStyle[property];
        } else if (window.getComputedStyle) {
            property_value = document.defaultView.getComputedStyle(o,null).getPropertyValue(property);
        }
        return property_value;
    },
    removeAllChildren: function(o) {
        if (!o || o == null) {
            return false;
        }
        while (o.hasChildNodes()) {
            o.removeChild(o.firstChild);
        }
    },
	changeSrc: function(o, newSrc) {
		if (!o) {
			return false;
		}
		if (!o.src) {
	        return false;
	    }
	    o.src = newSrc;
	    return true;
	},
	
	// use add event where your fuction needs to work in IE but the function does not make
	// use of the 'this' object.
	addEvent: function(element, ev_type, fn, sortIndex) {
	
		if (element == window && ev_type == "load") {
			if (arguments.length < 4) {
				sortIndex = 99;
			}
			if (self.loadEvents == null) {
				self.loadEvents = new Array();
			}
			self.loadEvents.push( new Array( fn, sortIndex ) );
			return true;
		}
	
		if (element.addEventListener) {
			
			element.addEventListener(ev_type, fn, false);
	        return true;
	        
	    } else if (element.attachEvent) {
		    
		    // this is the key line for IE. Any function attached here will not be able to make
		    // use of 'this'. This is a design flaw in MSFTs attachEvent function.
	        var r = element.attachEvent('on' + ev_type, fn);
	        return r;
	        
	    } else {
	        element['on' + ev_type] = fn;
	    }
	},

	// use replace event where your fuction to pass *must* make use
	// of the 'this' object, and you want it to work in IE	
	// NOTE: despite being named replace event, for firefox this method
	// still adds the event to the object.
	replaceEvent: function(element, ev_type, fn) {
		if (element.addEventListener) {
			
			element.addEventListener(ev_type, fn, false);
	        return true;
	        
	    } else {
		    
		    // this is the key line for IE. A function given here *can* make use of 'this'
		    // because the attachment is a simple assignment. Unfortunately this means
		    // any previously attached functions will be deleted and overwritten.
		    // That's why this method is called 'replaceEvent'
	        element['on' + ev_type] = fn;
	        
	    }
	},
	insertAfter: function(newElement, targetElement) {
		var parent = targetElement.parentNode;
		if (parent.lastChild == targetElement) {
			parent.appendChild(newElement);
		} else {
			parent.insertBefore(newElement, targetElement.nextSibling);
		}
	}
}

// set the attachRollovers function to run when the window has loaded.
// This will then add all the rollover handlers to their appropriate 
// image input elements
jojo.Common.addEvent(window, 'load', jojo.Common.attachRollovers);
String.prototype.trim = function () {
    return this.replace(/^\s*|\s*$/g,'');
}