function novaGetDocumentSizes() {
	
	var availWidth = 0;
	var availHeight = 0;
	
	if(self.innerHeight) {
        availWidth = self.innerWidth;
        availHeight = self.innerHeight;
	
	} else if(document.documentElement && document.documentElement.clientHeight) {
        availWidth = document.documentElement.clientWidth;
        availHeight = document.documentElement.clientHeight;
    
    } else {
		availWidth = document.body.clientWidth;
        availHeight = document.body.clientHeight;
    }
    
    var scrolledWidth = 0;
	var scrolledHeight = 0;
	
	if(document.documentElement) {
		scrolledWidth = document.documentElement.scrollLeft;
		scrolledHeight = document.documentElement.scrollTop;
	
	} else if(document.body.scrollTop || document.body.scrollLeft) {
		scrolledWidth = parseInt(document.body.scrollLeft);
		scrolledHeight = parseInt(document.body.scrollTop);
	}
	
	return { availWidth:availWidth, availHeight:availHeight, scrolledWidth:scrolledWidth, scrolledHeight:scrolledHeight };
}

function novaPositionObject(obj, x, y, xOffset, yOffset) {
	
	x = parseInt(x);
	y = parseInt(y);
    
	if(!xOffset) {
		xOffset = 0;
	}
	if(!yOffset) {
		yOffset = 0;
	}
    
	var documentSizes = novaGetDocumentSizes();
    
	var availWidth = documentSizes.availWidth;
	var availHeight = documentSizes.availHeight;
    
	var scrolledWidth = documentSizes.scrolledWidth;
	var scrolledHeight = documentSizes.scrolledHeight;
	
	var objectWidth = 0;
	
	// Save width on first access, and load on subsequent (to work around firefox scroll bug)
	if(obj.objectWidth) {
		objectWidth = obj.objectWidth;
		//objectWidth = obj.offsetWidth;
	
	} else {
		obj.objectWidth = objectWidth = obj.offsetWidth;
	}
	
	var objectHeight = obj.offsetHeight;
	
	var xSpaceLeft = availWidth - x;
	var ySpaceLeft = availHeight - y;

	var newXPosition = 0;
	if(xSpaceLeft < (objectWidth + xOffset)) {
		if(x >= objectWidth) {
			newXPosition = x - objectWidth;
		} else {
			newXPosition = x - objectWidth + xSpaceLeft;
		}
		xOffset *= -1;
        
	} else {
		newXPosition = x;
	}
    
	newXPosition += scrolledWidth + xOffset;
	if(newXPosition < 0) {
		newXPosition = 0;
	}
	obj.style.left = newXPosition + "px";

	var newYPosition = 0;
	if(ySpaceLeft < (objectHeight + yOffset)) {
		if(y >= objectHeight) {
			newYPosition = y - objectHeight;
		} else {
			newYPosition = y - objectHeight + ySpaceLeft;
		}
		yOffset *= -1;
		
	} else {
		newYPosition = y;
	}
    
	newYPosition += scrolledHeight + yOffset;
	if(newYPosition < 0) {
		newYPosition = 0;
	}
	obj.style.top = newYPosition + "px";
}    

function novaGetAbsolutePosition(obj) {
	var x = y = 0;
	
	if(obj.offsetParent) {
		
		x = obj.offsetLeft;
		y = obj.offsetTop;
		
		while(obj = obj.offsetParent) {
			x += obj.offsetLeft;
			y += obj.offsetTop;
		}
	}
	return { x:x, y:y };
}


// written by Dean Edwards, 2005
// with input from Tino Zijdel - crisp@xs4all.nl
// http://dean.edwards.name/weblog/2005/10/add-event/
function novaAddEvent(element, type, handler) {
	
	if(element.addEventListener) {
		element.addEventListener(type, handler, false);
	
	} else {
		if(!handler.$$guid) handler.$$guid = novaAddEvent.guid++;
		if(!element.events) element.events = {};
		var handlers = element.events[type];
		
		if(!handlers) {
			handlers = element.events[type] = {};
			if(element['on' + type]) {
				handlers[0] = element['on' + type];
			}
			element['on' + type] = novaHandleEvent;
		}
	
		handlers[handler.$$guid] = handler;
	}
}
novaAddEvent.guid = 1;

function novaRemoveEvent(element, type, handler) {
	
	if(element.removeEventListener) {
		element.removeEventListener(type, handler, false);
	
	} else if(element.events && element.events[type] && handler.$$guid) {
		delete element.events[type][handler.$$guid];
	}
}

function novaHandleEvent(event) {

	event = event || novaFixEvent(window.event);
	var returnValue = true;
	var handlers = this.events[event.type];

	for(var i in handlers) {
		if(!Object.prototype[i]) {
			this.$$handler = handlers[i];
			if(this.$$handler(event) === false) returnValue = false;
		}
	}

	if(this.$$handler) this.$$handler = null;

	return returnValue;
}

function novaFixEvent(event) {
	event.preventDefault = novaFixEvent.preventDefault;
	event.stopPropagation = novaFixEvent.stopPropagation;
	return event;
}

novaFixEvent.preventDefault = function() { this.returnValue = false; }
novaFixEvent.stopPropagation = function() {	this.cancelBubble = true; }


function novaAddClass(element, className) {
    if(!novaHasClass(element, className)) {
        if(element.className) {
			element.className += " " + className;
		
		} else {
			element.className = className;
		}
    }
}

function novaRemoveClass(element, className) {
    var regexp = new RegExp("(^|\\s)" + className + "(\\s|$)");
    element.className = element.className.replace(regexp, "$2");
}

function novaHasClass(element, className) {
    var regexp = new RegExp("(^|\\s)" + className + "(\\s|$)");
    return regexp.test(element.className);
}

function novaArrayIndexOf(array, value) {
    for(var i = 0; i < array.length; i++) {
        if(array[i] == value) {
            return i;
        }
    }

    return -1;
}