/* Copyright (c) 2007 Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * $LastChangedDate$
 * $Rev$
 */

(function($){$.ScrollWindow=function(element,settings,callbacks){var _self=this;this.settings=$.extend({relativeLinks:true,theme:'',id:'',monitor:true,autoEnable:true,scrollIncrement:12,mouseWheel:true,sliderMinHeight:20},settings||{});this.callbacks=$.extend({scroll:null,enable:null,disable:null,refresh:null,monitor:null,drag:null,mousewheel:null},callbacks||{});this.el=element;this.$el=$(element);this.$window=this.$el.wrap('<div id="'+this.settings.id+'" class="swWindow '+this.settings.theme+'">').parent();this.$content=this.$el.attr('id','').addClass('swContent');this.$track=$('<div class="swTrack">').appendTo(this.$window);this.$arrowUp=$('<div class="swArrowUp">').appendTo(this.$window);this.$arrowDown=$('<div class="swArrowDown">').appendTo(this.$window);this.$slider=$('<div class="swSlider">').appendTo(this.$track);this.$sliderWrap=$('<div class="swSliderWrap">').appendTo(this.$slider);this.$sliderTop=$('<div class="swSliderTop">').appendTo(this.$sliderWrap);this.$sliderMiddle=$('<div class="swSliderMiddle">').appendTo(this.$sliderWrap);this.$sliderBottom=$('<div class="swSliderBottom">').appendTo(this.$sliderWrap);$.extend(this,{version:0.1,monitorTimer:null,currentHeight:null,arrowTimeout:null,arrowTimer:null,trackTimeout:null,trackTimer:null,direction:null,currentArrowInc:null,lastMouseY:null,trackMousePos:null,dragMouseOffset:null,contentPixels:null,sliderPixels:null,addEvents:function(){$('.swArrowUp, .swArrowDown',_self.$window).bind('mouseover',_self.onArrowMouseOver).bind('mouseout',_self.onArrowMouseOut).bind('mousedown',_self.onArrowMouseDown).bind('mouseup',_self.onArrowMouseUp);_self.$slider.bind('mouseover',_self.onSliderMouseOver).bind('mouseout',_self.onSliderMouseOut).bind('mousedown',_self.onSliderMouseDown).bind('mouseup',_self.onSliderMouseUp);_self.$track.bind('mouseout',_self.onTrackMouseUp).bind('mousedown',_self.onTrackMouseDown).bind('mouseup',_self.onTrackMouseUp);if(_self.settings.mouseWheel&&jQuery.fn.mousewheel)_self.$window.mousewheel(_self.onMouseWheel,false);},removeEvents:function(){$('.swArrowUp, .swArrowDown',_self.$window).unbind('mouseover',_self.onArrowMouseOver).unbind('mouseout',_self.onArrowMouseOut).unbind('mousedown',_self.onArrowMouseDown).unbind('mouseup',_self.onArrowMouseUp);_self.$slider.unbind('mouseover',_self.onSliderMouseOver).unbind('mouseout',_self.onSliderMouseOut).unbind('mousedown',_self.onSliderMouseDown).unbind('mouseup',_self.onSliderMouseUp);_self.$track.unbind('mouseout',_self.onTrackMouseUp).unbind('mousedown',_self.onTrackMouseDown).unbind('mouseup',_self.onTrackMouseUp);if(_self.settings.mouseWheel&&jQuery.fn.mousewheel)_self.$window.unmousewheel(_self.onMouseWheel);},ignore:function(){return false;},onArrowMouseOver:function(){if(_self.dragMouseOffset)return;var $el=$(this);if($el.is('.swArrowUp'))$el.addClass('swArrowUp-over');else if($el.is('.swArrowDown'))$el.addClass('swArrowDown-over');},onArrowMouseOut:function(){var $el=$(this);if($el.is('.swArrowUp'))$el.removeClass('swArrowUp-over');else if($el.is('.swArrowDown'))$el.removeClass('swArrowDown-over');_self.onArrowMouseUp.apply(this);},onArrowMouseDown:function(){if(_self.settings.monitor)_self.unmonitor();var $el=$(this);$('body').bind('mouseup',_self.onArrowMouseUp).bind('mouseout',_self.onArrowMouseUp);if($el.is('.swArrowUp')){_self.direction=-1;$el.addClass('swArrowUp-active');}else if($el.is('.swArrowDown')){_self.direction=1;$el.addClass('swArrowDown-active');}_self.currentArrowInc=0;_self.whileArrowActive();_self.arrowTimeout=window.setTimeout(function(){_self.arrowTimer=window.setInterval(_self.whileArrowActive,100);},250);return false;},onArrowMouseUp:function(){if(_self.settings.monitor)_self.monitor();if(_self.dragMouseOffset)return;var $el=$(this);$('body').unbind('mouseup',_self.onArrowMouseUp).unbind('mouseout',_self.onArrowMouseUp);if(_self.arrowTimeout)window.clearTimeout(_self.arrowTimeout);if(_self.arrowTimer)window.clearInterval(_self.arrowTimer);if($el.is('.swArrowUp'))$el.removeClass('swArrowUp-active');else if($el.is('.swArrowDown'))$el.removeClass('swArrowDown-active');},whileArrowActive:function(){var top=Math.abs(parseFloat(_self.$content.css('top')))||0,increment=(_self.settings.scrollIncrement+(_self.settings.scrollIncrement*(_self.currentArrowInc/10)));_self.jumpTo(top+(increment*_self.direction));_self.currentArrowInc++;},onSliderMouseOver:function(){_self.$slider.addClass('swSlider-over');},onSliderMouseOut:function(){_self.$slider.removeClass('swSlider-over');},onSliderMouseDown:function(event){if(_self.settings.monitor)_self.unmonitor();_self.$slider.addClass('swSlider-active');var sliderTop=parseFloat(_self.$slider.css('top'));_self.lastMouseY=event.pageY;_self.dragMouseOffset=_self.lastMouseY-(_self.$track.offset().top+sliderTop);$('body').bind('mouseup',_self.onSliderMouseUp).bind('mousemove',_self.onDrag);if($.browser.msie)$('body').bind('dragstart',_self.ignore).bind('selectstart',_self.ignore);return false;},onSliderMouseUp:function(){if(_self.settings.monitor)_self.monitor();_self.dragMouseOffset=null;_self.$slider.removeClass('swSlider-active');$('body').unbind('mouseup',_self.onSliderMouseUp).unbind('mousemove',_self.onDrag);if($.browser.msie)$('body').unbind('dragstart',_self.ignore).unbind('selectstart',_self.ignore);},onDrag:function(event){if(_self.callbacks.drag&&_self.callbacks.drag()===false)return;var sliderTop=parseFloat(_self.$slider.css('top'))||0,y=sliderTop+(event.pageY-_self.lastMouseY),to=Math.min(Math.max(y,0),(_self.$track.height()-_self.$slider.height()));_self.$slider.css('top',to);_self.$content.css('top',to*_self.contentPixels*-1);if(y>to||y<to)return false;_self.lastMouseY=event.pageY;return false;},onTrackMouseDown:function(event){if(_self.settings.monitor)_self.unmonitor();_self.trackMousePos=event.pageY-_self.$track.offset().top;$('body').bind('mouseup',_self.onTrackMouseUp).bind('mouseout',_self.onTrackMouseUp);_self.whileTrackActive();_self.trackTimeout=setTimeout(function(){_self.trackTimer=setInterval(_self.whileTrackActive,100);},250);return false;},onTrackMouseUp:function(){if(_self.settings.monitor)_self.monitor();if(_self.dragMouseOffset)return;if(_self.trackTimeout)clearTimeout(_self.trackTimeout);if(_self.trackTimer)clearInterval(_self.trackTimer);$('body').unbind('mouseup',_self.onTrackMouseUp).unbind('mouseout',_self.onTrackMouseUp);},whileTrackActive:function(){var sliderTop=parseFloat(_self.$slider.css('top'))||0,to;if(sliderTop>_self.trackMousePos)to=sliderTop-_self.$slider.height();else if(sliderTop<_self.trackMousePos)to=sliderTop+_self.$slider.height();else _self.onTrackMouseUp();to=Math.min(Math.max(to,0),(_self.$track.height()-_self.$slider.height()));_self.$slider.css('top',to);_self.$content.css('top',to*_self.contentPixels*-1);},onMouseWheel:function(event,delta){if(_self.callbacks.mousewheel&&_self.callbacks.mousewheel()===false)return;var top=Math.abs(parseFloat(_self.$content.css('top')))||0;_self.jumpTo(top+((_self.settings.scrollIncrement*2)*(delta*-1)));if(top!=Math.abs(parseFloat(_self.$content.css('top')))){event.preventDefault();event.stopPropagation();}else if($(this).parents().filter('[_mwHandler]').length)event.preventDefault();},enable:function(){if(_self.callbacks.enable&&_self.callbacks.enable()===false)return;_self.$window.removeClass('disabled');_self.refresh();if(_self.settings.monitor)_self.monitor();},disable:function(){if(_self.callbacks.disable&&_self.callbacks.disable()===false)return;_self.$window.addClass('disabled');_self.removeEvents();if(_self.settings.monitor)_self.unmonitor();},refresh:function(){if(this.callbacks.refresh&&this.callbacks.refresh()===false)return;if(this.$content.outerHeight()>this.$window.height()){this.$window.removeClass('noScrollBar');this.$slider.height(Math.max((this.$window.height()/this.$content.outerHeight())*this.$track.height(),this.settings.sliderMinHeight));this.$sliderMiddle.css('top',((this.$slider.height()/2)-(this.$sliderMiddle.height()/2)));this.$sliderMiddle.height(this.$slider.height()-14);this.contentPixels=(this.$content.outerHeight()-this.$window.outerHeight())/(this.$track.height()-this.$slider.height());this.sliderPixels=(this.$track.height()-this.$slider.height())/(this.$content.outerHeight()-this.$window.height());this.addEvents();if(this.settings.relativeLinks)this.setupRelativeLinks();}else{this.$window.addClass('noScrollBar');this.removeEvents();}},monitor:function(){if(!_self.monitorTimer){rate=(_self.settings.monitor==Number)?_self.settings.monitor:250;_self.currentHeight=_self.$content.outerHeight();_self.monitorTimer=setInterval(_self.monitor,rate);_self.monitor();}else{if(_self.callbacks.monitor&&_self.callbacks.monitor()===false)return;if(_self.currentHeight!=_self.$content.outerHeight()){_self.currentHeight=_self.$content.outerHeight();_self.refresh();}}},unmonitor:function(){clearInterval(this.monitorTimer);},setupRelativeLinks:function(context){$('a[href^="#"]',context||this.$content).each(function(){if(this._relativeSetup)return;if(this.hash.length>1){this._relativeSetup=true;$(this).bind('click',function(){element=$(this.hash+', a[name='+this.href.split("#")[1]+']')[0];if(element)_self.jumpTo(element);return false;});}});},jumpTo:function(to){if(this.$window.is('.noScrollBar'))return;if(typeof to!='number')to=($(to).offset().top-this.$window.offset().top);to=Math.min(Math.max(to,0),(this.$content.outerHeight()-this.$window.height()));this.$content.css('top',to*-1);this.$slider.css('top',to*this.sliderPixels);}});$.each(("append,prepend,html,empty").split(","),function(i,o){_self[o]=function(html){_self.$content[o](html);_self.refresh();};});if(this.settings.autoEnable)this.enable();return this;};$.fn.scrollWindow=function(settings,callbacks){return new $.ScrollWindow(this[0],settings,callbacks);};})(jQuery);
