// CONSTANTS

// GLOBAL VARIABLES
var isIncludedLoaded = false;
var isSynonymsLoaded = false;
var isMapLoaded = false;
var isLiteratureLoaded = false;
var isTypesLoaded = false;
var isAssociationsLoaded = false;
var isHabitatsLoaded = false;
var isImagesLoaded = false;
var isOtherDBsLoaded = false;
var isTreatmentLoaded = false;
var isKeysLoaded = false;
var currentCoords = {lat: 0, long: 0};
var g_currentLit = null;
var g_currentLitFiltered = null;
var g_currentTypes = null;
var g_currentTypesFiltered = null;
var g_currentImages = null;
var g_currentAssocs = null;
var g_currentBreakdown = null;
var g_currentPhenology = null;
var g_bHideEmpty = false;
var g_nPhenologyView = 0; // By Year
var g_bValidOnly = false;
var g_bYearValidOnly = false;

// FUNCTIONS
function loader() {
	processInfoText();
	
	// Set current URL for links
	currentURL = location.href;
	
	if (currentURL.substring(0, currentURL.indexOf('?')).length > 0) {
		currentURL = currentURL.substring(0, currentURL.indexOf('?'));
	}
	
	// Set the page tnuid from query string variable, if set
	var tnuid = getQueryVariable('id');
	
	if (tnuid != -1) {
		currentTNUID = tnuid;
	} else if (currentURL == 'http://osuc.biosci.ohio-state.edu/Acarology/') {
		// Set default taxon for Mites (Acari)
		currentTNUID = 44503;
	}
	
	// Show DB-queried parts
	showHierarchy();
	showSections();
	loadSectionGeneral();
	
	// Google Analytics Tracking Processing
	try {
		var pageTracker = _gat._getTracker("UA-8677186-1");
		pageTracker._trackPageview();
	} catch(err) {}
}

function toggleSection(szSectionID, szIconID) {
	var section = document.getElementById(szSectionID);
	var icon = document.getElementById(szIconID);
	
	if (section) {
		if (section.style.visibility != 'visible') {
			// See if section needs loaded
			switch (szSectionID) {
				case 'hymIncludedBodyID': {
					// Check if section was already loaded
					if (isIncludedLoaded != true) {
						loadSectionIncluded();
					}
					break;
				}
				case 'hymSynonymsBodyID': {
					// Check if section was already loaded
					if (isSynonymsLoaded != true) {
						loadSectionSynonyms();
					}
					break;
				}
				case 'hymMapBodyID': {
					// Check if section was already loaded
					if (isMapLoaded != true) {
						loadMap();
					}
					break;
				}
				case 'hymLiteratureBodyID': {
					// Check if section was already loaded
					if (isLiteratureLoaded != true) {
						loadSectionLiterature();
					}
					break;
				}
				case 'hymTypesBodyID': {
					// Check if section was already loaded
					if (isTypesLoaded != true) {
						loadSectionTypes();
					}
					break;
				}
				case 'hymAssociationsBodyID': {
					// Check if section was already loaded
					if (isAssociationsLoaded != true) {
						loadSectionAssociations();
					}
					break;
				}
				case 'hymHabitatsBodyID': {
					// Check if section was already loaded
					if (isHabitatsLoaded != true) {
						loadSectionHabitats();
					}
					break;
				}
				case 'hymImagesBodyID': {
					// Check if section was already loaded
					if (isImagesLoaded != true) {
						loadSectionImages();
					}
					break;
				}
				case 'hymOtherDBsBodyID': {
					break;
				}
				case 'hymTreatmentBodyID': {
					break;
				}
				case 'hymKeysBodyID': {
					break;
				}
			}
			
			section.style.display = 'block';
			section.style.visibility = 'visible';
			icon.src = ICON_COLLAPSE_LOCATION;
			icon.title = 'collapse';
		} else {
			section.style.display = 'none';
			section.style.visibility = 'hidden';
			icon.src = ICON_EXPAND_LOCATION;
			icon.title = 'expand';
		}
	}
}

function showSections() {
	var urlStats = BASE_URL + 'OJ_Break.getTaxonStats?tnuid=' + currentTNUID + '&callback=handleSections';
	
	// Show loading image for sections
	showLoadingImage('hymBodyLoadingID');
	
	sendJSONRequest(urlStats);
}

function handleSections(jData) {
	if (jData == null) {
		// Parse problem so return
		return;
	}
	
	var section;
	var stats = jData.stats;
	
	// Hide loading image
	section = document.getElementById('hymBodyLoadingID');
	section.style.display = 'none';
	section.style.visibility = 'hidden';
	
	// Show sections based on whether there are data for them
	
	// General section is always displayed
	section = document.getElementById('hymSectionGeneralID');
	section.style.display = 'block';
	section.style.visibility = 'visible';
	
	// Always show maps, types, and literature
	document.getElementById('hymMapTitleID').innerHTML += ' (' + stats.maps + ')';
	
	section = document.getElementById('hymSectionMapID');
	section.style.display = 'block';
	section.style.visibility = 'visible';
	
	document.getElementById('hymLiteratureTitleID').innerHTML += ' (' + stats.lits + ')';
	
	section = document.getElementById('hymSectionLiteratureID');
	section.style.display = 'block';
	section.style.visibility = 'visible';
	
	document.getElementById('hymTypesTitleID').innerHTML += ' (' + stats.type_syns + ')';
	
	section = document.getElementById('hymSectionTypesID');
	section.style.display = 'block';
	section.style.visibility = 'visible';
	
	// Check if sections have content and should be displayed
	if (stats.included > 0) {
		document.getElementById('hymIncludedTitleID').innerHTML += ' (' + stats.included + ')';
		
		section = document.getElementById('hymSectionIncludedID');
		section.style.display = 'block';
		section.style.visibility = 'visible';
	}
	if (stats.synonym > 0) {
		document.getElementById('hymSynonymsTitleID').innerHTML += ' (' + stats.synonym + ')';
		
		section = document.getElementById('hymSectionSynonymsID');
		section.style.display = 'block';
		section.style.visibility = 'visible';
	}
	if (stats.assocs > 0) {
		document.getElementById('hymAssociationsTitleID').innerHTML += ' (' + stats.assocs + ')';
		
		section = document.getElementById('hymSectionAssociationsID');
		section.style.display = 'block';
		section.style.visibility = 'visible';
	}
	if (stats.habitats > 0) {
		document.getElementById('hymHabitatsTitleID').innerHTML += ' (' + stats.habitats + ')';
		
		section = document.getElementById('hymSectionHabitatsID');
		section.style.display = 'block';
		section.style.visibility = 'visible';
	}
	if (stats.images > 0) {
		document.getElementById('hymImagesTitleID').innerHTML += ' (' + stats.images + ')';
		
		section = document.getElementById('hymSectionImagesID');
		section.style.display = 'block';
		section.style.visibility = 'visible';
	}
	if (stats.keys > 0) {
		document.getElementById('hymKeysTitleID').innerHTML += ' (' + stats.keys + ')';
		
		section = document.getElementById('hymSectionKeysID');
		section.style.display = 'block';
		section.style.visibility = 'visible';
	}
	
	// Prepare other DB queries
	prepareGenBank();
}

function showChildInfo(tnuid, taxon, rank) {
	urlStats = BASE_URL + 'OJ_Break.getTaxonStats?tnuid=' + tnuid + '&callback=handleChildInfo';
	
	// Set temporary popup variables to hold taxon name w/ author and rank
	popupTemp1 = taxon;
	popupTemp2 = rank;
	
	// Show loading image within popup
	showLoadingImage('hymBodyPopupTextID');
	togglePopup('hymBodyPopupID', true);
	
	sendJSONRequest(urlStats);
}

function handleChildInfo(jData) {
	if (jData == null) {
		// Parse problem so return
		return;
	}
	
	var stats = jData.stats;
	var resultHTML = '';
	
	// Generate the beginning of the info popup (fill in info with temp popup variables)
	resultHTML += '<div class="hymPopupTextTitle">' + popupTemp1 + ' Info</div><hr>Taxonomic Rank: ' + popupTemp2 + '<br>Available Information:<ul>';
	
	// Check if stats are available
	if (stats.included > 0) {
		resultHTML += '<li>Included Taxa (' + stats.included + ')</li>';
	}
	if (stats.synonym > 0) {
		resultHTML += '<li>Synonyms (' + stats.synonym + ')</li>';
	}
	if (stats.maps > 0) {
		resultHTML += '<li>Map (' + stats.maps + ')</li>';
	}
	if (stats.lits > 0) {
		resultHTML += '<li>Literature (' + stats.lits + ')</li>';
	}
	if (stats.types > 0) {
		resultHTML += '<li>Types (' + stats.types + ')</li>';
	}
	if (stats.assocs > 0) {
		resultHTML += '<li>Associations (' + stats.assocs + ')</li>';
	}
	if (stats.habitats > 0) {
		resultHTML += '<li>Habitats (' + stats.habitats + ')</li>';
	}
	if (stats.images > 0) {
		resultHTML += '<li>Images (' + stats.images + ')</li>';
	}
	if (stats.dbs > 0) {
		resultHTML += '<li>Other DBs (' + stats.dbs + ')</li>';
	}
	if (stats.keys > 0) {
		resultHTML += '<li>Keys (' + stats.dbs + ')</li>';
	}
	
	// Generate the end of the info popup
	resultHTML += '</ul>';
	
	// Set the result HTML to the popup text
	document.getElementById('hymBodyPopupTextID').innerHTML = resultHTML;
}

function loadSectionGeneral() {
	var urlGeneral = BASE_URL + 'OJ_Break.getTaxonInfo?tnuid=' + currentTNUID + '&callback=handleGeneral';
	
	// Show loading image for sections
	showLoadingImage('hymGeneralBodyID');
	
	sendJSONRequest(urlGeneral);
}

