// jsscroll.js

// code to 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 Math.round(delta); //Safari Round
	}
});
// end mouse wheel support code


var jssccount = 0;

var DraggerAbstract = Class.create();
DraggerAbstract.prototype = { name: 'abstract dragger',
		initialize: function() {},
		dragInit: function(event) {},  // must be implemented by subclasses
		drag: function(event) {}, 		// must be implemented by subclass
		doDragInit: function(event) {
						
			if(this.isdrag)
				return true;
			
			this.isdrag=true;
			
			if(this.dragBinding == null)
				this.dragBinding=this.drag.bindAsEventListener(this);
			if(this.dragEndBinding == null)
				this.dragEndBinding=this.dragEnd.bindAsEventListener(this);

			Event.observe(document, 'mousemove',this.dragBinding);
			Event.observe(document, 'mouseup', this.dragEndBinding);

			return true;
		},
		calculateOffsets: function() {
			var offset=Position.positionedOffset(this.cursor);
			
			this.xinitpos=offset[0];
			this.yinitpos=offset[1];
			
			//alert(this.yinitpos);
		},
		dragEnd: function(event) {
	
			if(!this.isdrag)
				return false;
			
			Event.stopObserving(document, 'mousemove', this.dragBinding);
			Event.stopObserving(document, 'mouseup', this.dragEndBinding);

			this.drag(event);
			
			this.isdrag=false;
										
			if(this.dragEndImpl != null)
				this.dragEndImpl(event);
		}
	};


