/* author: Don Kent, eShopHost Ltd */
/* Copyright (C) 2004-6, eShopHost Ltd UK, all rights reserved. */
// TickerTape.js - use with TickerTape.html - see through an iframe, with various types of display of each of a set of messages. Web Element 198.

/* CONTENTS
1. startTicker() - called onload of TickerTape.html to initiate the display
2. runTheTicker() - The basic rotate function
3. setupNextStory() - Index to next story
4. drawStory() - Draw a teletype line
5. closeOutStory() - Finalise the item
6. getNextStory () - Retrieve next story's data
7. fillStoryBuffer () - load buffer
8. HTMLescape (Chr) - converts character to HTML string as required
9. linkClick (evt) - invoked onClick of <a> link to cancel if no URL

FEATURES & INSTRUCTIONS
See Web Build Instructions.doc (Offer 13)

FUTURE DEVELOPMENT
a. Add more feaatures - e.g. Single line, moving text off the left
b. Multi-line - making the iframe as high as the message it is showing
c. See Base Products CNs & BRs .xls

HISTORY
1.0 30/12/04 Don Kent. First used with equisafety
1.1 03/02/06 Add code so messages will work if updated via standard Text Self-Update.
1.2 03/02/06 Random message
1.3 04/02/06 Instructions, etc. to Web Build Instructions.doc
1.4 06/02/06 3. Fixed random to start from 1 (was 0)
1.5 06/02/06 Changed Library ids from numbers to Area1, etc - avoids capturing <body> somehow!
2.0 24/02/06 Added extra mode of operation: TickerTapeSmooth (from the right, smooth movement)
2.1 26/02/06 Added extra mode of operation: TickertapeCharjumpMultiple (as above but character jump movement (not smooth) and with subsequent messages visible and following
2.2 27/02/06 Changed means of writing to reduce jerkiness & improve chances of being able to click with mode: TickertapeCharjumpMultiple
2.3 27/02/06 Recognises story slot as empty if no text nodes. Disables link if no URL supplied
2.4 06/03/06 Added extra mode of operation: TickertapeSmoothMultiple (Mixture of TickerTapeSmooth & TickertapeCharjumpMultiple but 100% gap between the end of the message set and the start of the next run.
2.5 12/06/06 6. Link target changed when external link to new window; 9. click inhibited in error when external link - fixed; 3. Permit user to configure iframe width to reduce start-up delay
2.6 22/08/06 9. Fix. Empty href was being converted with a base URL, so now test for file name in href
2.7 22/08/06 1. FireFox sees whitespace as nodes, so add checks to childNodes [Still works with IE; unfortunately still doesn't work with Firefox]
2.8 01/09/06 1. Added check for not running in iframe - jumps to home page.
2.9 11/09/06 Firefox fix cont'd - childNodes
2.10 25/09/06 9. Fix: was not recognising href starting http:! 6c. Fix: clear link in case no text found in link space
*/

// --- Global variables (For configuration variables, see TickerTape.html)
	var ItemCount = 0;// No. of stories
	var StorySummary; // Current Story text
	var StoryBuffer = ""; // Following story text built into <a>
	var PositionLeft; // Story's current position
	var PositionLeftEnd; // Story's end position
	var objD; // Display object (TickerContainer)
	var objD1, objD2; // 2 sub-containers of above
	var Anchor1 = "<a class='TickerLink' onclick='linkClick(event)' target='";
	var Target = "_top"; // changed in 6.
	var Anchor2 = "' href='";
	var TargetLink;	 // Story's link URL
	var Anchor3 = "'>";
	var AnchorEnd = "</a>";
	var StoryState = 1;	// true means set up next story; false means display current story
	var CurrentStory = StartMessageNo -1;	// Story no. (0 for story 1)
	var CurrentLength = 0;	// How many current story characters currently output
	var LeadStringLength = 0; // ditto for LeadString
	var SpaceFillerLength = 0;
	var InterMessageLength = 0;
	var Segment = 0; // For multiple message display, what segment is currently being displayed?
	var IMS = ""; // Intermessage string with repetitions, not escaped

// Other globals in TickerTape.html (customers/aa-eshophostCommon/html/) - preset for the characteristics required

/* Story data in (hidden) body:
	1st DIV = story
	2nd DIV = URL to link to - relative or full
*/


