//
// XHR :: Custom xmlhttprequest Class
// Written by Andy Frey ( andy [at] onesandzeros [dot] biz )
// http://onesandzeros.biz/xhr/ for latest info
//
//  Versions--
//    1.3 (27 December 2005) -- fixed timeout problem
//    1.2 (4 November 2005) -- fixed query decoding issues
//

// will be the object from the browser for io calls
// it needs to be its own thing out in the global scope
var xmlhttp;
var xmlhttpTimer = -1; // used for timeouts on broken calls

// pass this consturctor a var/val pair string (var=val&var=val&var=val...)
// and it magically creates an array of objects such that { name:nameOfVar, value:valOfVar }
function VarPairs( u ) {
	// split query string into variable/value pairs
	this.pairs = new Array();
	this.uri = u;
	var vps = this.uri.split( "&" );
	// run through and load up varPairs with var/val objects { varname, varvalue }
	for( var i = 0; i < vps.length; i++ ) {
		this.pairs[i] = {
			name:decodeURIComponent( vps[i].substring( 0, vps[i].indexOf( "=" ) ) ), // get everything up to first = sign
			value:decodeURIComponent( vps[i].substring( vps[i].indexOf( "=" ) + 1 ) )// get everything after the first = sign
		};
	}

	// pass it the name of the variable whose var/val pair you'd like
	this.getVar = function ( n ) {
		for( var i = 0; i < this.pairs.length; i++ )
			if( this.pairs[i].name == n )
				return this.pairs[i];
		return { name:"", value:"" };
	};

}

var onXHRPreSend = function () {
	// stuff to do right before sendAndLoad() is called
};

var onXHRPostSend = function () {
	// stuff to do right after sendAndLoad() comes back from receipt of data
};

var onXHRWaiting = function ( n ) {
	// stuff to do while waiting for a response (n is the readyState value)
};

var onXHRRecv = function () {
	alert( "Received data OK!" );
};	

var onXHRTimeout = function () {
	alert( "Connection timed out." );
};

var onXHRErr = function ( e ) {
	alert( "Error loading data (status code " + e + ")." );
};	

// this function handles the firing of the above functions
// on return from io script
var onXMLHTTPChangeState = function () {
	
	switch( xmlhttp.readyState ) {
	
	case 0: // uninitialized
	case 1: // loading
	case 2: // loaded
	case 3: // interactive
		// fire off waiting method for all these states
		onXHRWaiting( xmlhttp.readyState );
		break;
	
	case 4: // complete
		// first, kill the timeout timer
		clearTimeout( xmlhttpTimer );
		if( xmlhttp.status == 200 )
			onXHRRecv();  // call receive method
		else
			onXHRErr( xmlhttp.status );  // call error method (pass it the status code)
		onXHRPostSend();
		break;

	default:  // in case we get something unknown
		onXHRWaiting( xmlhttp.readyState );

	}

}

