/*
RSVP is an acronym for Rapid Serial Visual Presentation,
which is a method of speed reading.

This RSVP class below takes the text you want to present via RSVP,
and the div where you want it shown, as well as any image names
that appear in your text.  You don't need to pass in the image names,
but it is helpful for preloading the images so that they don't 
appear to be loading when they first show up in the presentation.

To Do:
A more sophisticated version of this would scan the text to 
extract the images to preload, so you don't need to pass them 
in separately.

*/


function RSVP( textOfArticle, outputDiv, imgNames )
	{		
	this.textOfArticle = textOfArticle
	this.outputDiv = outputDiv
	this.imgNames = imgNames

	// When timer is running this is non-null
	this.timeOut = null;	
	this.wordCount = 0
	this.words = null

	// Preload the images, but don't show them in the browser, 
	// just create image objects in memory.
	var imgs = []
	if (document.images) 
		{
		for ( i in imgNames )
			{
			n = imgNames[i]
			imgs[ i ] = new Image()
			imgs[ i ].src = n
			}
		}
		
	this.stdDelay = 400
	this.periodDelay = 650
	this.imgDelay = 1750
	this.fastImgDelay = 700

	}

RSVP.prototype.load = function()	
	{
	this.wordCount = 0
	if ( null != this.timeOut )
		window.clearTimeout( this.timeOut )
		
	this.words =  this.textOfArticle.split( " " )
	}


	
RSVP.prototype.startIt = function()
	{		
	this.load()
	
	if ( null != this.timeOut )
		{
		window.clearTimeout( this.timeOut )	
		this.timeOut = null
		}
	this.wordCount = 0		
	this.nextWord( 300 )
	}


RSVP.prototype.hasPeriod = function ( word )
	{
	return ( word.indexOf( "." ) >= 0 )
	}

RSVP.prototype.nextWord = function() 
	{	
	var word = this.words[ this.wordCount ]
	var word2 = this.words[ this.wordCount + 1 ]
	var delay = this.stdDelay	
	
	if ( null != word )
		{
		// Check if this word has a period in it	
		if ( this.hasPeriod( word ) )
			{
			delay = this.periodDelay			
			}
		else
			{
			if ( null != word2 )
				{
				if ( (word2.indexOf( "<img" ) == -1) && ( ((word.length + word2.length) < 10) || (word.indexOf( "<img" ) >= 0) ) )
					{
					word = word + " " + word2
					this.wordCount++
					
					// If we have an image then choose the delay length
					if (word.indexOf( "<img" ) >= 0)
						{
						delay = this.imgDelay			
						// Kludgey way to make a specific image go fast...
						// Check for a ./ in the string, and that
						// is the signal to make a short delay.
						// This is kind of a hidden feature.  If you insert 
						// and image with a path like 
						// /images/./t.jpg   
						// it will trigger a fast 
						// step over the image, whereas the path 
						// to the same image written as 
						// /images/t.jpg   
						// will be regular image delay.
						if (word.indexOf( "./" ) >= 0 )
							delay = this.fastImgDelay
						}
					else if ( this.hasPeriod( word2 )  )
						delay = this.periodDelay
					}
					
				}
			}


		this.showWord( word  )
			
		this.wordCount++
		
		// When we call setTimeout we want it to execute the 
		// nextWord function on the "this" ( i.e. the current instance 
		// of this object ).  To achieve this we pass in a function reference 
		// that was created with a closure. That closure holds on to the arguments
		// I pass in to delayedCall.  The first argument is a reference to "this"
		// and the second is the function to call on "this" instance.
		var funcRef = this.delayedCall( this, 'nextWord' )
		this.timeOut = window.setTimeout( funcRef , delay );		
		}
	}
	
RSVP.prototype.delayedCall = function( obj, methodName)
	{
	// Create a closure here so the obj and methodName
	// passed in by the caller are maintained if used later on
	// in execution.
	return (
		function()
			{
			obj[methodName]()
			}
		)
	}


RSVP.prototype.showWord = function( word )
	{
	this.outputDiv.innerHTML = word			
	}


// Convert any object in to as string for
// debug purposes.  This string lists
// all attributes and values.
function toStr( obj )
	{
	var s = ""
	var i = null

	for ( i in obj )
		s += i + " " //"=" + obj[i] + ",  "

	return s
	}


