var nmMap;//http://code.google.com/apis/maps/documentation/javascript/reference.html#Map
var infoWindow;//http://code.google.com/apis/maps/documentation/javascript/reference.html#InfoWindow
var geocoder;//http://code.google.com/apis/maps/documentation/javascript/reference.html#Geocoder
var svService;//http://code.google.com/apis/maps/documentation/javascript/reference.html#StreetViewService
var directionService;//http://code.google.com/apis/maps/documentation/javascript/reference.html#DirectionsService
var directionRenderer;//http://code.google.com/apis/maps/documentation/javascript/reference.html#DirectionsRenderer
var pano;//http://code.google.com/apis/maps/documentation/javascript/reference.html#StreetViewPanorama

var curMarkersArray = [];//holds reference to displayed Markers to easily remove from Map
var allMarkersArray = [];//holds reference to all Markers for search results, for quick pagination

var zoomLevel_USA = 3;
var minAutoZoomLevel = 12;

//variables for pin icon address
var pinIconStartShadow = "chart.apis.google.com/chart?chst=d_map_pin_letter_withshadow&chld=";//will be prefixed with appropriate numerical subdomain (0-9) when icon URL is created
var pinIconStart = "chart.apis.google.com/chart?chst=d_map_pin_letter&chld=";
var pinIconEnd = "|FF776B|000000";

//error messages
var errZipCode = "Please enter a valid Zip Code.";
var errMessage = "Please enter a City and State OR a Zip Code.";
var errResults = "No office found. Please try different search criteria.";
var errGetDirections = "Google is unable to find this location. <br> " +
					"<ul><li>Make sure all data is accurate and spelled correctly</li>" +
					"<li>If you haven't already done so, try adding a city and state, or a zip code</li></ul>";

//search results messages
var searchMsg1 = "Search for <i><b>" ;
var searchMsg2 = "</b></i> returned <b>" ;
var searchMsg3 = "</b> result" ;
var searchMsg = "";

//Variable to store the type of search, 0=zip, 1=city & state
var searchType = 0;

//Variables to store the min and max latitudes and longitudes for bounding
var minLat = 90;
var maxLat = 0;
var minLng = 0 ;
var maxLng = -180 ;

//Variables to store the from and to page index used in back to search results
var myPageNumber = 1;

//hold resultDiv and PagerDiv content prior to directions search, used for "Back to Search Results"
var resultDiv_beforeDirections;
var PagerDiv_beforeDirections;

//prevent multiple searches from happening at the same time
var searchInProgress = false;

$(document).unload(function() {
	Gnload();
});

$(document).ready(function(){

window.onerror = function(){}

	var USAcenter = new google.maps.LatLng(38, -98);
	var mapOptions = {
		zoom : zoomLevel_USA,
		center : USAcenter,
		mapTypeId : google.maps.MapTypeId.ROADMAP,
		scaleControl : true,
		scaleControlOptions : {
			position : google.maps.ControlPosition.TOP_RIGHT
		}
	};
	var panoramaOptions = {
		visible : false,
		enableCloseButton : true
	};
	var routeMarkerOptions = {
		draggable : false
	};
	var rendererOptions = {
		draggable : true,
		markerOptions : routeMarkerOptions
	};

	var mapDiv = document.getElementById("mapDiv");
	var svDiv = document.getElementById("svDiv");

	//create global instances of Google Map Objects
	nmMap = new google.maps.Map(mapDiv, mapOptions);
	pano = new google.maps.StreetViewPanorama(svDiv, panoramaOptions);//used for split screen, fullscreen doesn't require special handling
	geocoder = new google.maps.Geocoder();
	infoWindow = new google.maps.InfoWindow();
	svService = new google.maps.StreetViewService();
	directionService = new google.maps.DirectionsService();
	directionRenderer = new google.maps.DirectionsRenderer(rendererOptions);

	//setup event handling for StreetView close button
	google.maps.event.addListener(pano, 'closeclick', function() {
		MakeMapVisible();
	});

	//Call function to enable/disable the divs on the page for default view
	MakeMapVisible();

	ClearResults();
	ShowSpinner();
	myPageNumber = 1;
	
	ShowInitialMap();
});


//called when user clicks on the search button
function locateOffice() {
	if (searchInProgress == false){//make sure only one search happens at a time
	     searchInProgress = true;
		var resultDiv = document.getElementById("resultDiv");
		resultDiv.className = "nmgol_Results";
		locateNMOffices();
	}

}

//Function to check if the enter key is pressed and call the apropriate function
function keyCheck(e, btnId) {
	try {
		var key;
		if(window.event) {
			key = window.event.keyCode;     //IE
		} else {
			key = e.which;     //firefox
		}

		if (key == 13) {
			document.getElementById(btnId).click();
			return false ;
		}
		return true;
	}
	catch (exc) {}
}


window.onresize = function() {
	try {
		if( navigator.userAgent.toLowerCase().indexOf("msie 7.") != -1) {
			document.getElementById( "divContent" ).className  = "nmgol_content";
		}
	} catch (ex) {}
}