// pass this thing the url to the script that will handle requests
function XHR( is, rt, to ) {
	this.ioScript = is; // the url for the io script
	this.queryString;
	this.vp;
	this.reqType = ( rt.toUpperCase == "GET" ) ? "GET" : "POST";
	this.timeout = to * 1000; // ms to elapse before io is considered dead
	this.currentVar = "";
	this.currentChildren = new Array();
	this.currentChild = 0;

	this.setIOTimeout = function ( t ) {
		this.timeout = t;
	};

	this.getIOTimeout = function () {
		return this.timeout;
	};

	this.setScript = function ( s ) {
		this.ioScript = s;
	};

	this.getScript = function () {
		return this.ioScript;
	};

	this.getQueryString = function () {
		return this.queryString;
	};

	this.nodeTypeToString = function ( n ) {
		switch( n ) {
			case 1: return "ELEMENT"; break;
			case 2: return "ATTRIBUTE"; break;
			case 3: return "TEXT"; break;
			case 4: return "CDATA_SECTION"; break;
			case 5: return "ENTITY_REFERENCE"; break;
			case 6: return "ENTITY"; break;
			case 7: return "PROCESSING_INSTRUCTION"; break;
			case 8: return "COMMENT"; break;
			case 9: return "DOCUMENT"; break;
			case 10: return "DOCUMENT_TYPE"; break;
			case 11: return "DOCUMENT_FRAGMENT"; break;
			case 12: return "NOTATION"; break;
			default: return "UNKNOWN (" + n + ")";
		}
	};

	this.getNode = function ( n ) {
		if( xmlhttp.responseXML )
			if( xmlhttp.responseXML.getElementsByTagName( n ).length )
				return xmlhttp.responseXML.getElementsByTagName( n )[0];
		return null;
	};

	this.getNodeValue = function ( n ) {
		if( xmlhttp.responseXML )
			if( this.getNode( n ).firstChild )
				return this.getNode( n ).firstChild.nodeValue;
		return "";
	};

	this.getNodeAttribute = function ( n, a ) {
		if( xmlhttp.responseXML )
			if( xmlhttp.responseXML.getElementsByTagName( n ).length )
				return xmlhttp.responseXML.getElementsByTagName( n )[0].getAttribute( a );
		return null;
	};

	this.resetNodes = function () {
		this.currentChild = 0;
	};

	this.getNodesCount = function () {
		return this.currentChildren.length;
	};

	this.getNodes = function ( n ) {
		if( this.currentVar != n ) {
			// name is different from the last search, so reset child info
			this.currentVar = n;
			this.currentChildren = xmlhttp.responseXML.getElementsByTagName( this.currentVar );
			this.currentChild = 0;
		}
		// there are multiple children by that name, so return them one at a time
		if( this.currentChild < this.currentChildren.length )
			return this.currentChildren[this.currentChild++];
		else
			return false;
	};

	this.getResponseXML = function () {
		return xmlhttp.responseXML;
	};

	this.getResponseText = function () {
		return xmlhttp.responseText;
	};

	// pass this method just the var=val&var=val string
	// note: don't forget to override the onXXX methods prior!
	this.sendAndLoad = function ( qs ) {
		this.queryString = encodeURI( qs );
		// reset the var getter thing's stuff (trust me, it must be this way)
		this.currentVar = "";
		this.currentChildren = new Array();
		this.currentChild = 0;
		// instantiate the request object
		if( window.XMLHttpRequest ) {
			// code for Mozilla, etc.
			xmlhttp = new XMLHttpRequest();
		} else if( window.ActiveXObject ) {
			// code for IE
			xmlhttp = new ActiveXObject( "Microsoft.XMLHTTP" );
		}
		// if it was instantiated OK
		if( xmlhttp ) {
			xmlhttp.onreadystatechange = onXMLHTTPChangeState;
			onXHRPreSend();
			xmlhttp.open( this.reqType, this.ioScript, true );
			xmlhttp.setRequestHeader( "Content-Type", "application/x-www-form-urlencoded" );
			xmlhttp.send( this.queryString );
			xmlhttpTimer = setTimeout( "onXHRTimeout()", this.timeout );
		}
	}

	this.getVar = function ( n ) {
		var varPairs = new VarPairs( xmlhttp.responseText );
		if( this.reqType == "GET" ) {
			for( var i = 0; i < varPairs.length; i++ )
				if( varPairs[i].name == n )
					return varPairs[i];
		}
		return false;
	};

}
/*
function show_screen_coord( event ) {
	x=event.screenX;
	y=event.screenY;
	alert( "Screen... X:" + x + ", Y:" + y );
}

function show_coords( event ) {
	x = event.clientX;
	y = event.clientY;
	alert( "X: " + x + ", Y: " + y );
}

<body onmousedown="show_coords( event ); show_screen_coords( event )">
*/

function isFunction( a ) {
    return typeof a == 'function';
}

function isObject( a ) {
    return ( a && typeof a == 'object' ) || isFunction( a );
}

function isAlien( a ) {
   return isObject( a ) && typeof a.constructor != 'function';
}

function isArray( a ) {
    return isObject( a ) && a.constructor == Array;
}

function isBoolean( a ) {
    return typeof a == 'boolean';
}

function isEmpty( o ) {
	var i, v;
	if( isObject( o ) ) {
		for( i in o ) {
			v = o[i];
			if( isUndefined( v ) && isFunction( v ) ) {
				return false;
			}
		}
	}
	return true;
}

function isNull( a ) {
    return typeof a == 'object' && !a;
}

function isNumber( a ) {
    return typeof a == 'number' && isFinite( a );
}

function isNumeric( a ) {
	return isNumber( a );
}

function isString( a ) {
    return typeof a == 'string';
}

function isUndefined( a ) {
    return typeof a == 'undefined';
}

function elementExists( el ) {
	try {
		var o = getElement( el );
	} catch( e ) {
		return false;
	}
	return true;
}

function getElement( e ) {
	if( document.all ) {
		if( document.all[e] ) {
			return document.all[e];
		} else {
			throw "getElement(): No such element: '" + e + "' (using document.all[])";
		}
	} else if( document.getElementById ) {
		if( document.getElementById( e ) ) {
			return document.getElementById( e );
		} else {
			throw "getElement(): No such element: '" + e + "' (using getElementById())";
		}
	}
	throw "getElement(): Could not get a reference to element ID '" + e + "'.";
}

