/* Globals */
var ie = (document.all) ? true : false;

function Ticker(cid, curl) {
	/* Browser detection */
	this.ie = (document.all) ? true : false;
	
	/*  Configurable values */
	this.vertical = false;				// default for ticker Orientation
	this.tickerMarOffset = 0;			// Ticker Margin Offset
	this.imageSize = 83;
	this.tickerDivLength = 715;			// change this to control width of ticker
	this.currentWidth = 0;				
	this.tickTime = 30;					// interval between calls to the tick() function
	this.primalityNumber = 31;			// ideally, number of images maintained active in the ticker strip at all times. Should be prime to ensure correct rotation of ticker items
	this.skipImages = 5;				// replace a ticker image with a new image every skipImages. If both this and pn are prime, we'll eventually replace all images.
	this.previewDelay = 600;
	this.imageGap = 2;
	this.imageDeco = "ticker";
	this.maxImageSize = (this.imageSize <= 50) ? 50 : 400;	// used to compute tickerDiv size
	this.cid = cid;
	this.preload = 30;
	this.linkImages = true;
	this.channelURL = curl;

	/* Flags */
	this.tickerRunning = false;
	this.tickerPaused = false;
	this.gettingIds = false;			// set to true when doing an Ajax request for id's
	this.transferDone = false;			// set to true when we've finished downloading initial ticker images.
	this.addedPadding = false;
	this.tickerStarted = false;
	this.primality = false;
	this.imgsAdded = false;

	this.tickerItems = new Array;		// stores TickerItem Objects
	this.tickerIds = new Array;			// stores only TickerItem Ids. Used for ajax requests mostly
	this.queue = new Array;				// used to keep track of currently displayed images

	/* Counters */
	this.tickerLoadImageCount = 0;
	this.widestImageWidth = 0;			// used to calculate padding in case it's needed.
	this.movedImages = 0;				// counts how many images have passed the ticker edge at a given moment. Is reset every skipImages

	/* Previewer*/
	this.previewer = (previewerEnabled && !self.staticTicker) ? new Previewer(this) : null;		// the previewer object handles zooming of images in sharing window

	/* Timers */
	this.tickerTimer = null;
	this.fadeTimer = null;
	this.previewerTimer = null;

	/* ******** Preloads ******** */
	var imagePreloads = new Array;
	
	for (var i = 1; i < 10; i++) {
		imagePreloads[i] = document.createElement("img");
		imagePreloads[i].src = tickerBaseURL + "/images/prev_img" + i + ".png";
	}
	imagePreloads[10] = document.createElement("img");
	imagePreloads[10].src =  tickerBaseURL + "/images/seemore_btn.gif";


	/* ******** Functions ******** */
	this.setProperties = function () {
		this.imageDeco = (this.vertical) ? "vticker" : "ticker";
		if (this.imageSize <= 50) {
			if (this.vertical) {
				this.imageDeco = "grid";
			} else {
				this.imageDeco = "sticker";
			}
		}
		this.fadeValue = this.tickerDivLength;
	}
	
	this.tickerPause = function (pause) {
		this.tickerPaused = pause;
	}

	this.togglePause = function () {
		this.tickerPaused = !this.tickerPaused;
	}
	
	this.getImageId = function (n) {
		return "tickimg" + n;
	}
	
	this.getImageLinkId = function (n) {
		return "ticklnk" + n;
	}
	
	this.createElement = function (parent, tagname) {
		var elem = document.createElement(tagname);
		parent.appendChild(elem);
		return elem;
	}
	
	this.clearDiv = function (d) {
		d = getObject(d);	  
		while (d.childNodes[0]) {
			d.removeChild(d.childNodes[0]);
		}
	}
	
	/* ******** Layout ******** */
	this.layoutTicker = function (tickerBase) {

		this.clearDiv(tickerBase);
		//tickerBase.style.padding = "5px 0 0 10px";
		tickerBase.style.textAlign = "center";

		if(this.vertical) tickerBase.style.height = (this.tickerDivLength + 40) + "px";

		var container = document.createElement('table');
		
		container.style.margin = "0 auto";
		
		var containerBody = document.createElement('tbody');
		
		var innerContainer = document.createElement('table');
		var innerContainerBody = document.createElement('tbody');

		container.cellPadding = 0;
		container.cellSpacing = 0;
		innerContainer.cellPadding = 0;
		innerContainer.cellSpacing = 0;
		
		var cellCounter = 0;
		
		var row1 = document.createElement('tr');
		var cell1 = document.createElement('td');
		var row2 = document.createElement('tr');
		var cell2 = document.createElement('td');
		var row3 = document.createElement('tr');
		var cell3 = document.createElement('td');
		
		if(!this.vertical) {
			cell1.style.height = "4px";
			cell2.style.height = (this.imageSize + 1) + "px";
			cell2.style.padding = "0 3px";
			cell3.style.height = "9px";
		} else {
			cell1.style.width = "3px";
			cell2.style.height = (this.tickerDivLength + 6) + "px";
			cell2.style.padding = "3px 0";
			cell2.style.width = this.imageSize + "px";
			cell3.style.width = "8px";
		}
		
		var chromeName = (this.vertical) ? 'vslapp' : 'slapp';
		
		if (!this.ie) {
			cell1.style.background = 'transparent url( ' + tickerBaseURL + '/images/' + chromeName + ((this.vertical) ? '4' : '2') + '.png ) no-repeat top left';
			cell2.style.background = 'transparent url( ' + tickerBaseURL + '/images/' + chromeName + '5.png ) no-repeat top left';
			cell3.style.background = 'transparent url( ' + tickerBaseURL + '/images/' + chromeName + ((this.vertical) ? '6' : '8') + '.png ) no-repeat top left';
		} 
		else {
			cell1.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + tickerBaseURL + '/images/' + chromeName + ((this.vertical) ? '4' : '2') + '.png\', sizingMethod=\'crop\')';
			cell2.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + tickerBaseURL + '/images/' + chromeName + '5.png\', sizingMethod=\'crop\')';
			cell3.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + tickerBaseURL + '/images/' + chromeName + ((this.vertical) ? '6' : '8') + '.png\', sizingMethod=\'crop\')';
		}

		if (!this.vertical) innerContainer.style.width = (this.tickerDivLength + 6) + "px";

		cell2.id = "tickerCell";
		cell2.style.textAlign = "left";
		cell2.style.verticalAlign = "top";
		
		if (!this.vertical) {
			row1.appendChild(cell1);
			row2.appendChild(cell2);
			row3.appendChild(cell3);
		} else {
			row1.appendChild(cell1);
			row1.appendChild(cell2);
			row1.appendChild(cell3);
		}

		innerContainerBody.appendChild(row1);
		if (!this.vertical) {
			innerContainerBody.appendChild(row2);
			innerContainerBody.appendChild(row3);
		}
		innerContainer.appendChild(innerContainerBody);
		
		var setContents = false;
		var currentCell = null;
		var signupLink = tickerBaseURL + "/basic_signup/external?mode=slideshow";
		// create table for image box
		for (var i = 0; i < 3; i++) {
			currentRow = document.createElement('tr');
			for (var j = 0; j < 3; j++) {
				cellCounter++;
				currentCell = null;

				var contentCell = ((this.vertical && i == 1) || (!this.vertical && j == 1)) ? true: false;

				if (contentCell) {
					// this cell contains tickerDiv
					if (!setContents) {
						setContents = true;
						currentCell = document.createElement('td');
						currentCell.style.textAlign = "left";
						currentCell.style.verticalAlign = "top";
						if (this.vertical) {
							currentCell.colSpan = "3";
						} else {
							currentCell.rowSpan = "3";
						}
						currentCell.appendChild(innerContainer);
					}
				} else {
				
					currentCell = document.createElement('td');

						 if (i == 0) { 
						 	currentCell.style.height = (this.vertical) ? '18px' : '14px'; 
						 		if (self.externalTicker) {
									if(j == 1 && this.vertical) {
										currentCell.style.textAlign = "left";
										var slideLink = document.createElement('a');
	
										if(ie) { 
											slideLink.style.position = "absolute";
										}
	
										slideLink.style.display = "block";
										slideLink.href = signupLink;
										slideLink.target = "_blank";
										slideLink.style.height = "18px";
										slideLink.style.width = (this.imageSize - 24) + "px";
	
										currentCell.appendChild(slideLink);
									}
						 		}
						 	
						 	}
					else if (i == 1) { currentCell.style.height = (this.vertical) ? (this.tickerDivLength) + 'px' : (this.imageSize - 20) +'px'; }
					else if (i == 2) { currentCell.style.height = '20px'; }

						 if (j == 0) { 
						 	currentCell.style.width = (this.vertical) ? '15px' : '18px';
								if(i == 1 && !this.vertical) {
									if (self.external) {
										currentCell.vAlign = "top";
										var slideLink = document.createElement('a');
	
										if(ie) { 
											slideLink.style.position = "absolute";
										}
	
										slideLink.style.display = "block";
										slideLink.href = signupLink;
										slideLink.target = "_blank";
										slideLink.style.height = (this.imageSize - 20) + 'px';
										slideLink.style.width = "18px";
	
										currentCell.appendChild(slideLink);
									}

									if(ie && self.external || !self.external) {
										var blankImg = document.createElement('img');
										blankImg.src = '/images/blank.gif';
										blankImg.style.height = "1px";
										blankImg.style.width = "18px";
										currentCell.appendChild(blankImg);
									}
							 	}
						 	}
					else if (j == 1) { if (this.vertical) currentCell.style.width = (this.imageSize - 24) + 'px'; }
					else if (j == 2) { 
							var cellWidth = (this.vertical) ? 22 : 20;
							currentCell.style.width = cellWidth + 'px';
								if(i == 1 && !this.vertical) {
									var blankImg = document.createElement('img');
									blankImg.src = '/images/blank.gif';
									blankImg.style.height = "1px";
									blankImg.style.width = cellWidth + 'px';
									currentCell.appendChild(blankImg);
							 	}
							}

					if (!ie) {
						if (!this.vertical) {
							currentCell.style.background = 'transparent url( ' + tickerBaseURL + '/images/' + chromeName + ((this.imageSize < 83 && i == 1 && (j == 0 || j == 2)) ? 'sm' : '') + cellCounter + '.png ) no-repeat top left';
						} else {
							currentCell.style.background = 'transparent url( ' + tickerBaseURL + '/images/' + chromeName + ((this.imageSize < 83 && (i == 0 || i == 2) && j == 1) ? 'sm' : '') + cellCounter + '.png ) no-repeat top left';
						}
					} 
					else {
						if (!this.vertical) {
							currentCell.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + tickerBaseURL + '/images/' + chromeName + ((this.imageSize < 83 && i == 1 && (j == 0 || j == 2)) ? 'sm' : '') + cellCounter + '.png\', sizingMethod=\'crop\')';
						} else {
							currentCell.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + tickerBaseURL + '/images/' + chromeName + ((this.imageSize < 83 && (i == 0 || i == 2) && j == 1) ? 'sm' : '') + cellCounter + '.png\', sizingMethod=\'crop\')';
						}
					}
				}
				if (currentCell != null) currentRow.appendChild(currentCell);
			}
			containerBody.appendChild(currentRow);
		}
		
		container.appendChild(containerBody);

		tickerBase.appendChild(container);
		

		// tickerContainer	
		var tc = createElement(getObject("tickerCell"), "div");
		tc.id = "tickerContainer";
		if (!this.vertical) {
			tc.style.width = this.tickerDivLength + "px";
			tc.style.height = this.imageSize + "px";
		} else {
			tc.style.width = this.imageSize + "px";
			tc.style.height = this.tickerDivLength + "px";
		}
		tc.style.margin = "0 auto";
		tc.style.overflow = "hidden";
		tc.style.position = "absolute";
		
		this.tcHandle = getNodeHandle(tc);

		// tickerStatus	
		var tsMargin = (Math.floor(this.tickerDivLength / 2) - 75);
		
		var ts = createElement(tc, "img");
		ts.id = "tickerStatus";
		if(!this.vertical) {
			ts.src = tickerBaseURL + "/images/ticker_loading.gif";
			ts.style.margin = "0 " + (tsMargin + 100) + "px 0 " + tsMargin + "px";
			if (this.imageSize < 83) { 
				ts.style.marginTop = - (42 - Math.floor(this.imageSize / 2)) + "px";
			}
		}
		
		this.tsHandle = getNodeHandle(ts);
		
		// tickerDiv
		var td = createElement(tc, "div");
		td.id="tickerDiv";
		td.style.position = "absolute";
		if (!this.vertical) {
			td.style.height = this.imageSize + "px";
			td.style.width = (this.maxImageSize * this.primalityNumber) + "px";
		} else {
			td.style.width = this.imageSize + "px";
			td.style.height = (this.maxImageSize * this.primalityNumber) + "px";
		}
		
		this.tdHandle = getNodeHandle(td);
	
	}
	
	this.positionOf = function (elem) {
		return this.GetElementPosition(elem).left;
	}
	
	this.makeImage = function (src) {
		var rv = new Image();
		rv.src = src;
		return rv;
	}

	this.transferImages = function () {

		if (!this.imgsAdded && this.tickerItems.length > 0) {
			this.imgsAdded = true;
			var addImgs = (this.tickerItems.length < this.primalityNumber) ? this.tickerItems.length : this.primalityNumber;
			for (var i = 0; i < addImgs; i++) {
				this.addTickerItem(getNodeByNodeHandle(this.tdHandle), i);
			}
		}
		if (!this.transferDone && this.tickerItems.length > 0) {
				this.transferDone = true;
				for (var i=0; i < this.tickerItems.length; i++) {
					var item = this.tickerItems[i];
					if (item.image == null) {
						item.image = this.makeImage(item.img_url + "/" + this.imageDeco);
						this.transferDone = false;
					} else if (!item.transferred) {
						if (item.image.complete) {
							this.setTickerItem(this.tickerLoadImageCount, item);
							this.currentWidth += (this.vertical) ? item.image.height : item.image.width;
							item.transferred = true;
							this.tickerIds['id' + item.id] = item;
							if (!this.vertical) {
								if (item.image.width > this.widestImageWidth) this.widestImageWidth = item.image.width;
							} else {
								if (item.image.height > this.widestImageWidth) this.widestImageWidth = item.image.height;
							}
							this.tickerLoadImageCount++;
						}
						this.transferDone = false;
					}
				}
		} else {		
			if(this.transferDone && (this.currentWidth < (this.tickerDivLength + this.widestImageWidth)) && !this.addedPadding) {
				this.addedPadding = true;
				var tickerPadding = ((this.tickerDivLength + this.widestImageWidth) - (this.currentWidth + (this.tickerLoadImageCount * this.imageGap)) + this.widestImageWidth);
				this.addTickerPadding(getNodeByNodeHandle(this.tdHandle), tickerPadding, this.tickerLoadImageCount);
				this.tickerLoadImageCount++;
			}			
	
			if(self.ajaxEnabled) {
				// Transfer's complete/needed. Let's get some new images.
				if ((this.transferDone || this.tickerItems == 0) && this.gettingIds == false) {
					this.gettingIds = true;
					this.getNewImageIds();
				}
			}
		}
	}
	
	this.addNewImages = function (newItems) {
			for (var i = 0; i < newItems.length; i++) {
				this.tickerIds['id' + newItems[i].id] = newItems[i];
				if(this.tickerItems.length < 30) {
					this.tickerItems.push(newItems[i]);
				} else {
					this.queue.push(newItems[i]);
				}
			}
	}

	this.doTick = function () {
		var t = this;
		
		this.transferImages();
		
		if (!this.tickerPaused) {
			if (this.tickerRunning) {
				this.tick();
			} else if (!this.tickerStarted && (this.currentWidth > this.fadeValue || this.transferDone )) {
				this.tickerStarted = true;
				getNodeByNodeHandle(this.tsHandle).style.display = "none";
	
				if (!(this.ie && self.externalTicker)) {
					FadeIn("tickerDiv", 0);
				}
				
				// 1.5 seconds to tick.
				setTimeout(function () { t.startTick() }, 1500);
			}
		}
		this.tickerTimer = setTimeout(function () { t.doTick() }, this.tickTime);
	}
	
	this.startTick = function () {
		if(!self.staticTicker) {
			this.tickerRunning = true;
		}
	}
	
	
	/* ******** Ajax ******** */
	this.getNewImageIds = function () {
		var t = this;
		asyncAction('channelajax',
		{'action': 'getitemids',
		 'cid'   : t.cid
		} ,
		function(theResponse) {
			if (!self.scriptLoaded) return;
			if (theResponse.substring(0,4) == "PASS") {
				var newImageIds = eval(theResponse.substring(5));
				// empty channel
				if(newImageIds.length == 0 && t.tickerIds.length == 0) {
					t.updateEmpty();
				}
				var previouslyUnseen = new Array();
				for (var i = 0; i < newImageIds.length; i++)
					if(t.tickerIds['id' + newImageIds[i]] == undefined) {
						previouslyUnseen.push(newImageIds[i]);
					}
				if(previouslyUnseen.length > 0) {
					t.getNewImageItems(previouslyUnseen);
				}
			}
		});
	}
	
	this.getNewImageItems = function (imageIds) {
		var t = this;
		
		// FIX: Why do we get an empty response when item number == 100?
		imageIds = imageIds.slice(0, 80);

		asyncAction('channelajax',
		{'action': 'gettickeritems',
		'cid' : t.cid,
		'item_ids' : '[' + imageIds + ']'
		} ,
		function(theResponse) {
			if (self.scriptLoaded) t.addNewImages(eval(theResponse.substring(5)));
		});
	}
	
	this.updateEmpty = function () {
			getNodeByNodeHandle(this.tsHandle).src = tickerBaseURL + "/images/ticker_noitems.gif";
			if (this.imageSize < 83) { 
				getNodeByNodeHandle(this.tsHandle).style.marginTop = - (42 - Math.floor(this.imageSize / 2)) + "px";
			}
			clearTimeout(this.tickerTimer);
	}

	this.popQueue = function () {
		var element = this.queue.pop();
	
		// if we popped the last element, reset flag. This causes a new request to go to the server
		if(this.queue.length == 0) this.gettingIds = false;
		
		return element;
	}
	
	
	this.tick = function () {
		this.tickerMarOffset++;
		var tickDiv = getNodeByNodeHandle(this.tdHandle);
	
		if(tickDiv == undefined) return;

		var firstpos = (!this.vertical) ? tickDiv.firstChild.offsetWidth : tickDiv.firstChild.offsetHeight;

		if (this.tickerMarOffset == firstpos) {
			// grow number of images to achieve primality
			if (!this.primality) {
				if (this.queue.length > 0 && this.tickerLoadImageCount < this.primalityNumber) {
					newTickerItem = this.popQueue();
					
					this.tickerLoadImageCount++;
					this.addTickerItem(tickDiv, this.tickerLoadImageCount);
					this.setTickerItem(this.tickerLoadImageCount, newTickerItem);
				
					// we have achieved primality
					if (this.tickerLoadImageCount >= this.primalityNumber) { 
						this.primality = true;
					}
				}
			}
			// if queue has images, add them every skipImages
			if (this.movedImages == this.skipImages && this.primality && this.queue.length > 0) {
				newTickerItem = this.popQueue();
				
				this.tickerLoadImageCount++;
				this.addTickerItem(tickDiv, this.tickerLoadImageCount);
				this.setTickerItem(this.tickerLoadImageCount, newTickerItem);
				
				// reset image counter
				this.movedImages = 0;
				
				// get rid of image
				tickDiv.removeChild(tickDiv.firstChild);
			} else {
				firstImage = tickDiv.firstChild;
				tickDiv.appendChild(tickDiv.removeChild(firstImage));
			}
			
			this.movedImages++;
			this.tickerMarOffset = 0;
	
			if (this.movedImages == (this.skipImages * 4)) {
				this.movedImages = 0;
				this.gettingIds = false;
			}
		}
		
		if(this.vertical) {
			tickDiv.style.marginTop = -this.tickerMarOffset + "px";
		} else {
			tickDiv.style.marginLeft = -this.tickerMarOffset + "px";
		}
		
	}
	
	
	this.addTickerPadding = function (parent, length, index) {
		var tickerPadding = new Image();
		tickerPadding.src = tickerBaseURL + "/images/blank.gif";
		tickerPadding.id = this.getImageLinkId(index);
		tickerPadding.style.border = "0px";
		tickerPadding.style.margin = "2px";
		tickerPadding.style.cssFloat = "left";
		tickerPadding.style.styleFloat = "left";
		if (!this.vertical) {
			tickerPadding.style.width = length + "px";
			tickerPadding.style.height = this.imageSize + "px";
		} else {
			tickerPadding.style.height = length + "px";
			tickerPadding.style.width = this.imageSize + "px";
		}
		parent.appendChild(tickerPadding);
	}
	
	this.addTickerItem = function (parent, index) {
		var a = this.createElement(parent, "a");
		a.id = this.getImageLinkId(index);
		a.style.border = "0px";

		if (!this.vertical) {
			a.style.display = "block";
			a.style.height = this.imageSize + "px";
			a.style.cssFloat = "left";
			a.style.styleFloat = "left";
			a.style.padding = "0 " + this.imageGap + "px 0 0";
			a.style.margin = "0";
		} else {
			a.style.display = "block";
			a.style.padding = this.imageGap + "px 0 0 0";
			a.style.lineHeight = "0px";
		}

		if (!self.staticTicker && this.linkImages) { 
			a.href = "#";
			a.target= this.clickTarget;
		}
		
		var img = this.createElement(a, "img");
		img.src = tickerBaseURL + "/images/blank.gif";
		img.style.border = "0px";
		img.style.width = "1px";
		img.style.height = "1px";	
	}
	
	
	this.setTickerItem = function (index, item) {
		if (self.scriptLoaded) {
	
			var a = getObject(this.getImageLinkId(index));
			if (a != undefined) {
				if (!self.staticTicker && this.linkImages) {
					a.href = this.getLink(item);
				}
				a.removeChild(a.firstChild);
				var img = this.createElement(a, "img");
				img.style.border = "0px";
				img.style.margin = "0";
				img.src = item.img_url + "/" + this.imageDeco;

				var t = this;

				if (t.previewer) {
					if (!ie) {
						a.onmouseover = function (e) 	{ if(t.tickerPause != undefined) t.hover(item, e ) } ;
						a.onmouseout =  function (e) 	{ if(t.tickerPause != undefined) t.previewUnhover(e, item, 'previewContainer') } ;
					} else {
						a.onmouseenter = function (e) 	{ if(t.tickerPause != undefined) t.hover(item, e ) } ;
						a.onmouseleave =  function (e) 	{ if(t.tickerPause != undefined) t.previewUnhover(e, item, 'previewContainer') } ;
					}
				} else {
					a.onmouseover = function (e) 	{ if(t.tickerPause != undefined) t.tickerPause(true) } ;
					a.onmouseout =  function (e) 	{ if(t.tickerPause != undefined) t.tickerPause(false) } ;
				}
			}
		}
	}
	
	
	this.go = function (tickerItem) {
		if (tickerItem.url.substring(0, tickerBaseURL.length) == tickerBaseURL) {
			this.info(tickerItem);
		} else {
			document.location = tickerItem.url;
		}
	}
	
	this.info = function (tickerItem) {
		if (self.gotoPageItem) {
			gotoPageItem(tickerItem.id);
		}
	}
	
	this.getLink = function (tickerItem) {
		return (signedIn || self.externalTicker) ? tickerItem.url : this.getInternalLink(tickerItem);
	}

	this.getInternalLink = function (tickerItem) {
		return this.channelURL + "/" + tickerItem.id;
	}
	
	this.previewUnhover = function (e, ti, pid)
	{
		clearTimeout(this.previewerTimer);
	
		if (!e) var e = window.event;
		var tg = (window.event) ? e.srcElement : e.target;
		var reltg = (e.relatedTarget) ? e.relatedTarget : e.toElement;
		try {
			while(reltg.id != pid && reltg.nodeName != 'BODY') {
				reltg = reltg.parentNode;
			}
		} catch (e) { return; }
		
		if (reltg.id == pid) return;
		
		// Mouseout took place when mouse actually left container
		// Handle event
		if(this.previewer != null) {
			this.previewer.shrink(ti);
		}
		this.tickerPause(false);
	}
	
	this.previewUnhoverIE = function (ti) {
		this.previewer.shrink(ti);
		this.tickerPause(false);
	}

function Previewer(parent) {

	var growStep = 10;
	var shrinkStep = 10;
	var growSpeed = 6;
	var shrinkSpeed = 6;
	var img = null;
	var imgLink = null;
	var largerImg = null;
	var div;
	var posx;
	var frm;
	var imageComplete = false;
	var controls;
	var marginIE = 0;
	var formHeight = (signedIn) ? 135 : 30;
	formHeight += (ie) ? 10 : 0;
	var formWidth = (signedIn) ? 280 : 103;

	this.grow = function(tickerItem, x, y, imgWidth, imgHeight) {

		// selects show up over previewer
		if(ie && getObject('channelPrivacy') != null) getObject('channelPrivacy').style.visibility = "hidden";

		marginIE = 0;

		var tempimg = parent.makeImage(tickerItem.img_url + "/" + parent.imageDeco);
		this.clearTimeout();
		this.kill();
		div = document.createElement('div');
		var offsetx = Math.floor((imgWidth - 4) / 2);
		var offsety = imgHeight - Math.floor(imgHeight / 4);
		
		posx = x + offsetx;
		
		div.style.position = "absolute";
		div.style.top = (y + offsety) + "px";
		div.style.left = posx + "px";
		
		var container = document.createElement('table');
		container.id = 'previewContainer';
		var containerBody = document.createElement('tbody');

		if(!ie) {
			container.onmouseout = function(e) {
				if(parent.tickerPause != undefined) parent.previewUnhover(e, tickerItem, container.id) } ;
		} else {
			container.onmouseleave = function() {
				parent.previewUnhoverIE(tickerItem) } ;
		}

		container.cellPadding = 0;
		container.cellSpacing = 0;

		imgLink = document.createElement("a");
		imgLink.href = parent.getLink(tickerItem);

		img = createElement(imgLink, "img");
		img.style.border = "0";
		
		if(ie) { imgLink.style.position = "absolute"; }
		
		controls = document.createElement("div");
		controls.style.overflow = "hidden";
		controls.id = "prevInviteDiv";
		controls.style.height = formHeight + "px";
		controls.style.width = formWidth + "px";

		var form_div = createElement(controls, "div");
		form_div.id = "prevInvite";
		form_div.style.width = formWidth + "px";
		
		frm = createElement(form_div, "form");

		var cellCounter = 0;

		// create table for image box
		for (var i = 0; i < 3; i++) {
			currentRow = document.createElement('tr');
			for (var j = 0; j < 3; j++) {
				cellCounter++;
				currentCell = document.createElement('td');
				currentCell.id = 'prev' + cellCounter;
				currentCell.style.width = '19px';
				currentCell.style.height = (cellCounter < 4) ? '15px' : '20px';

				if(i == 1 && j != 1) {
					var blankImg = document.createElement('img');
					blankImg.src = '/images/blank.gif';
					blankImg.style.width = "19px";
					blankImg.style.height = "1px";
	
					currentCell.appendChild(blankImg);
				}

				if (!ie) {
					currentCell.style.background = 'transparent url( ' + tickerBaseURL + '/images/prev_img' + cellCounter + '.png ) no-repeat top left';
				} 
				//else {
				//	currentCell.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + tickerBaseURL + '/images/prev_img' + cellCounter + '.png\', sizingMethod=\'crop\')';
				//}
				
				if (cellCounter == 5) {
					currentCell.align = "center";
					currentCell.appendChild(imgLink);
					currentCell.appendChild(controls);
				}
				currentRow.appendChild(currentCell);
			}
			containerBody.appendChild(currentRow);
		}
		
		container.appendChild(containerBody);

		div.appendChild(container);
		
		document.body.appendChild(div);

		this.div = div;
		this.controls = controls;
		this.img = img;
		this.width = 0;
		this.height = 0;
		this.divwidth = 0;
		this.divheight = 0;
		this.maxwidth = 350;
		this.maxheight = 166;
		this.minwidth = 10;
		this.formWidth = formWidth;
		
		// if (this.maxwidth > 200) this.maxwidth = 200;
		this.setWidth();

		this.img.src = tickerItem.img_url + "/" + parent.imageDeco;

		largerImg = new Image();

		largerImg.onload = function () {
			img.src = largerImg.src;
		}

		largerImg.src = tickerItem.img_url + "/zoomer";

		this.tickerItem = tickerItem;
		this.ticker = this.growing;
		this.tick();
	}
	this.growWidth = function () { 
	
		this.controls.style.width = this.divwidth + "px";	
			
		if (!imageComplete) {
			this.img.style.width = this.width + "px"; 
		}
		
		posx -= Math.floor(growStep / 2);
		div.style.left = posx + "px";

		if(ie) {
			this.controls.style.height = (img.offsetHeight + formHeight) + "px";
			// image has to be absolutely positioned for IE, so we add the margin ourselves.
			if (imageComplete) {
				marginIE += Math.floor(growStep / 2);
				this.img.style.marginLeft = marginIE + "px";
			}
		}
	}
	this.growing = function() {
		this.divwidth += growStep;
		this.height = img.offsetHeight;

		// We have reached max size for image
		if (this.width > this.maxwidth || this.height > this.maxheight) {
			imageComplete = true;
		} else {
			this.width += growStep;
		}
		
		// form measure. Have to make room for it
		if (imageComplete && this.divwidth > this.formWidth) {
			// draw form	
			parent.drawInvite(frm, 'I', 0, this.tickerItem, imgLink, this.formWidth);
			//return 0;
		} else {
			this.growWidth();
			return growSpeed;
		}
	}
	/* End Growing functions */
		
	/* Shrinking functions */
	this.shrink = function (tickerItem) {
		if(ie && getObject('channelPrivacy') != null) {
			getObject('channelPrivacy').style.visibility = "visible";
		}
		if (tickerItem == this.tickerItem) {
			// reset imageComplete for growing algo
			imageComplete = false;
			
			// delete form
			clearChildren(this.controls);
			
			this.clearTimeout();
			this.ticker = this.shrinking;
			this.tick();
		}
	}
	this.shrinking = function() {


		if(this.width >= this.divwidth) {
			this.width -= shrinkStep;
		}
					
		this.divwidth -= shrinkStep;

		if (this.width < this.minwidth) {
			this.width = this.maxwidth;
			this.kill();
			return 0;
		} else {
			this.shrinkWidth();
			return shrinkSpeed;
		}
	}
	this.shrinkWidth = function() { 
		if(this.img != null) {

			div.style.left = posx + "px";
			this.img.style.width = this.width + "px"; 
			this.controls.style.width = this.divwidth + "px";
			posx += Math.floor(shrinkStep / 2);

			if(ie) {
				if(marginIE > 0) {
					marginIE -= Math.floor(growStep / 2);
				} else {
					marginIE = 0;
				}
				this.controls.style.height = (img.offsetHeight + formHeight) + "px";
				// image has to be absolutely positioned for IE, so we reduce the margin ourselves.
				this.img.style.marginLeft = marginIE + "px";
				
			}

		}
	}
	/* End Shrinking functions */
	
	this.setWidth = function() { 
		this.img.style.width = this.width + "px"; 
		this.controls.style.width = this.width + "px"; 
	}
	
	this.kill = function() {
		if (this.div != null) {
			this.div.style.visibility = "hidden";
			this.div.parentNode.removeChild(this.div);
			this.img = null;
			this.div = null;
		}
	}
	this.tick = function() {
		var tm = this.ticker();
		if (tm > 0) {
			this.timer = setTimeout(function () { parent.doPreviewTick() }, tm);
		}
		else {
			this.timer = null;
		}
	}
	this.clearTimeout = function() {
		if (this.timer != null) {
			clearTimeout(this.timer);
			timer = null;
		}
	}

} // End Previewer

this.doPreviewTick = function () {
	this.previewer.tick();
}

this.hover = function (tickerItem, e) {
	this.tickerPause(true);
	var posx = 0;
	var posy = 0;
	var targ;
	
	if (!e) var e = window.event;

	if (e.target) {
		targ = e.target;
	} else if (e.srcElement) {
		targ = e.srcElement;
	}

	if (targ.nodeType == 3) { // defeat Safari bug
		targ = targ.parentNode;
	}
		
	posx = this.findPosX(targ);
	posy = this.findPosY(targ);
	
	var t = this;
	
	if (t != null && t.previewer != null) {
		this.previewerTimer = setTimeout(function () { t.previewer.grow(tickerItem, posx, posy, targ.offsetWidth, targ.offsetHeight); }, this.previewDelay); 
	}
}

this.unhover = function (tickerItem, e) {
	this.previewer.shrink(tickerItem);
	this.tickerPause(false);
}

// because IE won't play nice. From Quirksmode
this.findPosX = function (obj) {
	var curleft = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curleft += obj.offsetLeft;
			obj = obj.offsetParent;
		}
	}
	else if (obj.x)
		curleft += obj.x;
	return curleft;
}