//called when "Locate" button is clicked
function locateNMOffices() {
     directionRenderer.setMap(null);//remove directions from map (if the user is doing a new search while viewing driving directions)
	var lblError = document.getElementById("lblError");
	lblError.innerHTML = "";
	ClearResults();
	ShowSpinner();
	myPageNumber = 1;
	removeMarkers();

	//Get the zip code entered by the user and check if empty
	var txtZipCode = document.getElementById("txtZipCode");
	if (txtZipCode.value != "") {//zip search
		var zip = txtZipCode.value;
		//Check if zip code is valid
		if(/(^\d{5}(-\d{4})?$)/.test(zip) == false) {
			lblError.className = "nmgol_error_msg";
			lblError.innerHTML = errZipCode;
			ShowDefaultUSMap();
			searchInProgress = false;
		} else {
			searchType = 0;
			MakeMapVisible();
			searchMsg = searchMsg1 + zip + searchMsg2 ;
			var geocodeRequest = {
				region : "US",
				address : zip
			};
			geocoder.geocode(geocodeRequest, geocodeCallback);
		}
	} else {//city and state search
		var txtCity = document.getElementById("txtCity");
		var slState = document.getElementById("slState");
		if (( txtCity.value != "") && ( slState.selectedIndex != 0)) {
			searchType  = 1;
			MakeMapVisible();
			var address = "";
			var txtStreetAddress = document.getElementById("txtStreetAddress");
			searchMsg = searchMsg1;
			if (txtStreetAddress.value != "") {
				address = txtStreetAddress.value + " ";
				searchMsg += txtStreetAddress.value + ", ";  ;
			}
			searchMsg += txtCity.value + ", " + slState.options[slState.selectedIndex].innerHTML + searchMsg2 ;
			address += txtCity.value + " " + slState.options[slState.selectedIndex].innerHTML;
			var geocodeRequest = {
				region : "US",
				address : address
			};
			geocoder.geocode(geocodeRequest, geocodeCallback);
		} else {
			searchInProgress = false;
			lblError.className = "nmgol_error_msg";
			lblError.innerHTML = errMessage;
			ShowDefaultUSMap();
		}
	}
}

//callback for Google's Geocoder
function geocodeCallback(geocodeResults, geocodeStatus) {
	//http://code.google.com/apis/maps/documentation/javascript/reference.html#Geocoder
	var showError = true;
	if (geocodeStatus == google.maps.GeocoderStatus.OK) {//geocoded request successfully, call backend for offices at this location
		var firstResult = geocodeResults[0];
		var location = firstResult["geometry"]["location"];
		var lat = location.lat();
		var lng = location.lng();
		var olData = lat + "#" +  lng + "#" + GetZoomDistance();
		if (searchType == 1) {//city & state search, make sure Google returned a city in the proper state
			var selectedState = $('#slState').val().toUpperCase();
			for (var i in firstResult.address_components) {
				var addressComponent = firstResult.address_components[i];
				if ($.inArray('administrative_area_level_1', addressComponent.types) != -1) {//address component is for US state
					var returnedState = addressComponent.short_name.toUpperCase();
					if (selectedState == returnedState) {//google returned a city in the proper state, proceed
						showError = false;
					}
				}
			}
		} else {//zip search, no further verification required
			showError = false;
		}
	}
	
	if (showError) {//geocode failed, or returned state doesn't match what user entered
		searchInProgress = false;
		ShowDefaultUSMap();
		var lblError = document.getElementById("lblError");
		lblError.className = "nmgol_error_msg";
		if (searchType == 0) {
			lblError.innerHTML = errZipCode;
		} else {
			lblError.innerHTML = errResults;
		}
	} else {//no errors, proceed
	     DoCallback(olData, 'OfficeLocatorGoogleMaps');//ajax callback goes to ClientCallbackFunction
	}
}

//arg - Contains the list of nm offices in current map scope
//ctx is the second param passed to DoCallback
function ClientCallbackFunction(arg, ctx) {
     searchInProgress = false;
	try {
		if (ctx ==  'OfficeLocatorGoogleMaps') {//no reason why this wouldn't be true
			if (arg.indexOf("<EntityArray />") != -1) {//no results, XML is empty
				var lblError = document.getElementById("lblError");
				lblError.className = "nmgol_error_msg";
				lblError.innerHTML = errResults;
				ShowDefaultUSMap();
			} else {
			     allMarkersArray.length = 0;
				var endOfCleanXML = arg.indexOf("##@##");
				var cleanXML = arg.substring(0, endOfCleanXML);
				var $entities = $(createXML(cleanXML));//jQuery object with the Field Directory XML <EntityArray>
				var distanceString = arg.substring(endOfCleanXML + 5);//the rest of the string after the XML
				var distanceArr = distanceString.split('#');
				mapLocatorOffices($entities, distanceArr)
			}
		}
	} catch (exc) {}
}

//Function to which the control is returned if some error occurs in  async call
function ClientCallbackErrorFunction (arg, ctx) {}

function mapLocatorOffices($entities, distanceArr) {
	//Variables to store the min and max latitudes and longitude for bounding
	minLat = 90;//north pole
	maxLat = 0;//equator
	minLng = 0 ;//prime meridian
	maxLng =-180;//international date line
	var numEntities = $entities.find('Entity').length;

	//Create a new table for showing the results
	var resultTable = document.createElement("table");
	resultTable.setAttribute("id","resTable");
	var tblBody = document.createElement("tbody");
	var row = document.createElement("tr");
	var cell = document.createElement("td");
	row.appendChild(cell);
	tblBody.appendChild(row);

	searchMsg += numEntities  + searchMsg3 ;

	if (numEntities > 1) searchMsg += "s" ;
	var lblError = document.getElementById("lblError");
	lblError.className = "nmgol_info_msg";
	lblError.innerHTML = searchMsg ;
	
	//add marker and populate results on left
	var counter = 1;
	$entities.find('Entity').each(function() {
		var $entity = $(this);
		var addressHTML = GenerateAddressHTML($entity, distanceArr[counter-1]);
		if (counter < 11) {//first page of results, add markers to map immediately
		     var showMarker = true;
			CreateMapMarker($entity, counter, addressHTML, showMarker);
		} else {//results that won't be on first page, create marker, but don't add to map yet
		     var showMarker = false;
			CreateMapMarker($entity, counter, addressHTML, showMarker);
		}
		var newRow = CreateResultRow(counter , addressHTML);
		tblBody.appendChild(newRow);
		counter++;
	});

	//center and zoom map to show all results
	var swPoint = new google.maps.LatLng(minLat, minLng);
	var nePoint = new google.maps.LatLng(maxLat, maxLng);
	var resultsBounds = new google.maps.LatLngBounds(swPoint, nePoint);
	nmMap.fitBounds(resultsBounds);
	if (nmMap.getZoom() > minAutoZoomLevel) {
		nmMap.setZoom(minAutoZoomLevel);
	}
	SetMapDefaults();

	//Add all address to the result div
	resultTable.appendChild(tblBody);
	HideSpinner();
	var resultDiv = document.getElementById("resultDiv");
	resultDiv.appendChild(resultTable);

	//show pager if necessary
	if(numEntities > 10) {
		$('#PagerDiv').show();
		pager = new Pager('resTable', 10);
		pager.init();
		pager.showPrevPageNav('pager', 'PagerDiv');
		pager.showPage(myPageNumber);
	}
}

