Index: /main/trunk/greenstone3/web/interfaces/default/js/classifier_scripts.js
===================================================================
--- /main/trunk/greenstone3/web/interfaces/default/js/classifier_scripts.js	(revision 33288)
+++ /main/trunk/greenstone3/web/interfaces/default/js/classifier_scripts.js	(revision 33289)
@@ -29,6 +29,8 @@
 	if(section.length !== 0)
 	{
+		var expanding = false;
 		if(isExpanded(sectionID))
 		{
+			expanding = false;
 			section.css("display", "none");
 			sectionToggle.attr("src", gs.imageURLs.expand);
@@ -41,4 +43,5 @@
 		else
 		{
+			expanding = true;
 			section.css("display", "block");
 			sectionToggle.attr("src", gs.imageURLs.collapse);
@@ -46,6 +49,7 @@
 		}
 		updateOpenClassifiers();
-		if(typeof mapEnabled !== 'undefined' && mapEnabled){
+		if(typeof mapEnabled !== 'undefined' /*&& mapEnabled*/){
 			//console.log("Classifier scripts -> updateMap()");
+			toggleMapSection({"expand": expanding, "nodeID": sectionID});
 			updateMap();
 		}
Index: /main/trunk/greenstone3/web/interfaces/default/js/map-scripts.js
===================================================================
--- /main/trunk/greenstone3/web/interfaces/default/js/map-scripts.js	(revision 33288)
+++ /main/trunk/greenstone3/web/interfaces/default/js/map-scripts.js	(revision 33289)
@@ -4,21 +4,25 @@
 
 //var newLat, newLng = 0;
-var _docList = new Array();
-_docList.ids = new Array();
+var _docList = {};
+_docList.ids = [];
+
 _docList.getDocByIndex = function(index)
 {
 	return _docList[_docList.ids[index]];
 };
+
+var _nearbyDocListByProximity = [];
 
 var _map;
 var _intervalHandle;
 var _baseURL = document.URL.substring(0, document.URL.indexOf("?") + 1);
-var _retrievedClassifiers = new Array();
+var _retrievedClassifiers = [];
 var _preventLoopingSingleMarker = false;
 var _searchRunning = false;
-var _nearbyDocs = new Array();
-var _scrollThroughDefault = true; // TODO: default starts at true
+var _nearbyDocsByDistance = [];
+var _scrollThroughDefault = true;
 
 var LOW_OPACITY = 0.1; // make surrounding docs' opacity 10%
+var _DEBUGGING_ = false;
 
 function initializeMapScripts() 
@@ -36,4 +40,6 @@
 		{
 			mapEnabled = true;
+			showMap("initializeMapScripts");
+			
 			var resultsArea = $('#resultsArea');
 			if (resultsArea.length > 0){
@@ -49,5 +55,5 @@
 				console.log("#### " + jsonNodes[i].nodeID + " is a main doc: ");
 				console.log(jsonNodes[i]);
-				createMarkers(jsonNodes[i], options);
+				createOverlayItems(jsonNodes[i], options);
 			}
 			
@@ -58,7 +64,7 @@
 			//hiding the map
 			mapEnabled = false;
-			$("#map_canvas").css({display:"none"});
+			hideMap("initializeMapScripts");			
 			//return;
-		}	
+		}
 	}	
 	_docList.loopIndex = 0;
@@ -116,28 +122,33 @@
 		//console.log("@@@ created Google _map");
 		
-		google.maps.event.addListener(_map, 'bounds_changed', performSearchForMarkers);
-	}
-}
-
-function performSearchForMarkers()
-{
+		google.maps.event.addListener(_map, 'bounds_changed', performProximitySearch);
+	}
+}
+
+function performProximitySearch()
+{
+	_gsDebug("*** START OF performProximitySearch()");
+	
+
 	if(typeof mapEnabled === 'undefined') return;
 	if(!mapEnabled){ return; }
 	
-	//console.log("@@@ performSearchForMarkers()");
-	
-	var bounds = _map.getBounds();
-	var ne = bounds.getNorthEast();
-    var sw = bounds.getSouthWest();
-				  
-	//console.log("bounds: ne = " + ne + ", sw = " + sw);
+	_gsDebug("*** Got past mapEnabled test");
+	
+	
+	for(var i = 0 ; i < _nearbyDocListByProximity.length; i++) {
+		removeMarkersFromMap(_nearbyDocListByProximity[i]);
+	}
+	_nearbyDocListByProximity = [];
+	
+	
+	_debugPrintBounds(_map.getBounds(), "@@@ performProximitySearch():");	
 	
 	
 	if(_searchRunning)
 	{
-		//console.log("*** performSearchForMarkers(): already running search => not initiating an additional search");
+		_gsInfo("*** performProximitySearch(): already running search => not initiating an additional search");
 		return;
 	}
-	
 	
 	_searchRunning = true;
@@ -152,4 +163,8 @@
 	var latDistance = neLat - swLat;
 	var lngDistance = neLng - swLng;
+	
+	_gsDebug("****************START*****************");
+	_gsDebug("latDistance = " + latDistance);
+	_gsDebug("lngDistance = " + lngDistance);
 	
 	//Check which increment to use for latitude (i.e. 0.001, 0.01, 0.1 or 1 degree increments)
@@ -185,4 +200,8 @@
     if(lngDelta == 0.1){lngDelta = 1; lngPrecision = 0; }
 	
+	
+	
+	_gsDebug("Proximity search: lat precision BEFORE = " + latPrecision);
+	_gsDebug("Proximity search: lng precision BEFORE = " + lngPrecision);
 	
 	// Want consistent precision for both lat and lng.
@@ -194,9 +213,21 @@
 	}
 	