this.findPosY = function (obj)
{
	var curtop = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curtop += obj.offsetTop;
			obj = obj.offsetParent;
		}
	}
	else if (obj.y)
		curtop += obj.y;
	return curtop;
}

var addressesPattern = /^((([0-9a-zA-Z]+[-._+&])*[0-9a-zA-Z]+@([-0-9a-zA-Z]+[.])+[a-zA-Z]{2,6}|[A-Za-z][A-Za-z0-9-]*[A-Za-z0-9])[,; ]*)+$/
function isLegalAddresses(v) {
	return addressesPattern.test(v);
}


this.drawInvite = function (frm, id, type, tickerItem, imgObject, formWidth) {
	var emailDefault = " Enter email addresses"; 
	var messageDefault = " (Optional)";
	
	var buttonMargin = (signedIn) ? 90 : 0;
	if (signedIn && this.ie) buttonMargin = 0;
	
	var infob = this.createElement(frm, "a");
	infob.id = "infobutton";
	
	infob.style.margin = "5px 0 5px " + buttonMargin + "px";

	var t = this;
	infob.onclick = function() { return t.info(tickerItem); } ;
	infob.href = t.getInternalLink(tickerItem);
	
	createText(infob, " ");
	
	if (signedIn) {

		var emailDiv = createElement(frm, 'div');
		
		/* ====================================================  */
		
		var mytablearea = createElement(frm, "table");
		if (ie) mytablearea.style.position = "absolute";
		if (ie) mytablearea.style.left = "0px";
		mytablearea.id = "controlbackground";
		mytablearea.cellSpacing = '0';
		mytablearea.cellPadding = '0';
		var mytable = createElement(mytablearea, "tbody");

		var mycurrentrow = createElement(mytable, "tr");
		var mycurrentcol1 = createElement(mycurrentrow, "td");
		mycurrentcol1.id = "popuptopleft";
		var mycurrentcol2 = createElement(mycurrentrow, "td");
		mycurrentcol2.id = "popuptopcenter";
		var mycurrentcol3 = createElement(mycurrentrow, "td");
		mycurrentcol3.id = "popuptopright";
		var mycurrentrow2 = createElement(mytable, "tr");
		var mycurrentcol4 = createElement(mycurrentrow2, "td");
		mycurrentcol4.id = "popupcenterleft";
		var centercol = createElement(mycurrentrow2, "td");
		centercol.id = "popupcentercenter";
		/* centercol.style.width = (divwidth - 40) + "px";	*/
		var mycurrentcol6 = createElement(mycurrentrow2, "td");
		mycurrentcol6.id = "popupcenterright";
		var mycurrentrow3 = createElement(mytable, "tr");
		var mycurrentcol7 = createElement(mycurrentrow3, "td");
		mycurrentcol7.id = "popupbottomleft";
		var mycurrentcol8 = createElement(mycurrentrow3, "td");
		mycurrentcol8.id = "popupbottomcenter";
		var mycurrentcol9 = createElement(mycurrentrow3, "td");
		mycurrentcol9.id = "popupbottomright";
	
		/* ====================================================  */

		var textDiv = createElement(centercol, 'div');
		textDiv.style.clear = "both"; 
		textDiv.style.textAlign = "left";
		createText(textDiv, "Send this photo to friends:");
		
		var email = createInput(centercol, "text");
		email.id = "previnviteemail";
		email.name = "address";
		email.value = emailDefault;
		email.className = "def";
		email.tabIndex = "150";
		email.style.margin = "5px 0 0 5px";
		email.style.cssFloat = "right";
		email.style.styleFloat = "right";
		email.onfocus = function() { clearDefault(this, emailDefault); }
		email.onkeyup = function() { getObject('previnvitesubmit').disabled = !isLegalAddresses(this.value); }
		email.onchange = email.onkeyup;
		email.style.width = "190px";
		
		var textDiv2 = createElement(centercol, 'div');
		textDiv2.style.margin = "5px 0 0 0";
		textDiv2.style.textAlign = "right";
		createText(textDiv2, "To:");
		
		var message = createInput(centercol, "text");
		message.style.clear = "both"; 
		message.id = "previnvitemessage";
		message.name = "message";
		message.value = messageDefault;
		message.tabIndex = "151";
		message.style.margin = "5px 0 0 5px";
		message.style.cssFloat = "right";
		message.style.styleFloat = "right";
		message.className = "def";
		message.onfocus = function() { clearDefault(this, messageDefault); }
		message.style.width = "190px";
		
		var textDiv3 = createElement(centercol, 'div');
		textDiv3.style.padding = "5px 0 0 0";
		textDiv3.style.textAlign = "right";
		createText(textDiv3, "Message:");
	
       		var invitechanneltoo = createInput(centercol, "checkbox");
        	invitechanneltoo.id = "invitechanneltoo";
			invitechanneltoo.name = "invitechanneltoo";
			invitechanneltoo.style.margin = "8px 0 0 5px";
			invitechanneltoo.style.border = 0;
        	invitechanneltoo.checked = "checked";
        	invitechanneltoo.tabIndex = "152";
        	invitechanneltoo.style.styleFloat = "left";
        	invitechanneltoo.style.cssFloat = "left";
		
		var invitetext = createElement(centercol, 'label');
        	invitetext.style.styleFloat = "left";
        	invitetext.style.cssFloat = "left";
		invitetext.style.padding = "7px 0 0 5px";
		invitetext.style.textAlign = "left";
		createText(invitetext, "Share this feed too");
	
		var submitDiv = createElement(centercol, 'div');
		var submit = createInput(submitDiv, "submit");
		submit.style.clear = "both"; 
		submitDiv.style.clear = "both";
		submit.id = "previnvitesubmit";
		submit.className = "buttonInput";
		submit.style.cssFloat = "right";
		submit.style.styleFloat = "right";
		submit.style.height = "19px";
		submit.style.width = "45px";
		submit.style.margin = "-20px 0 0 0";
		submit.value = "Send";
		submit.tabIndex = "153";
		submit.disabled = false;
		submit.onclick = function () {
			blipItem(getObject("previnviteemail").value,
					 getObject("previnvitemessage").value,
					 tickerItem.id,
					 getObject("invitechanneltoo").checked,
					 messageDefault); return false;
		}	

	} // signedIn
	
	if (ie) {
		frm.style.width = formWidth + "px";
		frm.style.position = "absolute";
		frm.style.margin = imgObject.offsetHeight + "px 0 0 -" + Math.floor(formWidth / 2) + "px";		
	}
}

	
} // end Ticker()