//Function to generate the html for each nm address
function GenerateAddressHTML($entity,  distance) {
	var name = "";
	var address = "";
	var scNum ="";//used for SiteCatalyst tracking

	var type = $entity.children('Type').text();//using children as we don't want to grab Phone Type
	if (type == "FR") {
		var firstName = $entity.find('FirstName').text();
		var middleName = $entity.find('MiddleName').text();
		var lastName = $entity.find('LastName').text();
		if (middleName.length > 0) {
			name = firstName + " " + middleName + " " + lastName;
		} else {
			name = firstName + " " + lastName;
		}
		var title = $entity.find('Title').text();
		address = "<span class='nmgolAddressText' >" + title + "</span><br/>";
		scNum = $entity.find('AgentNum').text();
	} else {//NO or DNO
		name = $entity.find('GroupName').text();
		var noNum = $entity.find('NONum').text();
		var dnoNum = $entity.find('DNONum').text();
		if (dnoNum.length > 0) {
			scNum = noNum + dnoNum;
		} else {
			scNum = noNum + "000";
		}
	}

	var url = $entity.children('URL').text();
	if (url.indexOf("http://") == -1) {
		url = 'http://' + url ;
	}

	name = "<a  href='javascript:void(0)' class='nmgolAddressLink' onclick='openLink (\"" + "OfficeLocatorResults_" + scNum +  "\", \"" + url +"\"); return false ; ' ><b>" + name + "</b></a><br />";

	var street = $entity.find('Street').text();
	var building = $entity.find('Building').text();
	var city = $entity.find('City').text();
	var state = $entity.find('State').text();
	var zip = $entity.find('Zip').text();
	var zip4 = $entity.find('ZipLastFour').text();

	address += "<span class='nmgolAddressText'>" ;
	if (street.length > 0)		address += street + "<br/>";
	if (building.length > 0)		address += building + "<br />";
	if (city.length > 0)		address += city + ", ";
	if (state.length > 0)		address += state + " ";
	if (zip.length > 0)			address += zip;
	if (zip4.length > 0)		address += "-" + zip4;
	address +=  "<br/>";

	var $phones = $entity.find("Phone" );
	$phones.each(function(){
		var $phone = $(this);
		var area = $phone.find('AreaCode').text();
		var ctl = $phone.find('ControlNum').text();
		var unq = $phone.find('UniqueNum').text();
		var ext = $phone.find('Ext').text();
		address += "(" +  area + ") " + ctl + "-" + unq;
		if (ext.length > 0) {
			address += " x" + ext ;
		}
		address += "<br>";
	});

	address += "<br>" + distance + " miles from the center<br /><br /></span>";
	var totalAddress = name + address;
	return totalAddress ;
}

//Function to add a street address
function CreateResultRow(counter, addressHTML){
	var row = document.createElement("tr");
	var cell = document.createElement("td");
	var div = document.createElement('div');

	var imgDiv = document.createElement('div');
	imgDiv.className = "nmgol_left_img";

	var pinUrlPrefix = "http://" + counter % 10 + ".";//http://code.google.com/apis/chart/docs/making_charts.html#enhancements
	var pinUrl = pinUrlPrefix + pinIconStart + counter + pinIconEnd;

	if (navigator.appName.indexOf( "Microsoft Internet Explorer") != -1 ) {
		if( navigator.userAgent.indexOf("MSIE 6.0") != -1) {
			imgDiv.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + pinUrl + '", sizingMethod="scale");';
		} else {
			imgDiv.style.backgroundImage = 'url("' + pinUrl + '")';
		}
	} else {
		imgDiv.style.backgroundImage = 'url("' + pinUrl + '")';
	}

	if(counter%2 == 1) {
		div.className = "nmgol_with_bg";
	} else {
		div.className = "nmgol_no_bg";
	}

	var textDiv = document.createElement('div');
	textDiv.className = "nmgol_right_text";

	div.appendChild(imgDiv);
	if(textDiv.innerHTML != addressHTML )
	textDiv.innerHTML = addressHTML;
	div.appendChild(textDiv);
	cell.appendChild(div);
	row.appendChild(cell);
	return row;
}