-	/*
+	_gsDebug("Proximity search: lat precision AFTER = " + latPrecision);
+	_gsDebug("Proximity search: lng precision AFTER = " + lngPrecision);
+	_gsDebug("Proximity search with: latDelta = " + latDelta);
+	_gsDebug("Proximity search with: lngDelta = " + lngDelta);
+	
 	var query = "";
-	for(var i = 0; i <= Math.floor(latDistance / latDelta) + 1; i++)
-	{
-		for(var j = 0; j <= Math.floor(lngDistance / lngDelta) + 1; j++)
+	var iMax = Math.floor(latDistance / latDelta) + 1;
+	var jMax = Math.floor(lngDistance / lngDelta) + 1;
+	
+	_gsDebug("Proximity search with: iMax = " + iMax);
+	_gsDebug("Proximity search with: jMax = " + jMax);
+	
+	_gsDebug("****************END*****************");
+	
+	for(var i = 0; i <= iMax; i++) //for(var i = 0; i <= Math.floor(latDistance / latDelta) + 1; i++)
+	{
+		for(var j = 0; j <= jMax; j++) //for(var j = 0; j <= Math.floor(lngDistance / lngDelta) + 1; j++)
 		{
 			//Some necessary variables
@@ -215,55 +246,11 @@
 			//Construct query
 			query += "(";
-			query += "LA:" + coordToAbsDirected(newLatTrunc, "lat");
-			if(latDelta != 1)
-			{ 
-				query += "+AND+";
-				query += "LA:" + newLatString.substring(newLatString.indexOf(".") + 1, newLatString.indexOf(".") + latPrecision + 1);
-			}
-			query += "+AND+";
-			query += "LN:" + coordToAbsDirected(newLngTrunc, "lng");
-			if(lngDelta != 1)
-			{ 
-				query += "+AND+";
-				query += "LN:" + newLngString.substring(newLngString.indexOf(".") + 1, newLngString.indexOf(".") + lngPrecision + 1);
-			}
-			query += ")";
-
-			if(i != (Math.floor(latDistance / latDelta) + 1) || j != (Math.floor(lngDistance / lngDelta) + 1)){ query += "+OR+"; }
-		}
-	}
-	*/
-	var query = "";
-	var iMax = Math.floor(latDistance / latDelta) + 1;
-	var jMax = Math.floor(lngDistance / lngDelta) + 1;
-	for(var i = 0; i <= iMax; i++) //for(var i = 0; i <= Math.floor(latDistance / latDelta) + 1; i++)
-	{
-		for(var j = 0; j <= jMax; j++) //for(var j = 0; j <= Math.floor(lngDistance / lngDelta) + 1; j++)
-		{
-			//Some necessary variables
-			var newLat = neLat - (latDelta * i);
-			var newLatString = "" + newLat;
-			var newLatTrunc;
-			if(newLat < 0){newLatTrunc = Math.ceil(newLat);}
-			else{newLatTrunc = Math.floor(newLat);}
-			
-			var newLng = neLng - (lngDelta * j);
-			var newLngString = "" + newLng;
-			var newLngTrunc;
-			if(newLng < 0){newLngTrunc = Math.ceil(newLng);}
-			else{newLngTrunc = Math.floor(newLng);}
-
-			//Construct query
-			query += "(";
 			query += "CS:\"" + coordToAbsDirected(newLatTrunc, "lat");
-			//query += "CS:\"" + coordToAbsDirected(newLatTrunc, "lat") + "\" \"" + coordToAbsDirected(newLngTrunc, "lng") + "\""; //query += "LA:" + coordToAbsDirected(newLatTrunc, "lat");
+			
 			if(latDelta != 1)
 			{ 
 				query += newLatString.substring(newLatString.indexOf(".") + 1, newLatString.indexOf(".") + latPrecision + 1);
 			}
-			query += " ";
-			//query += "+AND+";
-			
-			//query += "LN:" + coordToAbsDirected(newLngTrunc, "lng");
+			query += " ";			
 			query += coordToAbsDirected(newLngTrunc, "lng");
 			if(lngDelta != 1)
@@ -274,6 +261,5 @@
 			query += ")";
 
-			//if(i != (Math.floor(latDistance / latDelta) + 1) || j != (Math.floor(lngDistance / lngDelta) + 1)){ query += "+OR+"; }
-			if(i != iMax || j != jMax){ query += "+OR+"; }
+			if(i != iMax || j != jMax){ query += "+OR+"; } //if(i != (Math.floor(latDistance / latDelta) + 1) || j != (Math.floor(lngDistance / lngDelta) + 1)){ query += "+OR+"; }
 		}
 	}