function handleGeneral(jData) {
	if (jData == null) {
		// Parse problem so return
		return;
	}
	
	// Fill in RSS information
	document.getElementById('hymGeneralTitleRSSID').innerHTML = '<a href="rss.html?id=' + currentTNUID + '&name=' + encodeURL(jData.taxon) + '&type=tnuid"><img src="/HymOnline/rss_icon.gif" title="Signup for an HOL RSS feed for this taxon"></a>';
	
	// Show general taxon info
	var szResultHTML = '<div class="hymSectionBodyItem">' + jData.rank + ': <span class="boldedText">' + jData.taxon + '</span><br>Author: <span class="boldedText">' + jData.author + '</span><br>Status: <span class="boldedText">' + jData.valid + ', ' + jData.status + '</span><br>';
	
	// If type species is defined, show the type species
	if (jData.type_species) {
		var type_species = jData.type_species;
		
		szResultHTML += '<span class="indent">Type Species: <span class="boldedText"><a href="index.html?id=' + type_species.id + '">' + type_species.taxon + '</a> ' + type_species.author + '</span></span><br>';
	}
	
	// If current taxon is invalid, show the valid taxon
	if (jData.valid == 'Invalid') {
		var valid_taxon = jData.valid_taxon;
		
		szResultHTML += '<span class="indent">Valid Name: <span class="boldedText"><a href="index.html?id=' + valid_taxon.id + '">' + valid_taxon.taxon + '</a> ' + valid_taxon.author + '</span></span><br>';
	}
	
	szResultHTML += 'Rank: <span class="boldedText">' + jData.rank + '</span>';
	
	// Check if original description citation needs shown
	if (jData.orig_desc) {
		szResultHTML += '<br>Original description citation: <span class="boldedText">' + formatReference(jData.orig_desc, true) + '</span>';
	}
	
	szResultHTML += '</div>';
	
	// Show general options
	szResultHTML += '<br><div class="underlinedText">Graphs</div><div class="hymSectionBodyItem"><a href="javascript:toggleSection(\'hymGeneralTaxaBreakdownBodyID\', \'hymGeneralTaxaBreakdownTitleIcon\');loadTaxonBreakdown();"><img src="/HymOnline/icon-expand.png" title="expand" id="hymGeneralTaxaBreakdownTitleIcon"></a> <span class="underlinedText">Taxon Breakdown</span></div><div class="hymSubSectionBody" id="hymGeneralTaxaBreakdownBodyID"><!-- To Be DB Generated //--></div><div class="hymSectionBodyItem"><a href="javascript:toggleSection(\'hymGeneralTaxonPhenologyBodyID\', \'hymGeneralTaxonPhenologyTitleIcon\');loadTaxonPhenology();"><img src="/HymOnline/icon-expand.png" title="expand" id="hymGeneralTaxonPhenologyTitleIcon"></a> <span class="underlinedText">Taxon Phenology</span></div><div class="hymSubSectionBody" id="hymGeneralTaxonPhenologyBodyID"><!-- To Be DB Generated //--></div><div class="hymSectionBodyItem"><a href="javascript:toggleSection(\'hymGeneralTaxonTaxaByPubsBodyID\', \'hymGeneralTaxonTaxaByPubsTitleIcon\');loadTaxaByPubs();"><img src="/HymOnline/icon-expand.png" title="expand" id="hymGeneralTaxonTaxaByPubsTitleIcon"></a> <span class="underlinedText">Available Taxa by Publication</span></div><div class="hymSubSectionBody" id="hymGeneralTaxonTaxaByPubsBodyID"><!-- To Be DB Generated //--></div><div class="hymSectionBodyItem"><a href="javascript:toggleSection(\'hymGeneralTaxonTaxaByYearBodyID\', \'hymGeneralTaxonTaxaByYearTitleIcon\');loadTaxaByYear();"><img src="/HymOnline/icon-expand.png" title="expand" id="hymGeneralTaxonTaxaByYearTitleIcon"></a> <span class="underlinedText">Available Taxa by Year</span></div><div class="hymSubSectionBody" id="hymGeneralTaxonTaxaByYearBodyID"><!-- To Be DB Generated //--></div><div class="hymSectionBodyItem"><a href="javascript:toggleSection(\'hymGeneralTaxonSizeByLatBodyID\', \'hymGeneralTaxonSizeByLatTitleIcon\');loadSizeByLatitude();"><img src="/HymOnline/icon-expand.png" title="expand" id="hymGeneralTaxonSizeByLatTitleIcon"></a> <span class="underlinedText">Specimen Size By Latitude</span></div><div class="hymSubSectionBody" id="hymGeneralTaxonSizeByLatBodyID"><!-- To Be DB Generated //--></div>';
	
	// Set the HTML of the section to be the results and set as loaded
	document.getElementById('hymGeneralBodyID').innerHTML = szResultHTML;
	
	isGeneralLoaded = true;
}

function loadTaxonBreakdown(bHideEmpty) {
	if (bHideEmpty == undefined) {
		g_bHideEmpty = false;
	} else {
		g_bHideEmpty = bHideEmpty;
	}
	
	if (g_currentBreakdown) {
		handleBreakdown();
	} else {
		var urlBreakdown = BASE_URL + 'OJ_Break.getTaxonBreakdown?tnuid=' + currentTNUID + '&callback=handleBreakdown';
		
		// Show loading image for sections
		showLoadingImage('hymGeneralTaxaBreakdownBodyID');
		
		sendJSONRequest(urlBreakdown);
	}
}

function handleBreakdown(jData) {
	if (jData == undefined) {
		// Do nothing
	} else if (jData == null) {
		// Parse problem so return
		return;
	} else {
		g_currentBreakdown = jData;
	}
	
	// Show taxon breakdown
	var taxa = g_currentBreakdown.taxa;
	var szResultHTML = '<div class="hymGraph" id="taxonBreakdownGraph"></div><ol><span class="underlinedText">Taxa</span>';
	
	// Check if taxa without specimens should be shown
	if (g_bHideEmpty) {
		szResultHTML += '<input type="radio" name="emptyDisplayBox" onClick="javascript:loadTaxonBreakdown(false);"><span title="Show taxa without any specimens">Show</span> <input type="radio" name="emptyDisplayBox" checked="checked" onClick="javascript:loadTaxonBreakdown(true);"><span title="Hide taxa without any specimens">Hide</span>';
	} else {
		szResultHTML += '<input type="radio" name="emptyDisplayBox" checked="checked" onClick="javascript:loadTaxonBreakdown(false);"><span title="Show taxa without any specimens">Show</span> <input type="radio" name="emptyDisplayBox" onClick="javascript:loadTaxonBreakdown(true);"><span title="Hide taxa without any specimens">Hide</span>';
	}
	
	// Sort the taxa by number of specimens
	taxa.sort(sortSpmByQuantity);
	
	// Load the Google visualization package
	google.load('visualization', '1', {'packages': ['columnchart'], 'callback': drawBreakdownGraph});
	
	function drawBreakdownGraph() {
		// Prepare the graph
		var dataTaxa = new google.visualization.DataTable();
		dataTaxa.addColumn('string', 'Taxon');
		dataTaxa.addColumn('number', '# of Specimens');
		
		// Load the results
		for (var taxonCount = 0; taxonCount < taxa.length; taxonCount++) {
			var taxon = taxa[taxonCount];
			
			// Check if taxon should be shown
			if (!g_bHideEmpty || taxon.count > 0) {
				var nRowIndex = dataTaxa.addRow();
				dataTaxa.setValue(nRowIndex, 0, taxon.taxon);
				dataTaxa.setValue(nRowIndex, 1, Number(taxon.count));
				
				szResultHTML += '<li><a href="index.html?id=' + taxon.tnuid + '">' + taxon.taxon + '</a> ' + taxon.author + ': ' + taxon.count + '</li>';
			}
		}
		
		szResultHTML += '</ol>';
		
		// Show the specimen number and sexes
		var sexes = g_currentBreakdown.sex;
		var nFemales = 0;
		var nMales = 0;
		var nUnsexed = 0;
		
		if (sexes.F) {
			nFemales = sexes.F;
		}
		if (sexes.M) {
			nMales = sexes.M;
		}
		if (sexes.U) {
			nUnsexed = sexes.U;
		}
		
		szResultHTML += '<div class="hymSectionBodyItem">Total Number of Specimens: <span class="boldedText">' + (nFemales + nMales + nUnsexed) + '</span></div>';
		szResultHTML += '<div class="hymSectionBodyItem">Number of Females: <span class="boldedText">' + nFemales + '</span></div>';
		szResultHTML += '<div class="hymSectionBodyItem">Number of Males: <span class="boldedText">' + nMales + '</span></div>';
		szResultHTML += '<div class="hymSectionBodyItem">Number of Unspecified: <span class="boldedText">' + nUnsexed + '</span></div>';
		
		// Set the HTML of the section to be the results and set as loaded
		document.getElementById('hymGeneralTaxaBreakdownBodyID').innerHTML = szResultHTML;
		
		// Display the bar graph
		var chart = new google.visualization.ColumnChart(document.getElementById('taxonBreakdownGraph'));
		chart.draw(dataTaxa, {width: 600, height: 400, showCategories: false, colors: ['#993300'], backgroundColor: '#E8E8E8', legend: 'none'});
	}
}

function loadTaxonPhenology(nPhenologyView) {
	if (nPhenologyView == undefined) {
		g_nPhenologyView = 0;
	} else {
		g_nPhenologyView = nPhenologyView;
	}
	
	if (g_currentPhenology) {
		handlePhenology();
	} else {
		var urlPhenology = BASE_URL + 'OJ_Break.getTaxonPhenology?tnuid=' + currentTNUID + '&callback=handlePhenology';
		
		// Show loading image for sections
		showLoadingImage('hymGeneralTaxonPhenologyBodyID');
		
		sendJSONRequest(urlPhenology);
	}
}

