/*

SCROLLER MODULE.

FEATURES:
		1.	HORIZONTAL OR VERTICAL
		2.	OBJECT-ORIENTED
		3.	ON MOUSEOVER, SCROLLER PAUSES
		4.	EVERYTHING TAKES PLACE WITHIN JAVASCRIPT
		5.	SUPPORTS IE AND FF.

USAGE:	A. INCLUDE THIS FILE AND CCallWrapper.js.

		B. IN THE EXACT PLACE IN YOUR HTML WHERE YOU WANT THE SCROLLER, OPEN A JAVASCRIPT, AND INSIDE THERE, DO THE FOLLOWING STEPS:
		1.	var myScroller = new scroller("myScroller", orientation, context, width, height[, direction, outerpadding].
			a. ALL ARGUMENTS REQUIRED EXCEPT LAST TWO
			b. FIRST ARGUMENT TO CONSTRUCTOR MUST MATCH NAME OF var!!
			c. SECOND ARGUMENT MUST BE "v" OR "h"
			d. THIRD ARGUMENT MUST BE "iframe" OR "inline"
			e. SIXTH ARGUMENT, "ltr" (DEFAULT) OR "rtl", SHOULD BE USED FOR HEBREW SCROLLERS
			f. LAST ARGUMENT IS PADDING AROUND ENTIRE SCROLLER, AS OPPOSED TO PADDING BETWEEN EACH ITEM WITHIN SCROLLER.
		2.	A SERIES OF OPTIONAL STATEMENTS: myScroller.attribute = value TO SET THE DESIRED ATTRIBUTES (SEE DEFAULTS BELOW):
			a. fontFamily
			b. bgcolor
			c. color
			d. fontSize
			e. scrollSpeed. DEFAULT: 30. HIGHER THAN 45 SLOWS IT DOWN & STARTS TO GET BUMPY; LOWER THAN 10 HAS NO IMPACT -- THAT IS FASTEST
			f. padding between items
		3.	A SERIES OF STATEMENTS: myScroller.add("text"), TO SET THE CONTENTS OF THE SCROLLER
		4.	myScroller.draw()

		C.	IF USING IN CONTEXT OF IFRAME, THEN:
		1.	THE ABOVE SCROLLER CODE SHOULD BE THE ENTIRE CONTENT OF THE BODY, AND THE BODY SHOULD PROBABLY BE style="margin:0;"
		2.	THE CALL IN THE PARENT TO THE IFRAME SHOULD HAVE scrolling="no" frameborder="0" AND ITS WIDTH AND HEIGHT SHOULD MATCH THOSE OF THE SCROLLER.

GENERAL NOTE: IFRAME OR NOT IFRAME:
		MOST OF THE DISCUSSION THAT FOLLOWS APPLIES TO THE CASE WHERE NO IFRAME IS USED. NOT USING AN IFRAME RENDERS THE WHOLE PROJECT QUITE A BIT MORE COMPLEX.

IMPLEMENTATION:
		SCROLLER CONSISTS OF ONE MAIN DIV, WITH TWO MAIN CHILDREN, WHICH ARE IDENTICAL TO EACH OTHER. EACH OF THESE TWO CHILDREN CONTAINS A SERIES OF DIVS, 
		EACH OF WHICH CONTAINS ONE CONTENT ITEM. BOTH MAIN CHILDREN ARE SET TO TOP:AUTO AND LEFT:AUTO WITHIN MAIN DIV. WHAT CAUSES THE SCROLLING MOTION IS
		THEIR MARGIN -- TOP FOR VERTICAL, LEFT FOR HORIZONTAL. ONE CHILD IS ALWAYS A FULL LENGTH BEHIND THE OTHER. WHEN THE LEAD CHILD SCROLLS COMPLETELY OUT OF
		VIEW, IT IS MOVED SO THAT IT IS NOW BEHIND AND THE OTHER CHILD IS NOW THE LEADER.

ISSUES:
		1.	USES POSITION RELATIVE FOR FF AND POSITION ABSOLUTE FOR IE. I DON'T KNOW WHAT TO USE FOR OPERA/SAFARI.
		2.	SIMILARLY, PADDING/WIDTH HANDLED DIFFERENTLY ON IE AND FF. DON'T KNOW ABOUT OPERA/SAFARI.
		3.	IFRAME IS RECOMMENDED, BECAUSE CODE IS LESS COMPLEX.
		4.	ALSO, "INLINE" VERSION A BIT BUMPY AND CHOPPY ON FF
		5.	ON IE, IF YOU LEAVE THE PAGE FOR A REALLY, REALLY LONG TIME, MOVEMENT BECOMES SLOW AND CHOPPY. NOT SURE HOW LONG.
		6.	USAGE OF CCallWrapper.js IS DUE TO INABILITY TO CALL SETTIMEOUT WITHIN A METHOD
		7.	CALLS TO INIT FUNCTIONS CALLED WITH TIMEOUT (ALTHOUGH 0!), OTHERWISE ON IE, CLIENTWIDTH/CLIENTHEIGHT RETURN 0!

DISCUSSION:
		- ON IE, WHOLE THING WAS QUITE TRIVIAL: SIMPLY SPECIFY OUTER DIV AS OVERFLOW HIDDEN, AND INNER DIVS AS POSITION ABSOLUTE, AND HAVE TOP/LEFT MOVE.
		PROBLEM WAS THAT, WHILE POSITION ABSOLUTE ON IE IS RELATIVE TO OUTER DIV, ON FF, IT IS ABSOLUTE TO ENTIRE WINDOW, SO RESULT LOOKED HORRIBLE.
		FURTHERMORE, ON FF, OVERFLOW:HIDDEN IS IGNORED WHEN CHILDEN ARE POSITION:ABSOLUTE. (NOTE THAT NEITHER OF THESE IS AN ISSUE WHEN USING IFRAMES.)
		- I NEXT TRIED TO USE CLIP INSTEAD OF OVERFLOW HIDDEN. THIS WORKED FINE , WITH ONE MAJOR PROBLEM: THE ENTIRE WINDOW GOT A SCROLLBAR, ON BOTH IE AND FF, BECAUSE,
		ALTHOUGH THE EXCESS WAS NOT BEING SHOWN, FROM THE BROWSER POINT OF VIEW IT WAS STILL THERE!
		- I THEN NOTICED THAT POSITION RELATIVE ON FF WORKS WELL, BUT NOT FOR IE! SO I ENDED UP USING RELATIVE FOR FF AND ABSOLUTE FOR IE.

POSSIBLE ENHANCEMENTS:
		1.	SPECIFY BORDER AROUND ENTIRE SCROLLER
		2.	SPECIFY HOW MUCH SPACE (AND POSSIBLY SOME DESIGN, LIKE ASTERISKS) BETWEEN END AND START
		3.	MORE ATTRIBUTES: BOLD, ITALIC, UNDERLINE. ANYTHING ELSE? ALLOW SIMPLY USE OF CLASSES.
		4.	ALLOW CENTERING FOR VERTICAL SCROLLER
*/

