var ScrollBox = Class.create();

/**
 *	OPTION CONTSTANTS
 */

// bar_action: what happens when you click on the blank part of the scrollbar?
//		pass this in when creating a ScrollBox or change in the default object set
//		found in the initialze method to change the default behavior
ScrollBox.NO_ACTION		= 0;	//Do nothing
ScrollBox.PAGE_ACTION	= 1;	//Jump forward or back one full page
ScrollBox.JUMP_ACTION	= 2;	//Jump to the position on the bar that was clicked

Object.extend(ScrollBox.prototype, {
	initialize: function(element, options){
		
		this.element = element;
		Element.addClassName(this.element, 'scrollbox');
		
		this.opts = {
			scroll_increment: 30,				//How many pixels to scroll per click/button press/etc
			hold_delay: 500,					//The delay when holding the mouse down before it starts auto scrolling
			hold_interval: 100,					//The interval between auto scroll increments
			drag_interval: 100,					//How often the display is updated while dragging the handle
			update_check_interval: 100,			//How often to run integrity check and make sure the scrollbar is up to date
			auto_hide: false,					//Does the scrollbar hide when the content is too short for scrolling?
			bar_action: ScrollBox.PAGE_ACTION	//What happens when you click the empty part of the scrollbar?
		};
		Object.extend(this.opts, options);
		
		//Move content into content div
		this.content_div = document.createElement('div');
		Element.addClassName(this.content_div, 'scrollbox_content');
		$A(this.element.childNodes).each(function(n){ this.content_div.appendChild(n);}.bind(this));
		this.element.appendChild(this.content_div);
		this.content_div.style.overflow = 'hidden';
		this.content_div.style.height = '100%';

		//Add scrollbar div to element
		this.scrollbar = document.createElement('div');
		Element.addClassName(this.scrollbar, 'scrollbox_scrollbar');
		this.element.appendChild(this.scrollbar);
		this.scrollbar.style.position = 'absolute';
		this.scrollbar.style.top = '0';
		this.scrollbar.style.right = '0';
		
		//Add up button
		this.up_button = document.createElement('div');
		Element.addClassName(this.up_button, 'scrollbox_up_button');
		this.up_button.style.position = 'absolute';
		this.up_button.style.width = '100%';
		this.up_button.style.top = '0';
		this.up_button.style.right = '0';
		this.scrollbar.appendChild(this.up_button);
		
		//Add down button
		this.down_button = document.createElement('div');
		Element.addClassName(this.down_button, 'scrollbox_down_button');
		this.down_button.style.position = 'absolute';
		this.down_button.style.width = '100%';
		this.down_button.style.bottom = '0';
		this.down_button.style.right = '0';
		this.scrollbar.appendChild(this.down_button);
		
		//Add Scroll Handle
		this.handle = document.createElement('div');
		Element.addClassName(this.handle, 'scrollbox_handle');
		this.handle.style.position = 'absolute';
		this.handle.style.width = '100%';
		this.handle.style.right = '0';
		this.scrollbar.appendChild(this.handle);

		//Setup State Info
		this.scroll_pos = 0;
		this.setSizes();
		
		//buttons actions
		Event.observe(this.up_button, 'mousedown', function(e){this.buttonDown(e, this.scrollUp.bind(this));}.bindAsEventListener(this));
		Event.observe(this.down_button, 'mousedown', function(e){this.buttonDown(e, this.scrollDown.bind(this));}.bindAsEventListener(this));
		Event.observe(document, 'mouseup', this.buttonUp.bindAsEventListener(this));
		
		//handle actions
		Event.observe(document, 'mousemove', this.setMousePos.bindAsEventListener(this));
		Event.observe(this.handle, 'mousedown', this.handleDown.bindAsEventListener(this));
		this.handle_update_interval = setInterval(this.updateCheck.bind(this), this.opts.update_check_interval);
		
		//bar actions
		Event.observe(this.up_button, 'click', function(e){Event.stop(e);}.bindAsEventListener(this));
		Event.observe(this.down_button, 'click', function(e){Event.stop(e);}.bindAsEventListener(this));
		Event.observe(this.handle, 'click', function(e){Event.stop(e);}.bindAsEventListener(this));
		Event.observe(this.scrollbar, 'click', this.scrollBarClick.bindAsEventListener(this));
		
		//handle keypress events
		this.keyboard_events = [
			[document, 'keypress', this.keyboardEvent.bindAsEventListener(this)]
		];
		Event.observe(this.element, 'click', this.enableKeyboardEvents.bindAsEventListener(this));
		Event.observe(document, 'click', this.disableKeyboardEvents.bindAsEventListener(this));
		
		//handle scroll wheel
		Event.observe(this.content_div, 'mousewheel', this.scrollWheel.bindAsEventListener(this), true);
		Event.observe(this.content_div, 'DOMMouseScroll', this.scrollWheel.bindAsEventListener(this), true);
		
	},
	scrollDown: function(){
		if(this.scroll_pos  < this.scroll_max){
			this.scrollTo(this.scroll_pos + this.opts.scroll_increment < this.scroll_max ? this.scroll_pos + this.opts.scroll_increment : this.scroll_max);
			return true;
		}
		else{
			return false;
		}
	},
	scrollUp: function(){
		if(this.scroll_pos > 0){
			this.scrollTo(this.scroll_pos > this.opts.scroll_increment ? this.scroll_pos - this.opts.scroll_increment : 0);
			return true;
		}
		else{
			return false;
		}
	},
	scrollTo: function(new_pos){
		// console.log(new_pos, this.content_div);
		if(new_pos < 0){
			new_pos = 0;
		}
		if(new_pos > this.scroll_max){
			new_pos = this.scroll_max;
		}
		this.content_div.scrollTop = new_pos;
		this.scroll_pos = new_pos;
		this.updateHandle();
	},
	buttonDown: function(event, action){
		action();
		this.timeout = setTimeout(function(){
			action();
			this.timeout = null;
			if(this.interval){ clearInterval(this.interval);}
			this.interval = setInterval(action, this.opts.hold_interval);
		}.bind(this), this.opts.hold_delay);
		Event.stop(event);
	},
	buttonUp: function(event){
		if(this.timeout){
			clearTimeout(this.timeout);
		}
		if(this.interval){
			clearInterval(this.interval);
		}
		this.timeout = null;
		this.interval = null;
		this.down_position = null;
	},
	updateHandle: function(){
		if(this.scroll_max){
			this.handle_height = Math.floor(this.bar_height / this.scroll_height_ratio);
		}
		else{
			this.handle_height = this.bar_height;
		}
		
		if(this.opts.auto_hide){
			if(this.handle_height == this.bar_height){
				this.scrollbar.style.visibility = 'hidden';
			}
			else{
				this.scrollbar.style.visibility = '';
			}
		}

		var handle_top = this.up_button.offsetHeight;
		var handle_bottom = this.up_button.offsetHeight + (this.bar_height - this.handle_height);
		var bar_dist_height = handle_bottom - handle_top;
		if(this.scroll_max)
			this.handle_pos = handle_top + Math.floor(bar_dist_height * (this.scroll_pos / this.scroll_max));
		else
			this.handle_pos = handle_top;
		
		this.handle.style.height = this.handle_height + 'px';
		this.handle.style.top = this.handle_pos + 'px';
	},
	handleDown: function(){
		this.down_position = this.raw_mouse_pos - Position.cumulativeOffset(this.handle)[1];
		// console.log('Down at: ' , this.down_position, Position.cumulativeOffset(this.handle)[1], this.mouse_pos);
		if(this.interval){ clearInterval(this.interval);}
		this.interval = setInterval(function(){
			this.scrollTo(this.mouse_pos - (this.down_position * this.scroll_height_ratio));
		}.bindAsEventListener(this), this.opts.drag_interval);
	},
	setMousePos: function(e){
		if (document.all) { // grab the x-y pos.s if browser is IE
			tempY = event.clientY + document.body.scrollTop;
		} else {  // grab the x-y pos.s if browser is NS
			tempY = e.pageY;
		}  
		// catch possible negative values
		if (tempY < 0){tempY = 0;}  

		this.raw_mouse_pos = tempY;
		this.mouse_pos = Math.floor((tempY - this.scrollbar_top) * this.scroll_height_ratio);
	},
	setSizes: function(){
		this.scroll_max = this.content_div.scrollHeight - this.content_div.offsetHeight;
		if(this.scroll_max < 0) this.scroll_max = 0;

		if(this.scroll_pos > this.scroll_max){
			this.scrollTo(this.scroll_max);
		}

		this.bar_height = this.scrollbar.offsetHeight - (this.up_button.offsetHeight + this.down_button.offsetHeight);
		if(!this.bar_height){
			setTimeout(this.setSizes.bind(this), 100);
		}

		this.scroll_height_ratio = (this.content_div.scrollHeight / this.bar_height);
		this.scroll_height_ratio = this.scroll_height_ratio >= 1 ? this.scroll_height_ratio : 1;

		this.scrollbar_top = Position.cumulativeOffset(this.scrollbar)[1] + this.up_button.offsetHeight;
		this.scrollbar_bottom = this.scrollbar_top + this.bar_height;

		this.updateHandle();
	},
	scrollBarClick: function(event){
		switch(this.opts.bar_action){
			case ScrollBox.PAGE_ACTION:
				//clicked above the handle
				if(this.mouse_pos < this.handle_pos * this.scroll_height_ratio){
					this.pageUp();
				}
				//clicked below the handle
				else{
					this.pageDown();
				}
				break;
			case ScrollBox.JUMP_ACTION:
				this.scrollTo(this.mouse_pos);
				break;
		}
	},
	pageUp: function(){
		this.scrollTo(this.scroll_pos - this.content_div.offsetHeight);
	},
	pageDown: function(){
		this.scrollTo(this.scroll_pos + this.content_div.offsetHeight);
	},
	scrollWheel: function(event){
		var scroll_amount = Event.wheel(event);
		if(scroll_amount > 0){
			for(var i = 0; i < Math.ceil(scroll_amount); ++i){
				this.scrollUp();
			}
			if(this.scroll_pos > 0){
				Event.stop(event);
			}
		}
		else if(scroll_amount < 0){
			for(var i = 0; i > Math.floor(scroll_amount); --i){
				this.scrollDown();
			}
			if(this.scroll_pos < this.scroll_max){
				Event.stop(event);
			}
		}
	},
	updateCheck: function(){
		//Has the scroll pos been changed by something else?
		if(this.content_div.scrollTop != this.scroll_pos){
			this.scrollTo(this.content_div.scrollTop);
		}
		
		if(this.scroll_max != this.content_div.scrollHeight - this.content_div.offsetHeight){
			this.setSizes();
		}
	},
	enableKeyboardEvents: function(event){
		this.disableKeyboardEvents(event);

		this.keyboard_events.each(function(ke){
			Event.observe(ke[0], ke[1], ke[2]);
		});
		
		this.within_enable_event = true;
	},
	disableKeyboardEvents: function(event){
		if(!this.within_enable_event){
			this.keyboard_events.each(function(ke){
				Event.stopObserving(ke[0], ke[1], ke[2]);
			});
		}
		else{
			this.within_enable_event = false;
		}
	},
	keyboardEvent: function(event){
		switch(event.keyCode){
			case Event.KEY_HOME:
				this.scrollTo(0);
				break;
			case Event.KEY_END:
				this.scrollTo(this.scroll_max);
				break;
			case Event.KEY_PAGEUP:
				this.pageUp();
				break;
			case Event.KEY_PAGEDOWN:
				this.pageDown();
				break;
			case Event.KEY_UP:
				this.scrollUp();
				break;
			case Event.KEY_DOWN:
				this.scrollDown();
				break;
			default:
				return;
		}
		Event.stop(event);
	}
});