function handlePhenology(jData) {
	if (jData == undefined) {
		// Do nothing
	} else if (jData == null) {
		// Parse problem so return
		return;
	} else {
		g_currentPhenology = jData;
	}
	
	// Show taxon phenology
	var spms = g_currentPhenology.spms;
	var szResultHTML = '<div class="hymGraph" id="taxonPhenologyGraph"></div><span class="underlinedText">Group Dates By</span>';
	
	// Load the Google visualization package
	google.load('visualization', '1', {'packages': ['columnchart'], 'callback': drawPhenologyGraph});
	
	function drawPhenologyGraph() {
		// Prepare the graph
		var dataDate = new google.visualization.DataTable();
		
		// Check on which date grouping is specified
		if (g_nPhenologyView == 1) {
			// Setup columns
			dataDate.addColumn('string', 'Month');
			dataDate.addColumn('number', '# of Specimens');
			
			// Group by month
			szResultHTML += '<input type="radio" name="phenologyDisplayBox" onClick="javascript:loadTaxonPhenology(0);"><span title="Group the specimens in the phenology graph by year">Year</span> <input type="radio" name="phenologyDisplayBox" checked="checked" onClick="javascript:loadTaxonPhenology(1);"><span title="Group the specimens in the phenology graph by month">Month</span>';
			
			spms.sort(sortSpmByMonth);
			
			// Load the results
			// Check if any specimen are present
			if (spms.length > 0) {
				var currentMonth = 0;
				var currentMonCount = 0;
				var currentSpmCount = 0;
				
				while (currentMonth <= 11) {
					// Make sure current specimen exists
					if (currentSpmCount < spms.length) {
						// Check if current specimen was collected in same month as previous specimen
						if (currentMonth + 1 < spms[currentSpmCount].coll_month) {
							// Add month with specimens
							var nRowIndex = dataDate.addRow();
							dataDate.setValue(nRowIndex, 0, getMonthFromInt(currentMonth));
							dataDate.setValue(nRowIndex, 1, Number(currentMonCount));
							
							szResultHTML += '<div class="hymSectionBodyItem">' + getMonthFromInt(currentMonth) + ': ' + currentMonCount + '</div>';
							
							// Increment month until new specimen month is reached
							currentMonth++;
							currentMonCount = 0;
							
							while (currentMonth + 1 < spms[currentSpmCount].coll_month) {
								// Add year without any specimens
								var nRowIndex = dataDate.addRow();
								dataDate.setValue(nRowIndex, 0, getMonthFromInt(currentMonth));
								dataDate.setValue(nRowIndex, 1, 0);
								
								szResultHTML += '<div class="hymSectionBodyItem">' + getMonthFromInt(currentMonth) + ': ' + currentMonCount + '</div>';
								
								currentMonth++;
								currentMonCount = 0;
							}
						}
						
						currentMonCount++;
						currentSpmCount++;
					} else {
						// Add month with specimens
						var nRowIndex = dataDate.addRow();
						dataDate.setValue(nRowIndex, 0, getMonthFromInt(currentMonth));
						dataDate.setValue(nRowIndex, 1, Number(currentMonCount));
						
						if (currentMonCount > 0) {
							szResultHTML += '<div class="hymSectionBodyItem">' + getMonthFromInt(currentMonth) + ': ' + currentMonCount + '</div>';
						}
						
						currentMonth++;
						currentMonCount = 0;
					}
				}
			} else {
				// Do nothing
			}
		} else {
			// Setup columns
			dataDate.addColumn('string', 'Year');
			dataDate.addColumn('number', '# of Specimens');
			
			// Group by year
			szResultHTML += '<input type="radio" name="phenologyDisplayBox" checked="checked" onClick="javascript:loadTaxonPhenology(0);"><span title="Group the specimens in the phenology graph by year">Year</span> <input type="radio" name="phenologyDisplayBox" onClick="javascript:loadTaxonPhenology(1);"><span title="Group the specimens in the phenology graph by month">Month</span>';
			
			spms.sort(sortSpmByYear);
			
			// Load the results
			var currentDate = new Date();
			
			// Check if any specimen are present
			if (spms.length > 0) {
				var currentYear = spms[0].coll_year;
				var currentYearCount = 0;
				var currentSpmCount = 0;
				
				while (currentYear <= currentDate.getFullYear()) {
					// Make sure current specimen exists
					if (currentSpmCount < spms.length) {
						// Check if current specimen was collected in same year as previous specimen
						if (currentYear < spms[currentSpmCount].coll_year) {
							// Add year with specimens
							var nRowIndex = dataDate.addRow();
							dataDate.setValue(nRowIndex, 0, String(currentYear));
							dataDate.setValue(nRowIndex, 1, currentYearCount);
							
							szResultHTML += '<div class="hymSectionBodyItem">' + currentYear + ': ' + currentYearCount + '</div>';
							
							// Increment year until new specimen year is reached
							currentYear++;
							currentYearCount = 0;
							
							while (currentYear < spms[currentSpmCount].coll_year) {
								// Add year without any specimens
								var nRowIndex = dataDate.addRow();
								dataDate.setValue(nRowIndex, 0, String(currentYear));
								dataDate.setValue(nRowIndex, 1, 0);
								
								currentYear++;
								currentYearCount = 0;
							}
						}
						
						currentYearCount++;
						currentSpmCount++;
					} else {
						// Add year with specimens
						var nRowIndex = dataDate.addRow();
						dataDate.setValue(nRowIndex, 0, String(currentYear));
						dataDate.setValue(nRowIndex, 1, currentYearCount);
						
						if (currentYearCount > 0) {
							szResultHTML += '<div class="hymSectionBodyItem">' + currentYear + ': ' + currentYearCount + '</div>';
						}
						
						currentYear++;
						currentYearCount = 0;
					}
				}
			} else {
				var nRowIndex = dataDate.addRow();
				dataDate.setValue(nRowIndex, 0, String(currentDate.getFullYear()));
				dataDate.setValue(nRowIndex, 1, 0);
			}
		}
		
		// Set the HTML of the section to be the results and set as loaded
		document.getElementById('hymGeneralTaxonPhenologyBodyID').innerHTML = szResultHTML;
		
		// Display the bar graph
		var chart = new google.visualization.ColumnChart(document.getElementById('taxonPhenologyGraph'));
		chart.draw(dataDate, {width: 600, height: 400, showCategories: true, colors: ['#993300'], backgroundColor: '#E8E8E8', legend: 'none'});
	}
}

function getMonthFromInt(nMonth) {
	switch (nMonth) {
		case 0: { return 'January'; break; }
		case 1: { return 'February'; break; }
		case 2: { return 'March'; break; }
		case 3: { return 'April'; break; }
		case 4: { return 'May'; break; }
		case 5: { return 'June'; break; }
		case 6: { return 'July'; break; }
		case 7: { return 'August'; break; }
		case 8: { return 'September'; break; }
		case 9: { return 'October'; break; }
		case 10: { return 'November'; break; }
		default: { return 'December'; break; }
	}
}

function loadTaxaByPubs(bValidOnly) {
	var urlTaxaByPub = BASE_URL + 'OJ_Break.getTaxonNewTaxaByPub?tnuid=' + currentTNUID + '&callback=handleTaxaByPubs';
	
	if (bValidOnly == undefined || !bValidOnly) {
		g_bValidOnly = false;
		
		urlTaxaByPub += '&validOnly=N';
	} else {
		g_bValidOnly = true;
		
		urlTaxaByPub += '&validOnly=Y';
	}
	
	// Show loading image for sections
	showLoadingImage('hymGeneralTaxonTaxaByPubsBodyID');
	
	sendJSONRequest(urlTaxaByPub);
}

function handleTaxaByPubs(jData) {
	if (jData == undefined) {
		// Do nothing
	} else if (jData == null) {
		// Parse problem so return
		return;
	}
	
	// Show taxa by pubs
	var pubs = jData.pubs;
	var szResultHTML = '<div class="hymGraph" id="taxonTaxaByPubGraph"></div><ol><span class="underlinedText">Invalid Taxa</span>';
	var nTaxaCount = 0;
	var szTotalSubtitle;
	
	// Load the Google visualization package
	google.load('visualization', '1', {'packages': ['columnchart'], 'callback': drawTaxaByPubs});
	
	function drawTaxaByPubs() {
		// Prepare the graph
		var dataPubs = new google.visualization.DataTable();
		dataPubs.addColumn('string', 'Publication');
		dataPubs.addColumn('number', '# of Taxa');
		
		// Check on which date grouping is specified
		if (g_bValidOnly) {
			szResultHTML += '<input type="radio" name="pubsDisplayBox" checked="checked" onClick="javascript:loadTaxaByPubs(true);"><span title="Exclude invalid taxa in taxa count">Exclude</span> <input type="radio" name="pubsDisplayBox" onClick="javascript:loadTaxaByPubs(false);"><span title="Include invalid taxa in taxa count">Include</span>';
			
			szTotalSubtitle = 'Valid Only';
		} else {
			szResultHTML += '<input type="radio" name="pubsDisplayBox" onClick="javascript:loadTaxaByPubs(true);"><span title="Exclude invalid taxa in taxa count">Exclude</span> <input type="radio" name="pubsDisplayBox" checked="checked" onClick="javascript:loadTaxaByPubs(false);"><span title="Include invalid taxa in taxa count">Include</span>';
			
			szTotalSubtitle = 'Invalid Included';
		}
		
		// Load the results
		for (var pubCount = 0; pubCount < pubs.length; pubCount++) {
			var pub = pubs[pubCount];
			var lit_ref = pub.pub_ref;
			var szRefString = '';
			
			nTaxaCount += (pub.taxa_num - 0);
			
			szResultHTML += '<li><p>';
			
			// Check for which type of publication
			switch (lit_ref.type) {
				case 'book':
					szResultHTML += lit_ref.author + '. ' + lit_ref.date + '. <span class="italicizedText">' + lit_ref.title + '</span> ' + lit_ref.publisher + ', ' + lit_ref.city + '. ' + lit_ref.num_pages + ' pp.';
					szRefString = lit_ref.author + ' (' + lit_ref.date + ')';
				break;
				case 'article':
					var bNeedColon = false;
					
					// Check for a contributor
					if (lit_ref.contrib_author) {
						szResultHTML += lit_ref.contrib_author + ' <span class="italicizedText"><span class="boldedText">in</span></span> ';
					}
					
					szResultHTML += lit_ref.author + '. ' + lit_ref.date + '. ' + lit_ref.title + ' <span class="italicizedText">' + lit_ref.journal + '</span>, ';
					
					// Check for series, volume, and volume number and output if necessary
					if (lit_ref.series.length > 0) {
						szResultHTML += '(' + lit_ref.series + ')';
						
						bNeedColon = true;
					}
					if (lit_ref.volume.length > 0) {
						szResultHTML += '<span class="boldedText">' + lit_ref.volume + '</span>';
						
						bNeedColon = true;
					}
					if (lit_ref.vol_num.length > 0) {
						szResultHTML += '(' + lit_ref.vol_num + ')';
						
						bNeedColon = true;
					}
					
					// Check if a colon is needed
					if (bNeedColon) {
						szResultHTML += ': ';
					}
					
					// Output page number and check if a range annotation is needed
					szResultHTML += lit_ref.start_page;
					
					if (lit_ref.end_page.length > 0) {
						szResultHTML += '-' + lit_ref.end_page;
					}
					
					// Add finishing period
					szResultHTML += '.';
					
					szRefString = lit_ref.author + ' (' + lit_ref.date + ')';
				break;
				case 'bulletin':
					szResultHTML += lit_ref.author + '. ' + lit_ref.date + '. ' + lit_ref.title + ' <span class="italicizedText">' + lit_ref.journal + '</span>. No. ';
					
					// Check for series, volume, and volume number and output if necessary
					if (lit_ref.series.length > 0) {
						szResultHTML += '(' + lit_ref.series + ')';
					}
					if (lit_ref.volume.length > 0) {
						szResultHTML += lit_ref.volume;
					}
					if (lit_ref.vol_num.length > 0) {
						szResultHTML += '(' + lit_ref.vol_num + ')';
					}
					
					// Output page number and check if a range annotation is needed
					szResultHTML += '. ' + lit_ref.num_pages + ' pp.';
					
					szRefString = lit_ref.author + ' (' + lit_ref.date + ')';
				break;
				case 'chapter':
					szResultHTML += lit_ref.chap_author + '. ' + lit_ref.date + '. ' + lit_ref.chap_title;
					
					// Check for chapter number and output if necessary
					if (lit_ref.chap_num.length > 0) {
						szResultHTML += ' (' + lit_ref.chap_num + ')';
					}
					
					// Output page number and check if a range annotation is needed
					if (lit_ref.end_page.length > 0) {
						szResultHTML += ' Pages ' + lit_ref.start_page + '-' + lit_ref.end_page;
					} else {
						szResultHTML += ' Page ' + lit_ref.start_page;
					}
					
					// Output book info for chapter
					szResultHTML += ' <span class="italicizedText"><span class="boldedText">in</span></span> ' + lit_ref.author + '. <span class="italicizedText">' + lit_ref.title + '</span> ' + lit_ref.publisher + ', ' + lit_ref.city + '. ' + lit_ref.num_pages + ' pp.';
					
					szRefString = lit_ref.chap_author + ' in ' + lit_ref.author + ' (' + lit_ref.date + ')';
				break;
			}
			
			// Add row to data set
			var nRowIndex = dataPubs.addRow();
			dataPubs.setValue(nRowIndex, 0, szRefString);
			dataPubs.setValue(nRowIndex, 1, Number(pub.taxa_num));
			
			// Check if there is a pdf to link
			if (lit_ref.url.length > 0) {
				szResultHTML += ' <a href="http://' + lit_ref.url + '" target="_new"><img src="/HymOnline/pdf_icon.gif" title="View full PDF (' + lit_ref.filesize + ')"></a>';
			}
			
			szResultHTML += '<span class="hymSectionTitleOption"><a href="reference-full.html?id=';
			
			// Check for contribution ID for pub. ID
			if (lit_ref.contrib_id) {
				szResultHTML += lit_ref.contrib_id;
			} else {
				szResultHTML += lit_ref.pub_id;
			}
			
			szResultHTML += '" title="View the extended reference of the current publication">view extended reference</a></span>: ' + pub.taxa_num + '</p></li>';
		}
		
		szResultHTML += '</ol>';
		
		szResultHTML += '<div class="hymSectionBodyItem">Total Number of Taxa (' + szTotalSubtitle + '): <span class="boldedText">' + nTaxaCount + '</span></div>';
		
		// Set the HTML of the section to be the results and set as loaded
		document.getElementById('hymGeneralTaxonTaxaByPubsBodyID').innerHTML = szResultHTML;
		
		// Display the bar graph
		var chart = new google.visualization.ColumnChart(document.getElementById('taxonTaxaByPubGraph'));
		chart.draw(dataPubs, {width: 600, height: 400, showCategories: false, colors: ['#993300'], backgroundColor: '#E8E8E8', legend: 'none'});
	}
}