//		HELPER FUNCTIONS

function MSbrowser () {
	return found(navigator.appName, "Microsoft")
}

function found (haystack, needle) {
	return haystack.search(needle) != -1
}

function isnull (arg) {
	arg = arg + ""
	return arg == "" || arg == "null" || arg == "undefined"
}

//	CONSTRUCTOR

function scroller (scrollerName, orientation, context, width, height, direction, outerPadding) {
	this.id				= scrollerName
	this.orientation	= orientation
	this.context		= context
	this.outerPadding	= isnull(outerPadding) ? 5 : outerPadding
	this.height			= height

	this.direction		= isnull(direction) ? "ltr" : direction
	if (this.direction == "rtl") {
		this.align		= "right"
		this.multiplier = -1
	}
	else {
		this.align		= "left"
		this.multiplier = 1
	}

	//	DUE TO DIFFERENCE BETWEEN MS AND FF ON PADDING AND WIDTH. NEEDS TO BE DONE ONLY FOR IFRAME BECAUSE THAT'S WHEN WE USE POSITION ABSOLUTE
	if (orientation == "v" && context == "iframe" && !MSbrowser()) {
		this.width		= width - this.outerPadding * 2
		this.adjust1		= true
	}
	else {
		this.width		= width
		this.adjust1	= false
	}
	this.adjust2		= orientation == "v" && context == "inline" && !MSbrowser() ? this.outerPadding : 0
	this.outer_padding_clause = orientation == "v" ? ("padding-left:" + this.outerPadding + "px; padding-right:" + this.outerPadding + "px; ") :
		"padding-top:" + this.outerPadding + "px; "

	if (context == "iframe") {
		this.absolute	= true
		this.position	= "absolute"
	}
	else {
		this.absolute	= MSbrowser()
		this.position	= this.absolute ? "absolute" : "relative"
	}

	this.scrollSpeed	= 30
	this.padding		= 10
	this.content		= []
	this.pause			= false
}
	