// Add mouse wheel support to prototype
Object.extend(Event, {
        wheel:function (event){
                var delta = 0;
                if (!event) event = window.event;
                if (event.wheelDelta) {
                        delta = event.wheelDelta/120;
                        if (window.opera) delta = -delta;
                } else if (event.detail) { delta = -event.detail/3;     }
                return delta; //Safari Round
        }
});

/*  slider  */

if(!Control) var Control = {};
Control.Slider = Class.create();

// options:
//  axis: 'vertical', or 'horizontal' (default)
//
// callbacks:
//  onChange(value)
//  onSlide(value)
Control.Slider.prototype = {
  initialize: function(handle, track, options) {
    var slider = this;
    
    if(handle instanceof Array) {
      this.handles = handle.collect( function(e) { return $(e) });
    } else {
      this.handles = [$(handle)];
    }
    
    this.track   = $(track);
    this.options = options || {};

    this.axis      = this.options.axis || 'horizontal';
    this.increment = this.options.increment || 1;
    this.step      = parseInt(this.options.step || '1');
    this.range     = this.options.range || $R(0,1);
    
    this.value     = 0; // assure backwards compat
    this.values    = this.handles.map( function() { return 0 });
    this.spans     = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
    this.options.startSpan = $(this.options.startSpan || null);
    this.options.endSpan   = $(this.options.endSpan || null);

    this.restricted = this.options.restricted || false;

    this.maximum   = this.options.maximum || this.range.end;
    this.minimum   = this.options.minimum || this.range.start;

    // Will be used to align the handle onto the track, if necessary
    this.alignX = parseInt(this.options.alignX || '0');
    this.alignY = parseInt(this.options.alignY || '0');
    
    this.trackLength = this.maximumOffset() - this.minimumOffset();

    this.handleLength = this.isVertical() ? 
      (this.handles[0].offsetHeight != 0 ? 
        this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) : 
      (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth : 
        this.handles[0].style.width.replace(/px$/,""));

    this.active   = false;
    this.dragging = false;
    this.disabled = false;

    if(this.options.disabled) this.setDisabled();

    // Allowed values array
    this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
    if(this.allowedValues) {
      this.minimum = this.allowedValues.min();
      this.maximum = this.allowedValues.max();
    }

    this.eventMouseDown = this.startDrag.bindAsEventListener(this);
    this.eventMouseUp   = this.endDrag.bindAsEventListener(this);
    this.eventMouseMove = this.update.bindAsEventListener(this);

    // Initialize handles in reverse (make sure first handle is active)
    this.handles.each( function(h,i) {
      i = slider.handles.length-1-i;
      slider.setValue(parseFloat(
        (slider.options.sliderValue instanceof Array ? 
          slider.options.sliderValue[i] : slider.options.sliderValue) || 
         slider.range.start), i);
      Element.makePositioned(h); // fix IE
      Event.observe(h, "mousedown", slider.eventMouseDown);
    });
    
    Event.observe(this.track, "mousedown", this.eventMouseDown);
    Event.observe(document, "mouseup", this.eventMouseUp);
    Event.observe(document, "mousemove", this.eventMouseMove);
    
    this.initialized = true;
  },
  dispose: function() {
    var slider = this;    
    Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
    Event.stopObserving(document, "mouseup", this.eventMouseUp);
    Event.stopObserving(document, "mousemove", this.eventMouseMove);
    this.handles.each( function(h) {
      Event.stopObserving(h, "mousedown", slider.eventMouseDown);
    });
  },
  setDisabled: function(){
    this.disabled = true;
  },
  setEnabled: function(){
    this.disabled = false;
  },  
  getNearestValue: function(value){
    if(this.allowedValues){
      if(value >= this.allowedValues.max()) return(this.allowedValues.max());
      if(value <= this.allowedValues.min()) return(this.allowedValues.min());
      
      var offset = Math.abs(this.allowedValues[0] - value);
      var newValue = this.allowedValues[0];
      this.allowedValues.each( function(v) {
        var currentOffset = Math.abs(v - value);
        if(currentOffset <= offset){
          newValue = v;
          offset = currentOffset;
        } 
      });
      return newValue;
    }
    if(value > this.range.end) return this.range.end;
    if(value < this.range.start) return this.range.start;
    return value;
  },
  setValue: function(sliderValue, handleIdx){
    if(!this.active) {
      this.activeHandleIdx = handleIdx || 0;
      this.activeHandle    = this.handles[this.activeHandleIdx];
      this.updateStyles();
    }
    handleIdx = handleIdx || this.activeHandleIdx || 0;
    if(this.initialized && this.restricted) {
      if((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
        sliderValue = this.values[handleIdx-1];
      if((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
        sliderValue = this.values[handleIdx+1];
    }
    sliderValue = this.getNearestValue(sliderValue);
    this.values[handleIdx] = sliderValue;
    this.value = this.values[0]; // assure backwards compat
    
    this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] = 
      this.translateToPx(sliderValue);
    
    this.drawSpans();
    if(!this.dragging || !this.event) this.updateFinished();
  },
  setValueBy: function(delta, handleIdx) {
    this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta, 
      handleIdx || this.activeHandleIdx || 0);
  },
  translateToPx: function(value) {
    return Math.round(
      ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) * 
      (value - this.range.start)) + "px";
  },
  translateToValue: function(offset) {
    return ((offset/(this.trackLength-this.handleLength) * 
      (this.range.end-this.range.start)) + this.range.start);
  },
  getRange: function(range) {
    var v = this.values.sortBy(Prototype.K); 
    range = range || 0;
    return $R(v[range],v[range+1]);
  },
  minimumOffset: function(){
    return(this.isVertical() ? this.alignY : this.alignX);
  },
  maximumOffset: function(){
    return(this.isVertical() ? 
      (this.track.offsetHeight != 0 ? this.track.offsetHeight :
        this.track.style.height.replace(/px$/,"")) - this.alignY : 
      (this.track.offsetWidth != 0 ? this.track.offsetWidth : 
        this.track.style.width.replace(/px$/,"")) - this.alignY);
  },  
  isVertical:  function(){
    return (this.axis == 'vertical');
  },
  drawSpans: function() {
    var slider = this;
    if(this.spans)
      $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
    if(this.options.startSpan)
      this.setSpan(this.options.startSpan,
        $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
    if(this.options.endSpan)
      this.setSpan(this.options.endSpan, 
        $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
  },
  setSpan: function(span, range) {
    if(this.isVertical()) {
      span.style.top = this.translateToPx(range.start);
      span.style.height = this.translateToPx(range.end - range.start + this.range.start);
    } else {
      span.style.left = this.translateToPx(range.start);
      span.style.width = this.translateToPx(range.end - range.start + this.range.start);
    }
  },
  updateStyles: function() {
    this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
    Element.addClassName(this.activeHandle, 'selected');
  },
  startDrag: function(event) {
    if(Event.isLeftClick(event)) {
      if(!this.disabled){
        this.active = true;
        
        var handle = Event.element(event);
        var pointer  = [Event.pointerX(event), Event.pointerY(event)];
        var track = handle;
        if(track==this.track) {
          var offsets  = Position.cumulativeOffset(this.track); 
          this.event = event;
          this.setValue(this.translateToValue( 
           (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
          ));
          var offsets  = Position.cumulativeOffset(this.activeHandle);
          this.offsetX = (pointer[0] - offsets[0]);
          this.offsetY = (pointer[1] - offsets[1]);
        } else {
          // find the handle (prevents issues with Safari)
          while((this.handles.indexOf(handle) == -1) && handle.parentNode) 
            handle = handle.parentNode;
        
          this.activeHandle    = handle;
          this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
          this.updateStyles();
        
          var offsets  = Position.cumulativeOffset(this.activeHandle);
          this.offsetX = (pointer[0] - offsets[0]);
          this.offsetY = (pointer[1] - offsets[1]);
        }
      }
      Event.stop(event);
    }
  },
  update: function(event) {
   if(this.active) {
      if(!this.dragging) this.dragging = true;
      this.draw(event);
      // fix AppleWebKit rendering
      if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
      Event.stop(event);
   }
  },
  draw: function(event) {
    var pointer = [Event.pointerX(event), Event.pointerY(event)];
    var offsets = Position.cumulativeOffset(this.track);
    pointer[0] -= this.offsetX + offsets[0];
    pointer[1] -= this.offsetY + offsets[1];
    this.event = event;
    this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
    if(this.initialized && this.options.onSlide)
      this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
  },
  endDrag: function(event) {
    if(this.active && this.dragging) {
      this.finishDrag(event, true);
      Event.stop(event);
    }
    this.active = false;
    this.dragging = false;
  },  
  finishDrag: function(event, success) {
    this.active = false;
    this.dragging = false;
    this.updateFinished();
  },
  updateFinished: function() {
    if(this.initialized && this.options.onChange) 
      this.options.onChange(this.values.length>1 ? this.values : this.value, this);
    this.event = null;
  }
}

/*  glider  */

Glider = Class.create();
Object.extend(Object.extend(Glider.prototype, Abstract.prototype), {
	initialize: function(wrapper, options){
	    this.scrolling  = false;
	    this.wrapper    = $(wrapper);
	    this.controls   = this.wrapper.getElementsBySelector('div.controls a');
	    this.scroller   = this.wrapper.down('div.scroller');
	    this.sections   = this.wrapper.getElementsBySelector('div.section');
	    this.options    = Object.extend({ duration: 1.0, frequency: 3, initialSection: this.controls[0].href.split('#')[1] }, options || {});

	    this.sections.each( function(section, index) {
	      section._index = index;
	    });    

	    this.events = {
	      click: this.click.bind(this)
	    };

	    this.addObservers();
			if(this.options.initialSection) this.moveTo(this.options.initialSection, this.scroller, { duration:this.options.duration });  // initialSection should be the id of the section you want to show up on load
			if(this.options.autoGlide) this.start();
	  },
	
  addObservers: function() {
    this.controls.invoke('observe', 'click', this.events.click);
  },	

  click: function(event) {
		this.stop();
    var element = Event.findElement(event, 'a');
    if (this.scrolling) this.scrolling.cancel();
    
    this.moveTo(element.href.split("#")[1], this.scroller, { duration:this.options.duration });         
     Event.stop(event);
  },

	moveTo: function(element, container, options){
			this.current = $(element);

			Position.prepare();
	    var containerOffset = Position.cumulativeOffset(container),
	     elementOffset = Position.cumulativeOffset($(element));

		  this.scrolling 	= new Effect.SmoothScroll(container, 
				{duration:options.duration, x:(elementOffset[0]-containerOffset[0]), y:(elementOffset[1]-containerOffset[1])});
				
				var currentSection = this.current.id;
        this.controls.each(function(control) {
        
        if (control.href.split('#')[1] == currentSection) {
        
        control.addClassName('active');
        } else {
        control.removeClassName('active');
        }
        });

		  return false;
		},
		
  next: function(){
    if (this.current) {
      var currentIndex = this.current._index;
      var nextIndex = (this.sections.length - 1 == currentIndex) ? 0 : currentIndex + 1;      
    } else var nextIndex = 1;

    this.moveTo(this.sections[nextIndex], this.scroller, { 
      duration: this.options.duration
    });
  },
	
  previous: function(){
    if (this.current) {
      var currentIndex = this.current._index;
      var prevIndex = (currentIndex == 0) ? this.sections.length - 1 : 
       currentIndex - 1;
    } else var prevIndex = this.sections.length - 1;
    
    this.moveTo(this.sections[prevIndex], this.scroller, { 
      duration: this.options.duration
    });
  },

	stop: function()
	{
		clearTimeout(this.timer);
	},
	
	start: function()
	{
		this.periodicallyUpdate();
	},
		
	periodicallyUpdate: function()
	{ 
		if (this.timer != null) {
			clearTimeout(this.timer);
			this.next();
		}
		this.timer = setTimeout(this.periodicallyUpdate.bind(this), this.options.frequency*1000);
	}

});

Effect.SmoothScroll = Class.create();
Object.extend(Object.extend(Effect.SmoothScroll.prototype, Effect.Base.prototype), {
  initialize: function(element) {
    this.element = $(element);
    var options = Object.extend({
      x:    0,
      y:    0,
      mode: 'absolute'
    } , arguments[1] || {}  );
    this.start(options);
  },
  setup: function() {
    if (this.options.continuous && !this.element._ext ) {
      this.element.cleanWhitespace();
      this.element._ext=true;
      this.element.appendChild(this.element.firstChild);
    }
   
    this.originalLeft=this.element.scrollLeft;
    this.originalTop=this.element.scrollTop;
   
    if(this.options.mode == 'absolute') {
      this.options.x -= this.originalLeft;
      this.options.y -= this.originalTop;
    } 
  },
  update: function(position) {   
    this.element.scrollLeft = this.options.x * position + this.originalLeft;
    this.element.scrollTop  = this.options.y * position + this.originalTop;
  }
});