//Create Marker for each location and associated InfoWindow
//Add Marker to the map if showMarker=true
function CreateMapMarker($entity, myCounter, addressHTML, showMarker) {
	//Get the latitude and longitude for the nm office
	var myLat = parseFloat($entity.find('Latitude').text());
	var myLng = parseFloat($entity.find('Longitude').text());
	if (myLat > maxLat) maxLat = myLat;
	if (myLat < minLat) minLat = myLat;
	if (myLng > maxLng) maxLng = myLng;
	if (myLng < minLng) minLng = myLng;

	//Change the css class
	addressHTML = addressHTML.replace("nmgolAddressLink" , "nmgolAddressLink nmgolAddressLinkWithBg");

	//Get the current address in a string
	var currentaddress = "";
	var street = $entity.find('Street').text();
	var city = $entity.find('City').text();
	var state = $entity.find('State').text();
	var zip = $entity.find('Zip').text();
	var zip4 = $entity.find('ZipLastFour').text();
	if (street.length > 0)	currentaddress += street + ", " ;
	if (city.length > 0)	currentaddress += city + ", ";
	if (state.length > 0)	currentaddress += state + " ";
	if (zip.length > 0) 	currentaddress += zip;
	if (zip4.length > 0)	currentaddress += "-" + zip4;

	var getDirections = "<br />";
	getDirections += "<input type='text' id='txtDir" + myCounter +
		"' class='nmgolGetDirections' value='Enter starting address'  onclick='clearText("
		+ myCounter +"); " + "' onkeypress='return keyCheck(event, \"btnGetDir" + myCounter + "\");' " + " />";
	//hidden input used for submission on enter key press
	getDirections += "<input id='btnGetDir" + myCounter + "' type='button' style='visibility:hidden; display:none;' "
		+ " onclick='GetMyDirections( " +  myLat + ", " +  myLng + ", " + myCounter + ", \"" + currentaddress + "\"  );' "
		+ " />&nbsp;"  +
		"<img width='99' height='22' class='btnGetDirImg' id='btnimgGetDir" + myCounter
		+ "' src='/NMFNIMAGES/GetDirectionsButton.jpg' "
		+ " onclick='GetMyDirections( " +  myLat + ", " +  myLng + ", " + myCounter + ", \"" + currentaddress + "\"  );' "
		+ " />";

	var myPoint = new google.maps.LatLng(myLat, myLng);
	var pinUrlPrefix = "http://" + myCounter % 10 + ".";//http://code.google.com/apis/chart/docs/making_charts.html#enhancements
	var numberedIcon = pinUrlPrefix + pinIconStartShadow + myCounter + pinIconEnd;
	var markerOptions = {
		position : myPoint,
		icon : numberedIcon
	};
	var nmMarker = new google.maps.Marker(markerOptions);
	
	if (showMarker) {
		nmMarker.setMap(nmMap);
		curMarkersArray.push(nmMarker);//store global reference to this currently visible marker
	}
	allMarkersArray.push(nmMarker);//store global reference to this marker
	
	//InfoWindow example http://code.google.com/apis/maps/documentation/javascript/overlays.html#InfoWindows
	google.maps.event.addListener(nmMarker, 'click', function() {
		if (pano.getVisible() == false) {//street view is not currently visible
			//see if StreetViewPanorama is available within 50 meters
			svService.getPanoramaByLocation(myPoint, 50, function(data, status){//async
				var popupHtml = "<div id='nmgolPopup' >" +  addressHTML;
				if (status == google.maps.StreetViewStatus.OK) {
					var streetView = "<a href=\'javascript:void(0)\' onclick=\"ShowSplitStreetView(\'"
						+ myLat + "\', \'" + myLng
						+ "\'); return false ; \" class='nmgolStreetViewLink' ><b>Street View</b></a>";
					popupHtml += streetView + "<br />" ;
				}
				popupHtml += getDirections  + "</div>" ;
				infoWindow.setContent(popupHtml);
				infoWindow.open(nmMap, nmMarker);
			});
		}
	});
}

//Functions for pager
function Pager(tableName, itemsPerPage) {
	try {
		this.tableName = tableName;
		this.itemsPerPage = itemsPerPage;
		this.currentPage = 1;
		this.pages = 0;
		this.inited = false;
		var rows = document.getElementById(tableName).rows;

		this.showRecords = function(from, to) {
			// i starts from 1 to skip table header row
			for (var i = 1; i < rows.length; i++) {
				if (i < from || i > to) {
					rows[i].style.display = 'none';
				} else {
					rows[i].style.display = '';
				}
			}
			//Remove previous markers and populate new ones
			ShowMarkerRange(from , to);
		}


		this.showPage = function(pageNumber) {
			myPageNumber = pageNumber ;
			if (! this.inited) {
				return;
			}
			var oldPageAnchor = document.getElementById('pg'+this.currentPage);
			oldPageAnchor.className = 'nmgol_pagination_notselected';

			this.currentPage = pageNumber;

			var from = (pageNumber - 1) * itemsPerPage + 1;
			var to = (from + itemsPerPage - 1);

			this.showRecords(from, to);
			if (this.currentPage == 1) {
				this.showPrevPageNav('pager','PagerDiv');
			} else if(this.currentPage == this.pages) {
				this.showNextPageNav('pager','PagerDiv');
			} else {
				this.showPageNav('pager','PagerDiv');
			}

			var newPageAnchor = document.getElementById('pg'+this.currentPage);
			newPageAnchor.className = 'nmgol_pagination_selected';
		}

		this.prev = function() {
			if (this.currentPage > 1) {
				this.showPage(this.currentPage - 1);
			}
		}

		this.next = function() {
			if (this.currentPage < this.pages) {
				this.showPage(this.currentPage + 1);
			}
		}

		this.init = function() {
			var records = (rows.length - 1);
			this.pages = Math.ceil(records / itemsPerPage);
			this.inited = true;
		}

		this.showPrevPageNav = function(pagerName, positionId) {//draws prev, page #, and next links, called on first page
			if (! this.inited) {
				//alert("not inited");
				return;
			}
			var element = document.getElementById(positionId);

			var pagerHtml = '<span id="spPrevious" class="nmgol_disablepagination_notselected"> Prev </span> | ';

			if(this.pages > 5) {
				for (var page = 1; page <= 5; page++) {
					pagerHtml += '<span id="pg' + page + '" class="nmgol_pagination_notselected" onclick="' + pagerName + '.showPage(' + page + ');">' + page + '</span> | ';
				}
			} else {
				for (var page = 1; page <= this.pages; page++) {
					pagerHtml += '<span id="pg' + page + '" class="nmgol_pagination_notselected" onclick="' + pagerName + '.showPage(' + page + ');">' + page + '</span> | ';
				}
			}
			pagerHtml += '<span id="spNext" onclick="'+pagerName+'.next();" class="nmgol_pagination_notselected"> Next </span>';

			element.innerHTML = pagerHtml;
		}

		this.showNextPageNav = function(pagerName, positionId) {
			if (! this.inited) {
				alert("not inited");
				return;
			}
			var element = document.getElementById(positionId);

			var pagerHtml = '<span id="spPrevious" onclick="'+pagerName+'.prev();" class="nmgol_pagination_notselected"> Prev </span> | ';

			var numPages = Math.floor(this.pages/5);
			var lastpage = this.pages%5;
			if(lastpage > 0) {
				numPages += 1;
			}
			var curPage = ((numPages-1)*5) + 1;

			for (var page = curPage; page <= this.pages; page++) {
				pagerHtml += '<span id="pg' + page + '" class="nmgol_pagination_notselected" onclick="' + pagerName + '.showPage(' + page + ');">' + page + '</span> | ';
			}

			pagerHtml += '<span id="spNext" class="nmgol_disablepagination_notselected"> Next </span>';

			element.innerHTML = pagerHtml;
		}

		this.showPageNav = function(pagerName, positionId) {
			if (! this.inited) {
				alert("not inited");
				return;
			}
			var element = document.getElementById(positionId);

			var pagerHtml = '<span onclick="' + pagerName + '.prev();" class="nmgol_pagination_notselected"> Prev </span> | ';
			var numPages = Math.floor(this.pages/5);
			var lastpage = this.pages%5;
			if(lastpage > 0) {
				numPages += 1;
			}
			for(var cnt = 0; cnt < numPages; cnt++) {
				if (Math.floor((this.currentPage-1)/5) == cnt)
				var curPage = (cnt*5) + 1;
			}
			if(curPage != numPages) {
				for (var page = curPage; page < (curPage+5); page++)
				pagerHtml += '<span id="pg' + page + '" class="nmgol_pagination_notselected" onclick="' + pagerName + '.showPage(' + page + ');">' + page + '</span> | ';
			} else {
				for (var page = curPage; page <= this.pages; page++)
				pagerHtml += '<span id="pg' + page + '" class="nmgol_pagination_notselected" onclick="' + pagerName + '.showPage(' + page + ');">' + page + '</span> | ';
			}

			pagerHtml += '<span onclick="'+pagerName+'.next();" class="nmgol_pagination_notselected"> Next </span>';

			element.innerHTML = pagerHtml;
		}
	} catch(ex) {}
}