//	ADD CONTENT TO SCROLLER

scroller.prototype.add = function (content) {
	this.content[this.content.length] = content
}

//	HELPER FUNCTION TO CREATE EACH DIV WITHIN THE SCROLLER

function buildDiv (i, myObject) {
		if (myObject.orientation == "v") {
			padding1 = "top"
			padding2 = "bottom"
			more_style = ""
			extra = ""
		}
		else {
			padding1 = "left"
			padding2 = "right"
			more_style = "float:" + (myObject.direction == "rtl" ? "right" : "left") + "; "
			extra = "nowrap"
		}
		textQuality = ""
		if (!isnull(myObject.fontSize))
			textQuality += "font-size:" + myObject.fontSize + "; "
		if (!isnull(myObject.fontFamily))
			textQuality += "font-family:" + myObject.fontFamily + "; "
		if (!isnull(myObject.color))
			textQuality += "color:" + myObject.color + "; "
		return "<div id='" + myObject.id + "_div1_" + (i + 1) + "' style='text-align:" + this.align + "; direction:" + myObject.direction + "; " + textQuality +
			"padding-" + padding1 + ":" + (myObject.padding / 2) + "; " + more_style + myObject.outer_padding_clause +
			"padding-" + padding2 + ":" + (myObject.padding / 2) + ";' " + extra + ">" + myObject.content[i] + "</div>"
}

//	PRODUCE THE ACTUAL HTML OF THE SCROLLER

scroller.prototype.draw = function () {
	var child_style = "style='text-align:" + this.align + "; position:" + this.position + "; top:0; left:0; '"
	var buildHTML = "<div style='" + (this.adjust1 ? this.outer_padding_clause : "") + "overflow:hidden; " +
		(isnull(this.bgcolor) ? "" : "background-color:" + this.bgcolor + "; ") + "width:" + this.width + "px; height:" + this.height + "px;' > \
		<div onmouseover='" + this.id + ".doPause(true)' onmouseout='" + this.id + ".doPause(false)' id='" + this.id + "_aTicker' " + child_style + ">"
	for (var i = 0; i < this.content.length; i++)
		buildHTML += buildDiv(i, this)
	buildHTML += "</div><div id='" + this.id + "_bTicker' " + child_style + "></div></div>"
	document.writeln(buildHTML)
	var callwrapper = new CCallWrapper(this, 0, this.orientation == "h" ? "initHorizontal" : "initVertical")
	CCallWrapper.asyncExecute(callwrapper)
}

//	INITIALIZE VERTICAL SCROLLER

scroller.prototype.initVertical = function () {
	var aTic = document.getElementById(this.id + "_aTicker")
	var bTic = document.getElementById(this.id + "_bTicker")
	bTic.onmouseover = aTic.onmouseover
	bTic.onmouseout = aTic.onmouseout
	for (var i = 1; i <= this.content.length; i++)
		document.getElementById(this.id + "_div1_" + i).style.width = this.width - this.adjust2
	bTic.innerHTML = aTic.innerHTML.replace(/_div1_/g, "_div2_")
	aTic.style.height = bTic.style.height = this.room = aTic.clientHeight
	aTic.style.marginTop = 0
	var myFunction
	if (this.absolute) {
		bTic.style.marginTop = this.room
		myFunction = "scrollVerticalMS"
	}
	else {
		this.leader = "a"
		this.follower = "b"
		bTic.style.marginTop = 0
		myFunction = "scrollVerticalFF"
	}
	var callwrapper = new CCallWrapper(this, this.scrollSpeed, myFunction)
	CCallWrapper.asyncExecute(callwrapper)
}