function startTicker() { // 1.
	// 0. Check if not running in an iframe (e.g. linked to from a Search Engine)
	if (location.protocol == "http:") { // Skip if local (test)
		if (!window.frameElement) { // not in iframe
			location.href = location.protocol + "//" + location.hostname; // go to home page
		}
	}

	// Set up initial values
	// a. Determine ItemCount based upon the story slots and if they are populated
	var inputs, El;
	while (!inputs) {
		if (El = getObj("Area" + (++ItemCount))) { // Story slot exists (id = 1, 2, etc.)
			// e.g. <DIV id="Area1"> exists
			if (El.childNodes) {
				// e.g. <DIV><!--PerlTagStart01t-->Message number 1<!--PerlTagEnd01t--></DIV>
				// El.childnodes are the 2 DIV objects: [0] is the story, [1] is the URL
				// childnodes of story DIV contain just the 2 comments (PerlTags) if slot is empty
				// Story slot may contain story as more than 2 nodes, including perl comment tags

				// b. Clean up the story & URL to plain text
				var c = 0;
				for (var i = 0; i < El.childNodes.length; i++) {
					if (El.childNodes[i].tagName == "DIV") {
						var S, S2;
						S = El.childNodes[i].innerHTML; // Content of DIV
						S2 = S.substring(22, S.length - 20); // Skip the Perl Tags
						S2 = S2.replace(/<[^>]*>/g, ""); // Strip HTML tags
						El.childNodes[i].innerHTML = S2;
						if (c ==0 && El.childNodes[i].innerHTML.length == 0) { // no text
							inputs = true; ItemCount--;
							break;
						}
						c++;
					}
				}
			} else { // No story
				inputs = true; ItemCount--;
			}
		} else { // No story slot
			inputs = true; ItemCount--;
		}
	}

	// c. Begin the ticker       
	objD = getObj("TickerContainer");
	//objD.style.height = "50px"; // TRY - necessary! auto doesn't work
	//objD.style.visibility = "visible"; // TRY - no
	//objD.style.overflow = "visible"; // TRY - no
	//objD.style.clip = "rect(0px,999px,50px,0px)"; // TRY - no
	//objD.style.top = "0px"; // TRY - no
	for (var j = 0; j < InterMessageStringReps; j++) {
		IMS += InterMessageString;
	} // Build Intermessage string with repetitions

	switch (Mode) {
		case "TickertapeCharjumpMultiple":
			// Split TickerContainer
			objD.innerHTML = "<span id='hottext'></span><span id='queuetext'></span>";
			fillStoryBuffer ();
			objD1 = getObj ("hottext");
			objD2 = getObj ("queuetext");
			break;
	}
	runTheTicker();
}


function runTheTicker() { // 2. The basic rotate function
	// a. Has Story closed?
	if(StoryState == 1) {
	   setupNextStory();
	}

	// b. Has Story reached end of transition?
	var Draw = false;
	switch (Mode) {
		case "MoveLR": // Start with whole and move left to right
			break;
		case "MoveRL": // Start with whole and move right to left
			break;
		case "TickertapeCharjumpMultiple":
			Draw = true;
			if (Segment == 0) {
				if (LeadStringLength >= LeadString.length) {
					Segment = 1;
				}
			} else if (Segment == 1) {
				if (CurrentLength >= StorySummary.length) {
					Segment = 2;
				}
			} else if (Segment == 2) {
				if (SpaceFillerLength >= SpaceFiller.length) {
					Segment = 3;
				}
			} else if (InterMessageLength == 0) {
				// strip InterMessage from start of StoryBuffer as drawStory will do it
				StoryBuffer = StoryBuffer.substr(StoryBuffer.indexOf("<a"));
			} else {
				if (InterMessageLength >= InterMessageStringReps * InterMessageString.length) {
					StoryState = 1;
				}
			}
			break;
		case "TickertapeSmoothMultiple":
		case "TickertapeSmooth": // Traditional Tickertape movement from R to L but smooth
			if (PositionLeft > PositionLeftEnd) {
			   Draw = true;
			}
			break;
		default: // Teletype
			if(CurrentLength < StorySummary.length) {
			   Draw = true;
			}
	} // End switch

	// c. Draw or close story
	if (Draw) {
	   drawStory();
	} else {
	   closeOutStory();
	}
}