function loadTaxaByYear(bValidOnly) {
	var urlTaxaByYear = BASE_URL + 'OJ_Break.getTaxonNewTaxaByYear?tnuid=' + currentTNUID + '&callback=handleTaxaByYear';
	
	if (bValidOnly == undefined || !bValidOnly) {
		g_bYearValidOnly = false;
		
		urlTaxaByYear += '&validOnly=N';
	} else {
		g_bYearValidOnly = true;
		
		urlTaxaByYear += '&validOnly=Y';
	}
	
	// Show loading image for sections
	showLoadingImage('hymGeneralTaxonTaxaByYearBodyID');
	
	sendJSONRequest(urlTaxaByYear);
}

function handleTaxaByYear(jData) {
	if (jData == undefined) {
		// Do nothing
	} else if (jData == null) {
		// Parse problem so return
		return;
	}
	
	// Show taxa by year
	var years = jData.years;
	var szResultHTML = '<div class="hymGraph" id="taxonTaxaByYearGraph"></div><span class="underlinedText">Invalid Taxa</span>';
	
	// Load the Google visualization package
	google.load('visualization', '1', {'packages': ['columnchart'], 'callback': drawTaxaByYear});
	
	function drawTaxaByYear() {
		// Prepare the graph
		var dataYears = new google.visualization.DataTable();
		dataYears.addColumn('string', 'Year');
		dataYears.addColumn('number', '# of Taxa');
		
		// Check on which date grouping is specified
		if (g_bYearValidOnly) {
			szResultHTML += '<input type="radio" name="pubsYearDisplayBox" checked="checked" onClick="javascript:loadTaxaByYear(true);"><span title="Exclude invalid taxa in taxa count">Exclude</span> <input type="radio" name="pubsYearDisplayBox" onClick="javascript:loadTaxaByYear(false);"><span title="Include invalid taxa in taxa count">Include</span>';
		} else {
			szResultHTML += '<input type="radio" name="pubsYearDisplayBox" onClick="javascript:loadTaxaByYear(true);"><span title="Exclude invalid taxa in taxa count">Exclude</span> <input type="radio" name="pubsYearDisplayBox" checked="checked" onClick="javascript:loadTaxaByYear(false);"><span title="Include invalid taxa in taxa count">Include</span>';
		}
		
		szResultHTML += '';
		
		// Load the results
		var currentDate = new Date();
		
		// Check if any years are present
		if (years.length > 0) {
			var currentYear = years[0].year;
			var currentYearCount = 0;
			
			while (currentYear <= currentDate.getFullYear()) {
				// Check if current year matches taxa count year
				if (years[currentYearCount]) {
					if (years[currentYearCount].year == currentYear) {
						// Add row to data set
						var nRowIndex = dataYears.addRow();
						dataYears.setValue(nRowIndex, 0, String(currentYear));
						dataYears.setValue(nRowIndex, 1, Number(years[currentYearCount].taxa_num));
						
						szResultHTML += '<div class="hymSectionBodyItem">' + currentYear + ': ' + years[currentYearCount].taxa_num + '</div>';
						
						currentYear++;
						currentYearCount++;
					} else {
						// Add row to data set
						var nRowIndex = dataYears.addRow();
						dataYears.setValue(nRowIndex, 0, String(currentYear));
						dataYears.setValue(nRowIndex, 1, 0);
						
						currentYear++;
					}
				} else {
					// Add row to data set
					var nRowIndex = dataYears.addRow();
					dataYears.setValue(nRowIndex, 0, String(currentYear));
					dataYears.setValue(nRowIndex, 1, 0);
					
					currentYear++;
				}
			}
		} else {
			// Add row to data set
			var nRowIndex = dataYears.addRow();
			dataYears.setValue(nRowIndex, 0, String(currentDate.getFullYear()));
			dataYears.setValue(nRowIndex, 1, 0);
		}
		
		// Set the HTML of the section to be the results and set as loaded
		document.getElementById('hymGeneralTaxonTaxaByYearBodyID').innerHTML = szResultHTML;
		
		// Display the bar graph
		var chart = new google.visualization.ColumnChart(document.getElementById('taxonTaxaByYearGraph'));
		chart.draw(dataYears, {width: 600, height: 400, showCategories: true, colors: ['#993300'], backgroundColor: '#E8E8E8', legend: 'none'});
	}
}

function loadSizeByLatitude(nGraphType) {
	/*if (nPhenologyView == undefined) {
		g_nPhenologyView = 0;
	} else {
		g_nPhenologyView = nPhenologyView;
	}
	
	if (g_currentPhenology) {
		handlePhenology();
	} else {*/
		var urlSizeLat = BASE_URL + 'vSysLab.getMeasurements?tnuid=' + currentTNUID + '&callback=handleSizeByLatitude';
		
		// Show loading image for sections
		showLoadingImage('hymGeneralTaxonSizeByLatBodyID');
		
		sendJSONRequest(urlSizeLat);
	//}
}

function handleSizeByLatitude(jData) {
	if (jData == undefined) {
		// Do nothing
	} else if (jData == null) {
		// Parse problem so return
		return;
	} 
	
	// Show taxon size by latitude
	var measurements = jData.measurements;
	var szResultHTML = '<div class="hymGraph" id="taxonSizeByLatGraph"></div><span class="underlinedText">Data List</span>';
	
	// Load the Google visualization package
	google.load('visualization', '1', {'packages': ['scatterchart'], 'callback': drawSizeByLat});
	
	function drawSizeByLat() {
		// Prepare the graph
		var dataSizes = new google.visualization.DataTable();
		dataSizes.addColumn('number', 'Size (mm)');
		dataSizes.addColumn('number', 'Latitude');
		
		// Order by latitude
		measurements.sort(sortSpmByLatitude);
		
		// Check if any measurements are present
		if (measurements.length > 0) {
			for (var measureCount = 0; measureCount < measurements.length; measureCount++) {
				// Make sure the measurement type is for body length
				var measurement = measurements[measureCount];
				
				if (measurement.type == 'body length') {
					// Add measurement to data set
					var nRowIndex = dataSizes.addRow();
					dataSizes.setValue(nRowIndex, 0, Number(measurement.value));
					dataSizes.setValue(nRowIndex, 1, Number(measurement.lat));
					
					szResultHTML += '<div class="hymSectionBodyItem"><a href="spmInfo.html?id=' + encodeURL(measurement.cuid) + '">' + measurement.cuid + '</a>: ' + measurement.lat + '°, ' + measurement.value + ' ' + measurement.units + '</div>';
				}
			}
		} else {
			// Add measurement to data set
			var nRowIndex = dataSizes.addRow();
			dataSizes.setValue(nRowIndex, 0, 0);
			dataSizes.setValue(nRowIndex, 1, 0);
		}
		
		// Set the HTML of the section to be the results and set as loaded
		document.getElementById('hymGeneralTaxonSizeByLatBodyID').innerHTML = szResultHTML;
		
		// Display the dot graph
		var chart = new google.visualization.ScatterChart(document.getElementById('taxonSizeByLatGraph'));
		chart.draw(dataSizes, {width: 600, height: 400, showCategories: true, titleX: 'Size (mm)', titleY: 'Latitude (°)', colors: ['#993300'], backgroundColor: '#E8E8E8', legend: 'none'});
	}
}

function loadSectionIncluded() {
	var urlIncluded = BASE_URL + 'OJ_Break.getIncludedTaxa?tnuid=' + currentTNUID;
	
	// Show loading image for sections
	showLoadingImage('hymIncludedBodyID');
	
	// Get status of showing invalid taxa and fossil taxa
	if (document.getElementById('hymIncludedShowInvalidCheckID').checked) {
		urlIncluded += '&showSyns=Y';
	} else {
		urlIncluded += '&showSyns=N';
	}
	if (document.getElementById('hymIncludedShowFossilsCheckID').checked) {
		urlIncluded += '&showFossils=Y';
	} else {
		urlIncluded += '&showFossils=N';
	}
	
	urlIncluded += '&callback=handleIncluded';
	
	sendJSONRequest(urlIncluded);
}

function handleIncluded(jData) {
	if (jData == null) {
		// Parse problem so return
		return;
	}
	
	var children = jData.includedTaxa;
	var resultHTML = '<table class="hymSectionBodyTable">';
	
	// Load the results
	for (var childrenCount = 0; childrenCount < children.length; childrenCount++) {
		var child = children[childrenCount];
		
		// Check on position to determine what table formatting to apply
		if (childrenCount % SECTION_BODY_COLUMNS == 0) {
			resultHTML += '<tr>';
		}
		
		resultHTML += '<td><div class="hymSectionBodyItem">';
		
		// Check if current taxon is invalid
		if (child.valid_flag == 'invalid') {
			resultHTML += '*';
		}
		// Check if current taxon is a fossil
		if (child.fossil == 'Y') {
			resultHTML += '†';
		}
		
		resultHTML += '<a href="index.html?id=' + child.id + '">' + child.name + ' ' + child.author + '</a> <a href="javascript:showChildInfo(' + child.id + ', \'' + encodeURIComponent(child.name + ' ' + child.author) + '\', \'' + encodeURIComponent(child.rank) + '\');"><img src="/HymOnline/help.gif" title="Basic Taxon Info"></a></div></td>';
		
		if (childrenCount % SECTION_BODY_COLUMNS == SECTION_BODY_COLUMNS - 1) {
			resultHTML += '</tr>';
		}
	}
	
	// An ending 'tr' will have to be added if the last row is not full
	if (children.length % SECTION_BODY_COLUMNS != SECTION_BODY_COLUMNS - 1) {
		resultHTML += '</tr>';
	}
	
	resultHTML += '</table>';
	
	// Set the HTML of the section to be the results and set as loaded
	document.getElementById('hymIncludedBodyID').innerHTML = resultHTML;
	
	isIncludedLoaded = true;
}

function loadSectionSynonyms() {
	var urlSynonyms = BASE_URL + 'OJ_Break.getTaxonSynonyms?tnuid=' + currentTNUID;
	
	// Show loading image for sections
	showLoadingImage('hymSynonymsBodyID');
	
	// Get status of showing fossil taxa
	if (document.getElementById('hymSynonymsShowFossilsCheckID').checked) {
		urlSynonyms += '&showFossils=Y';
	} else {
		urlSynonyms += '&showFossils=N';
	}
	
	urlSynonyms += '&callback=handleSynonyms';
	
	sendJSONRequest(urlSynonyms);
}