var CursorDragger = Class.create();
CursorDragger.prototype = Object.extend(new DraggerAbstract(), {
		name: 'Cursor Dragger',
		initialize: function(cursor, pane, isvertical) {
			
			if(this.mouseWheelBinding == null)
				this.mouseWheelBinding=this.mouseWheel.bindAsEventListener(this);

			Event.observe(pane, 'mousewheel', this.mouseWheelBinding);
			Event.observe(pane, 'DOMMouseScroll', this.mouseWheelBinding);
			
			this.cursor = $(cursor);
			this.pane = $(pane);
			this.isvertical = isvertical;
			
			this.isDisabled = false;
			
			this.cursor.ondrag = function() { return false; };

			if(isvertical) {
				this.yshift = this.cursor.offsetTop;
								
				if(this.pane.parentNode.offsetHeight >= this.pane.offsetHeight)
					this.isDisabled = true; 
			} else {
				this.xshift = this.cursor.offsetLeft;
				if(this.pane.parentNode.offsetWidth >= this.pane.offsetWidth)
					this.isDisabled = true;
			}
			
			if(this.isDisabled)
				this.greyOut(this.cursor.parentNode);
				
		},
		greyOut: function(node) {
		
			$(node).hide();
			
			return;
		
			var id = this.generateID();
			new Insertion.After(node,'<div id="' + id + '" style="background-color: black; z-index: 500; position: absolute;"></div>');
			Position.clone(node,id);
			this.setOpacity($(id),0.5);
			alert($(id).offsetLeft);
		},
		setOpacity: function(node,val) {
		
			node.style.filter = "alpha(opacity=" + (val * 100) + ")";
			node.style['-moz-opacity'] = val;
			node.style['-khtml-opacity'] = val;
			node.style.opacity = val;
		
		},
		generateID: function() {
			return 'jssc' + String(jssccount++) + 'id'; 
		},
		moveCursor: function() {
			
			if(this.isDisabled)
				return;
			
			this.adjustBounds();
			
			//alert(this.xshift + ' ' + this.yshift);
			
			if(!this.isvertical) 
				this.cursor.style.left = this.xshift + 'px';
			else
				this.cursor.style.top = this.yshift + 'px';
			
			
			var percent = null;
			var ypercent = null;
			
			if(!this.isvertical) 
				var percent = this.xshift / (this.cursor.parentNode.offsetWidth - this.cursor.offsetWidth);
			else
				var percent = this.yshift / (this.cursor.parentNode.offsetHeight - this.cursor.offsetHeight);
			
			this.shiftPane(percent);
			
		},
		adjustBounds: function() {
								
			var parent = this.cursor.parentNode;
				
			this.xshift = Math.max(this.xshift,0);
			this.yshift = Math.max(this.yshift,0);
			
			this.xshift = Math.min(this.xshift,parent.offsetWidth-this.cursor.offsetWidth);
			this.yshift = Math.min(this.yshift,parent.offsetHeight-this.cursor.offsetHeight);
				
		},
		mouseWheel: function(event) {

			var a = Event.wheel(event);
			Event.stop(event);
			
			if(this.isvertical)
				this.yshift -= a;
			else 
				this.xshift -= a;

			this.moveCursor();
				
			return false;
			
		},
		drag: function(event) {
		
			var xnew = Event.pointerX(event);
			var ynew = Event.pointerY(event);
			
			var xchg = xnew - this.xinitcur;
			var ychg = ynew - this.yinitcur;
						
			if(this.isvertical)
				this.yshift = this.yinitpos + ychg;
			else 
				this.xshift = this.xinitpos + xchg;
						
			if(this.isdrag) {
				
				this.moveCursor();
				
				return false;
			}
				
			return true;
		},
		jumpPlusMinus: function(isup) {
			if(this.isvertical) {
				var inc = (this.cursor.parentNode.offsetHeight * 0.0125);
				this.yshift += isup ? inc * -1 : inc;
			} else {
				var inc = (this.cursor.parentNode.offsetWidth * 0.0125);
				this.xshift += isup ? inc * -1 : inc;
			}
			
			this.moveCursor();
		},
		jumpPlus: function() {
			this.jumpPlusMinus(true);
		},
		jumpMinus: function() {
			this.jumpPlusMinus(false);
		},
		startRepeater: function(fcn,node) {

			if(node._repTimer !== null)
				return;
			
			node._repTimer = new PeriodicalExecuter( fcn , 0.008 );
						
			fcn();
			
		},
		stopRepeater: function(node) {
			
			//alert('ok');
			
			if(node._repTimer == null)
				return;
			
			node._repTimer.stop();
			
			node._repTimer = null;
		
		},
		createButton: function(button,isplus) {
			
			if(this.isDisabled) {
				this.greyOut($(button));
				return;
			}
			
			$(button)._repTimer = null;
		
			if(isplus)
				var starter = function(event) {
						this.startRepeater(this.jumpPlus.bind(this), $(button)); 
						Event.stop(event);
						return false;
					};
			else
				var starter = function(event) {
						this.startRepeater(this.jumpMinus.bind(this), $(button));
						Event.stop(event);
						return false;
					};
			
			Event.observe(button,'mousedown',starter.bindAsEventListener(this));
						
			var mover = function() { this.setRepeater(this.jumpPlus, true); };
			
			var stopper = function() {
				this.stopRepeater($(button));
			};
			
			Event.observe(button,'mouseout',stopper.bind(this));
			Event.observe(button,'mouseup',stopper.bind(this));
			Event.observe(document,'mouseup',stopper.bind(this));

			
			$(button).style.cursor = "pointer";

		},
		dragInit: function(event) {
			
			this.xinitcur=Event.pointerX(event);
			this.yinitcur=Event.pointerY(event);
	
			if(!Position.within(this.cursor.parentNode,this.xinitcur,this.yinitcur) &&
					!Position.within(this.cursor,this.xinitcur,this.yinitcur)) {
				return false;
			}						

			this.calculateOffsets();
			
			if(!Position.within(this.cursor,this.xinitcur,this.yinitcur)) {
				this.isdrag=true;
				this.drag(event);
				this.isdrag=false;
			}
			
			this.doDragInit(event);
			
			return true;
		},
		shiftPane: function(percent) {
			
			if(this.isvertical)
				var diff = this.pane.offsetHeight - this.pane.parentNode.offsetHeight;
			else
				var diff = this.pane.offsetWidth - this.pane.parentNode.offsetWidth;
						
			if(this.isvertical)
				this.pane.style.top = (-1 * diff * percent) + 'px';
			else
				this.pane.style.left = (-1 * diff * percent) + 'px';
				
			
			
		}
		
		
});

var mouseDelegator = { name: 'mouse delegator',
		initialize: function() {
			this.delegates = new Array();
		
		},
		add: function(elem) {
			this.delegates[this.delegates.length] = $(elem);
		},
		callDelegates: function(event) {
			var res = this.delegates.collect(function(elem) {
					return elem.dragInit(event); });
			return !res.any();
		}
	};