function setupNextStory() { // 3. Index to next story
	StoryState = 0;
	var IM = "";
	// Build InterMessage String (escaped)
	for (var j = 0; j < IMS.length; j++) {
		IM += HTMLescape(IMS.charAt(j));
	}

	// a. get next Story
	switch (Mode) {
		case "TickertapeCharjumpMultiple":
			// Extract story & link from beginning of StoryBuffer
			var arr = StoryBuffer.match ( /href='(.*?)'.*?>(.*?)<\/a>/ ); //'
			//alert (StoryBuffer + "\n\n" + arr[1] + "\n\n" + arr[2]);
			// Strip initial story
			StoryBuffer = StoryBuffer.substr(StoryBuffer.indexOf("</a>")+4);
			// Strip leading Intermessage strings
			StoryBuffer = StoryBuffer.substr(StoryBuffer.indexOf("<a "));
			// Add more stories if required
			if (StoryBuffer.length < 999) {
				getNextStory ();
				// Add story to buffer
				StoryBuffer = StoryBuffer + Anchor1 + Target + Anchor2 + TargetLink + Anchor3 + LeadString + StorySummary + SpaceFiller + AnchorEnd + IM ;
			}
			// Set current story & link
			StorySummary = arr[2];
			StorySummary = StorySummary.substring(LeadString.length, StorySummary.length - SpaceFiller.length);
			TargetLink = arr[1];
			// Initialise counters
			LeadStringLength = 0;
			CurrentLength = 0;
			SpaceFillerLength = 0
			InterMessageLength = 0;
			// Initialise Queue display buffer
			objD2.innerHTML = StoryBuffer;
			break;
		case "TickertapeSmoothMultiple":
			// Fill Display area with complete set of stories
			for (var i = 0; i < ItemCount; i++) {
				getNextStory (); // Sets CurrentStory, StorySummary, TargetLink
				StoryBuffer += Anchor1 + Target + Anchor2 + TargetLink + Anchor3 + LeadString + StorySummary + SpaceFiller + AnchorEnd + IM;
			}
			break;
		default:
			getNextStory (); // Sets CurrentStory, StorySummary, TargetLink
	}

	// b. Initial values
	CurrentLength = 0; // For character based movements
	PositionLeft = (WindowWidth) ? WindowWidth: 800; // For position based movements. If display width unknown, guess
	Segment = 0; // For Char jump, multiple messages based movements
	switch (Mode) {
		case "MoveLR": // Start with whole and move left to right
		case "MoveRL": // Start with whole and move right to left
		case "TickertapeSmoothMultiple":
			PositionLeftEnd = -2 * (StoryBuffer.length + 50); // Actual string width unknown - intelligent guess.
			objD.innerHTML = StoryBuffer;
			break;
		case "TickertapeSmooth": // Traditional Tickertape movement from R to L but smooth
			PositionLeftEnd = -12 * StorySummary.length; // Actual string width unknown - intelligent guess.
			objD.innerHTML = Anchor1 + Target + Anchor2 + TargetLink + Anchor3 + LeadString + StorySummary + SpaceFiller + AnchorEnd;
	}
}


function drawStory() { // 4.
	// a. Get display area object
	// b. Draw according to Mode
	switch (Mode) {
		case "MoveLR": // Start with whole and move left to right
			break;
		case "MoveRL": // Start with whole and move right to left
			break;
		case "TickertapeSmoothMultiple": // As below, but multiple messages
		case "TickertapeSmooth": // Traditional Tickertape movement from R to L but smooth
			objD.style.left = PositionLeft + "px"; // Shift position
			PositionLeft -= Movement; // next position left
			break;
		case "TickertapeCharjumpMultiple":
			var IM = ""; // Intermessage string
			for (var i = InterMessageLength; i < IMS.length; i++) {
				IM += HTMLescape(IMS.charAt(i));
			}
			objD1.innerHTML = Anchor1 + Target + Anchor2 + TargetLink + Anchor3 + LeadString.substr(LeadStringLength) + StorySummary.substr(CurrentLength) + SpaceFiller.substr(SpaceFillerLength) + AnchorEnd + IM;
			if (Segment == 0) {
				LeadStringLength++;
			} else if (Segment == 1) {
				CurrentLength++;
			} else if (Segment == 2) {
				SpaceFillerLength++;
			} else {
				InterMessageLength++;
			}
			break;
		default: // Draw a teletype line
			var TTYchar;
			if((CurrentLength % 2) == 1) {
				TTYchar = TTY1;
			}
			else {
				TTYchar = TTY2;
			}
			objD.innerHTML = Anchor1 + Target + Anchor2 + TargetLink + Anchor3 + LeadString + StorySummary.substring(0,CurrentLength) + TTYchar + SpaceFiller + AnchorEnd;
			CurrentLength++;
	}
	// c. Wait before next action
	setTimeout("runTheTicker()", CharTimeout);
}