//	INITIALIZE HORIZONTAL SCROLLER

scroller.prototype.initHorizontal = function () {
	var aTic = document.getElementById(this.id + "_aTicker")
	var bTic = document.getElementById(this.id + "_bTicker")
	bTic.onmouseover = aTic.onmouseover
	bTic.onmouseout = aTic.onmouseout
	bTic.innerHTML = aTic.innerHTML.replace(/_div1_/g, "_div2_")
	var total = 0
	for (var i = 1; i <= this.content.length; i++)
		total += document.getElementById(this.id + "_div1_" + i).clientWidth
	aTic.style.width = bTic.style.width = this.room = total
	if (this.direction == "rtl") {
		aTic.style.marginLeft = this.width - this.room
		bTic.style.marginLeft = parseInt(aTic.style.marginLeft) - total
	}
	else {
		aTic.style.marginLeft = 0
		bTic.style.marginLeft = total
	}
	var callwrapper = new CCallWrapper(this, this.scrollSpeed, "scrollHorizontal")
	CCallWrapper.asyncExecute(callwrapper)
}

//	VERTICAL SCROLLER: SCROLL UP ONE PIXEL: FF

scroller.prototype.scrollVerticalFF = function () {
	if (!this.pause) {
		var aTic = document.getElementById(this.id + "_" + this.leader + "Ticker")
		var bTic = document.getElementById(this.id + "_" + this.follower + "Ticker")
		aTop = parseInt(aTic.style.marginTop)
		aTic.style.marginTop = aTop - 1
		if (aTop - 1 < -this.room) {
			if (this.leader == "a") {
				aTic.style.marginTop = this.room
				bTic.style.marginTop = -this.room
			}
			else {
				aTic.style.marginTop = bTic.style.marginTop = 0
			}
			var temp = this.leader
			this.leader = this.follower
			this.follower = temp
		}
	}
	var callwrapper = new CCallWrapper(this, this.scrollSpeed, "scrollVerticalFF")
	CCallWrapper.asyncExecute(callwrapper)
}

//	VERTICAL SCROLLER: SCROLL UP ONE PIXEL: MM

scroller.prototype.scrollVerticalMS = function () {
	if (!this.pause) {
		var aTic = document.getElementById(this.id + "_aTicker")
		var bTic = document.getElementById(this.id + "_bTicker")
		aTop = parseInt(aTic.style.marginTop)
		bTop = parseInt(bTic.style.marginTop)
		aTic.style.marginTop = aTop - 1
		bTic.style.marginTop = bTop - 1
		if (aTop - 1 < -this.room)
			aTic.style.marginTop = bTop + this.room
		else if (bTop - 1 < -this.room)
			bTic.style.marginTop = aTop + this.room
	}
	var callwrapper = new CCallWrapper(this, this.scrollSpeed, "scrollVerticalMS")
	CCallWrapper.asyncExecute(callwrapper)
}

function atEdge (position, totalWidth, direction) {
	if (direction == "ltr") {
		return position < -totalWidth
	}
	return position > totalWidth
}

//	HORIZONTAL SCROLLER: SCROLL UP ONE PIXEL

scroller.prototype.scrollHorizontal = function () {
	if (!this.pause) {
		var aTic = document.getElementById(this.id + "_aTicker")
		var bTic = document.getElementById(this.id + "_bTicker")
		aLeft = parseInt(aTic.style.marginLeft)
		bLeft = parseInt(bTic.style.marginLeft)
		aTic.style.marginLeft = aLeft - 1 * this.multiplier
		bTic.style.marginLeft = bLeft - 1 * this.multiplier
		if (atEdge(aLeft - 1 * this.multiplier, this.room, this.direction))
			aTic.style.marginLeft = bLeft + this.room * this.multiplier
		else if (atEdge(bLeft - 1 * this.multiplier, this.room, this.direction))
			bTic.style.marginLeft = aLeft + this.room * this.multiplier
	}
	var callwrapper = new CCallWrapper(this, this.scrollSpeed, "scrollHorizontal")
	CCallWrapper.asyncExecute(callwrapper)
}

//	PAUSE THE SCROLLER

scroller.prototype.doPause = function (myBoolean) {
	this.pause = myBoolean
}

