// This script was created by Talon Designs Inc. 2008
// http://www.talon-designs.com

// The code contained in this script is copyright and cannot be used in full or
// part without the express written permission from Talon Designs Inc.

// NOTE:
// There may be an error with sizing/scrolling/positioning when using both
// horizontal and vertical scroll bars on the same scroller AND using AutoScale.
// The scrollbars may or may not show up and your content may get cut off.
// If this does happen, the fix needs to be applied in the VerticalRatioCalcs()
// and HorizontalRatioCalcs() functions.

TDScroller = function(ScrollerObj) {
	var self = this;
  
	var clicked = {};
	var ScrollBarV = false;
	var ScrollTrackV = false;
	var TrackSliderV = false;
	var Viewport = {};
	var AttachTop = false;
	var AttachBottom = false;
	var Content = {};
	var ScrollerScale = -1;		// tri-state variable to determine if scroller needs to be rescaled (-1 = not set, 0 = do not autoscale, 1 = autoscale)
	this.Anchors = {};		// public variable
	this.Tween = false;		// public variable - is tweening on of off?
	this.AutoScale = true;  // public variable - expands the content area when scroll bar is hidden
  
	var ScrollDistance = 10;	// distance to scroll in a single click
	var ScrollSpeed = 20;		// repeat interval when the mouse button is held down
	var Viewpoint = {};		// point of content to draw at viewport top
	var RatioV = 0;			// determines the size of the slider
	var Ratio2V = 0;			// determines where the slider is placed in relation to the contents
	var Timer;				// timer object to repeat when mouse button is held down
	var Tweening = false;
	var TweenStep = 0;
	var ClickPoint;   		// click spot for drag drop of the slider
  
	this.onMouseDown = function(){};
	this.onMouseUp = function(){};
	
	var ViewportBase = {};      // variable to hold the base size of the viewport
  
	function init() {
		if (GetIEVersion() >= 5.5 && GetIEVersion() < 7) {
			Viewport = FindComponent(ScrollerObj, "TDViewport");
			Content = FindComponent(Viewport, "TDContent");
			ScrollerObj.innerHTML = Content.innerHTML;
			ScrollerObj.style.overflow = "auto";
		} else {
			Viewpoint.X = 0;
			Viewpoint.Y = 0;
			Anchors = FindComponent(ScrollerObj, "TDAnchorList");
			Viewport = FindComponent(ScrollerObj, "TDViewport");
			ViewportBase.Left = Viewport.offsetLeft;
			ViewportBase.Right = Viewport.offsetParent.offsetWidth - (Viewport.offsetLeft + Viewport.offsetWidth);
			Content = FindComponent(Viewport, "TDContent");
			ScrollBarV = FindComponent(ScrollerObj, "TDScrollBarV");
			if (ScrollBarV) initVertical();
			
			AddEvent(ScrollerObj, "mousedown", MouseDownPrimer);
			AddEvent(Content, "mousewheel", ScrollWheel);
		
			Scroll();
		}
	};
  
	function initVertical() {
		ScrollTrackV = FindComponent(ScrollBarV, "TDScrollTrackV");
		TrackSliderV = FindComponent(ScrollTrackV, "TDScrollSliderV");
		AttachTop = FindComponent(ScrollTrackV, "TDScrollAttachTop");
		AttachBottom = FindComponent(ScrollTrackV, "TDScrollAttachBottom");
		VerticalRatioCalcs();
	};
	
	function VerticalRatioCalcs() {
		if (Content.offsetHeight == 0) {
			RatioV = 1;
			Ratio2V = 1;
		} else {
			if ((TrackSliderV.offsetHeight && TrackSliderV.offsetHeight <= 4 && ScrollerScale == -1) || (ScrollerScale == 1)) {
				RatioV = Viewport.offsetHeight / Content.offsetHeight;
				Ratio2V = ScrollTrackV.offsetHeight / Content.offsetHeight;
				if (RatioV < 1) TrackSliderV.style.height = Math.floor(ScrollTrackV.offsetHeight * RatioV) + "px";
				if (ScrollerScale == -1) ScrollerScale = 1;
			} else {
				RatioV = Viewport.offsetHeight / Content.offsetHeight;
				
				if (Content.offsetHeight - Viewport.offsetHeight == 0) 
					Ratio2V = 1;
				else
					Ratio2V = (ScrollTrackV.offsetHeight - TrackSliderV.offsetHeight) / (Content.offsetHeight - Viewport.offsetHeight);
					
				if (ScrollerScale == -1) ScrollerScale = 0;
			}
		}

		if (RatioV >= 1) {
		    ScrollBarV.style.visibility = "hidden";
			//Viewpoint.Y = 0;
			Content.style.top = "0px";
		    if (self.AutoScale == true) {
				Viewport.style.left = "0px";
				Viewport.style.right = "0px";
		    }
		} else {
			ScrollBarV.style.visibility = "visible";
			if (self.AutoScale == true) {
				Viewport.style.left = ViewportBase.Left + "px";
				Viewport.style.right = ViewportBase.Right + "px";
				if (ScrollBarV.offsetLeft < Viewport.offsetLeft) Viewport.style.left = (Viewport.offsetLeft + ScrollBarV.offsetWidth) + "px";
				Scroll();
			}
		}
	};
  	
	this.Rescale = function() {
		if (ScrollBarV) VerticalRatioCalcs();
	};
  
// searches the content for any <h3> tags to create a hyperlink list
// uses the TDAnchorStyle to style the link list for external styling
// the separator variable allows the user to decide how to separate each entry
// ex: <hr> would put a horizontal rule between each one, &nbsp; would add a blank space, etc.
	this.FillAnchorList = function(ctrlName, separator) {
		var tags = Content.getElementsByTagName("h3");
	    var offset = {};
		var adj = {};
		
		adj.X = 0;
		adj.Y = 0;
		
		if (tags) {
			for (var x = 0; x < tags.length; x++) {
				offset = FindElementOffset(tags[x], "TDContent");
				if (ScrollBarV) {
					adj.X = offset.X
					adj.Y = offset.X
				}
				Anchors.innerHTML += "<a href=\"javascript:" + ctrlName + ".ScrollTo(" + (offset.X - adj.X) + ", " + (offset.Y - adj.Y) + ")\"><span class=\"TDAnchorStyle\">" + tags[x].innerHTML + "</span></a><span class=\"TDAnchorStyle\">" + separator + "</span>";
			}
		}
	};
  
	function MouseDownPrimer(e) {
		e = e?e:event;   // if e, e = e, else,  e = event     // still not sure what this is here for
		if (!e.target) e.target = e.srcElement;   // if the event doesn't have a target, set the target to the source element
		clicked = e.target;   // store the target of the event to use with the mouse up event
		MouseDown(e.target.className, e);
	};
  
	function MouseDown(classObj, eventObj) {
		var ClickSpot = 0;
		var Rclick;
		var ClickObjName = "";
	
		// check for rightclick
		if (eventObj.which) Rclick = (eventObj.which == 3);
		else if (eventObj.button) Rclick = (eventObj.button == 2);
	
		if (!Rclick) {
			AddEvent(document, "mouseup", ScrollEnd);
			if (eventObj.target.className){
				if (eventObj.target.className == "TDFixPNG")
					ClickObjName = eventObj.target.offsetParent.className;
				else
					ClickObjName = eventObj.target.className;

				if (ClickObjName.indexOf("TDScrollUp") > -1){
					document.onselectstart = function (){ return false; };
					ScrollStart(0, -ScrollDistance);
					self.onMouseDown(eventObj.target, classObj, eventObj);
				} else if (ClickObjName.indexOf("TDScrollDown") > -1){
					document.onselectstart = function (){ return false; };
					ScrollStart(0, ScrollDistance);
					self.onMouseDown(eventObj.target, classObj, eventObj);
				} else if (ClickObjName.indexOf("TDScrollTrackV") > -1){
					ClickSpot = GetClickPoint(eventObj);
					document.onselectstart = function (){ return false; };
					self.ScrollTo(Viewpoint.X, (ClickSpot.Y - (TrackSliderV.offsetHeight / 2)) / Ratio2V);
					self.onMouseDown(eventObj.target, classObj, eventObj);
				} else if (ClickObjName.indexOf("TDScrollAttachTop") > -1 || ClickObjName.indexOf("TDScrollAttachBottom") > -1 ){
					ClickSpot = GetClickPoint(eventObj);
					document.onselectstart = function (){ return false; };
					self.ScrollTo(Viewpoint.X, (ClickSpot.Y - (TrackSliderV.offsetHeight / 2)) / Ratio2V);
					self.onMouseDown(eventObj.target, classObj, eventObj);
					PreventImgDrag(eventObj);
				} else if (ClickObjName.indexOf("TDScrollSliderV") > -1){
					ClickSpot = GetClickPoint(eventObj);
					document.onselectstart = function (){ return false; };
					ClickPoint = eventObj.clientY;
					AddEvent(document, "mousemove", DragBarV);
					self.onMouseDown(eventObj.target, classObj, eventObj);
					PreventImgDrag(eventObj);
				}
			}
		}
	};

	function ScrollStart(Hdist, Vdist) {
		if (Timer) window.clearInterval(Timer);
		Timer = window.setInterval(function() { ScrollBy(Hdist, Vdist); }, ScrollSpeed);
	};
  
	function ScrollEnd(e) {
		document.onselectstart = function (){ return true; };
		e = e?e:event;   // if e, e = e, else,  e = event
    
		RemoveEvent(document, "mouseup", ScrollEnd);
		RemoveEvent(document, "mousemove", DragBarV);
	
		if (!Tweening) if (Timer) window.clearInterval(Timer);
	
		self.onMouseUp(clicked, clicked.className, e);
	};
  
	function ScrollWheel(e) {
		var dist = 0;
		e = e?e:event;	// if e, e = e, else,  e = event
	
		if (e.wheelDelta >= 120) dist = -ScrollDistance;
		if (e.wheelDelta <= -120) dist = ScrollDistance;
	
		ScrollBy(0, dist);
	
		e.returnValue = false;
	};
  
	function DragBarV(e) {
		e = e?e:event;   // if e, e = e, else,  e = event
		ScrollBy(0, (e.clientY - ClickPoint) / Ratio2V);
		ClickPoint = e.clientY;
	};
  
	function ScrollBy(Hdist, Vdist) {
		Viewpoint.X += Hdist;
		Viewpoint.Y += Vdist;
		Scroll();
	};
  
	this.ScrollTo = function(Xpoint, Ypoint) {
		var steps = [];

		if (self.Tween) {
			if (Timer) window.clearInterval(Timer);

			if (Viewpoint.X == Xpoint) {
				steps = Tween(Ypoint - Viewpoint.Y);
				TweenStep = 0;
				Tweening = true;
				Timer = window.setInterval( function () {
					Viewpoint.Y += steps[TweenStep];
					Scroll();
					if (TweenStep == steps.length - 1) {
						Viewpoint.Y = Ypoint;
						Scroll();
						Tweening = false;
						window.clearInterval(Timer);
					} else {
						TweenStep++;
					}
				}, ScrollSpeed);
			} else {
				steps = Tween(Xpoint - Viewpoint.X);
				TweenStep = 0;
				Tweening = true;
				Timer = window.setInterval( function () {
					Viewpoint.X += steps[TweenStep];
					Scroll();
					if (TweenStep == steps.length - 1) {
						Viewpoint.X = Xpoint;
						Scroll();
						Tweening = false;
						window.clearInterval(Timer);
					} else {
						TweenStep++;
					}
				}, ScrollSpeed);
			}
		} else {
			Viewpoint.X = Xpoint;
			Viewpoint.Y = Ypoint;
			Scroll();
		}
	};
  
	function Scroll() {
		if (Viewpoint.X > Content.offsetWidth - Viewport.offsetWidth) Viewpoint.X = Content.offsetWidth - Viewport.offsetWidth;
		if (Viewpoint.Y > Content.offsetHeight - Viewport.offsetHeight) Viewpoint.Y = Content.offsetHeight - Viewport.offsetHeight;
	
		if (Viewpoint.X < 0) Viewpoint.X = 0;
		if (Viewpoint.Y < 0) Viewpoint.Y = 0;

		if (ScrollBarV) {
			if (Math.ceil(Viewpoint.Y * Ratio2V) < (ScrollTrackV.offsetHeight - TrackSliderV.offsetHeight))
				TrackSliderV.style.top = Math.ceil(Viewpoint.Y * Ratio2V) + "px";
			else
				TrackSliderV.style.top = (ScrollTrackV.offsetHeight - TrackSliderV.offsetHeight) + "px";
		}
			
	
		if (AttachTop) AttachTop.style.top = (TrackSliderV.offsetTop - AttachTop.offsetHeight) + "px";
		if (AttachBottom) AttachBottom.style.top = (TrackSliderV.offsetTop + TrackSliderV.offsetHeight) + "px";
	
		Content.style.top = -Viewpoint.Y + "px";
		Content.style.left = -Viewpoint.X + "px";
	};

	function Tween(Distance) {
		var Steps = [0, 10, 15, 20, 15, 10, 5, 5, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1];
		var Values = [];

		for (var x = 0; x < Steps.length; x++) {
			Values[x] = Math.ceil(Distance * (Steps[x] / 100));
		}

		return Values;
	};
  
	init();
};