function closeOutStory() { // 5. Finalise the item
	switch (Mode) {
		case "TickertapeSmoothMultiple":
			StoryBuffer = "";
			StoryState = 1;
			setTimeout("runTheTicker()", 20);
			break;
		default:
			objD.innerHTML = Anchor1 + Target + Anchor2 + TargetLink + Anchor3 + LeadString + StorySummary + SpaceFiller + AnchorEnd;
			objD.style.left = "0px"; // Shift position
			StoryState = 1;
			setTimeout("runTheTicker()", StoryTimeout);
	}
}


function getNextStory () { // 6. Sets CurrentStory, StorySummary, TargetLink
	// a. Next Story - Random or linear?
	if (StartMessageNo) { // non-zero, so increment from last
		// Linear
		CurrentStory = CurrentStory % ItemCount;
		CurrentStory++;
	} else {
		// Random
		var rn;
		do {
			rn = Math.floor(Math.random() * ItemCount) + 1;
		} while (CurrentStory == rn && (ItemCount > 1)) // ensure a different story each time
		CurrentStory = rn;
	}

	// b. Get next Story
	var El = getObj ("Area" + (CurrentStory));
	var ElStory;
	var c = 0;
	for (var i = 0; i < El.childNodes.length; i++) {
		if (El.childNodes[i].tagName == "DIV") {
			if (c == 0) {
				ElStory = El.childNodes[i];
				for (var j = 0; j < ElStory.childNodes.length; j++) {
					var ElStoryText = ElStory.childNodes[j];
					if (ElStoryText.nodeType == 3) { // Text node
						StorySummary = ElStoryText.nodeValue;
						break;
					}
				}
			}
			
			// c. Get & set link
			if (c == 1) {
				var ElStoryURL = El.childNodes[i];
				TargetLink = ""; // clear in case no text node found below
				for (var k = 0; k < ElStoryURL.childNodes.length; k++) {
					if (ElStoryURL.childNodes[k].nodeType == 3) { // Text node
						TargetLink = ElStoryURL.childNodes[k].nodeValue;
						if (TargetLink == "undefined") {TargetLink = "";}
						Target = (TargetLink.indexOf("http://") == 0) ? "_blank" : "_top"; // new window if external
						break;
					}
				}
				if (!TargetLink) {TargetLink = "";}
			}
			c++;
		}
	}
}


function fillStoryBuffer () { // 7. Load buffer with stories
	while (StoryBuffer.length < 500) {
		getNextStory (); // StorySummary, TargetLink
		StoryBuffer += Anchor1 + Target + Anchor2 + TargetLink + Anchor3 + LeadString + StorySummary + SpaceFiller + AnchorEnd;
		// add Intermessage strings
		for (var i = 0; i < InterMessageStringReps; i++) {
			for (var j = 0; j < InterMessageString.length; j++) {
				StoryBuffer += HTMLescape(InterMessageString.charAt(j));
			}
		}
	}
}


var ChrArr = new Array();
ChrArr [" "] = "&nbsp;";
function HTMLescape (Chr) { // 8.
	if (ChrArr[Chr]) {
		return ChrArr[Chr];
	}
	return Chr;
}


function linkClick (evt) { // 9. invoked onClick of <a> link to cancel if no URL
	var IE;
	if (event) { // IE model
		evt = event;
		IE = true;
	} else if (evt) { // W3CDOM/ NN model
		IE = false;
	} else {
		evt = null;
	}
	if (evt) {
		var el = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null);
		if (el) {
			if ( (el.href.length < 2)	// too small
				|| ( (el.href.search(/\w+\.\w+$/) == -1)	// no terminating file name e.g. page.html
					&& (el.href.search(/^http:\/\/\w+\.\w+/i) == -1) )	// no http://.. address
				) { // no URL in href of <a>: 
				if (IE) {
					evt.returnValue = false;
				} else {
					evt.preventDefault();
				}
				return false;
			} else {
				return true;
			}
		}
	}
}