@@ -281,10 +267,10 @@
 	// This works, why not from the double loop above?
 	//query = "(CS:\"" + coordToAbsDirected(newLatTrunc, "lat") + " " + coordToAbsDirected(newLngTrunc, "lng") + "\")";	
-	//alert("@@@@in map-scripts::performSearchForMarkers() - query: " + query);
+	//alert("@@@@in map-scripts::performProximitySearch() - query: " + query);
 	
 	//var url = gs.xsltParams.library_name + "?a=q&s=RawQuery&rt=rd&c=" + gs.cgiParams.c + "&s1.rawquery=" + query + "&excerptid=jsonNodes";
 	var url = gs.xsltParams.library_name;
 	var data = "a=q&s=RawQuery&rt=rd&c=" + gs.cgiParams.c + "&s1.rawquery=" + query + "&excerptid=jsonNodes";
-	//console.log("*** performSearchForMarkers(): rawQuery query data = " + query);
+	//_gsDebug("*** performProximitySearch(): rawQuery query data = " + query);
 	
 	$.ajax({type:"POST", url:url, data:data})
@@ -293,13 +279,4 @@
 		//console.log("*** responseText (first 250) = " + responseText.substring(0,256));
 		
-		// The first time, docList.ids contains ONLY the main/visible doc's ID and its subsections' IDs.
-		// Any one of these will do to determine
-		if(_docList.ids.length > 0) {
-			var mainDocID = _docList.ids[0];
-			var endIndex = mainDocID.indexOf('.');
-			if(endIndex == -1) { endIndex = mainDocID.length; }
-			mainDocID = mainDocID.substring(0, endIndex);
-		}
-		
 		if(responseText.search("id=\"jsonNodes") != -1)
 		{
@@ -310,5 +287,5 @@
 
 			var jsonNodes = eval(responseText.substring(startIndex+1, endIndex));
-			//console.log("Number of matches returned from ajax rawQuery search = " + jsonNodes.length);
+			_gsDebug("@@@@ performProximitySearch - Number of matches returned from ajax rawQuery search = " + jsonNodes.length);
 			if(jsonNodes && jsonNodes.length > 0)
 			{
@@ -320,7 +297,6 @@
 					for(var j = 0; j < _docList.ids.length; j++) {
 						if(doc.nodeID == _docList.ids[j]) {
-							found = true;							
-							console.log("Found nearby ID " + doc.nodeID + " was already drawn:");
-							console.log(jsonNodes[i]);
+							found = true;
+							_gsDebug("performProximitySearch(): Found nearby ID " + doc.nodeID + " was already drawn:", jsonNodes[i]);
 							break;
 						}
@@ -329,17 +305,6 @@
 					if(!found)
 					{
-						_docList[doc.nodeID] = doc;
-						_docList.ids.push(doc.nodeID);
-
-						// Some "nearby docs" are actually subsections of the main document, which are retrieved
-						// as a nearby doc by performSearchForMarkers() BEFORE the subsection is ever expanded.
-						// We need to distinguish between subsections of the main doc -- which should be displayed
-						// in their specified opacity -- and other docs and their subsections which should be displayed
-						// faded out.
-						if(typeof(mainDocID) !== 'undefined' && doc.nodeID.includes(mainDocID)) {
-							createMarkers(doc, {"mainDoc": true});
-						} else {
-							createMarkers(doc, {"mainDoc": false});
-						}						
+						_nearbyDocListByProximity.push(doc);
+						createOverlayItems(doc, {"mainDoc": false});					
 					}
 					
@@ -355,5 +320,5 @@
 	}).fail(function(responseText, textStatus, errorThrown) // fail() has replaced error(), http://api.jquery.com/jquery.ajax/
 		{
-			console.log("In map-scripts.performSearchForMarkers(): Got an error in ajax call");
+			console.log("In map-scripts.performProximitySearch(): Got an error in ajax call");
 			_searchRunning = false;
 	});
@@ -390,9 +355,129 @@
 }
 
