// Same as extend but throws an error if the key doesn't exist
// in the destination. Stricter checking = better code.
Object.extend(Object,{
	restrict: function(destination, source){
		for (property in source) {
			if (destination[property] === undefined){
				throw "The key "+property+" could not be found in the destination object."
			}
		}
		return Object.extend(destination, source);
	}
})

// consider adding a "require" method to object

Object.extend(Event,{
	KEY_PGUP: 33,
	KEY_PGDN: 34,
	cancel: function(event){
		if (event.stopPropogation) {
			event.stopPropagation();
		} else {
			event.cancelBubble = true;
		}
	}
})

Object.extend(Element,{
  findElement: function(element, tagName) {
    while (element.parentNode && (!element.tagName ||
        (element.tagName.toUpperCase() != tagName.toUpperCase())))
      element = element.parentNode;
    return element;
  }
})

// String manipulation
/*
Object.extend(String.prototype,{
	
	// converts camel case (backgroundColor) into a normal style (background-color)
	decamelize: function(){
		var style = this;
		var capPositions = style.match(/[A-Z]/g);
		if(capPositions){
			for(var i=0; i<capPositions.length; i++){
				style = style.replace(capPositions[i],'-'+)
			}
		}
		return r;
	}

})
*/

/*
function g_parseStyle(style){
	var r=new Object(); // return value
	// parse a css style
	if (style.indexOf("-")!=-1) {
		var array=style.split("-");
		var jsStyle=array[0];
		var s;
		for (var i=1;i<array.length;i++){
			s=array[i];
			jsStyle+=s.substring(0,1).toUpperCase()+s.substring(1);
		}
		r.css=style;
		r.js=jsStyle;
	} else {
		var search;
		var cssStyle=style;
		// returns an array of matches of capital letters
		search=cssStyle.match(/[A-Z]/g);
		if(search){
			// replaces them, one by one, with css compatible format
			for(i=0;i<search.length;i++){
				cssStyle=cssStyle.replace(search[i],"-"+search[i].toLowerCase());
			}
		}
		r.css=cssStyle;
		r.js=style;
	}
	return r;
}
*/

// Positioning helpers. Extends Position in prototype.js and util.js
Object.extend(Position,{

	getPageWidth:function(){
		return document.body.clientWidth;
	},
	
	getPageHeight: function(){
		return document.body.clientHeight;
	},
	
	getRect:function(element){
		var pos=Position.positionedOffset(element);
		var width=element.offsetWidth;
		var height=element.offsetHeight;
		return {
			left:pos[0],
			top:pos[1],
			width:width,
			height:height,
			right:pos[0]+width,
			bottom:pos[1]+height
		};
	},
	
	// helper for positionedRect and cumulativeRect
	_rect:function(element,left,top){
		var width=element.offsetWidth;
		var height=element.offsetHeight;
		return {
			left:left,
			top:top,
			width:width,
			height:height,
			right:left+width,
			bottom:top+height
		}
	},
	
	positionedRect:function(element){
		var pos=Position.positionedOffset(element);
		return Position._rect(element,pos[0],pos[1]);
	},
	
	cumulativeRect:function(element){
		var pos=Position.cumulativeOffset(element);
		return Position._rect(element,pos[0],pos[1]);
	},
	
	positionAround:function(button,element,padding){
		// sets default padding to 2 pixels
		var padding=padding?padding:2;
		var buttonRect=Position.getRect(button);
		var elementRect=Position.getRect(element);
		var pageWidth=Position.getPageWidth();
		var left=0;
		if(buttonRect.left+elementRect.width<=pageWidth-padding){
			left=buttonRect.left;
		}else{
			left=pageWidth-elementRect.width-padding;
			if(left<padding){left=padding}
		}
		element.style.left=left;
		element.style.top=buttonRect.bottom+padding;
	},
	
	positionCentered: function(element){
		var rect = Position.getRect(element);
		var left = (Position.getPageWidth() - rect.width) / 2;
		var top = (Position.getPageHeight() - rect.height) / 2;
		Element.setStyle(element,{
			left: parseInt(left) + 'px',
			top: parseInt(top) + 'px'
		})
	},
	
	getScrollTop: function(){
		Position.prepare();
		return this.deltaY;
	}
	
})