function getCoords( e ) {
	var obj = getElement( e );
	if( obj.offsetParent && arguments.length > 1 && arguments[1] ) {
		var coords = { left:0, top:0 };
		while( obj.offsetParent ) {
			coords.left += obj.offsetLeft
			coords.top += obj.offsetTop
			obj = obj.offsetParent;
		}
		return coords;
	} else if( obj.x ) {
		return { left:obj.x, top:obj.y };
	}
	throw "Could not determine coords for element '" + e + "'.";
}

function moveElement( e, coords ) {
	var o = getElement( e );
	if( document.all ) {
		o.moveTo( coords.x, coords.y );
	} else {
		o.pixelLeft = coords.x + document.body.scrollLeft;
		o.pixelTop = coords.y + document.body.scrollTop;
		//return false;
	}
}

function showElement() {
	try {
		if( arguments.length == 1 )
			getElement( arguments[0] ).style.display = "inline";
		else if( arguments.length == 2 )
			getElement( arguments[0] ).style.display = arguments[1];
	} catch( e ) {
		alert( e );
	}
}

function hideElement( e ) {
	getElement( e ).style.display = "none";
}

function toggleElementVisibility( e ) {
	try {
		if( getElement( e ).style.display == "none" )
			showElement( e );
		else
			hideElement( e );
	} catch( e ) {
		alert( e );
	}
}

function disableElement( objName ) {
	getElement( objName ).disabled = true;
}

function enableElement( objName ) {
	getElement( objName ).disabled = false;
}

function elementClear( e ) {
	getElement( e ).innerHTML = "";
}

function elementWrite( e, m ) {
	if( arguments.length > 2 && arguments[2] )
		getElement( e ).innerHTML += escape( m );
	else
		getElement( e ).innerHTML += m;
}

function elementWriteln( e, m ) {
	if( arguments.length > 2 && arguments[2] )
		elementWrite( e, m + "\n", arguments[2] );
	else
		elementWrite( e, m + "\n" );
}

function elementWritebr( e, m ) {
	if( arguments.length > 2 && arguments[2] )
		elementWrite( e, m + "<br />\n", arguments[2] );
	else
		elementWrite( e, m + "<br />\n" );
}

function setElementHTML( e, h ) {
	getElement( e ).innerHTML = h;
}

function getElementHTML( e ) {
	return getElement( e ).innerHTML;
}

function isEnabled( name ) {
	return !getElement( name ).disabled;
}

function isDisabled( name ) {
	return getElement( name ).disabled;
}


//
// General text field functions
//
function focusField( name ) {
	getElement( name ).focus();
}

function getFieldValue( name ) {
	return getElement( name ).value;
}

function setFieldValue( name, val ) {
	getElement( name ).value = val;
}

function setCheckbox( name, yn ) {
	if( isEnabled( name ) )
		getElement( name ).checked = ( yn == 'y' || yn == 'Y' );
}

function isChecked( name ) {
	return getElement( name ).checked;
}

function checkboxLabel( name ) {
	if( isEnabled( name ) )
		getElement( name ).checked = !getElement( name ).checked;
	return isEnabled( name );
}

function addOption( sel, txt, val, selected ) {
	getElement( sel ).options[ getElement( sel ).options.length ] = new Option( txt, val );
	getElement( sel ).options[ getElement( sel ).options.length - 1 ].selected = selected;
}

function clearSelect( name ) {
	getElement( name ).options.length = 0;
}

function getSelectedIndex( o ) {
	return getElement( o ).selectedIndex;
}

function getSelectedText( o ) {
	var s = getElement( o ); 
	return s.options[s.selectedIndex].text;
}

function getSelectedValue( o ) {
	var s = getElement( o ); 
	return s.options[s.selectedIndex].value;
}

function selectIndexByValue( o, v ) {
	var s = document.getElementById( o );
	for( var i = 0; i < s.length; i++ ) {
		if( s.options[i].value == v ) {
			s.selectedIndex = i;
			return;
		}
	}
}

function selectIndexByText( o, t ) {
	var s = document.getElementById( o );
	for( var i = 0; i < s.length; i++ ) {
		if( s.options[i].text == t ) {
			s.selectedIndex = i;
			return;
		}
	}
}

function getIndexByValue( o, v ) {
	var s = document.getElementById( o );
	for( var i = 0; i < s.length; i++ ) {
		if( s.options[i].value == v ) {
			return i;
		}
	}
	return -1;
}