+function toggleMapSection(options)
+{
+	
+	var sectionID = options["nodeID"];
+	
+	var titleClassifierEl = document.getElementById("title"+sectionID);
+	var jsonNodesStr = titleClassifierEl.getAttribute("data-gps-map-json");
+	var jsonNodes = JSON.parse(jsonNodesStr);
+	
+	if(options["expand"]){
+		_gsDebug("expanding classifier - sectionID: " + sectionID);		
+		
+		if(jsonNodes && jsonNodes.length > 0)
+		{
+			for(var i = 0; i < jsonNodes.length; i++)
+			{
+				var doc = jsonNodes[i];
+				if(_docList[doc.nodeID]) continue; // already in list, don't add again
+				
+				_docList[doc.nodeID] = doc;
+				_docList.ids.push(doc.nodeID);
+	
+				var options = {
+					"mainDoc": true // TODO: should this be true or false???
+				};
+				createOverlayItems(doc, options);
+			}				
+		}
+		
+	} else { // closing the bookshelf
+		_gsDebug("closing classifier - sectionID: " + sectionID);
+		if(jsonNodes && jsonNodes.length > 0)
+		{
+			for(var i = 0; i < jsonNodes.length; i++)
+			{
+				// remove the doc from _docList and its id from _docList.ids
+				// and remove its markers/shapes from the map
+				var nodeID = jsonNodes[i].nodeID;
+				var doc = _docList[nodeID];
+				if(doc) {
+					removeMarkersFromMap(doc);
+					
+					delete _docList[nodeID];	
+					
+					var filtered_ids_to_keep = [];
+					for(var j = 0; j < _docList.ids.length; j++) {
+						if(_docList.ids[j] !== nodeID) {
+							filtered_ids_to_keep.push(_docList.ids[j]);
+						}
+					}
+					
+					_docList.ids = filtered_ids_to_keep;
+					
+				} else {
+					console.log("**** In toggleMapSection: shouldn't happen - failed to find doc on closing node: " + nodeID);
+				}
+			}		
+			
+		}
+	}
+	
+	_debugPrintDocList();
+	
+	mapEnabled = (_docList.ids.length > 0);	
+	
+	if(mapEnabled) {
+		showMap("toggleMapSection");
+	} else {
+		hideMap("toggleMapSection");
+	}
+	
+	
+}
+
+/* Given a doc, removes all its shapes doc.shapes from the map _map */
+function removeMarkersFromMap(doc) {	
+	for(var i = 0; i < doc.shapes.length; i++) {
+		var shape = doc.shapes[i];
+		shape.setMap(null);
+	}
+}
+
+// In order for fitBounds to work out a non-zero bounds, have to use visibility, not display when hiding/showing the map.
+// AND should not set height to 0px when using visibility hidden. But not setting height to 0 means an invisible map takes up space.
+// In order for the resulting invisible map, that still takes up space, to not break the flow of the visible items
+// on the page, need to swap map between position relative when map visible versus position absolute when the map is hidden.
+// https://developers.google.com/maps/documentation/javascript/reference/map#Map.fitBounds
+function showMap(callingFunction) {
+	
+	//$("#map_canvas").css({display:"block"});
+	//$("#map_canvas").css({visibility:"visible", height:"100%"}); // not working in conjunction with hidden 0px
+	//$("#map_canvas").css({visibility:"visible", height: "400px"}); // but this works in conjunction with hidden 0px
+	$("#map_canvas").css({visibility:"visible", position: "relative"});
+	
+	if(!_DEBUGGING_) return;
+	
+	//var message = "map_canvas display BLOCK";
+	var message = "map_canvas visibility VISIBLE, position relative";
+	if(typeof callingFunction !== 'undefined') {
+		message = "showMap() called from" + callingFunction + ":" + message;
+	}
+	console.log("### " + message);
+}
+
+function hideMap(callingFunction) {
+	//$("#map_canvas").css({display:"none"});
+	//$("#map_canvas").css({visibility:"hidden", height:"0px"});
+	$("#map_canvas").css({visibility:"hidden", position:"absolute"});
+	
+	if(!_DEBUGGING_) return;
+	
+	//var message = "map_canvas display NONE";
+	var message = "map_canvas visibility HIDDEN, position absolute";
+	if(typeof callingFunction !== 'undefined') {
+		message = "hideMap() called from" + callingFunction + ":" + message;
+	}
+	console.log("### " + message);	
+}
+
 function updateMap()
 {
-	//console.log("@@@ updateMap()");	
+	//console.log("@@@ updateMap()");
     var markersOnMap = 0;
     var bounds =  new google.maps.LatLngBounds();
+	
 	for(var i = 0; i < _docList.ids.length; i++)
 	{
@@ -423,6 +508,5 @@
 		}
 		
-		if(doc.shapes) {
-			console.log("@@@@ HERE IN doc.shapes");
+		if(doc.shapes) {			
 			var docSection_overlay_bounds = ShapesUtil.overlayBounds(doc.shapes);
 			// We now have the current document or document subsection's bounds.
@@ -438,8 +522,14 @@
 	}
 	
-	//console.log("@@@ UpdateMap() : bounds = " + bounds);				
+	_debugPrintBounds(bounds, "@@@ UpdateMap():");
+	
+	
 	if(markersOnMap > 1)
     {
-		_map.fitBounds(bounds);
+		_debugPrintBounds(_map.getBounds(), "@@@ UpdateMap() : BEFORE fitbounds, map");	
+		
+		_map.fitBounds(bounds);		
+		
+		_debugPrintBounds(_map.getBounds(), "@@@ UpdateMap() : AFTER fitbounds, map");
     } else if (markersOnMap == 1) {
 		//console.log("@@@ updating bounds with " + markersOnMap + " markers on the map");
@@ -451,4 +541,5 @@
     }
 }
+
 
 // TODO: FUNCTION DUPLICATED IN panoramaViewer.js
@@ -604,5 +695,5 @@
 }
 