function TickerItem(id, img_url, url, detail_url) {
	this.id = id;
	this.img_url = img_url;
	this.url = url;
	this.detail_url = detail_url;
	this.image = null;
	this.transferred = false;
}

var currentTicker = null;

var _minNodeHandle = 1000;
var _allNodes = {}

var getNodeHandle = function(node) {
    if (node.nodeHandle == undefined) {
        node.nodeHandle = String(_minNodeHandle++);
        _allNodes[node.nodeHandle] = node;
    }
    return node.nodeHandle;
}

var getNodeByNodeHandle  = function(nodeHandle) {
    return _allNodes[nodeHandle];
}

if (!ie) {
    getNodeByNodeHandle = getNodeHandle = function(x) { return x; } ;
}

function initializeTicker(cid, curl, reload, unlinked) {

	if (currentTicker != null) {
		if (currentTicker.tickerTimer) {
			clearTimeout(currentTicker.tickerTimer);
			if(currentTicker.previewer) {
				currentTicker.previewer.clearTimeout();
				currentTicker.previewer.kill();
			}
		}
	}

	if(unlinked) previewerEnabled = false;
	
	_allNodes = {};	
	currentTicker = new Ticker(cid, curl);

	if(self.slidePlayer && self.slidePlayer.length > 0) {
	
		var tickerNumber = 0;
	
		if(slidePlayer[tickerNumber].vertical) currentTicker.vertical = true;
		
		// enforce Min/Max Values
		// backwards compatibility
		if(slidePlayer[tickerNumber].playerWidth > 1200) slidePlayer[tickerNumber].playerWidth = 1200;
		if(slidePlayer[tickerNumber].playerWidth < 50) slidePlayer[tickerNumber].playerWidth = 50;
		if(slidePlayer[tickerNumber].playerWidth) slidePlayer[tickerNumber].playerSize = slidePlayer[tickerNumber].playerWidth;

		if(slidePlayer[tickerNumber].imageHeight > 83) slidePlayer[tickerNumber].imageHeight = 83;
		if(slidePlayer[tickerNumber].imageHeight < 50) slidePlayer[tickerNumber].imageHeight = 50;
		if(slidePlayer[tickerNumber].imageHeight) slidePlayer[tickerNumber].imageSize = slidePlayer[tickerNumber].imageHeight;

		if(slidePlayer[tickerNumber].imageWidth > 83) slidePlayer[tickerNumber].imageWidth = 83;
		if(slidePlayer[tickerNumber].imageWidth < 50) slidePlayer[tickerNumber].imageWidth = 50;
		if(slidePlayer[tickerNumber].imageWidth) slidePlayer[tickerNumber].imageSize = slidePlayer[tickerNumber].imageWidth;
		
		// the one true way
		if(slidePlayer[tickerNumber].imageSize > 83) slidePlayer[tickerNumber].imageSize = 83;
		if(slidePlayer[tickerNumber].imageSize < 50) slidePlayer[tickerNumber].imageSize = 50;

		if(slidePlayer[tickerNumber].playerSize > 1194) slidePlayer[tickerNumber].playerSize = 1194;
		if(slidePlayer[tickerNumber].playerSize < 50) slidePlayer[tickerNumber].playerSize = 50;
		
		currentTicker.tickerDivLength = slidePlayer[tickerNumber].playerSize;
		currentTicker.imageSize = slidePlayer[tickerNumber].imageSize;
		currentTicker.clickTarget = slidePlayer[tickerNumber].clickTarget || "_top";
		currentTicker.setProperties();
	}

	if(unlinked) {
		currentTicker.linkImages = false;
	}

	var tickerBase = getObject("ticker");
	
	if (!tickerBase) tickerBase = getObject("ticker" + cid);
	
	if (!tickerBase) return; // no ticker base, no ticker
	
	// if ticker is being reloaded, empty array (item fetching done through AJAX)	
	if (tickerItems == undefined || reload) {
		currentTicker.tickerItems = [];
	} else {
		currentTicker.tickerItems = tickerItems;
	} 

	trimArray(currentTicker.tickerItems);

	currentTicker.layoutTicker(tickerBase);

	if (currentTicker.tickerItems.length == 0 && !reload) {
		getNodeByNodeHandle(currentTicker.tsHandle).src = tickerBaseURL + "/images/ticker_noitems.gif";
		return;
	}

	currentTicker.doTick();
}

var scriptLoaded = true;