//Show markers for current page
function ShowMarkerRange(from, to) {
	removeMarkers();
	MakeMapVisible();
	
	//Variables to store the min and max latitudes and longitude for bounding
	minLat = 90;//north pole
	maxLat = 0;//equator
	minLng = 0 ;//prime meridian
	maxLng =-180;//international date line
	
	for (var i=from-1; i<to; i++) {
		var marker = allMarkersArray[i];
		if (marker != null) {
			marker.setMap(nmMap);
			curMarkersArray.push(marker);
			var position = marker.getPosition();
			if (position.lat() < minLat) minLat = position.lat();
			if (position.lat() > maxLat) maxLat = position.lat();
			if (position.lng() < minLng) minLng = position.lng();
			if (position.lng() > maxLng) maxLng = position.lng();
		}
	}
	
	var swPoint = new google.maps.LatLng(minLat, minLng);
	var nePoint = new google.maps.LatLng(maxLat, maxLng);
	var resultsBounds = new google.maps.LatLngBounds(swPoint, nePoint);
	nmMap.fitBounds(resultsBounds);
	if (nmMap.getZoom() > minAutoZoomLevel) {
		nmMap.setZoom(minAutoZoomLevel);
	}
	SetMapDefaults();
}

//shows the split street & map view
function ShowSplitStreetView(lat, lng) {
	infoWindow.close();
	var officeLocation = new google.maps.LatLng(lat, lng);
	pano.setPosition(officeLocation);
	$('#mapDiv').removeClass('nmgol_visibleDiv').addClass('nmgol_visibleDiv_map');
	$('#svDiv').removeClass('nmgol_hiddenDiv').addClass('nmgol_visibleDiv_street');
	nmMap.setStreetView(pano);
	pano.setVisible(true);
	google.maps.event.trigger(nmMap, 'resize');
	nmMap.setCenter(officeLocation);
}

//Function to show the main mapdiv and hide the street view divs
function MakeMapVisible () {
	$('#mapDiv').addClass('nmgol_visibleDiv').removeClass('nmgol_visibleDiv_map');
	$('#svDiv').addClass('nmgol_hiddenDiv').removeClass('nmgol_visibleDiv_street');
	var currentCenter = nmMap.getCenter();
	pano.setVisible(false);
	nmMap.setStreetView(null);//instead of using our pano object, map will now default to its own (which is fullscreen)
	google.maps.event.trigger(nmMap, 'resize');//if we are changing from split screen to fullscreen, this forces map to reestablish its bounds so it draws correctly
	nmMap.setCenter(currentCenter);
}

//get directions button on the info window is clicked
function GetMyDirections(toLat, toLng, myCounter, toaddr){
	var txtBox = document.getElementById('txtDir' + myCounter);
	var fromAddress = txtBox.value;
	var toAddress = toLat + " , " + toLng;

	if (fromAddress.trim() != "") {
		GetDirections(fromAddress, toAddress);
	} else {
		ErrorInDirections();
	}
}

