Function.prototype.debounce = function (threshold, execAsap) {
    var func = this, // reference to original function
        timeout; // handle to setTimeout async task (detection period)
    // return the new debounced function which executes the original function only once
    // until the detection period expires
    return function debounced () {
        var obj = this, // reference to original context object
            args = arguments; // arguments at execution time
        // this is the detection function. it will be executed if/when the threshold expires
        function delayed () {
            // if we're executing at the end of the detection period
            if (!execAsap)
                func.apply(obj, args); // execute now
            // clear timeout handle
            timeout = null; 
        };
        // stop any current detection period
        if (timeout)
            clearTimeout(timeout);
        // otherwise, if we're not already waiting and we're executing at the beginning of the waiting period
        else if (execAsap)
            func.apply(obj, args); // execute now
        // reset the waiting period
        timeout = setTimeout(delayed, threshold || 100); 
    };
}
startArticlesScrolling = function() {
	document.getElementsByClassName('makeScroll').each(makeScrollable);
};
makeScrollable = function(el){
	putInDiv(el);
	scrollDown(el);
	pauseOnMouseOver(el);
};
pauseOnMouseOver = function(el){
	Event.observe(el,'mouseover',stopEffect.debounce(100,false));
	Event.observe(el,'mouseout',startEffect.debounce(100,false));
};
stopEffect = function(){
	if(lastScrollerEffect.animating) {
		e = lastScrollerEffect.effect;
		lastScrollerEffect.effect.cancel();
		lastScrollerEffect.animating=false;
	}
};
startEffect = function(){
	if(!lastScrollerEffect.animating) {
		var f = lastScrollerEffect.up ? scrollUp : scrollDown;
		f(lastScrollerEffect.effect.element);
	}
};

putInDiv = function(el) {
	var div = document.createElement("div");
	var children = [];
	for(var a = 0 ; a<el.childNodes.length ; a++){
		children[a] = el.childNodes[a];
	}
	for(var a = 0 ; a<children.length ; a++){
		el.removeChild(children[a]);
		div.appendChild(children[a]);
	}
	el.appendChild(div);
};
var lastScrollerEffect = {animating: false, effect: null, up: false};
scrollUp = function(el) {
	lastScrollerEffect.effect = new Effect.ScrollClient(el,{ rate: 20, afterFinish: function(){
		scrollDown(el);
	}});
	lastScrollerEffect.animating=true;
	lastScrollerEffect.up=true;
};
scrollDown = function(el){
	lastScrollerEffect.effect = new Effect.ScrollClient(el,{ rate:20, to:0,
	afterFinish: function(){
		scrollUp(el);
	}});
	lastScrollerEffect.animating=true;
	lastScrollerEffect.up=false;
};
Effect.ScrollClient = Class.create();
Object.extend(Object.extend(Effect.ScrollClient.prototype, Effect.Base.prototype), {
  initialize: function(element) {
    this.element = $(element);
    var visibleHeight=this.element.getHeight();
    var childHeight = 0;
    for(var a = 0 ; a<this.element.childNodes.length ; a++){
    	var el = $(this.element.childNodes[a]);


	childHeight += el.getHeight();
    }
    options =	Object.extend({
		from:this.element.scrollTop,
		to:childHeight-visibleHeight,
		rate:10,
		delay: 1
		}, arguments[1] || {});
    options.duration = (options.to-options.from)/options.rate;
    if(options.duration<0) options.duration=-options.duration;
    this.start(options);
  },
  setup: function() {
    Position.prepare();
    this.scrollStart = this.options.from;
    this.delta = this.options.to-this.scrollStart;
  },
  update: function(position) {
    this.lastPosition=position;
    Position.prepare();
    //this.element.scrollTo(0,this.scrollStart+(position*this.delta));
    this.element.scrollTo(0,position);
  }
});

Event.observe(window,'load',startArticlesScrolling,false);

Element.addMethods({
  scrollTo: function(element, left, top){
    var element = $(element);
    if (arguments.length == 1){
      var pos = element.cumulativeOffset();
      window.scrollTo(pos[0], pos[1]);
    } else {
      element.scrollLeft = left;
      element.scrollTop  = top;
    }
    return element;
  }
});