function getIndexByText( o, t ) {
	var s = document.getElementById( o );
	for( var i = 0; i < s.length; i++ ) {
		if( s.options[i].text == t ) {
			return i;
		}
	}
	return -1;
}

function setOpacity( e, o ) {
	// example of transparency in either major browser
	// pass in a value (o) from 0 to 100
	if( o >= 0 && o <= 100 ) {
		//getElement( e ).
		if( document.all )
			getElement( e ).style.filter = "alpha( opacity = " + o + " )";
		else
			getElement( e ).style.opacity = o / 100;
	} else {
		throw "Opacity of " + o + " is out of range for the setOpacity() function.";
	}
}

function getOpacity( e ) {
	// example of transparency in either major browser
	// returns a value from 0 to 100
	if( document.all )
		getElement( e ).style.filter = "alpha( opacity = " + o + " )";
	else
		getElement( e ).style.opacity = o / 100;
	return 0;
}


function blankRequest() {
	getElement( "request" ).value = "<request command=\"search\">\n\t<type>image</type>\n\t<metaField name=\"\"></metaField>\n</request>";
}

function assetRequest() {
	getElement( "request" ).value = "<request command=\"href\">\n\t<key version=\"0\">(paste key here)</key>\n</request>";
}
// create the http request object thing
var xhr = new XHR( "/gal/service.php", "POST", 30 );
onXHRTimeout = function () {
	window.status = "Conneciton to " + xhr.getScript() + " timed out.";
};

var currentPhoto = 0;
var photoList = new Array();
var photoDelay = 7;
var winGallery = 0;
var photoTimer = '';

function launchGallery() {
	winGallery = window.open( "/gal/gallery.php?cityID=" + cityID + "&issueDate=" + issueDate + "&sectionBase=" + sectionBase + "&cid=" + cid, "galleryViewer", "height=600, width=728, toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no" );
	winGallery.focus();
}


function photoRotator() {
	onXHRRecv = function () {
		if( xhr.getNodeAttribute( "response", "status" ) == "ok" ) {
			// got a good response back from the server
			var row;
			while( row = xhr.getNodes( "image" ) )
				photoList.push( {
					href:row.getElementsByTagName("href")[0].firstChild.nodeValue,
					credit:row.getElementsByTagName("credit")[0].firstChild ? row.getElementsByTagName("credit")[0].firstChild.nodeValue : '',
					caption:row.getElementsByTagName("caption")[0].firstChild ? row.getElementsByTagName("caption")[0].firstChild.nodeValue : ''
				} );
			// make the DIV visible... divisible... hmmm... funny.
			showElement( 'storyPhotos' );
			// now, get that rotation going!
			nextPhoto( 'storyPhotoHeader', 'storyPhotoImg', 'storyPhotoCaption' );
			if (photoList.length > 1) {
				playPhotos( 'storyPhotoHeader', 'storyPhotoImg', 'storyPhotoCaption' );
			}
		}/* else {
			alert( "Uh oh! " + xhr.getNodeValue( "message" ) );
		}*/
	};
	var request = "<mediaRequest command=\"storyPhotos\" cityID=\"" + cityID + "\" cid=\"" + cid + "\" />";

	xhr.sendAndLoad( "_r=" + request );
}

function nextPhoto( credit, imageTag, caption ) {
	currentPhoto++;
	if( currentPhoto == photoList.length ) currentPhoto = 0;
	elementClear( credit );
	elementWrite( credit, photoList[currentPhoto].credit );
	getElement( imageTag ).src = "http://media.citypages.com" + photoList[currentPhoto].href;
	elementClear( caption );
	elementWrite( caption, photoList[currentPhoto].caption );
}

function playPhotos( credit, imageTag, caption ) {
	photoTimer = setInterval( function () { nextPhoto( credit, imageTag, caption, cityID, cid ) }, photoDelay * 1000 );
}


function stopPhotos() {
	if (photoTimer) {
		clearInterval( photoTimer );
	}
}

var mediaHost = "media.citypages.com";
var mediaURL = "http://" + mediaHost + "/";
var mediaVer = 26;
var urlDefaultImage = "/gal/default_home.jpg";
var photoDIV = "galleryPhoto";
var photoCount = 0;
var currentPhoto = 0;
var photoList = new Array();
var photoTimer = -1;
var countdown = 0;
var paused = true;
var playControlsHTML = '<img id="playControls" src="/gal/play_controls.gif" border="0" useMap="#playControlsMap" style="z-index: 1; position: relative; margin-left: -40px; margin-bottom: 5px;" />';
var xhr = new XHR( "/gal/service.php", "POST", 30 ); // create the http request object thing