//Function to get the directions and route
function GetDirections(fromAddress, toAddress) {
	//http://code.google.com/apis/maps/documentation/javascript/services.html#Directions
	/*
		switch maps into directions mode
		setup the directions renderer, only needs to be done once
		clear existing results
	*/
	var $resultsDiv = $('#resultDiv');
	if (directionRenderer.getMap() == null) {//directions are being called for the first time
		//save result and pager div HTML for "Back to Search Results"
		resultDiv_beforeDirections = $resultsDiv.html();
		PagerDiv_beforeDirections = $('#PagerDiv').html();
		hideMarkers();
		infoWindow.close();
		directionRenderer.setMap(nmMap);
	}
	ClearResults();
	var $directionsPanel = $('<div>').attr("id", "GoogleDirectionsPanel").prependTo($resultsDiv);
	directionRenderer.setPanel($directionsPanel.get(0));//let Google draw their own directions steps
	
	//create controls to be displayed under driving directions
	var $controls = $('<div id="directionsBottomControls">').appendTo($resultsDiv);
	var $centered = $('<div>').css("text-align", "center").appendTo($controls);
	$('<img>').attr("src","/NMFNIMAGES/reversebutton.jpg")
			.appendTo($centered)
			.click(function(){
				GetDirections(toAddress, fromAddress);
	});
	$('<img>').attr({'id':'PrintImg','src':'/NMFNIMAGES/print.jpg'})
			.appendTo($controls);
	$('<a>').attr({'id':'PrintLink'})
			.text(" Print")
			.addClass('nmgolDirectionsLink')
			.appendTo($controls)
			.click(CreatePrintWindow);
	$('<br>').appendTo($controls);
	$('<a>').text("> Back to Search Results")
			.addClass('nmgolDirectionsLink')
			.appendTo($controls)
			.click(BackToSearchResults);
	
	var directionsRequest = {
		origin : fromAddress,
		destination : toAddress,
		travelMode : google.maps.DirectionsTravelMode.DRIVING,
		region : "US"
	};
	directionService.route(directionsRequest, DirectionsCallback);
}

//callback from Google's DirectionService
function DirectionsCallback(directionsResult, directionsStatus) {
	if (directionsStatus == google.maps.DirectionsStatus.OK) {
		directionRenderer.setDirections(directionsResult);
	} else {
	     ErrorInDirections();
	}
}

//return the map to the state it was in before driving directions were displayed
function BackToSearchResults() {
	directionRenderer.setMap(null);//remove directions from map
	showHiddenMarkers();
	$('#resultDiv').html(resultDiv_beforeDirections);//restore office listing
	$('#PagerDiv').html(PagerDiv_beforeDirections).show();//restore pager
	resultDiv_beforeDirections = null;
	PagerDiv_beforeDirections = null;
}

//Function called in case of error in directions searched for.  Either no text was entered, or Google was unable to find anything.
function ErrorInDirections(){
	var $resultsDiv = $('#resultDiv');
	if (resultDiv_beforeDirections == null) {//ErrorInDirections directly called without first going through GetDirections
		resultDiv_beforeDirections = $resultsDiv.html();
		PagerDiv_beforeDirections = $('#PagerDiv').html();
		hideMarkers();
		infoWindow.close();
	}
	ClearResults();
	
	var $errMsg = $('<div>').addClass('nmgol_dir_errormsg').html(errGetDirections);
	$resultsDiv.append($errMsg);
	
	var $controls = $('<div id="directionsBottomControls">').appendTo($resultsDiv);
	$('<a>').text("> Back to Search Results")
			.addClass('nmgolDirectionsLink')
			.appendTo($controls)
			.click(BackToSearchResults);
}

//Function to clear the default text from the get directions text box in the info window
function clearText(myCounter) {
	try {
	    var txtBox = document.getElementById('txtDir' + myCounter);
	    txtBox.focus();
	    if(txtBox.value == "Enter starting address")
	    txtBox.value = "";
	} catch (exc){}
}

//Creates a new window for print directions
function CreatePrintWindow() {
	var pw = "";//print window HTML string
	pw += '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">';
	pw += '<html>';
	pw += '<head>';
	pw += '<title>Print Map and Directions</title>';
	pw += '<link href="/Style%20Library/NM.css" rel="stylesheet" type="text/css">';
	pw += '<script src="/NMFNJS/jquery-1.3.2.min.js" type="text/javascript" language="javascript"></script>';
	pw += '<script src="/NMFNJS/OfficeLocatorGooglePrint.js" language="javascript" type="text/javascript"></script>';
	pw += '<script type="text/javascript">';
	pw += CreatePrintWindowVariables();
	pw += '</script>';
	pw += '<style type="text/css">@media print{.gmnoprint{display:none}#tblPrintDirectionsTable{display:none}}@media screen{.gmnoscreen{display:none}}';
	pw += '</style>';
	pw += '</head>';
	pw += '<body class="nmgol_print_body">';
	
	pw += '<div id="nmgol_PrintResults">';
	pw += '<table id="tblPrintDirectionsTable">';
	pw += '	<tbody>';
	pw += '	<tr><td>';
	pw += '	<div id="PrintDiv">';
	pw += '	<img src="/NMFNIMAGES/print.jpg">';
	pw += '	<a href="" class="nmgol_link" id="printLink">Print</a>&nbsp;&nbsp;';
	pw += '	<input id="rbtnTextAndMap" name="PrintTextAndMap" checked="checked" type="radio">&nbsp;';
	pw += '	<span class="nmgol_bold">Text &amp; Map</span>&nbsp;';
	pw += '	<input id="rbtnText" name="PrintTextAndMap" type="radio">&nbsp;';
	pw += '	<span class="nmgol_bold">Text Only</span>';
	pw += '	</div></td>';
	pw += '	<td align="right">';
	pw += '	<div id="dirDiv" style="text-align: right;">';
	pw += '	<a class="nmgol_btd" id="closeLink">Back to Directions</a>';
	pw += '	</div></td>';
	pw += '	</tr>';
	pw += '	</tbody>';
	pw += '</table><!-- tblPrintDirectionsDiv -->';
	pw += '<div id="PrintDirDiv"></div><!-- /PrintDirDiv -->';//google populates this
	pw += '<div id="PrintMapDiv"></div><!-- /PrintMapDiv -->';//google populates this
	pw += '</div><!-- /nmgol_PrintResults -->';
	//load order issues in IE, resolved by moving the google maps script into the body and using the bootstrap callback rather than document.ready
	pw += '<script src="http://maps.google.com/maps/api/js?v=3&client=gme-northwesternmutual&sensor=false&callback=initPrintPage" type="text/javascript" ></script>';
	pw += '</body>';
	pw += '</html>';

	var printWindow = window.open("","sub","location=0,resizable=1,toolbar=1,scrollbars=1");
	var printWindowDocument = printWindow.document;
	printWindowDocument.write(pw);
	printWindowDocument.close();

	if(printWindow.focus) {
		printWindow.focus();
	}
}