function handleSynonyms(jData) {
	if (jData == null) {
		// Parse problem so return
		return;
	}
	
	var children = jData.synonyms;
	var resultHTML = '<table class="hymSectionBodyTable">';
	
	// Load the results
	for (var childrenCount = 0; childrenCount < children.length; childrenCount++) {
		var child = children[childrenCount];
		
		// Check on position to determine what table formatting to apply
		if (childrenCount % SECTION_BODY_COLUMNS == 0) {
			resultHTML += '<tr>';
		}
		
		resultHTML += '<td><div class="hymSectionBodyItem">';
		
		// Check if current taxon is a fossil
		if (child.fossil == 'Y') {
			resultHTML += '†';
		}
		
		resultHTML += '<a href="index.html?id=' + child.id + '">' + child.name + ' ' + child.author + '</a> <a href="javascript:showChildInfo(' + child.id + ', \'' + encodeURIComponent(child.name + ' ' + child.author) + '\', \'' + encodeURIComponent(child.rank) + '\');"><img src="/HymOnline/help.gif" title="Basic Taxon Info"></a></div></td>';
		
		if (childrenCount % SECTION_BODY_COLUMNS == SECTION_BODY_COLUMNS - 1) {
			resultHTML += '</tr>';
		}
	}
	
	// An ending 'tr' will have to be added if the last row is not full
	if (children.length % SECTION_BODY_COLUMNS != SECTION_BODY_COLUMNS - 1) {
		resultHTML += '</tr>';
	}
	
	resultHTML += '</table>';
	
	// Set the HTML of the section to be the results and set as loaded
	document.getElementById('hymSynonymsBodyID').innerHTML = resultHTML;
	
	isSynonymsLoaded = true;
}

function createListener(marker, locID, lat, long) {
	GEvent.addListener(marker, "click", function () {
		showLocalityInfo(locID, lat, long);
	});
	
	return marker;
}

function loadMap() {
	// Show loading image
	showLoadingImage('hymMapLoadingID');
	
	var urlQuery;
	
	// Get status of showing children
	if (document.getElementById('hymMapShowChildrenCheckID').checked) {
		urlQuery = BASE_URL + 'OJ_Break.getLocalities?tnuid=' + currentTNUID + '&instID=0&precDecimals=4&showChildren=Y&callback=handleMap';
	} else {
		urlQuery = BASE_URL + 'OJ_Break.getLocalities?tnuid=' + currentTNUID + '&instID=0&precDecimals=4&showChildren=N&callback=handleMap';
	}
	
	sendJSONRequest(urlQuery);
}

function handleMap(jData) {
	if (jData == null) {
		// Parse problem so return
		return;
	}
	
	var hymMap = new GMap2(document.getElementById('hymMapID'));
	var hierarchy = new GHierarchicalMapTypeControl();
	hymMap.setCenter(new GLatLng(0, 0), 1);
	hymMap.addControl(new GSmallMapControl());
	hymMap.addMapType(G_PHYSICAL_MAP);
	hymMap.addControl(hierarchy);
	hymMap.enableDoubleClickZoom();
	
	var localities = jData.localities;
	var point, marker;
	var pt_icon = new GIcon();
	var poly_icon = new GIcon();
	var marker;
	var arrayPoints = [];
	var arrayPolys = [];
	
	pt_icon.image = '/images/icons/pt_icon.png';
	pt_icon.iconSize = new GSize(10, 10);
	pt_icon.iconAnchor = new GPoint(5, 10);
	pt_icon.infoWindowAnchor = new GPoint(5, 5);
	
	poly_icon.image = '/images/icons/poly_icon.png';
	poly_icon.iconSize = new GSize(10, 10);
	poly_icon.iconAnchor = new GPoint(5, 10);
	poly_icon.infoWindowAnchor = new GPoint(5, 5);
	
	var hymMgrOptions = {borderPadding: 50};
	var hymMgr = new MarkerManager(hymMap, hymMgrOptions);
	
	// Loop until all of the localities are plotted
	for (var spmCount = 0; spmCount < localities.length; spmCount++) {
		var locality = localities[spmCount];
		
		// Check on locality type
		if (locality.type == 'point') {
			point = new GLatLng(locality.lat, locality.long);
			marker = new GMarker(point, {icon: pt_icon});
			arrayPoints.push(createListener(marker, locality.id, locality.lat, locality.long));
		} else {
			polygon = new GLatLng(locality.lat, locality.long);
			marker = new GMarker(polygon, {icon: poly_icon});
			arrayPolys.push(createListener(marker, locality.id, locality.lat, locality.long));
		}
	}
	
	hymMgr.addMarkers(arrayPoints, 1);
	hymMgr.addMarkers(arrayPolys, 1);
	
	// Hide loading image
	hideLoadingImage('hymMapLoadingID');
	
	// Show the map (w/ map info) and refresh so it displays
	document.getElementById('hymMapID').style.display = 'block';
	document.getElementById('hymMapID').style.visibility = 'visible';
	document.getElementById('hymMapInfoID').style.visibility = 'visible';
	hymMgr.refresh();
	
	// Reset the center and reload the Google Map
	hymMap.checkResize();
	hymMap.panTo(new GLatLng(0, 0));
	
	// Set the map as loaded
	isMapLoaded = true;
}

function showLocalityInfo(locID, lat, long) {
	// Show loading image
	showLoadingImage('hymMapInfoBodyID');
	
	var urlQuery;
	
	// Get status of showing children
	if (document.getElementById('hymMapShowChildrenCheckID').checked) {
		urlQuery = BASE_URL + 'OJ_Break.getLocalityInfo?locID=' + locID + '&tnuid=' + currentTNUID + '&instID=0&showChildren=Y&callback=handleLocalityInfo';
	} else {
		urlQuery = BASE_URL + 'OJ_Break.getLocalityInfo?locID=' + locID + '&tnuid=' + currentTNUID + '&instID=0&showChildren=N&callback=handleLocalityInfo';
	}
	
	// Set the current coordinates
	currentCoords.lat = lat;
	currentCoords.long = long;
	
	sendJSONRequest(urlQuery);
}

function handleLocalityInfo(jData) {
	if (jData == null) {
		// Parse problem so return
		return;
	}
	
	var locInfo = jData.locInfo;
	var resultHTML = '';
	var long, lat;
	
	// Load the locality name and coordinates
	resultHTML += 'Locality Name: <span class="boldedText">' + locInfo.name + '</span><br>';
	
	if (currentCoords.lat > 0) {
		lat = currentCoords.lat + '&deg;N';
	} else {
		lat = currentCoords.lat.replace('-','') + '&deg;S';
	}
	if (currentCoords.long > 0) {
		long = currentCoords.long + '&deg;E';
	} else {
		long = currentCoords.long.replace('-','') + '&deg;W';
	}
	
	resultHTML += 'Coordinates: <span class="boldedText">' + lat + ' ' + long + '</span><br>';
	
	// Load the geographic hierarchy
	var hier = locInfo.hier;
	
	if (hier.pol0) {
		resultHTML += 'Country: <span class="boldedText">' + hier.pol0.name + '</span> (' + hier.pol0.type + ')<br>';
	}
	if (hier.pol1) {
		resultHTML += 'State: <span class="boldedText">' + hier.pol1.name + '</span> (' + hier.pol1.type + ')<br>';
	}
	if (hier.pol2) {
		resultHTML += 'County: <span class="boldedText">' + hier.pol2.name + '</span> (' + hier.pol2.type + ')<br>';
	}
	if (hier.place) {
		resultHTML += 'Place Name: <span class="boldedText">' + hier.place.name + '</span> (' + hier.place.type + ')<br>';
	}
	
	// Load the specimen IDs
	var spms = locInfo.cuids;
	
	resultHTML += 'Specimen ID(s): <span class="boldedText">';
	
	for (var spmCount = 0; spmCount < spms.length; spmCount++) {
		if (spmCount != 0) {
			resultHTML += ', ';
		}
		
		resultHTML += '<a href="spmInfo.html?id=' + encodeURL(spms[spmCount].cuid) + '">' + spms[spmCount].cuid + '</a>';
	}
	
	resultHTML += '</span>';
	
	// Set the HTML of the section to be the results and set as loaded
	document.getElementById('hymMapInfoBodyID').innerHTML = resultHTML;
	
	// Adjust section height if locality info is larger
	var infoElement = document.getElementById('hymMapInfoID');
	var bodyElement = document.getElementById('hymMapBodyID');
	
	if (infoElement.clientHeight > bodyElement.clientHeight - 4) {
		bodyElement.style.height = (infoElement.clientHeight + 4) + 'px';
	}
}

function loadSectionImages() {
	var urlImages = BASE_URL + 'OJ_Break.getTaxonImages?tnuid=' + currentTNUID + '&callback=handleImages';
	
	// Show loading image
	showLoadingImage('hymImagesBodyID');
	
	sendJSONRequest(urlImages);
}

function handleImages(jData, nStart) {
	if (jData == undefined) {
		jData = g_currentImages;
	} else if (jData == null) {
		// Parse problem so return
		return;
	} else {
		g_currentImages = jData;
	}
	
	var imagesCount;
	var images = jData.images;
	var resultHTML = '<div class="hymSectionBodyNav" id="hymImagesNaviTopID"><!-- To Be DB Generated //--></div><table class="hymSectionBodyTable">';
	
	// Check which image to begin with
	if (nStart == undefined) {
		nStart = 0;
	}
	
	// Load the results
	for (imagesCount = 0; imagesCount + nStart < images.length && imagesCount < MAX_RESULT_PAGE; imagesCount++) {
		var image = images[imagesCount + nStart];
		
		// Check on position to determine what table formatting to apply
		if (imagesCount % SECTION_IMAGES_COLUMNS == 0) {
			resultHTML += '<tr>';
		}
		
		// Check for a thumbnail, else use the normal-res
		if (image.thumb.length > 0) {
			resultHTML += '<td><div class="hymSectionBodyItem"><a href="javascript:showImage(\'' + image.normalRes + '\', \'' + image.highRes + '\', \'' + image.highResSource + '\', \'' + encodeURL(image.caption) + '\', \'' + image.license +'\', \'' + encodeJavascript(image.copyright) +'\', false);"><img src="' + image.thumb + '" title="Show Full-size Image"></a><div class="hymBodyCaption"><a href="index.html?id=' + image.tnuid + '">' + image.taxon + '</a> ' + image.author + '</div></div></td>';
		} else {
			resultHTML += '<td><div class="hymSectionBodyItem"><a href="javascript:showImage(\'' + image.normalRes + '\', \'' + image.highRes + '\', \'' + image.highResSource + '\', \'' + encodeURL(image.caption) + '\', \'' + image.license +'\', \'' + encodeJavascript(image.copyright) +'\', true);"><img src="' + image.normalRes + '" title="Show Full-size Image" style="width: 75px;"></a><div class="hymBodyCaption"><a href="index.html?id=' + image.tnuid + '">' + image.taxon + '</a> ' + image.author + '</div></div></td>';
		}
		
		if (imagesCount % SECTION_IMAGES_COLUMNS == SECTION_IMAGES_COLUMNS - 1) {
			resultHTML += '</tr>';
		}
	}
	
	// An ending 'tr' will have to be added if the last row is not full
	if (images.length % SECTION_IMAGES_COLUMNS != SECTION_IMAGES_COLUMNS - 1) {
		resultHTML += '</tr>';
	}
	
	resultHTML += '</table><div class="hymSectionBodyNav" id="hymImagesNaviBottomID"><!-- To Be DB Generated //--></div>';
	
	// Set the HTML of the section to be the results and set as loaded
	document.getElementById('hymImagesBodyID').innerHTML = resultHTML;
	
	displayPageNavigation('hymImagesNavi', 'handleImages', nStart, imagesCount, images.length);
	
	isImagesLoaded = true;
}

