if(!window.Scrollable) {
	window.Scrollable = (function(){
		var self = {
			scrollSpeed : 20,
			init : function(){
				if(this.initialized==true)
					return false;
				this.initialized = true;
				if(document && document.getElementsByTagName) {
					var el = document.getElementsByTagName("*");
					for(var x=0; x<el.length; x++)
						if(el[x].className && el[x].className=="scrollable")
							this.Activate(el[x]);
					this._parseTimer = window.setInterval("Scrollable.parseDOM();", 500);
				}
			},
			cleanup : function(){
				if(this.initialized!=true)
					return false;
				this.initialized = false;
				for(var x=0; x<this.all.length; x++) {
					if(this.all[x]._isScrolling_timer)
						try{ window.clearTimeou(this.all[x]._isScrolling_timer); }catch(err){}
					if(this.all[x]._mousemove_timer)
						try{ window.clearTimeou(this.all[x]._mousemove_timer); }catch(err){}
				}
				while(this.all.length>0)
					this.all.pop();
				try{ delete this.all; }catch(err){ this.all=null; }
				try{clearTimeout(this._parseTimer);}catch(err){}
			},
			activate : function(el) {
				var oldOverflow = el.style.overflow;
				el.style.overflow = "hidden";
				
				// check for an existing scrollable:
				for(var x=0; x<this.all.length; x++) {
					if(this.all[x].el==el) {
						el.getScrollableObj = function(){
							for(var x=0; x<window.Scrollable.all.length; x++)
								if(window.Scrollable.all[x].el == this)
									return window.Scrollable.all[x];
							return null;
						};
						this.all[x].active = true;
						this.all[x].offset.top = el.scrollTop;
						this.all[x].offset.left = el.scrollLeft;
						this.all[x].oldOverflow = oldOverflow;
						return true;
					}
				}
				
				var scrollTop = el.scrollTop;
				var scrollLeft = el.scrollTop;
				
				var v_base = document.createElement("div");
				v_base.className = "scrollable_v_base";
				v_base.style.position = "absolute";
				v_base._type = "v";
				el.parentNode.appendChild(v_base);
				
				var h_base = document.createElement("div");
				h_base.className = "scrollable_h_base";
				h_base.style.position = "absolute";
				h_base._type = "h";
				el.parentNode.appendChild(h_base);
				v_base.onmouseout = h_base.onmouseout = function() {
					this._scroll.isOverBar = false;
					if(this._scroll._mousemove_timer)
						try{ window.clearTimeout(this._scroll._mousemove_timer); }catch(e){}
					this._scroll._mousemove_timer = window.setTimeout("Scrollable.all["+this._scroll._index+"].hideBothBars();", 1000);
				};
				v_base.onmousemove = v_base.onmouseover = h_base.onmousemove = h_base.onmouseover = function() {
					this._scroll.isOverBar = true;
					if(this._scroll._mousemove_timer)
						try{ window.clearTimeout(this._scroll._mousemove_timer); }catch(e){}
				};
				
				var ins = [	"v_bg_top","v_bg_mid","v_bg_bot","v_fg_base","v_fg_top","v_fg_mid","v_fg_bot" , 
							"h_bg_left","h_bg_mid","h_bg_right","h_fg_base","h_fg_left","h_fg_mid","h_fg_right" ];
				var i;
				for(var x=0; x<ins.length; x++) {
					i = document.createElement("div");
					i.className = "scrollable_"+ins[x];
					if(ins[x]=="v_fg_top" || ins[x]=="v_fg_mid" || ins[x]=="v_fg_bot")
						v_fg_base.appendChild(i);
					else if(ins[x]=="h_fg_left" || ins[x]=="h_fg_mid" || ins[x]=="h_fg_right")
						h_fg_base.appendChild(i);
					else if(ins[x].substring(0,1)=="v")
						v_base.appendChild(i);
					else
						h_base.appendChild(i);
					eval("var "+ins[x]+" = i;");
				}
				
				el.getScrollableObj = function() {
					for(var x=0; x<window.Scrollable.all.length; x++)
						if(window.Scrollable.all[x].el == this)
							return window.Scrollable.all[x];
					return null;
				};
				
				el.scrollTo = function(left,top) {
					if(!this.getScrollableObj)
						return true;
					else
						return this.getScrollableObj().scrollTo(left,top);
				};
				
				el.scrollBy = function(left,top){
					if(!this.getScrollableObj)
						return true;
					else
						return this.getScrollableObj().scrollBy(left,top);
				};
				
				el.setScrollSnapping = function(x,y){
					if( !(obj=this.getScrollableObj()) )
						return false;
					if( x!=null && x!="undefined" )
						obj.xsnap = x;
					if( y!=null && y!="undefined" )
						obj.ysnap = y;
					return true;
				};
				
				el._scrollable_oldmousemove = el.onmousemove?el.onmousemove:function(){};
				el.onmousemove = function(e){
					if(!e)e=window.event;
					if(this.getScrollableObj && (s=this.getScrollableObj())) {
						if(s._mousemove_timer)
							try{ window.clearTimeout(s._mousemove_timer); }catch(e){}
						var mx=e.pageX?e.pageX:(e.clientX+(document.documentElement?document.documentElement:document.body).scrollLeft);
						var my=e.pageY?e.pageY:(e.clientY+(document.documentElement?document.documentElement:document.body).scrollTop);
						var c = el;
						var ol = 0;
						var ot = 0;
						var nodes = el.childNodes.length;
						while(c && c.parentNode){
							ol += c.offsetLeft;
							ot += c.offsetTop;
							c = c.parentNode;
						}
						if(s._isManuallyScrolling!=true && (nodes!=s.lastNodeCount || ol!=s.lastLeft || ot!=s.lastTop || this.offsetHeight!=s.lastHeight || this.offsetWidth!=s.lastWidth || this.scrollHeight!=s.lastScrollHeight || this.scrollWidth!=s.lastScrollWidth) ){
							s.scrollBy(0,0);
							s.adjustSizes();
						}
						s.lastLeft = ol;
						s.lastTop = ot;
						s.lastNodeCount = nodes;
						s.lastHeight = this.offsetHeight+0;
						s.lastWidth = this.offsetWidth+0;
						s.lastScrollHeight = this.scrollHeight+0;
						s.lastScrollWidth = this.scrollWidth+0;
						mx -= ol;
						my -= ot;
						if(Math.abs(this.offsetWidth-mx)<s.visibilityRadius+s.v.base.offsetWidth)
							s.showVerticalBar();
						else
							s.hideVerticalBar();
						if(Math.abs(this.offsetHeight-my)<s.visibilityRadius+s.h.base.offsetHeight)
							s.showHorizontalBar();
						else
							s.hideHorizontalBar();
					}
					this._scrollable_oldmousemove(e);
				};
				
				el._scrollable_oldmouseover = el.onmouseover?el.onmouseover:function(){};
				el.onmouseover = function(e){
					if(!e)e=window.event;
					if( this.getScrollableObj && (s=this.getScrollableObj()) && s._isManuallyScrolling!=true ){
						s.scrollBy(0,0);
						s.adjustSizes();
					}
					this._scrollable_oldmouseover(e);
				};
				
				
				v_base.onmousedown = this.MouseHandler;
				h_base.onmousedown = this.MouseHandler;
				
				
				var obj = {
					el : el,
					xsnap : 1,
					ysnap : 1,
					visibilityRadius : 10,
					active : true,
					oldOverflow : oldOverflow,
					v : {
						base : v_base,
						bg : {
							top : v_bg_top,
							mid : v_bg_mid,
							bot : v_bg_bot
						},
						fg : {
							base : v_fg_base,
							top : v_fg_top,
							mid : v_fg_mid,
							bot : v_fg_bot
						},
						ratio : 1,
						visible : true
					},
					h : {
						base : h_base,
						bg : {
							left : h_bg_left,
							mid : h_bg_mid,
							right : h_bg_right
						},
						fg : {
							base : h_fg_base,
							left : h_fg_left,
							mid : h_fg_mid,
							right : h_fg_right
						},
						ratio : 1,
						visible : true
					},
					offset : {
						top : scrollTop,
						left : scrollLeft
					},
					scrollTo : function(left, top, useRatio) {
						//this.v.ratio = this.el.offsetHeight / this.el.scrollHeight;
						//this.h.ratio = this.el.offsetWidth / this.el.scrollWidth;
						this.v.ratio = this.v.base.offsetHeight / this.el.scrollHeight;
						this.h.ratio = this.h.base.offsetWidth / this.el.scrollWidth;
						
						if(left!=null && left!="undefined" && left==parseFloat(left))
							this.offset.left = left / (useRatio==true?this.h.ratio:1);
						if(top!=null && top!="undefined" && top==parseFloat(top))
							this.offset.top = top / (useRatio==true?this.v.ratio:1);
						
						var oldScrollLeft = this.el.scrollLeft;
						var oldScrollTop  = this.el.scrollTop;
						
						if(this.xsnap>1)
							this.offset.left -= this.offset.left%this.xsnap;
						else
							this.offset.left = Math.ceil(this.offset.left/this.xsnap)*this.xsnap;
						if(this.ysnap>1)
							this.offset.top -= this.offset.top%this.ysnap;
						else
							this.offset.top = Math.ceil(this.offset.top/this.ysnap)*this.ysnap;
						
						if(this.offset.left<0)
							this.offset.left = 0;
						else if(this.offset.left>this.el.scrollWidth-this.el.offsetWidth)
							this.offset.left = this.el.scrollWidth-this.el.offsetWidth;
						
						if(this.offset.top<0)
							this.offset.top = 0;
						else if(this.offset.top>this.el.scrollHeight-this.el.offsetHeight)
							this.offset.top = this.el.scrollHeight-this.el.offsetHeight;
						
						this.el.scrollLeft = this.offset.left;
						this.el.scrollTop = this.offset.top;
						
						this.v.fg.base.style.height = (this.el.offsetHeight/this.el.scrollHeight * (this.v.base.offsetHeight)) + "px";
						this.h.fg.base.style.width = (this.el.offsetWidth/this.el.scrollWidth * (this.h.base.offsetWidth)) + "px";
						
						this.v.fg.base.style.top = (this.el.scrollTop/this.el.scrollHeight * this.v.base.offsetHeight) + "px";
						this.h.fg.base.style.left = (this.el.scrollLeft/this.el.scrollWidth * this.h.base.offsetWidth) + "px";
						
						this.adjustSizes();
						
						var changedx = Math.abs(this.el.scrollLeft - oldScrollLeft) >= 1;
						var changedy = Math.abs(this.el.scrollTop - oldScrollTop) >= 1;
						
						if(changedx || changedy) {
							if(this._isScrolling_timer)
								try{ window.clearTimeout(this._isScrolling_timer); }catch(e){}
							this.isScrolling = true;
							if(this._isManuallyScrolling!=true)
								this._isScrolling_timer = window.setTimeout("Scrollable.all["+this._index+"].isScrolling=false; Scrollable.all["+this._index+"].hideBothBars(); Scrollable.all["+this._index+"]._isScrolling_timer=null;", 1000);
						}
						
						if(changedx==true)
							this.showHorizontalBar();
						if(changedy==true)
							this.showVerticalBar();
						
						return changedx || changedy;
					},
					scrollBy : function(left,top) {
						return this.scrollTo( left==parseFloat(left)?(this.offset.left+left):null , top==parseFloat(top)?(this.offset.top+top):null );
					},
					adjustSizes : function() {
						this.v.base.style.height = this.el.offsetHeight+"px";
						this.v.base.style.top = this.el.offsetTop+"px";
						this.v.base.style.left = (this.el.offsetLeft+this.el.offsetWidth-this.v.base.offsetWidth)+"px";
						
						this.h.base.style.width = (this.el.offsetWidth - this.v.base.offsetWidth) + "px";
						this.h.base.style.top = (this.el.offsetTop+this.el.offsetHeight-this.h.base.offsetHeight)+"px";
						this.h.base.style.left = this.el.offsetLeft+"px";
						
						this.v.base.style.height = (this.el.offsetHeight - this.h.base.offsetHeight) + "px";
						
						this.v.bg.mid.style.height = (this.v.base.offsetHeight-this.v.bg.top.offsetHeight-this.v.bg.bot.offsetHeight) + "px";
						this.v.bg.mid.style.top = this.v.bg.top.offsetHeight + "px";
						this.v.fg.mid.style.height = (this.v.fg.base.offsetHeight-this.v.fg.top.offsetHeight-this.v.fg.bot.offsetHeight) + "px";
						this.v.fg.mid.style.top = this.v.fg.top.offsetHeight + "px";
						
						this.h.bg.mid.style.width = (this.h.base.offsetWidth-this.h.bg.left.offsetWidth-this.h.bg.right.offsetWidth) + "px";
						this.h.bg.mid.style.left = this.h.bg.left.offsetWidth + "px";
						this.h.fg.mid.style.width = (this.h.fg.base.offsetWidth-this.h.fg.left.offsetWidth-this.h.fg.right.offsetWidth) + "px";
						this.h.fg.mid.style.left = this.h.fg.left.offsetWidth + "px";
						
						if(this.v.visible==true)
							this.showVerticalBar();
						if(this.h.visible==true)
							this.showHorizontalBar();
					},
					showVerticalBar : function() {
						if(this.el.scrollHeight>this.el.offsetHeight) {
							this.v.base.style.visibility = "visible";
							this.v.visibile = true;
						}
						else
							this.hideVerticalBar();
					},
					hideVerticalBar : function() {
						if(this.isScrolling==true || this.isManuallyScrolling==true || this.isOverBar==true)
							return false;
						this.v.base.style.visibility = "hidden";
						this.v.visible = false;
					},
					showHorizontalBar : function() {
						if(this.el.scrollWidth>this.el.offsetWidth) {
							this.h.base.style.visibility = "visible";
							this.h.visible = true;
						}
						else
							this.hideHorizontalBar();
					},
					hideHorizontalBar : function() {
						if(this.isScrolling==true || this.isManuallyScrolling==true || this.isOverBar==true)
							return false;
						this.h.base.style.visibility = "hidden";
						this.h.visible = false;
					},
					hideBothBars : function(){
						this.hideHorizontalBar();
						this.hideVerticalBar();
					},
					showBothBars : function(){
						this.showHorizontalBar();
						this.showVerticalBar();
					},
					timers : []
				};
				
				v_base._scroll = obj;
				h_base._scroll = obj;
				
				obj._index = this.all.length;
				this.all.push(obj);
				
				obj.adjustSizes();
				obj.hideBothBars();
				el.scrollTo(scrollLeft || 0, scrollTop || 0);
				
				return el;
			},
			MouseHandler : function(e) {
				if(!e) e=window.event;
				var mx = e.pageX ? e.pageX : (e.clientX + (document.documentElement?document.documentElement:document.body).scrollLeft);
				var my = e.pageY ? e.pageY : (e.clientY + (document.documentElement?document.documentElement:document.body).scrollTop);
				window.Scrollable._current = null;
				window.Scrollable._current = {
					obj : this._scroll,
					start : null,
					startY : this._scroll.v.fg.base.offsetTop + 0,
					startX : this._scroll.h.fg.base.offsetLeft + 0,
					type : this._type + "",
					oldmove : window.onmousemove ? window.onmousemove : function(){},
					oldup : window.onmouseup ? window.onmouseup : function(){}
				};
				window.onmousemove = function(e) {
					if(Scrollable._current) {
						var mx = e.pageX ? e.pageX : (e.clientX + (document.documentElement?document.documentElement:document.body).scrollLeft);
						var my = e.pageY ? e.pageY : (e.clientY + (document.documentElement?document.documentElement:document.body).scrollTop);
						if(Scrollable._current.start==null) {
							Scrollable._current.start = Scrollable._current.type=="v" ? my : mx;
							Scrollable._current.obj.isManuallyScrolling=true;
						}
						else if(Scrollable._current.type=="v")
							Scrollable._current.obj.scrollTo(null, Scrollable._current.startY + my - Scrollable._current.start, true);
						else
							Scrollable._current.obj.scrollTo(Scrollable._current.startX + mx - Scrollable._current.start, null, true);
					}
					else
						window.onmouseup();
					return Scrollable.stopEvt(e);
				};
				window.onmouseup = function(e) {
					Scrollable._current.obj.isManuallyScrolling = false;
					Scrollable._current.obj.hideBothBars();
					window.onmousemove = Scrollable._current.oldmove;
					window.onmouseup = Scrollable._current.oldup;
					Scrollable._current.obj[Scrollable._current.type].onmousedown = Scrollable.MouseHandler;
					try{ delete window.Scrollable._current; }catch(e){ window.Scrollable._current=null; }
					return Scrollable.stopEvt(e);
				};
				return Scrollable.stopEvt(e);
			},
			Deactivate : function(el) {
				if(el && el.getScrollableObj && el.getScrollableObj() && el.getScrollableObj().active==true) {
					el.style.overflow = el.getScrollableObj().oldOverflow;
					el.getScrollableObj().active = false;
					el.getScrollableObj = false;
					return true;
				}
				return false;
			},
			stopEvt : function(e) {
				if(!e)
					e = window.event;
				if(e.stopPropagation)
					e.stopPropagation();
				if(e.preventDefault)
					e.preventDefault();
				e.returnValue = false;
				return false;
			},
			parseDOM : function() {
				var c = document.getElementsByTagName("*");
				for(var x=0; x<c.length; x++) {
					if(c[x].className && c[x].className.match(/\bscrollable\b/mgi)!=null && !c[x].getScrollableObj)
						Scrollable.Activate(c[x]);
					else if(c[x] && c[x].className && c[x].className.match(/\bscrollable\b/mgi)==null && c[x].getScrollableObj && c[x].getScrollableObj() && c[x].getScrollableObj().active==true)
						Scrollable.Deactivate(c[x]);
				}
				for(var x=0; x<this.all.length; x++)
					if(this.all[x].active==true && Math.abs(this.all[x].el.scrollTop-this.all[x].offset.top)>=1 || Math.abs(this.all[x].el.scrollLeft-this.all[x].offset.left)>=1)
						this.all[x].el.scrollTo(this.all[x].el.scrollLeft, this.all[x].el.scrollTop);
			},
			initialParse : function() {
				var c = document.getElementsByTagName("*");
				for(var x=0; x<c.length; x++) {
					if(c[x].style.overflow && c[x].style.overflow.match(/(scroll|auto)/mgi)!=null && !c[x].getScrollableObj)
						Scrollable.Activate(c[x]);
				}
			},
			all : []
		};
		self.Init = function(){ this.init(); };
		self.Activate = function(el){ this.activate(el); };
		
		return self;
	})();
	Scrollable.oldWindowLoad = window.onload?window.onload:function(){};
	window.onload = function(){
		Scrollable.init();
		Scrollable.oldWindowLoad();
	};
	
	Scrollable._onMouseWheel = function(e) {
		if(!e) { e=window.event; }
		
		var el = e.target ? e.target : e.srcElement;
		var tries = 0;
		while( el && el.parentNode && !el.getScrollableObj ) {
			el = el.parentNode;
			if(el.getScrollableObj)
				break;
		}
		
		if( !el || !el.getScrollableObj )
			return true;
		
		var obj = el.getScrollableObj();
		
		var delta = 0;
		if(e.wheelDelta)	//IE/Opera
			delta = e.wheelDelta/120;
		if(navigator.userAgent.match(/\bsafari\b/mgi))	//Safari
			delta = -delta/2;
		else if(window.opera)	//Opera
			delta = -delta;
		else if(e.detail)	//mozilla
			delta = e.detail/3;
		
		var amount = Math.pow(delta*5/3,2)*4*delta/Math.abs(delta) + delta/Math.abs(delta);
		
		if(Scrollable._shiftKeyIsDown || e.shiftKey || e.ctrlKey || (window.opera && e.altKey))
			var scrolled = obj.scrollBy( obj.xsnap>2 ? (obj.xsnap*amount/Math.abs(amount)) : amount , null);
		else
			var scrolled = obj.scrollBy( null , obj.ysnap>2 ? (obj.ysnap*amount/Math.abs(amount)) : amount );
		
		if(scrolled==true)
			return Scrollable.stopEvt(e);
		else
			return true;
	};
	
	if (window.addEventListener) {
		window.addEventListener('DOMMouseScroll', function(e) {
			if(!e) e=window.event;
			return Scrollable._onMouseWheel(e);
		}, false);
	}
	Scrollable.oldWindowScroll = window.onmousewheel ? window.onmousewheel : function(){};
	Scrollable.oldDocumentScroll = document.onmousewheel ? document.onmousewheel : function(){};
	function _wheel(e) {
		if(!e) e=window.event;
		var ret = Scrollable._onMouseWheel(e);
		if(ret==true) {
			if(this==document)
				return Scrollable.oldDocumentScroll.apply(document,arguments);
			else
				return Scrollable.oldWindowScroll.apply(window,arguments);
		}
		else
			return Scrollable.stopEvt(e);
	};
	window.onmousewheel = document.onmousewheel = _wheel;
	
	Scrollable._oldWinKeyDown = window.onkeydown ? window.onkeydown : function(){};
	window.onkeydown = function(e) {
		if(!e)e=window.event;
		var key = e.keyCode?e.keyCode:e.which;
		if(key==16)
			Scrollable._shiftKeyIsDown = true;
		return Scrollable._oldWinKeyDown.apply(this,arguments);
	};
	Scrollable._oldWinKeyUp = window.onkeyup ? window.onkeyup : function(){};
	window.onkeyup = function(e) {
		if(!e)e=window.event;
		var key = e.keyCode?e.keyCode:e.which;
		if(key==16)
			Scrollable._shiftKeyIsDown = false;
		return Scrollable._oldWinKeyUp.apply(this,arguments);
	};
}