//return a string representing all the JavaScript variables the print window will need
function CreatePrintWindowVariables() {
	/*
	*	See link for information on undocumented via_waypoint
	*	http://code.google.com/p/gmaps-api-issues/issues/detail?id=2746
	*/
	var routeDraggedWaypointLats = [];
	var routeDraggedWaypointLngs = [];
	var routeDraggedWaypoints = directionRenderer.directions.routes[0].legs[0].via_waypoint;

	for (var i in routeDraggedWaypoints) {
		routeDraggedWaypointLats[i] = routeDraggedWaypoints[i].location.lat();
		routeDraggedWaypointLngs[i] = routeDraggedWaypoints[i].location.lng();
	}
	
	var userWaypointLatString = routeDraggedWaypointLats.toString();//use split() on print page to make it back into array
	var userWaypointLngString = routeDraggedWaypointLngs.toString();//use split() on print page to make it back into array
	var userZoom = nmMap.getZoom();
	var userMapCenterLat = nmMap.getCenter().lat();
	var userMapCenterLng = nmMap.getCenter().lng();
	var startAddress = directionRenderer.directions.routes[0].legs[0].start_address;
	var endAddress = directionRenderer.directions.routes[0].legs[0].end_address;
	
	var printWindowVars = "var userWaypointLatString = '" + userWaypointLatString + "';\n";
	printWindowVars += "var userWaypointLngString = '" + userWaypointLngString + "';\n";
	printWindowVars += "var userZoom = '" + userZoom + "';\n";
	printWindowVars += "var userMapCenterLat = '" + userMapCenterLat + "';\n";
	printWindowVars += "var userMapCenterLng = '" + userMapCenterLng + "';\n";
	printWindowVars += "var startAddress = '" + startAddress + "';\n";
	printWindowVars += "var endAddress = '" + endAddress + "';\n";
	
	return printWindowVars;
}

//Show the map for the initial page load
function ShowInitialMap() {
	var urlParams = window.location.search;
	var zipPattern = /zipcode=([0-9]{5})/i;
	var cityPattern = /city=([^&]+)/i;
	var statePattern = /state=([^&]+)/i;
	try {
		if (zipPattern.test(urlParams) || (cityPattern.test(urlParams) && statePattern.test(urlParams)) ) {//state or city and zip are in the URL querystring
		/*	OfficeOnly=true     always set from widget
		 *	zipcode=" + h_zipcode.value   EITHER
		 *	city=" + h_city.value    OR (w/state)
		 *	state=" + h_state.value  OR (w/city)
		 */
			var queryStringAddress = "";
			if (zipPattern.test(urlParams)) {
				queryStringAddress = zipPattern.exec(urlParams)[1];
			}
			if (cityPattern.test(urlParams) && statePattern.test(urlParams)) {
				var city = cityPattern.exec(urlParams)[1];
				var state = statePattern.exec(urlParams)[1];
				queryStringAddress = city + " " + state;
			}
			var geocodeRequest = {
				region : "US",
				address : queryStringAddress
			};
			geocoder.geocode(geocodeRequest, GeocodeCallbackOfficeOnly);
		} else {
			var clientLatitude;
			var clientLongitude;
			if (geoip_latitude() != null) {//function from MaxMind's geoip.js is available, user is geolocated
				clientLatitude = geoip_latitude();
				clientLongitude = geoip_longitude();
				var visitorLatLng = new google.maps.LatLng(clientLatitude, clientLongitude);
				nmMap.setCenter(visitorLatLng);
				SetMapDefaults();
				//Set the city and state from the Maxmind web service
				PopulateSearchFields();
				//Do a asynchronous call to server to fetch the nm offices within the current map scope
				var backendData = clientLatitude + "#" +  clientLongitude + "#20";//formatted this way for the Sharepoint service
				DoCallback(backendData, 'OfficeLocatorGoogleMaps');
			} else {//MaxMind not available
				ShowDefaultUSMap();
			}
		}
	} catch (Exc) {
		// If maxmind is not available then display below error message
		var lblError = document.getElementById("lblError");
		lblError.className = "nmgol_error_msg";
		lblError.innerHTML = errResults;
		HideSpinner();
		return true;
	}
}

//Function to set the default map of US in case of no results
function ShowDefaultUSMap(){
	HideSpinner();
	var USAcenter = new google.maps.LatLng(38, -98);
	var mapOptions = {
		zoom: zoomLevel_USA,
		center: USAcenter,
		mapTypeId: google.maps.MapTypeId.ROADMAP
	};
	nmMap.setOptions(mapOptions);

	//Show no borders to the result div
	var resultDiv = document.getElementById("resultDiv");
	resultDiv.className = "nmgol_Results_WhiteBorder";
}

//Populates search fields based on MaxMind data
function PopulateSearchFields() {
	var state = geoip_region();//two char state abbreviation
	var city = geoip_city();
	if ((state != null) && (city  != null)) {//maxmind returned value for city and state
		$('#txtCity').val(city);
		$('#slState').val(state);
	}
	//show the user what was searched for
	searchMsg = searchMsg1 + city + ", " + state + searchMsg2;
}