function showImage(image, hiRes, hiResSource, caption, license, copyright, loaded) {
	// Show loading image within popup
	showLoadingImage('hymBodyPopupTextID');
	togglePopup('hymBodyPopupID', true);
	
	// Check if a hi-res image is available
	var hiResHTML = '';
	
	if (hiRes.length > 0) {
		// Check the hi-res source
		if (hiResSource == 'MorphBank') {
			hiResHTML = 'Hi-Res Image: <a href="' + hiRes + '" target="_new" onMouseOver="javascript:toggleImageLink(\'hymMorphBankImageID\', true);" onMouseOut="javascript:toggleImageLink(\'hymMorphBankImageID\', false);"><img src="/HymOnline/mbLogo-gray.png" id="hymMorphBankImageID" title="Go to GenBank for hi-res image"></a><br>';
		} else if (hiResSource == 'Specimage') {
			hiResHTML = 'Hi-Res Image: <a href="' + hiRes + '" target="_new">Specimage</a><br>';
		}
	}
	
	// Generate the image popup
	var resultHTML = '<div class="hymPopupTextTitle">Full-size Image</div><hr>' + hiResHTML + 'Comments: ' + caption + '<br><img src="' + image + '" id="hymPopupImage">';
	
	// Check if license if defined
	if (license) {
		var dateCurrent = new Date();
		
		resultHTML += '<a href="http://creativecommons.org/licenses/' + license + '/" target="_new" title="View license information"><img src="http://i.creativecommons.org/l/' + license + '/80x15.png" style="border: none;"></a> &copy; ' + dateCurrent.getFullYear() + ', ' + copyright + '';
	}
	
	resultHTML += '</div>';
	
	// Load image and call image handler when finished loading
	var preImage =  new Image();
	preImage.src = image;
	
	// Set temporary popup variables to hold image object and the built image HTML
	popupTemp1 = preImage;
	popupTemp2 = resultHTML;
	
	// If image was already loaded, call handleImage function directly, other it will be called on complete
	if (loaded == false) {
		preImage.onload = handleImage;
	} else {
		handleImage();
	}
}

function handleImage() {
	// Get the image width and pad a bit
	var imageSize = popupTemp1.width + 10;
	
	// Set the result HTML to the popup text
	document.getElementById('hymBodyPopupTextID').innerHTML = popupTemp2;
	
	// Resize popup to fit image and resize image if > MAX_IMAGE_WIDTH
	if (imageSize > MAX_IMAGE_WIDTH) {
		document.getElementById('hymPopupImage').style.width = MAX_IMAGE_WIDTH + 'px';
		document.getElementById('hymBodyPopupID').style.width = (MAX_IMAGE_WIDTH + 10) + 'px';
	} else {
		document.getElementById('hymBodyPopupID').style.width = imageSize + 'px';
	}
}

function loadSectionLiterature() {
	var urlLit;
	
	// Get status of showing synonyms or bibliography
	if (document.getElementById('hymLitShowBibCheckID').checked) {
		urlLit = BASE_URL + 'OJ_Break.getTaxonLiterature?tnuid=' + currentTNUID + '&showSyns=B&callback=handleLiterature';
		
		// Disable show synonyms checkbox
		document.getElementById('hymLitShowSynsCheckID').disabled = true;
	} else if (document.getElementById('hymLitShowSynsCheckID').checked) {
		urlLit = BASE_URL + 'OJ_Break.getTaxonLiterature?tnuid=' + currentTNUID + '&showSyns=Y&callback=handleLiterature';
		
		// Enable show synonyms checkbox
		document.getElementById('hymLitShowSynsCheckID').disabled = false;
	} else {
		urlLit = BASE_URL + 'OJ_Break.getTaxonLiterature?tnuid=' + currentTNUID + '&showSyns=N&callback=handleLiterature';
		
		// Enable show synonyms checkbox
		document.getElementById('hymLitShowSynsCheckID').disabled = false;
	}
	
	// Show loading image
	showLoadingImage('hymLiteratureBodyID');
	
	sendJSONRequest(urlLit);
}

function handleLiterature(jData, nStart, szAuthor) {
	var bUpdateTableOnly = false;
	var bSort = true;
	
	if (jData == undefined) {
		// Check if the collection filter needs applied
		if (g_currentLitFiltered && szAuthor == undefined) {
			jData = g_currentLitFiltered;
			
			bUpdateTableOnly = true;
			bSort = false;
		} else {
			// Check if a new author filter is specified
			if (szAuthor != undefined && szAuthor != -1) {
				// Create new filtered array by checking if collecting event contains collection specimens
				var pubs = g_currentLit.lit.pubs;
				g_currentLitFiltered = {"lit":{"pubs":[]}};
				
				for (var pubCount = 0; pubCount < pubs.length; pubCount++) {
					var pub = pubs[pubCount];
					
					// Add pub to filtered array if authors match
					if (pub.author == szAuthor) {
						g_currentLitFiltered.lit.pubs.push(pub);
					}
				}
				
				jData = g_currentLitFiltered;
			} else {
				jData = g_currentLit;
				g_currentLitFiltered = null;
				bSort = false;
			}
		}
	} else if (jData == null) {
		// Parse problem so return
		return;
	} else {
		g_currentLit = jData;
		g_currentLitFiltered = null;
	}
	
	// Check which pub to begin with
	if (nStart == undefined) {
		nStart = 0;
	}
	
	var lit = jData.lit;
	var pubs = lit.pubs;
	var ref_array = new Array();
	var szBodyHTML = '<div class="hymSectionBodyFilter"><div class="underlinedText">Filter</div><p>Authors: <select class="hymBodyFormSmallFilterInput" id="hymLitFilterAuthorID" onChange="javascript:handleLiterature(null, 0, this.value);"><option value="-1">all</option></select></p></div><div id="hymLitDataBodyID"><!-- To Be DB Generated //--></div>';
	var resultHTML = '<div class="hymSectionBodyNav" id="hymLitNaviTopID"><!-- To Be DB Generated //--></div>';
	
	// Sort the pubs, if necessary
	if (bSort) {
		pubs.sort(sortLit);
	}
	
	// Load the results
	for (var pubCount = 0; pubCount + nStart < pubs.length && pubCount < MAX_RESULT_PAGE; pubCount++) {
		var pub = pubs[pubCount + nStart];
		
		resultHTML += '<div class="hymSectionBodyItem"><a href="javascript:toggleSection(\'hymLitRefBody' + pubCount + 'ID\', \'hymLitRefTitle' + pubCount + 'Icon\');loadLitRef(' + pub.pub_id + ', \'hymLitRefBody' + pubCount + 'ID\');"><img src="/HymOnline/icon-expand.png" title="expand" id="hymLitRefTitle' + pubCount + 'Icon"></a> ';
		
		// If the taxon is a genus or lower, italicize
		if (pub.rank == 'genus' || pub.rank == 'species' || pub.rank == 'subspecies' || pub.rank == 'subgenus') {
			// Check if current citation is for an original description
			if (pub.comments.match(/.riginal description.*/) || pub.comments.match(/.irst available.*/)) {
				resultHTML += '<span class="boldedText"><span class="italicizedText">' + pub.name + '</span> ' + pub.describer + '</span>';
			} else {
				resultHTML += '<span class="boldedText"><span class="italicizedText">' + pub.name + '</span> ' + pub.describer + '</span>: ' + pub.author;
			}
		} else {
			// Check if current citation is for an original description
			if (pub.comments.match(/.riginal description.*/) || pub.comments.match(/.irst available.*/)) {
				resultHTML += '<span class="boldedText">' + pub.name + ' ' + pub.describer + '</span>';
			} else {
				resultHTML += '<span class="boldedText">' + pub.name + ' ' + pub.describer + '</span>: ' + pub.author;
			}
		}
		
		resultHTML += ', ' + pub.year + ': ';
		
		// Handle pages along with PDF references
		var pages = pub.pages;
		
		for (var pageCount = 0; pageCount < pages.length; pageCount++) {
			var pageInfo = pages[pageCount];
			
			// Check whether to add a comma (not during 1st loop)
			if (pageCount > 0) {
				resultHTML += ', ';
			}
			
			// Check if there is a pdf to link
			if (pageInfo.url.length > 0) {
				resultHTML += ' <a href="/HymOnline/literature-viewer.html?id=' + pub.pub_id + '&page=' + pageInfo.page + '" target="_new" title="View PDF of page ' + pageInfo.page + ' in literature viewer">' + pageInfo.page + '</a>';
			} else {
				resultHTML += pageInfo.page;
			}
		}
		
		resultHTML +=  '.';
		
		// Check if citation text exists
		if (pub.comments) {
			resultHTML +=  ' ' + pub.comments + '.';
		}
		
		resultHTML +=  ' <span id="hymLitRefBody' + pub.pub_id + '|' + pub.tnuid + 'ID_plazi"></span>';
		resultHTML += '</div><div class="hymSubSectionBody" id="hymLitRefBody' + pubCount + 'ID"><!-- To Be DB Generated //--></div>';
		
		ref_array.push(pub.pub_id);
	}
	
	resultHTML += '<div class="hymSectionBodyNav" id="hymLitNaviBottomID"><!-- To Be DB Generated //--></div>';
	
	// Check if only the publication data table needs updated
	if (bUpdateTableOnly) {
		// Set the HTML for the literature
		document.getElementById('hymLitDataBodyID').innerHTML = resultHTML;
		
		displayPageNavigation('hymLitNavi', 'handleLiterature', nStart, pubCount, pubs.length);
	} else {
		// Set the HTML for the collecting trips
		document.getElementById('hymLiteratureBodyID').innerHTML = szBodyHTML;
		document.getElementById('hymLitDataBodyID').innerHTML = resultHTML;
		
		displayPageNavigation('hymLitNavi', 'handleLiterature', nStart, pubCount, pubs.length);
		
		// Fill the filter
		var selectBox = document.getElementById('hymLitFilterAuthorID');
		var filter_pubs = g_currentLit.lit.pubs;
		var arrayAuthors = new Array();
		
		// Place all authors into new array and remove duplicates
		for (var pubCount = 0; pubCount < filter_pubs.length; pubCount++) {
			arrayAuthors.push(filter_pubs[pubCount].author);
		}
		
		arrayAuthors = arrayAuthors.unique();
		arrayAuthors.sort(sortName);
		
		// Fill in the authors filter for the array
		for (var authorCount = 0; authorCount < arrayAuthors.length; authorCount++) {
			var author = arrayAuthors[authorCount];
			var bIsSelected = false;
			
			// Check if current checkbox should be selected
			if (author == szAuthor) {
				bIsSelected = true;
			}
			
			var option = new Option(author, author, bIsSelected);
			
			selectBox.options[selectBox.options.length] = option;
		}
	}
	
	// Check if a Plazi treatments are available
	prepareTreatments(ref_array.toString());
	
	isLiteratureLoaded = true;
}

