(function(){
	
	//Check for String.replace callback support without browser sniffing - 
	//Safari will return 'String' here instead of '' and that's how we detect it.
	if ("".replace (/^/, String)) {
		// replace callback support for safari.
		var default_replace = String.prototype.replace;
		String.prototype.replace = function (search, replace) {
			
			// replace is not function
			if (typeof replace != "function"){
				return default_replace.apply (this,arguments)
			}
			var str = "" + this;
			var callback = replace;
			// search string is not RegExp
			if (!(search instanceof RegExp)){
				var idx = str.indexOf (search);
				return idx == -1 ? str :
					default_replace.apply (str, [search, callback (search, idx, str)])
			}
			var reg = search;
			var result = [];
			var lastidx = reg.lastIndex;
			var re;
			while ((re = reg.exec (str)) != null) {
				var idx  = re.index;
				var args = re.concat (idx, str);
				result.push (
					str.slice (lastidx,idx),
					callback.apply (null,args).toString()
				);
				if (!reg.global) {
					lastidx += RegExp.lastMatch.length;
					break
				} else {
					lastidx = reg.lastIndex;
				}
			}
			result.push (str.slice (lastidx));
			return result.join ("")
		}
	}	
	
	//We have Safari patched now so we can use this tiny function here.
	var camelizeCSSProperty = function (property) {
		return property.replace (/\-([a-z])/g, function (str) { return str.charAt(1).toUpperCase(); });  
	};
	
	if (typeof window.addEventListener == 'undefined') {
		window.addEventListener = function (eventType, callback, dummy) {
			window.attachEvent ('on' + eventType, function() {
				var e = window.event;
				e.target = e.srcElement;
				e.preventDefault = function() { this.returnValue = false; }
				callback (e); 
			});
		}
		document.addEventListener = function (eventType, callback, dummy) {
			document.attachEvent ('on' + eventType, function() {
				var e = window.event;
				e.target = e.srcElement;
				e.preventDefault = function() { this.returnValue = false; }
				callback (e); 
			});
		}
	}
	
	window.addMainListener = function (eventType, callback) {
		if (document.all) {
			document.addEventListener (eventType, callback, null);
		} else {
			window.addEventListener (eventType, callback, true);
		}
	}
	
	if (typeof window.getComputedStyle == 'undefined') {
		window.getComputedStyle = function (element, pseudoclass) {
			//pseudoclass not supported.
			return new function() {
				//Currently only getPropertyValue is suppored.
				this.getPropertyValue = function (property) {
					return element.currentStyle[camelizeCSSProperty (property)];
				}                        
			}
		}
	}

	
})();