-function createMarkers(doc, options) {
+function createOverlayItems(doc, options) {
 	if(doc.mapoverlay) {
 		//console.log("Have shapes: " + doc.mapoverlay.toString());
@@ -617,5 +708,5 @@
 	
 	if(!shape.description) {
-		console.log("@@@@ " + shape.type.toString() + " had no description/label");
+		_gsInfo("#### " + shape.type.toString() + " had no description/label");
 		return;
 	}
@@ -632,5 +723,5 @@
 	if(shape.type === google.maps.drawing.OverlayType.MARKER) {
 		var marker = shape;
-		console.log("Coord for marker is " + coord.toString());
+		_gsDebug("Coord for marker is " + coord.toString());
 		
 		marker.addListener('mouseover', function() {
@@ -644,5 +735,5 @@
 	else {
 		var coord = ShapesUtil.getLabelCoordinate(shape);		
-		console.log("Coord for " + shape.type.toString() + " is " + coord.toString());
+		_gsDebug("Coord for " + shape.type.toString() + " is " + coord.toString());
 		infoWindow.setPosition(coord);
 		shape.addListener('mouseover', function() {
@@ -805,9 +896,13 @@
 		var endIndex = responseText.indexOf("</");
 		
-		var jsonNodes = eval(responseText.substring(startIndex+1, endIndex));
+		var jsonNodesStr = responseText.substring(startIndex+1, endIndex);
+		var jsonNodes = eval(jsonNodesStr); //responseText.substring(startIndex+1, endIndex));
 		if(jsonNodes && jsonNodes.length > 0)
 		{
+			
 			mapEnabled = true;
-			
+			showMap("httpMapBrowseRequest");
+			
+			//var jsonNodesStr = "";			
 			for(var i = 0; i < jsonNodes.length; i++)
 			{
@@ -816,11 +911,21 @@
 				_docList.ids.push(doc.nodeID);
 	
+				//$("#div"+doc.nodeID).attr("data-gps-map-json", JSON.stringify(jsonNodes[i]));
+				//jsonNodesStr += JSON.stringify(jsonNodes[i]); // can't do this after createOverlayItems, as we get cyclical ref error
 				var options = {
 					"mainDoc": true // TODO: should this be true or false???
 				};
-				createMarkers(doc, options);
-			}
-			
-			$("#map_canvas").css({display:"block"});
+				createOverlayItems(doc, options);
+			}
+			
+			///var tmp = $("#title"+sectionID);			
+			///console.log(tmp);		// WRONG
+			///var tmp2 = document.getElementById("title"+sectionID);
+			///console.log(tmp2);		// RIGHT, WHY?
+			
+			// create data-* attribute to store this sectionID's JSON on the section's div			
+			//$("#title"+sectionID).attr("data-gps-map-json", "hello world"); // TODO: Doesn't work. Why?
+			var titleClassifierEl = document.getElementById("title"+sectionID);
+			titleClassifierEl.setAttribute("data-gps-map-json", jsonNodesStr);
 		}
 		
@@ -936,5 +1041,5 @@
 			var docLink = response.substring(docLinkStart + 4, docLinkEnd);
 
-			_nearbyDocs.push({title:docLink, distance:dist, lat:lats[i], lng:lngs[i++]}); 
+			_nearbyDocsByDistance.push({title:docLink, distance:dist, lat:lats[i], lng:lngs[i++]}); 
 			
 			index = docLinkEnd;
@@ -965,9 +1070,9 @@
 {
 	var sortedTable = '<table id="nearbyDocs" onmouseleave="clearTimeout(map_centering_timeout); recenterMap('+base_lat+','+base_lng+');"><tr><th><a href="javascript:;">Distance</a></th><th><a href="javascript:sortAlphabetically('+base_lat+', '+base_lng+');">Document</a></th></tr>';
-	_nearbyDocs.sort(function(a, b){return (a.distance - b.distance);});
-	for(var i = 0; i < _nearbyDocs.length; i++)
+	_nearbyDocsByDistance.sort(function(a, b){return (a.distance - b.distance);});
+	for(var i = 0; i < _nearbyDocsByDistance.length; i++)
     {
 	
-	    sortedTable += "<tr><td>" + prettifyDistance(_nearbyDocs[i].distance) + '</td><td onmouseover="clearTimeout(map_centering_timeout); map_centering_timeout = setTimeout(recenterMapF(' + _nearbyDocs[i].lat + ',' + _nearbyDocs[i].lng + '), 900)" >' + _nearbyDocs[i].title + "</td></tr>";
+	    sortedTable += "<tr><td>" + prettifyDistance(_nearbyDocsByDistance[i].distance) + '</td><td onmouseover="clearTimeout(map_centering_timeout); map_centering_timeout = setTimeout(recenterMapF(' + _nearbyDocsByDistance[i].lat + ',' + _nearbyDocsByDistance[i].lng + '), 900)" >' + _nearbyDocsByDistance[i].title + "</td></tr>";
 	}
 	sortedTable += "</table>";
@@ -996,5 +1101,5 @@
 {
 	var sortedTable = '<table id="nearbyDocs" onmouseleave="clearTimeout(map_centering_timeout); recenterMap('+base_lat+','+base_lng+');"><tr><th><a href="javascript:sortByDistance('+base_lat+', '+base_lng+');">Distance</a></th><th><a href="javascript:;">Document</a></th></tr>';
-	_nearbyDocs.sort(function(a, b)
+	_nearbyDocsByDistance.sort(function(a, b)
 	{
 		var firstTitleStartIndex = a.title.indexOf(">");
@@ -1006,7 +1111,7 @@
 		return ((firstTitle.toLowerCase() == secondTitle.toLowerCase()) ? 0 : ((firstTitle.toLowerCase() > secondTitle.toLowerCase()) ? 1 : -1));
 	});
-	for(var i = 0; i < _nearbyDocs.length; i++)
-	{
-		sortedTable += "<tr><td>" + _nearbyDocs[i].distance + '</td><td onmouseover="clearTimeout(map_centering_timeout); map_centering_timeout = setTimeout(recenterMapF(' + _nearbyDocs[i].lat + ',' + _nearbyDocs[i].lng + '), 900)">' + _nearbyDocs[i].title + "</td></tr>";
+	for(var i = 0; i < _nearbyDocsByDistance.length; i++)
+	{
+		sortedTable += "<tr><td>" + _nearbyDocsByDistance[i].distance + '</td><td onmouseover="clearTimeout(map_centering_timeout); map_centering_timeout = setTimeout(recenterMapF(' + _nearbyDocsByDistance[i].lat + ',' + _nearbyDocsByDistance[i].lng + '), 900)">' + _nearbyDocsByDistance[i].title + "</td></tr>";
 	}
 	sortedTable += "</table>";
@@ -1072,2 +1177,35 @@
 	return queryStringTerm;
 }
+
+function _gsInfo(message, optObject) {
+	console.log(message);
+	if(typeof optObject !== 'undefined') {
+		console.log(optObject);
+	}
+}
+
+function _gsDebug(message, optObject) {
+	if(_DEBUGGING_) {
+		_gsInfo(message, optObject);
+	}
+}
+
+
+function _debugPrintDocList() {	
+	if(!_DEBUGGING_) return;
+	
+	console.log("@@@@ printing docList:");
+	for(var i = 0; i < _docList.ids.length; i++)
+	{	
+		var doc = _docList.getDocByIndex(i);
+		console.log("     At index = " + i + " ids[i]: " + _docList.ids[i]);
+		console.log("     At index = " + i + " ids[i]: " + _docList.ids[i] + ", doc: " + doc.nodeID);
+	}
+}
+
+function _debugPrintBounds(bounds, message) {
+	if(!_DEBUGGING_) return;
+	var ne = bounds.getNorthEast();
+    var sw = bounds.getSouthWest();				  
+	console.log(message + " bounds: ne = " + ne + ", sw = " + sw);
+}