function loadLitRef(nPubID, szSubsectionID) {
	var urlLitRef = BASE_URL + 'OJ_Break.getLitReference?pub_id=' + nPubID + '&callback_opt1=' + szSubsectionID + '&callback=handleLitRef';
	
	// Show loading image
	showLoadingImage(szSubsectionID);
	
	sendJSONRequest(urlLitRef);
}

function handleLitRef(jData) {
	if (jData == null) {
		// Parse problem so return
		return;
	}
	
	var szSubsectionID = jData.callback_opt1;
	var lit_ref = jData.pub_ref;
	var szresultHTML = '' + formatReference(lit_ref) + '</p>';
	
	// Set the HTML of the section to be the results and set as loaded
	document.getElementById(szSubsectionID).innerHTML = szresultHTML;
}

function formatReference(ref, noLitFormat) {
	var szresultHTML = '';
	var nLitID;
	var nBasePubID;
	
	// Check for contribution ID for pub. ID
	if (ref.contrib_id) {
		nLitID = ref.contrib_id;
		nBasePubID = ref.contrib_id;
	} else {
		nLitID = ref.pub_id;
		nBasePubID = ref.pub_id;
	}
	
	if (noLitFormat) {
	} else {
		szresultHTML += '<span class="underlinedText">Full Reference</span> <span class="hymSectionTitleOption"><a href="reference-full.html?id=' + nLitID + '" title="View the extended reference of the current publication">view extended reference</a></span><p>';
	}
	
	// Check for which type of publication
	switch (ref.type) {
		case 'book':
			szresultHTML += ref.author + '. ' + ref.date + '. <span class="italicizedText">' + ref.title + '</span> ' + ref.publisher + ', ' + ref.city + '. ' + ref.num_pages + ' pp.';
		break;
		case 'article':
			var bNeedColon = false;
			
			// Check for a contributor
			if (ref.contrib_author) {
				szresultHTML += ref.contrib_author + ' <span class="italicizedText"><span class="boldedText">in</span></span> ';
			}
			
			szresultHTML += ref.author + '. ' + ref.date + '. ' + ref.title + ' <span class="italicizedText">' + ref.journal + '</span>, ';
			
			// Check for series, volume, and volume number and output if necessary
			if (ref.series.length > 0) {
				szresultHTML += '(' + ref.series + ')';
				
				bNeedColon = true;
			}
			if (ref.volume.length > 0) {
				szresultHTML += '<span class="boldedText">' + ref.volume + '</span>';
				
				bNeedColon = true;
			}
			if (ref.vol_num.length > 0) {
				szresultHTML += '(' + ref.vol_num + ')';
				
				bNeedColon = true;
			}
			
			// Check if a colon is needed
			if (bNeedColon) {
				szresultHTML += ': ';
			}
			
			// Output page number and check if a range annotation is needed
			szresultHTML += ref.start_page;
			
			if (ref.end_page.length > 0) {
				szresultHTML += '-' + ref.end_page;
			}
			
			// Add finishing period
			szresultHTML += '.';
		break;
		case 'bulletin':
			szresultHTML += ref.author + '. ' + ref.date + '. ' + ref.title + ' <span class="italicizedText">' + ref.journal + '</span>. No. ';
			
			// Check for series, volume, and volume number and output if necessary
			if (ref.series.length > 0) {
				szresultHTML += '(' + ref.series + ')';
			}
			if (ref.volume.length > 0) {
				szresultHTML += ref.volume;
			}
			if (ref.vol_num.length > 0) {
				szresultHTML += '(' + ref.vol_num + ')';
			}
			
			// Output page number and check if a range annotation is needed
			szresultHTML += '. ' + ref.num_pages + ' pp.';
		break;
		case 'chapter':
			szresultHTML += ref.chap_author + '. ' + ref.date + '. ' + ref.chap_title;
			
			// Check for chapter number and output if necessary
			if (ref.chap_num.length > 0) {
				szresultHTML += ' (' + ref.chap_num + ')';
			}
			
			// Output page number and check if a range annotation is needed
			if (ref.end_page.length > 0) {
				szresultHTML += ' Pages ' + ref.start_page + '-' + ref.end_page;
			} else {
				szresultHTML += ' Page ' + ref.start_page;
			}
			
			// Output book info for chapter
			szresultHTML += ' <span class="italicizedText"><span class="boldedText">in</span></span> ' + ref.author + '. <span class="italicizedText">' + ref.title + '</span> ' + ref.publisher + ', ' + ref.city + '. ' + ref.num_pages + ' pp.';
		break;
	}
	
	// Check if there is a pdf to link
	if (ref.url.length > 0) {
		szresultHTML += ' <a href="http://' + ref.url + '" target="_new"><img src="/HymOnline/pdf_icon.gif" title="View full PDF (' + ref.filesize + ')"></a> - <a href="literature-viewer.html?id=' + nBasePubID + '" target="_new" title="Browse by page through publication">browse</a>';
	}
	
	szresultHTML += '</p>';
	
	return szresultHTML;
}

function loadSectionTypes() {
	var urlTypes;
	
	// Get status of showing synonyms or bibliography
	if (document.getElementById('hymLitShowAllTypesCheckID').checked) {
		urlTypes = BASE_URL + 'OJ_Break.getTypes?tnuid=' + currentTNUID + '&showSyns=F&callback=handleTypes';
	} else {
		urlTypes = BASE_URL + 'OJ_Break.getTypes?tnuid=' + currentTNUID + '&showSyns=Y&callback=handleTypes';
	}
	
	// Show loading image for sections
	showLoadingImage('hymTypesBodyID');
	
	sendJSONRequest(urlTypes);
}

function handleTypes(jData, nStart, szInst, nTypeID) {
	var bUpdateTableOnly = false;
	
	if (jData == undefined) {
		// Check if the collection filter needs applied
		if (g_currentTypesFiltered && szInst == undefined) {
			jData = g_currentTypesFiltered;
			
			bUpdateTableOnly = true;
		} else {
			// Check if a filter is specified
			if ((szInst != undefined && szInst != -1) || nTypeID > 0) {
				g_currentTypesFiltered = g_currentTypes;
				
				// Check if collections are filtered
				if (szInst != undefined && szInst != -1) {
					// Create new filtered array by checking if type info matches collection
					var types = g_currentTypes.types;
					g_currentTypesFiltered = {"types":[]};
					
					for (var typeCount = 0; typeCount < types.length; typeCount++) {
						var type = types[typeCount];
						
						// Add pub to filtered array if authors match
						if (type.inst_code == szInst) {
							g_currentTypesFiltered.types.push(type);
						}
					}
				}
				
				// Check if kind of type is filtered
				if (nTypeID > 0) {
					// Create new filtered array by checking if type info matches collection
					var types = g_currentTypesFiltered.types;
					g_currentTypesFiltered = {"types":[]};
					
					for (var typeCount = 0; typeCount < types.length; typeCount++) {
						var type = types[typeCount];
						
						// Add pub to filtered array if authors match
						if (type.type == 'Holotype' || type.type == 'Neotype' || type.type == 'Lectotype') {
							g_currentTypesFiltered.types.push(type);
						}
					}
				}
				
				jData = g_currentTypesFiltered;
			} else {
				jData = g_currentTypes;
				g_currentTypesFiltered = null;
			}
		}
	} else if (jData == null) {
		// Parse problem so return
		return;
	} else {
		g_currentTypes = jData;
		g_currentTypesFiltered = null;
	}
	
	// Check where to begin
	if (nStart == undefined) {
		nStart = 0;
	}
	
	var types = jData.types;
	var szBodyHTML = '<div class="hymSectionBodyFilter"><div class="underlinedText">Filter</div><p>Collections: <select class="hymBodyFormSmallFilterInput" id="hymTypesFilterInstID" onChange="javascript:handleTypes(null, 0, this.value, document.getElementById(\'hymTypesFilterTypeID\').value);"><option value="-1">all</option></select> Type: <select class="hymBodyFormSmallFilterInput" id="hymTypesFilterTypeID" onChange="javascript:handleTypes(null, 0, document.getElementById(\'hymTypesFilterInstID\').value, this.value);"><option value="-1">all</option><option value="1">primary types only</option></select></p></div><div id="hymTypesDataBodyID"><!-- To Be DB Generated //--></div>';
	var resultHTML = '<div class="hymSectionBodyNav" id="hymTypesNaviTopID"><!-- To Be DB Generated //--></div><table class="hymSectionBodyTable">';
	
	// Load the results
	for (var typesCount = 0; typesCount + nStart < types.length && typesCount < MAX_RESULT_PAGE; typesCount++) {
		var type = types[typesCount + nStart];
		
		// Show header for first record
		if (typesCount == 0) {
			resultHTML += '<tr><td class="hymSectionBodyTableHeader">Specimen ID</td><td class="hymSectionBodyTableHeader">Collection</td><td class="hymSectionBodyTableHeader">Taxon</td><td class="hymSectionBodyTableHeader">Type</td><td class="hymSectionBodyTableHeader">Taxonomic Hierarchy</td></tr>';
		}
		
		resultHTML += '<tr><td><div class="hymSectionBodyItem"><a href="spmInfo.html?id=' + encodeURL(type.cuid) + '">' + type.cuid + '</a></div></td><td><div class="hymSectionBodyItem"><a href="inst-full.html?id=' + type.inst_id + '">' + type.inst_code + '</a></div></td><td><div class="hymSectionBodyItem"><a href="index.html?id=' + type.tnuid + '">' + type.taxon + ' ' + type.author + '</a></div></td><td><div class="hymSectionBodyItem">' + type.type + '</div></td><td><div class="hymSectionBodyItem">';
		
		// Show parent taxa
		var currentRank = 'Order'; // Starting rank
		var nCount = 0;
		var hierarchy = type.hier;
		
		// Loop through the hierarchy to display all of the names
		while (currentRank != 'null' && hierarchy[currentRank]) {
			// For the first taxon, do no prepend with <
			if (nCount != 0) {
				resultHTML += ': ';
			} else {
				nCount = 1;
			}
			
			resultHTML += hierarchy[currentRank].name;
			
			// End at genus
			if (currentRank == 'Genus') {
				break;
			}
			
			// Get next taxon in hierarchy
			currentRank = hierarchy[currentRank].next;
		}
		
		resultHTML += '</div></td></tr>';
	}
	
	resultHTML += '</table>';
	resultHTML += '<div class="hymSectionBodyNav" id="hymTypesNaviBottomID"><!-- To Be DB Generated //--></div>';
	
	// Check if only the types data table needs updated
	if (bUpdateTableOnly) {
		// Set the HTML for the literature
		document.getElementById('hymTypesDataBodyID').innerHTML = resultHTML;
		
		displayPageNavigation('hymTypesNavi', 'handleTypes', nStart, typesCount, types.length);
	} else {
		// Set the HTML for the collecting trips
		document.getElementById('hymTypesBodyID').innerHTML = szBodyHTML;
		document.getElementById('hymTypesDataBodyID').innerHTML = resultHTML;
		
		displayPageNavigation('hymTypesNavi', 'handleTypes', nStart, typesCount, types.length);
		
		// Fill the filter
		var selectBox = document.getElementById('hymTypesFilterInstID');
		var filter_types = g_currentTypes.types;
		var arrayInsts = new Array();
		
		// Place all collections into new array and remove duplicates
		for (var typeCount = 0; typeCount < filter_types.length; typeCount++) {
			arrayInsts.push(filter_types[typeCount].inst_code);
		}
		
		arrayInsts = arrayInsts.unique();
		arrayInsts.sort(sortName);
		
		// Fill in the collections filter for the array
		for (var instCount = 0; instCount < arrayInsts.length; instCount++) {
			var inst = arrayInsts[instCount];
			var bIsSelected = false;
			
			// Check if current checkbox should be selected
			if (inst == szInst) {
				bIsSelected = true;
			}
			
			var option = new Option(inst, inst, bIsSelected);
			
			selectBox.options[selectBox.options.length] = option;
		}
		
		// Check if kind of type is filtered
		if (nTypeID == 1) {
			document.getElementById('hymTypesFilterTypeID').selectedIndex = 1;
		} else {
			document.getElementById('hymTypesFilterTypeID').selectedIndex = 0;
		}
	}
	
	isTypesLoaded = true;
}