onXHRTimeout = function () {
	window.status = "Conneciton to " + xhr.getScript() + " timed out.";
};

function photoGallery( city, galID, tagID, imgVer ) {
	photoDIV = tagID;
	mediaVer = imgVer;
	// load DIV with initial/default image
	//setElementHTML( photoDIV, '<img src="' + urlDefaultImage + '" alt="Home Page Photo Gallery" />' );
	// make sure it is visible
	//showElement( photoDIV );
	// now, start comms with media server
	onXHRRecv = function () {
		if( xhr.getNodeAttribute( "response", "status" ) == "ok" ) {
			// got a good response back from the server
			var row;
			while( row = xhr.getNodes( "photo" ) ) {
				elementWrite( photoDIV,
					'<div id="photo' + photoCount + '" delay="' + row.getAttribute( "delay" ) + '" style="display: ' + ( photoCount == 0 ? 'inline' : 'none' ) + '" class="photoGalleryFrame">' + 
					'<a href="' + ( row.getElementsByTagName( "link" )[0].firstChild ? row.getElementsByTagName( "link" )[0].firstChild.nodeValue : '' ) + '" ' + 
						'target="' + ( row.getElementsByTagName( "link" )[0].getAttribute( "target" ) ? row.getElementsByTagName( "link" )[0].getAttribute( "target" ) : '' ) + '" ' + 
						'title="' + ( row.getElementsByTagName( "title" )[0].firstChild ? row.getElementsByTagName( "title" )[0].firstChild.nodeValue : '' ) + '">' + 
					'<img src="' + mediaURL + row.getAttribute( "id" ) + '.' + mediaVer + '.jpg" ' + 
						'alt="' + ( row.getElementsByTagName( "altText" )[0].firstChild ? row.getElementsByTagName( "altText" )[0].firstChild.nodeValue : '' ) + '" ' + 
						'border="0" />' +
					'</a>' + 
					'</div>'
				);
				photoCount++;
			}
			// if there are two or more photos, draw the controls in the lower-right corner
			if( photoCount > 1 ) {
				elementWrite( photoDIV,
					playControlsHTML + 
					'<map name="playControlsMap">' + 
						'<area shape="rect" coords="0,0,8,13" alt="previous photo" title="previous photo" onmousedown="previousPhoto()" />' + 
						'<area shape="rect" coords="11,0,23,13" alt="play/pause photos" title="play/pause photos" onmousedown="togglePlay()" />' + 
						'<area shape="rect" coords="26,0,34,13" alt="next photo" title="next photo" onmousedown="nextPhoto()" />' + 
					'</map>'
				);
			}
			if( photoCount > 1 ) {
				// set up the countdown timer if there are two or more photos
				photoTimer = setInterval(
					function () {
						if( !paused ) {
							if( countdown <= 0 )
								nextPhoto();
							else
								countdown--;
						}
					}, 
					1000
				);
				showPhoto( 0 );
				playPhotos();
			} else if( photoCount == 1 ) {
				showPhoto( 0 );
			}
		}
	};
	xhr.sendAndLoad(  "_r=<mediaRequest command=\"getPhotoGallery\" cityID=\"" + city + "\" galleryID=\"" + galID + "\" />" );
}

function showPhoto() {
	if( !photoCount ) return;
	if( arguments.length == 1 ) currentPhoto = arguments[0];
	showElement( "photo" + currentPhoto );
	countdown = getElement( "photo" + currentPhoto ).getAttribute( "delay" );
	if( photoCount > 1 )
		showElement( "playControls" );
	else
		hideElement( "playControls" );
}

function nextPhoto() {
	if( photoCount < 2) return;
	// hide current photo
	hideElement( "photo" + currentPhoto );
	currentPhoto++;
	if( currentPhoto == photoCount ) currentPhoto = 0;
	showPhoto();
}

function previousPhoto() {
	if( photoCount < 2 ) return;
	// hide current photo
	hideElement( "photo" + currentPhoto );
	currentPhoto--;
	if( currentPhoto < 0 ) currentPhoto = photoCount - 1;
	showPhoto();
}

function playPhotos() {
	if( photoCount < 2 ) return;
	paused = false;
}

function togglePlay() {
	if( photoCount < 2 ) return;
	paused = !paused;
	getElement( "playControls" ).src = "/gal/play_controls" + ( paused ? "_paused" : "" ) + ".gif";
}

function stopPhotos() {
	paused = true;
}

function isPlaying() {
	return !paused;
}