//Function to get the miles for the map
function GetZoomDistance() {
	var slDistance = document.getElementById("slDistance");
	var distance  = 20;
	switch (slDistance.selectedIndex) {
		case 0:
			distance = 5;
			break;
		case 1:
			distance = 10;
			break;
		case 2:
			distance = 20;
			break;
		case 3:
			distance = 30;
			break;
		case 4:
			distance = 50;
			break;
		case 5:
			distance = 100;
			break;				
	} 
	return distance;
}

//Clear results div and pager, and hide the pager
function ClearResults() {
	$('#resultDiv').empty();
	$('#PagerDiv').empty().hide();
}

//show a spinning graphic while waiting for async results
function ShowSpinner() {
	var resultDiv = document.getElementById("resultDiv");
	var swrillImage = document.createElement('img');
	swrillImage.id ='swrillImage';
	swrillImage.src = "/NMFNIMAGES/ajax-loader.gif";
	swrillImage.style.position = 'absolute';
	swrillImage.style.top = '50%';
	swrillImage.style.left = '50%';
	swrillImage.style.marginLeft = '-20px';
	swrillImage.style.marginTop = '-40px';
	swrillImage.style.zIndex = '60';
	resultDiv.appendChild(swrillImage);
}

//hide the spinning graphic
function HideSpinner() {
	$('#swrillImage').remove();
}

//Set the map settings to default, basically just make sure its the roadmap
function SetMapDefaults() {
	nmMap.setMapTypeId(google.maps.MapTypeId.ROADMAP);
}


//function to display only offices when redirected from widget page
function GeocodeCallbackOfficeOnly(geocodeResults, geocodeStatus) {
	if (geocodeStatus == google.maps.GeocoderStatus.OK) {
		var firstResult = geocodeResults[0];
		var location = firstResult["geometry"]["location"];
		var lat = location.lat();
		var lng = location.lng();
		var olData = lat + "#" +  lng + "#20";//defaults to 20 miles for OfficeOnly=true
		var zipcode;
		var city;
		var state;
		
		//update the searchMsg, which is shown in lblError.  Shows message like "Search for 66762 returned 2 results"
		var q_string = window.location.search.substring(1);
		if(q_string.toLowerCase().indexOf("zipcode") != -1) {
			zipcode = q_string.substring(q_string.toLowerCase().indexOf("zipcode")+8);
			searchMsg = searchMsg1 + zipcode + searchMsg2;
		} else if((q_string.toLowerCase().indexOf("city")) && (q_string.toLowerCase().indexOf("state"))) {
			city = q_string.substring(q_string.toLowerCase().indexOf("city")+5,q_string.toLowerCase().indexOf("state")-1);
			var c_1 = city.substring(0,1);
			var c_2 = city.substring(1,city.length);
			city = unescape(c_1.toUpperCase() + c_2);
			state = q_string.substring(q_string.toLowerCase().indexOf("state")+6);
			searchMsg = searchMsg1 + city + ", " + state + searchMsg2 ;
		}
		
		//populate inputs with the values that were searched on (from query string params)
		if ((state != null) && (city  != null)) {
			var txtCity= document.getElementById("txtCity");
			txtCity.value = city ;
			var slState= document.getElementById("slState");
			for (var stateCnt = 1; stateCnt <= 50; ++stateCnt) {
				if ( slState.options[stateCnt].innerHTML == state ) {
					slState.selectedIndex = stateCnt ;
					break;
				}
			}
		} else if(zipcode != null) {
			var txtZipcode = document.getElementById("txtZipCode");
			txtZipcode.value = zipcode;
		}
		
		//call back-end to get offices for this location
		DoCallback(olData, 'OfficeLocatorGoogleMaps');
		
	} else {
		var lblError = document.getElementById("lblError");
		lblError.className = "nmgol_error_msg";
		if (searchType == 0) {//zip code search
			lblError.innerHTML = errZipCode;
		} else {//city/state search
			lblError.innerHTML = errResults;
		}
		ShowDefaultUSMap();
	}
}

//remove all marker pins from the map
//http://code.google.com/apis/maps/documentation/javascript/overlays.html#RemovingOverlays
function removeMarkers() {
	if (curMarkersArray) {
		for (i in curMarkersArray) {
			curMarkersArray[i].setMap(null);
		}
		curMarkersArray.length = 0;
	}
}

//hide markers, but don't delete them
function hideMarkers() {
	if (curMarkersArray) {
		for (i in curMarkersArray) {
			curMarkersArray[i].setVisible(false);
		}
	}
}

//show markers that were previously hidden
function showHiddenMarkers() {
	//restore map zoom and centering using previously calculated min and max coords
	var swPoint = new google.maps.LatLng(minLat, minLng);
	var nePoint = new google.maps.LatLng(maxLat, maxLng);
	var resultsBounds = new google.maps.LatLngBounds(swPoint, nePoint);
	nmMap.fitBounds(resultsBounds);
	if (nmMap.getZoom() > minAutoZoomLevel) {
		nmMap.setZoom(minAutoZoomLevel);
	}

	if (curMarkersArray) {
		for (i in curMarkersArray) {
			curMarkersArray[i].setVisible(true);
		}
	}
}

function createXML(data) {
	var xml;
	if ($.browser.msie) {//IE 6, 7, 8
		xml = new ActiveXObject("Microsoft.XMLDOM");
		xml.async = false;
		xml.loadXML(data);
	} else {
		xml = data;
	}
	return xml;
}

//Function to open links in new window after calling the site catalyst code
function openLink(linkName, url) {
	var anchorElement = this;
	recordSiteCatalystCustomLink(anchorElement, linkName);
	window.open (url, "", "");
}