function loadSectionAssociations() {
	var urlAssociations = BASE_URL + 'OJ_Break.getAssociations?tnuid=' + currentTNUID + '&callback=handleAssociations';
	
	// Show loading image for sections
	showLoadingImage('hymAssociationsBodyID');
	
	sendJSONRequest(urlAssociations);
}

function handleAssociations(jData, nStart) {
	if (jData == undefined) {
		jData = g_currentAssocs;
	} else if (jData == null) {
		// Parse problem so return
		return;
	} else {
		g_currentAssocs = jData;
	}
	
	var associations = jData.associations;
	var resultHTML = '<div class="hymSectionBodyNav" id="hymAssocsNaviTopID"><!-- To Be DB Generated //--></div><table class="hymSectionBodyTable">';
	var currentRank;
	var nCount = 0;
	var hierarchy;
	var associationsCount;
	
	// Check which image to begin with
	if (nStart == undefined) {
		nStart = 0;
	}
	
	// Load the results
	for (associationsCount = 0; associationsCount + nStart < associations.length && associationsCount < MAX_RESULT_PAGE; associationsCount++) {
		var association = associations[associationsCount + nStart];
		
		// Show header for first record
		if (associationsCount == 0) {
			resultHTML += '<tr><td class="hymSectionBodyTableHeader">Taxon</td><td class="hymSectionBodyTableHeader">Association Type</td><td class="hymSectionBodyTableHeader">Taxonomic Hierarchy</td><td class="hymSectionBodyTableHeader">Association IDs</td></tr>';
		}
		resultHTML += '<tr><td><div class="hymSectionBodyItem"><a href="index.html?id=' + association.id + '">' + association.taxon + '</a> ' + association.author + '</div></td><td><div class="hymSectionBodyItem">' + association.type + '</div></td><td><div class="hymSectionBodyItem">';
		
		// Show parent taxa
		currentRank = 'Order'; // Starting rank
		nCount = 0;
		hierarchy = association.hier;
		
		// Loop through the hierarchy to display all of the names
		while (currentRank != 'null' && hierarchy[currentRank]) {
			// For the first taxon, do no prepend with <
			if (nCount != 0) {
				resultHTML += ': ';
			} else {
				nCount = 1;
			}
			
			resultHTML += hierarchy[currentRank].name;
			
			// End at family
			if (currentRank == 'Family') {
				break;
			}
			
			// Get next taxon in hierarchy
			currentRank = hierarchy[currentRank].next;
		}
		
		resultHTML += '</div></td><td><div class="hymSectionBodyItem">';
		
		// Check for IDs
		if (association.cuids.length > 0) {
			var assocCuids = association.cuids;
			
			// Outut the IDs
			for (var assocCuidCount = 0; assocCuidCount < assocCuids.length; assocCuidCount++) {
				if (assocCuidCount > 0) {
					resultHTML += ', ';
				}
				
				resultHTML += '<a href="spmInfo.html?id=' + assocCuids[assocCuidCount] + '">' + assocCuids[assocCuidCount] + '</a>';
			}
		}
		
		resultHTML += '</div></td></tr>';
	}
	
	resultHTML += '</table><div class="hymSectionBodyNav" id="hymAssocsNaviBottomID"><!-- To Be DB Generated //--></div>';
	
	// Set the HTML of the section to be the results and set as loaded
	document.getElementById('hymAssociationsBodyID').innerHTML = resultHTML;
	
	displayPageNavigation('hymAssocsNavi', 'handleAssociations', nStart, associationsCount, associations.length);
	
	isAssociationsLoaded = true;
}

function loadSectionHabitats() {
	var urlHabitats = BASE_URL + 'OJ_Break.getHabitats?tnuid=' + currentTNUID + '&callback=handleHabitats';
	
	// Show loading image for sections
	showLoadingImage('hymHabitatsBodyID');
	
	sendJSONRequest(urlHabitats);
}

function handleHabitats(jData) {
	if (jData == null) {
		// Parse problem so return
		return;
	}
	
	var habitats = jData.habitats;
	var resultHTML = '';
	
	// Load the results
	for (var habitatsCount = 0; habitatsCount < habitats.length; habitatsCount++) {
		var habitat = habitats[habitatsCount];
		
		resultHTML += '<div class="hymSectionBodyItem">' + habitat.habitat + '</div>';
	}
	
	// Set the HTML of the section to be the results and set as loaded
	document.getElementById('hymHabitatsBodyID').innerHTML = resultHTML;
	
	isHabitatsLoaded = true;
}

function viewLargeMap() {
	// Go to large map page
	window.location = 'map-large.html?id=' + currentTNUID;
}

function prepareGenBank() {
	var urlGenBank = 'http://hymfiles.biosci.ohio-state.edu/scripts/OJ_Break.pl?action=getGenBankCount&name=' + encodeURL(currentTaxon) + '&callback=handlePrepareGenBank';
	
	sendJSONRequest(urlGenBank);
}

function handlePrepareGenBank(jData) {
	if (jData == null) {
		// Parse problem so return
		return;
	}
	
	// Prepare GenBank if data is available
	if (jData.count > 0) {
		document.getElementById('hymOtherDBsTitleID').innerHTML += ' (' + jData.count + ')';
		
		section = document.getElementById('hymSectionOtherDBsID');
		section.style.display = 'block';
		section.style.visibility = 'visible';
		
		// Produce content for section
		var szResultHTML = '';
		var dbs = jData.dbs;
		
		// Load the results
		for (var dbCount = 0; dbCount < dbs.length; dbCount++) {
			var db = dbs[dbCount];
			
			szResultHTML += '<div class="hymSectionBodyItem"><a href="http://www.ncbi.nlm.nih.gov/sites/entrez?db=' + db.db + '&term=' + encodeURL(currentTaxon) + '" title="Visit NCBI ' + db.db_name + ' Database" target="_new">' + db.db_name + ' (' + db.db_count + ')</div>';
		}
		
		// Set the HTML of the section to be the results and set as loaded
		document.getElementById('hymOtherDBsBodyID').innerHTML = szResultHTML;
		
		isOtherDBsLoaded = true;
	}
}

function prepareTreatments(pub_list) {
	var urlTreatment = 'http://hymfiles.biosci.ohio-state.edu/scripts/OJ_Break.pl?action=getTreatments&pub_list=' + pub_list + '&callback=handlePrepareTreatments';
	
	sendJSONRequest(urlTreatment);
}

function handlePrepareTreatments(jData) {
	if (jData == null) {
		// Parse problem so return
		return;
	}
	
	// Prepare treatments
	for (var pubCount = 0; pubCount < jData.length; pubCount++) {
		var pub = jData[pubCount];
		var tnuids = pub.tnuids;
		
		for (var tnuidCount = 0; tnuidCount < tnuids.length; tnuidCount++) {
			// Check if annotation is present
			if (document.getElementById('hymLitRefBody' + pub.pub_id + '|' + tnuids[tnuidCount] + 'ID_plazi')) {
				document.getElementById('hymLitRefBody' + pub.pub_id + '|' + tnuids[tnuidCount] + 'ID_plazi').innerHTML = ' <a href="http://plazi2.cs.umb.edu/GgServer/search?resultFormat=html&taxonomicName.isNomenclature=taxonomicName.isNomenclature&taxonomicName.exactMatch=taxonomicName.exactMatch&taxonomicName.LSID=urn:lsid:biosci.ohio-state.edu:osuc_concepts:' + tnuids[tnuidCount] + '&MODS.ModsDocID=' + pub.pub_id + '&indexName=0" target="_new"><img src="/HymOnline/plazi_logo.png" title="View formatted treatments from Plazi"></a>';
			}
		}
	}
}

// Sorting functions
function sortName(nameA, nameB, pos) {
	// Set pos to 0 if not defined
	if (!pos) {
		pos = 0;
	}
	
	// Check for end of string (either nameA or nameB)
	if (pos >= nameA.length || pos >= nameB.length) {
		if (nameA.length > nameB.length) {
			return 1;
		} else if (nameA.length < nameB.length) {
			return -1;
		} else {
			return 0;
		}
	} else {
		var chA, chB;
		
		chA = nameA.charAt(pos);
		chB = nameB.charAt(pos);
		
		if (chA > chB) {
			return 1;
		} else if (chA < chB) {
			return -1;
		} else {
			return sortName(nameA, nameB, pos + 1);
		}
	}
}

function sortLit(a, b) {
	// First, check years
	if (a.year > b.year) {
		return 1;
	} else if (a.year < b.year) {
		return -1;
	} else {
		// Next, check months
		if (a.month > b.month) {
			return 1;
		} else if (a.month < b.month) {
			return -1;
		} else {
			return sortName(a.author, b.author);
		}
		
		return 0;
	}
}

function sortSpmByQuantity(a, b) {
	if (a.count - 0 > b.count - 0) {
		return -1;
	} else if (a.count - 0 < b.count - 0) {
		return 1;
	} else {
		return 0;
	}
}

function sortSpmByYear(a, b) {
	if (a.coll_year - 0 < b.coll_year - 0) {
		return -1;
	} else if (a.coll_year - 0 > b.coll_year - 0) {
		return 1;
	} else {
		return 0;
	}
}

function sortSpmByMonth(a, b) {
	if (a.coll_month - 0 < b.coll_month - 0) {
		return -1;
	} else if (a.coll_month - 0 > b.coll_month - 0) {
		return 1;
	} else {
		return 0;
	}
}

function sortSpmBySize(a, b) {
	// First, keep types grouped
	if (a.type - 0 > b.type - 0) {
		return -1;
	} else if (a.type - 0 < b.type - 0) {
		return 1;
	} else {
		// Next, order by size
		if (a.value - 0 > b.value - 0) {
			return -1;
		} else if (a.value - 0 < b.value - 0) {
			return 1;
		} else {
			return 0;
		}
	}
}

function sortSpmByLatitude(a, b) {
	// First, keep types grouped
	if (a.type - 0 > b.type - 0) {
		return -1;
	} else if (a.type - 0 < b.type - 0) {
		return 1;
	} else {
		// Next, order by latitude
		if (a.lat - 0 > b.lat - 0) {
			return -1;
		} else if (a.lat - 0 < b.lat - 0) {
			return 1;
		} else {
			return 0;
		}
	}
}
