source: main/trunk/greenstone3/web/interfaces/default/js/map-scripts.js@ 33147

Last change on this file since 33147 was 33147, checked in by wy59, 5 years ago

Dr Bainbridge wanted red markers when viewing subclassifiers, as red markers represent documents listed on the page currently open in running GSDL, whereas blue markers represent docs in the same collection which are NOT listed on the current GSDL page, but on the next pages (of search results or classifier).

  • Property svn:executable set to *
File size: 26.1 KB
Line 
1var mapEnabled = true; // variable to detect when map-scripts have been included into document_scripts.js and classifier_scripts.js
2
3//var newLat, newLng = 0;
4var _docList = new Array();
5_docList.ids = new Array();
6_docList.getDocByIndex = function(index)
7{
8 return _docList[_docList.ids[index]];
9};
10
11var _map;
12var _intervalHandle;
13var _baseURL = document.URL.substring(0, document.URL.indexOf("?") + 1);
14var _retrievedClassifiers = new Array();
15var _preventLoopingSingleMarker = false;
16var _searchRunning = false;
17var _nearbyDocs = new Array();
18var _scrollThroughDefault = true;
19
20function initializeMapScripts()
21{
22 setUpMap();
23
24 var jsonNodeDiv = $("#jsonNodes");
25 if(jsonNodeDiv.length)
26 {
27 //console.log("@@@ JSON node div html: " + jsonNodeDiv.html());
28 var jsonNodes = eval(jsonNodeDiv.html());
29
30 if(jsonNodes && jsonNodes.length > 0)
31 {
32 for(var i = 0; i < jsonNodes.length; i++)
33 {
34 _docList[jsonNodes[i].nodeID] = jsonNodes[i];
35 _docList.ids.push(jsonNodes[i].nodeID);
36 createMarkers(jsonNodes[i], true);
37 }
38 updateMap();
39 }
40 else
41 {
42 //hiding the map
43 //$("#map_canvas").css({visibility:"hidden", height:"0px"});
44 $("#map_canvas").css({visibility:"hidden"}); // if you comment this out, add a log message saying "suppressing hiding map"
45 }
46 }
47
48 _docList.loopIndex = 0;
49
50 if(_docList.ids.length > 1)
51 {
52 var startStopCheckbox = $("<input>", {"type": "checkbox", "checked": _scrollThroughDefault, "id": "scrollCheckbox"});
53 startStopCheckbox.click(function()
54 {
55 // http://stackoverflow.com/questions/901712/how-to-check-if-a-checkbox-is-checked-in-jquery
56 // http://stackoverflow.com/questions/5270689/attrchecked-checked-does-not-work
57
58 if($('#scrollCheckbox').is(':checked')) // OR: if(document.getElementById('scrollCheckbox').checked)
59 {
60 if(_intervalHandle == null)
61 {
62 _intervalHandle = setInterval(loopThroughMarkers, 2000);
63 }
64 }
65 else
66 {
67 clearInterval(_intervalHandle);
68 _intervalHandle = null;
69 }
70 });
71
72 var label = $("<span>Scroll through places</span>");
73 var container = $("<div>", {"class": "ui-widget-header ui-corner-all", "style": "clear:right; float:right; padding:0px 5px 3px 0px;"});
74 container.append(startStopCheckbox);
75 container.append(label);
76
77 $(container).insertAfter("#map_canvas");
78
79 if (_scrollThroughDefault) {
80 _intervalHandle = setInterval(loopThroughMarkers, 2000);
81 }
82
83 }
84}
85
86function setUpMap()
87{
88 //alert("@@@@in map-scripts::setUpMap()");
89
90 var myOptions =
91 {
92 zoom: 2,
93 center: new google.maps.LatLng(0, 0),
94 mapTypeId: google.maps.MapTypeId.HYBRID
95 };
96 var $map_canvas = $("#map_canvas");
97
98 if ($map_canvas.length > 0) {
99 _map = new google.maps.Map($map_canvas[0], myOptions);
100 google.maps.event.addListener(_map, 'bounds_changed', performSearchForMarkers);
101 }
102}
103
104function performSearchForMarkers()
105{
106 if(_searchRunning)
107 {
108 return;
109 }
110
111
112
113 _searchRunning = true;
114
115 var bounds = _map.getBounds();
116
117 var neLat = bounds.getNorthEast().lat();
118 var neLng = bounds.getNorthEast().lng();
119 var swLat = bounds.getSouthWest().lat();
120 var swLng = bounds.getSouthWest().lng();
121
122 var latDistance = neLat - swLat;
123 var lngDistance = neLng - swLng;
124
125 //Check which increment to use for latitude (i.e. 0.001, 0.01, 0.1 or 1 degree increments)
126 var latDelta;
127 var latPrecision;
128 for(var i = 3; i >= 0; i--)
129 {
130 latDelta = (1 / Math.pow(10, i));
131 if((latDistance / latDelta) <= 5 || latDelta == 1)
132 {
133 latPrecision = i;
134 break;
135 }
136 }
137
138 //Check which increment to use for longitude (i.e. 0.001, 0.01, 0.1 or 1 degree increments)
139 var lngDelta;
140 for(var i = 3; i >= 0; i--)
141 {
142 lngDelta = (1 / Math.pow(10, i));
143 if((lngDistance / lngDelta) <= 5 || lngDelta == 1)
144 {
145 lngPrecision = i;
146 break;
147 }
148 }
149
150 if(latDelta == 0.1){latDelta = 1; latPrecision = 0; }
151 if(lngDelta == 0.1){lngDelta = 1; lngPrecision = 0; }
152
153 /*
154 var query = "";
155 for(var i = 0; i <= Math.floor(latDistance / latDelta) + 1; i++)
156 {
157 for(var j = 0; j <= Math.floor(lngDistance / lngDelta) + 1; j++)
158 {
159 //Some necessary variables
160 var newLat = neLat - (latDelta * i);
161 var newLatString = "" + newLat;
162 var newLatTrunc;
163 if(newLat < 0){newLatTrunc = Math.ceil(newLat);}
164 else{newLatTrunc = Math.floor(newLat);}
165
166 var newLng = neLng - (lngDelta * j);
167 var newLngString = "" + newLng;
168 var newLngTrunc;
169 if(newLng < 0){newLngTrunc = Math.ceil(newLng);}
170 else{newLngTrunc = Math.floor(newLng);}
171
172 //Construct query
173 query += "(";
174 query += "LA:" + coordToAbsDirected(newLatTrunc, "lat");
175 if(latDelta != 1)
176 {
177 query += "+AND+";
178 query += "LA:" + newLatString.substring(newLatString.indexOf(".") + 1, newLatString.indexOf(".") + latPrecision + 1);
179 }
180 query += "+AND+";
181 query += "LN:" + coordToAbsDirected(newLngTrunc, "lng");
182 if(lngDelta != 1)
183 {
184 query += "+AND+";
185 query += "LN:" + newLngString.substring(newLngString.indexOf(".") + 1, newLngString.indexOf(".") + lngPrecision + 1);
186 }
187 query += ")";
188
189 if(i != (Math.floor(latDistance / latDelta) + 1) || j != (Math.floor(lngDistance / lngDelta) + 1)){ query += "+OR+"; }
190 }
191 }
192 */
193 var query = "";
194 var iMax = Math.floor(latDistance / latDelta) + 1;
195 var jMax = Math.floor(lngDistance / lngDelta) + 1;;
196 for(var i = 0; i <= iMax; i++) //for(var i = 0; i <= Math.floor(latDistance / latDelta) + 1; i++)
197 {
198 for(var j = 0; j <= jMax; j++) //for(var j = 0; j <= Math.floor(lngDistance / lngDelta) + 1; j++)
199 {
200 //Some necessary variables
201 var newLat = neLat - (latDelta * i);
202 var newLatString = "" + newLat;
203 var newLatTrunc;
204 if(newLat < 0){newLatTrunc = Math.ceil(newLat);}
205 else{newLatTrunc = Math.floor(newLat);}
206
207 var newLng = neLng - (lngDelta * j);
208 var newLngString = "" + newLng;
209 var newLngTrunc;
210 if(newLng < 0){newLngTrunc = Math.ceil(newLng);}
211 else{newLngTrunc = Math.floor(newLng);}
212
213 //Construct query
214 query += "(";
215 query += "CS:\"" + coordToAbsDirected(newLatTrunc, "lat");
216 //query += "CS:\"" + coordToAbsDirected(newLatTrunc, "lat") + "\" \"" + coordToAbsDirected(newLngTrunc, "lng") + "\""; //query += "LA:" + coordToAbsDirected(newLatTrunc, "lat");
217 if(latDelta != 1)
218 {
219 query += newLatString.substring(newLatString.indexOf(".") + 1, newLatString.indexOf(".") + latPrecision + 1);
220 }
221 query += " ";
222 //query += "+AND+";
223
224 //query += "LN:" + coordToAbsDirected(newLngTrunc, "lng");
225 query += coordToAbsDirected(newLngTrunc, "lng");
226 if(lngDelta != 1)
227 {
228 query += newLngString.substring(newLngString.indexOf(".") + 1, newLngString.indexOf(".") + lngPrecision + 1);
229 }
230 query += "\"";
231 query += ")";
232
233 //if(i != (Math.floor(latDistance / latDelta) + 1) || j != (Math.floor(lngDistance / lngDelta) + 1)){ query += "+OR+"; }
234 if(i != iMax || j != jMax){ query += "+OR+"; }
235 }
236 }
237
238 // This works, why not from the double loop above?
239 //query = "(CS:\"" + coordToAbsDirected(newLatTrunc, "lat") + " " + coordToAbsDirected(newLngTrunc, "lng") + "\")";
240 //alert("@@@@in map-scripts::performSearchForMarkers() - query: " + query);
241
242 //var url = gs.xsltParams.library_name + "?a=q&s=RawQuery&rt=rd&c=" + gs.cgiParams.c + "&s1.rawquery=" + query + "&excerptid=jsonNodes";
243 var url = gs.xsltParams.library_name;
244 var data = "a=q&s=RawQuery&rt=rd&c=" + gs.cgiParams.c + "&s1.rawquery=" + query + "&excerptid=jsonNodes";
245 $.ajax({type:"POST", url:url, data:data})
246 .success(function(responseText)
247 {
248 //console.log("*** responseText (first 250) = " + responseText.substring(0,256));
249
250 if(responseText.search("id=\"jsonNodes") != -1)
251 {
252 var startIndex = responseText.indexOf(">");
253 var endIndex = responseText.indexOf("</");
254
255 //console.log("@@@@ performSearch, got response: " + responseText);
256
257 var jsonNodes = eval(responseText.substring(startIndex+1, endIndex));
258 if(jsonNodes && jsonNodes.length > 0)
259 {
260 for(var i = 0; i < jsonNodes.length; i++)
261 {
262 var doc = jsonNodes[i];
263
264 var found = false;
265 for(var j = 0; j < _docList.ids.length; j++){if(doc.nodeID == _docList.ids[j]){found = true; break;}}
266
267 if(!found)
268 {
269 _docList[doc.nodeID] = doc;
270 _docList.ids.push(doc.nodeID);
271
272 createMarkers(doc, false);
273 }
274 }
275 }
276 }
277 else
278 {
279 console.log("No JSON information received");
280 }
281
282 _searchRunning = false;
283 }).fail(function(responseText, textStatus, errorThrown) // fail() has replaced error(), http://api.jquery.com/jquery.ajax/
284 {
285 console.log("In map-scripts.performSearchForMarkers(): Got an error in ajax call");
286 _searchRunning = false;
287 });
288}
289
290function coordToAbsDirected(coord, type)
291{
292 var value = "" + coord;
293 if(coord < 0)
294 {
295 value = value.substring(1);
296 if(type == "lat")
297 {
298 value += "S";
299 }
300 else
301 {
302 value += "W";
303 }
304 }
305 else
306 {
307 if(type == "lat")
308 {
309 value += "N";
310 }
311 else
312 {
313 value += "E";
314 }
315 }
316
317 return value;
318}
319
320function updateMap()
321{
322 var markersOnMap = 0;
323 var bounds = new google.maps.LatLngBounds();
324 for(var i = 0; i < _docList.ids.length; i++)
325 {
326 var doc = _docList.getDocByIndex(i);
327 if(doc.parentCL && doc.parentCL.style.display == "none")
328 {
329 if(doc.shapes) {
330 for(var x = 0; x < doc.shapes.length; x++) {
331 doc.shapes[x].setVisible(false);
332 }
333 markersOnMap = doc.shapes.length;
334 } else {
335 doc.marker.setVisible(false);
336 }
337 continue;
338 }
339 else
340 {
341 if(doc.shapes) {
342 for(var x = 0; x < doc.shapes.length; x++) {
343 doc.shapes[x].setVisible(true);
344 }
345 markersOnMap = doc.shapes.length;
346 } else {
347 doc.marker.setVisible(true);
348 }
349 markersOnMap++;
350 }
351
352
353 if(doc.coords) {
354 for(var x = 0; x < doc.coords.length; x++) {
355 var coord = doc.coords[x];
356 var coordInfo = getLatLngForCoord(doc.coords[x]);
357 bounds.extend(new google.maps.LatLng(coordInfo.lat, coordInfo.lng));
358 }
359 }
360 else {
361 bounds.extend(new google.maps.LatLng(doc.lat, doc.lng));
362 }
363 }
364
365 if(markersOnMap > 1)
366 {
367 _map.fitBounds(bounds);
368 } else if (markersOnMap == 1) {
369 // sometimes a single point bounds are too small for the map to display, so use center and zoom instead of fitbounds.
370 _map.setCenter(bounds.getCenter());
371 _map.setZoom(18); // arbitrary value that looked nice for my example
372 }
373}
374
375function getLatLngForCoord(coord) {
376
377 // https://stackoverflow.com/questions/2559318/how-to-check-for-an-undefined-or-null-variable-in-javascript
378 if(!coord) {
379 // some_variable is either null, undefined, 0, NaN, false, or an empty string
380 console.log("@@@@ In map-scripts::getLatLngForCoord(): no or invalid coord info");
381 return null;
382 }
383
384 // coord is of the form: "37S77 157E53"
385 // lat will be 37S77, lng 157E53.
386 var indexOfSpace = coord.indexOf(" ");
387 if(indexOfSpace === -1) {
388 console.log("@@@@ In map-scripts::getLatLngForCoord(): bad format for coord " + coord);
389 return null;
390 }
391 var latitude = coord.substring(0, indexOfSpace);
392 var longitude = coord.substring(indexOfSpace+1);
393 return {lat: latitude, lng: longitude}; // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects
394}
395
396function loopThroughMarkers()
397{
398 if(_docList.ids.length == 0)
399 {
400 return;
401 }
402
403 var visibleMarkers = new Array();
404 for(var i = 0; i < _docList.ids.length; i++)
405 {
406 var doc = _docList.getDocByIndex(i);
407 if(doc.marker.getVisible())
408 {
409 visibleMarkers.push(doc);
410 }
411 }
412
413 if(visibleMarkers.length < 2)
414 {
415 clearAllInfoBoxes();
416 return;
417 }
418
419 clearAllInfoBoxes();
420
421 var elem = null;
422 while(!elem)
423 {
424 if(_docList.loopIndex >= visibleMarkers.length)
425 {
426 _docList.loopIndex = 0;
427 }
428
429 var doc = visibleMarkers[_docList.loopIndex];
430 var elem = gs.jqGet("div" + doc.nodeID);
431 if(elem.length)
432 {
433 elem.css("background", "#BBFFBB");
434 setTimeout(function(){elem.css("background", "");}, 2000);
435 }
436 _docList.loopIndex++;
437 }
438 doc.marker.markerInfo.open(_map, doc.marker);
439}
440
441
442function focusDocument(id)
443{
444 var doc = _docList[id];
445 if(doc)
446 {
447 clearInterval(_intervalHandle);
448 _intervalHandle = null;
449 if(doc.coords) {
450 for(var x = 0; x < doc.coords.length; x++) {
451 var coord = doc.coords[x];
452 var coordInfo = getLatLngForCoord(doc.coords[x]);
453 _map.panTo(new google.maps.LatLng(coordInfo.lat, coordInfo.lng));
454 }
455 } else {
456 _map.panTo(new google.maps.LatLng(doc.lat, doc.lng));
457 }
458 clearAllInfoBoxes();
459 doc.marker.markerInfo.open(_map, doc.marker);
460 var scrollCheckbox = $("#scrollCheckbox");
461 if(scrollCheckbox.checked)
462 {
463 scrollCheckbox.checked = false;
464 }
465 }
466}
467
468function clearAllInfoBoxes()
469{
470 for(var i = 0; i < _docList.ids.length; i++)
471 {
472 var doc = _docList.getDocByIndex(i);
473 doc.marker.markerInfo.close();
474 }
475}
476
477function createMarkers(doc, mainMarker) {
478 if(doc.mapoverlay) {
479 //console.log("Have shapes: " + doc.mapoverlay.toString());
480 createShapes(doc, mainMarker);
481 } else { // backwards compatible to deal with Lat and Lng meta stored for doc
482 pos = new google.maps.LatLng(doc.lat,doc.lng);
483 createMarker(doc, pos, mainMarker);
484 }
485}
486
487function addInfoMarker(doc, shape) {
488
489 if(!shape.description) {
490 //console.log("@@@@ " + shape.type.toString() + " had no description/label");
491 return;
492 }
493
494 // else add an InfoWindow for this shape using the label (shape.description)
495
496 // https://developers.google.com/maps/documentation/javascript/infowindows
497 // An InfoWindow's "position contains the LatLng at which this info window is anchored.
498 // Note: An InfoWindow may be attached either to a Marker object (in which case its position is based on the marker's location)
499 // or on the map itself at a specified LatLng. Opening an info window on a marker will automatically update the position."
500 var infoWindow = new google.maps.InfoWindow({content:shape.description}); // NOTE: if not setting content or position properties
501 // inside this constructor, need to call setContent/setPosition to set them
502
503 if(shape.type === google.maps.drawing.OverlayType.MARKER) {
504 var marker = shape;
505 marker.addListener('mouseover', function() {
506 infoWindow.open(_map, marker);
507 });
508 marker.addListener('mouseout', function() {
509 infoWindow.close();
510 });
511 attachClickHandler(marker, doc.nodeID); // do what the original code used to do here
512 }
513 else {
514 var coord = ShapesUtil.getLabelCoordinate(shape);
515 console.log("Coord for " + shape.type.toString() + " is " + coord.toString());
516 infoWindow.setPosition(coord);
517 shape.addListener('mouseover', function() {
518 infoWindow.open(_map);
519 });
520 shape.addListener('mouseout', function() {
521 infoWindow.close();
522 });
523 attachClickHandler(shape, doc.nodeID); // as above
524 }
525}
526
527// This function will create Google Shapes/Overlays and markers out of a given doc JSONNode's doc.mapOverlay
528// (doc.mapOverlay shapes are stored as an array of JSON) and store the shapes/overlays in the doc.shapes array.
529// Note: doc.coords are just an array of all the coordinates in a doc, not indicating to which shapes they belong.
530// They're only **for searching** - for seaching which coords (hence docs) are in a map.
531// Param mainMarker: if set to true, marker is red. If false, marker is blue
532function createShapes(doc, mainMarker)
533{
534 // for doc.shapes: don't store JSON anymore, convert them to google Shapes overlays and store them instead
535 doc.shapes = [];
536 for (var i=0; i<doc.mapoverlay.length; i++) {
537 var shape = ShapesUtil.JSONToShape(doc.mapoverlay[i]);
538 doc.shapes[i] = shape;
539 shape.setMap(_map);
540 shape["title"] = doc.title;
541
542 // Unset editable and draggable properties of shape
543 // And for markers, which are initialised to clickable besides, undo the clickability
544 // and set them
545 if(shape.type === google.maps.drawing.OverlayType.MARKER) {
546 var marker = shape;
547 // mainMarkers should be red
548 if(!mainMarker) {
549 marker["icon"] = "interfaces/" + gs.xsltParams.interface_name + "/images/bluemarker.png";
550 }
551 marker.clickable = false; // only markers
552 }
553
554 shape.editable = false;
555 shape.draggable = false;
556
557
558
559 // doc[i]'s label = doc.shapes[i].description
560 addInfoMarker(doc, shape);
561 }
562
563 var docElement = gs.jqGet("div" + doc.nodeID);
564 var parent;
565 if(docElement)
566 {
567 parent = docElement.parentNode;
568 }
569
570 while(parent && parent.nodeName != "BODY")
571 {
572 if($(parent).attr("id") && $(parent).attr("id").search("divCL") != -1)
573 {
574 doc.parentCL = parent;
575 break;
576 }
577
578 parent = parent.parentNode;
579 }
580}
581
582// This method is only for backwards compatibility: for those collections with docs that only have Lat and Lng meta
583// and no GPS.mapOverlay (and hence Coordinate) meta.
584// Param mainMarker: if set to true, marker is red. If false, marker is blue
585function createMarker(doc, pos, mainMarker)
586{
587 var marker;
588 if(mainMarker)
589 {
590 marker = new google.maps.Marker
591 ({
592 position: pos,
593 title:doc.title,
594 map:_map
595 });
596 }
597 else
598 {
599 marker = new google.maps.Marker
600 ({
601 position: pos,
602 title:doc.title,
603 map:_map,
604 icon:"interfaces/" + gs.xsltParams.interface_name + "/images/bluemarker.png"
605 });
606 }
607
608 var docElement = gs.jqGet("div" + doc.nodeID);
609 var parent;
610 if(docElement)
611 {
612 parent = docElement.parentNode;
613 }
614
615 while(parent && parent.nodeName != "BODY")
616 {
617 if($(parent).attr("id") && $(parent).attr("id").search("divCL") != -1)
618 {
619 doc.parentCL = parent;
620 break;
621 }
622
623 parent = parent.parentNode;
624 }
625
626 var info = new google.maps.InfoWindow({content:doc.title});
627 marker.markerInfo = info;
628 doc.marker = marker;
629 attachClickHandler(marker, doc.nodeID);
630}
631
632// TODO: with the following, it seems that clicking on shape expands the entire document
633// Should it be that clicking on a shape should expand the doc section that contains that shape meta?
634function attachClickHandler(shapeOrMarker, nodeID)
635{
636 google.maps.event.addListener(shapeOrMarker, 'click', function()
637 {
638 document.location.href = gs.xsltParams.library_name + "?a=d&ed=1&c=" + gs.cgiParams.c + "&d=" + nodeID + "&dt=hierarchy&p.a=b&p.sa=&p.s=ClassifierBrowse";
639 });
640}
641
642function NewLatLng(lat, lng)
643{
644 console.log("Latitude " + lat);
645 console.log("Longitude " + lng);
646}
647
648function getSubClassifier(sectionID)
649{
650 var url = gs.xsltParams.library_name + "?a=b&rt=s&s=ClassifierBrowse&c=" + gs.cgiParams.c + "&cl=" + sectionID + "&excerptid=jsonNodes";
651 $.ajax(url)
652 .success(function(responseText)
653 {
654 var startIndex = responseText.indexOf(">");
655 var endIndex = responseText.indexOf("</");
656
657 var jsonNodes = eval(responseText.substring(startIndex+1, endIndex));
658 if(jsonNodes && jsonNodes.length > 0)
659 {
660 for(var i = 0; i < jsonNodes.length; i++)
661 {
662 var doc = jsonNodes[i];
663 _docList[doc.nodeID] = doc;
664 _docList.ids.push(doc.nodeID);
665
666 createMarkers(doc, true);
667 }
668
669 $("#map_canvas").css({"visibility": "visible", "height": ""});
670 }
671
672 updateMap();
673 })
674 .error(function()
675 {
676 console.log("Error getting subclassifiers");
677 return;
678 });
679}
680
681function performDistanceSearchWithCoordinates(id, coord, degrees)
682{
683 var coordInfo = getLatLngForCoord(coord);
684 if(!coordInfo) {
685 console.log("@@@ ERROR in map-scripts::performDistanceSearchWithCoordinates: coordInfo is null");
686 }
687 performDistanceSearch(id, coordInfo.lat, coordInfo.lng, degrees);
688}
689
690function performDistanceSearch(id, lat, lng, degrees)
691{
692 if(parseFloat(lat) > 180 || parseFloat(lat) < -180 || parseFloat(lng) > 180 || parseFloat(lat) < -180)
693 {
694 console.log("Latitude or longitude incorrectly formatted");
695 return;
696 }
697
698 if(lat.indexOf(".") == -1 || lng.indexOf(".") == -1 || (lat.indexOf(".") + 3) >= lat.length || (lng.indexOf(".") + 3) >= lng.length)
699 {
700 console.log("Latitude or longitude does not have the required precision for a distance search");
701 return;
702 }
703
704 var query = "";
705 for(var i = 0; i < degrees * 2; i++)
706 {
707 for (var j = 0; j < degrees * 2; j++)
708 {
709 var latDelta = (i - degrees) * 0.01;
710 var lngDelta = (j - degrees) * 0.01;
711
712 query += "(" + getDistanceQueryString(lat, latDelta, 2, "LA", ["N","S"]);
713 query += "+AND+";
714 query += getDistanceQueryString(lng, lngDelta, 2, "LN", ["E","W"]) + ")";
715
716 if(i != ((degrees * 2) - 1) || j != ((degrees * 2) - 1)){ query += "+OR+"; }
717 }
718 }
719
720 var inlineTemplate = '\
721 <xsl:template match="/" priority="5">\
722 <table id="nearbyDocs">\
723 <tr>\
724 <th><a href="javascript:sortByDistance();">Distance</a></th><th><a href="javascript:sortAlphabetically();">Document</a></th>\
725 </tr>\
726 <xsl:apply-templates select="//documentNode"/>\
727 </table>\
728 </xsl:template>\
729 \
730 <xsl:template match="documentNode" priority="5">\
731 <xsl:if test="@nodeID !=\''+id+'\'">\
732 <tr>\
733 <td>___<gsf:metadata name="Latitude"/>______<gsf:metadata name="Longitude"/>___</td>\
734 <td><gsf:link title="'+gs.text.doc.nearby_doc_tooltip+'" type="document"><gsf:metadata name="Title"/></gsf:link></td>\
735 </tr>\
736 </xsl:if>\
737 </xsl:template>';
738
739 var url = gs.xsltParams.library_name + "?a=q&s=RawQuery&rt=rd&c=" + gs.cgiParams.c + "&s1.rawquery=" + query + "&excerptid=nearbyDocs&ilt=" + inlineTemplate.replace(/ /, "%20");
740 $.ajax(url)
741 .success(function(response)
742 {
743 response = response.replace(/<img src="[^"]*map_marker.png"[^>]*>/g, "");
744
745 var nearbyDocsArray = new Array();
746
747 var lats = new Array();
748 var lngs = new Array();
749 var matches = response.match(/___(-?[0-9\.]*)___/g);
750 for(var i = 0; i < matches.length; i += 2)
751 {
752 var matchLatFloat = parseFloat(matches[i].replace("___", ""));
753 var matchLngFloat = parseFloat(matches[i+1].replace("___", ""));
754
755 lats.push(matchLatFloat);
756 lngs.push(matchLngFloat);
757 var distance = Math.sqrt(Math.pow(matchLatFloat - parseFloat(lat), 2) + Math.pow(matchLngFloat - parseFloat(lng), 2)) * (40000.0/360.0);
758 var distanceString = "" + distance;
759 distanceString = distanceString.substring(0, 6);
760 response = response.replace(matches[i] + matches[i+1], distanceString);
761 }
762
763 var index = 0;
764 var i = 0;
765 while(true)
766 {
767 var distanceStart = response.indexOf("<td>", index);
768 if(distanceStart == -1)
769 {
770 break;
771 }
772 var distanceEnd = response.indexOf("</td>", distanceStart);
773
774 var docLinkStart = response.indexOf("<td>", distanceEnd);
775 var docLinkEnd = response.indexOf("</td>", docLinkStart);
776
777 var dist = response.substring(distanceStart + 4, distanceEnd);
778 var docLink = response.substring(docLinkStart + 4, docLinkEnd);
779
780 _nearbyDocs.push({title:docLink, distance:dist, lat:lats[i], lng:lngs[i++]});
781
782 index = docLinkEnd;
783 }
784
785 sortByDistance(lat,lng);
786
787 var toggle = $("#nearbyDocumentsToggle");
788 toggle.attr("src", gs.imageURLs.collapse);
789 gs.functions.makeToggle(toggle, $("#nearbyDocuments"));
790 });
791}
792
793var map_centering_timeout = null;
794function recenterMapF(lat, lng)
795{
796 return function() {
797 _map.setCenter(new google.maps.LatLng(lat, lng));
798 }
799}
800function recenterMap(lat, lng)
801{
802
803 _map.setCenter(new google.maps.LatLng(lat, lng));
804
805}
806function sortByDistance(base_lat,base_lng)
807{
808 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>';
809 _nearbyDocs.sort(function(a, b){return (a.distance - b.distance);});
810 for(var i = 0; i < _nearbyDocs.length; i++)
811 {
812
813 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>";
814 }
815 sortedTable += "</table>";
816
817 $("#nearbyDocuments").html(sortedTable);
818}
819function prettifyDistance(distance) {
820
821 var new_distance;
822 if (distance < 1) {
823 new_distance = (distance * 1000);
824 // Round to nearest whole number - don't need to show points of metres..
825 new_distance = Math.round(new_distance);
826 new_distance += " m";
827 }
828 else {
829 new_distance = distance +" km";
830
831 }
832 return new_distance;
833}
834
835
836
837function sortAlphabetically(base_lat, base_lng)
838{
839 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>';
840 _nearbyDocs.sort(function(a, b)
841 {
842 var firstTitleStartIndex = a.title.indexOf(">");
843 var firstTitleEndIndex = a.title.indexOf("<", firstTitleStartIndex);
844 var firstTitle = a.title.substring(firstTitleStartIndex + 1, firstTitleEndIndex);
845 var secondTitleStartIndex = b.title.indexOf(">");
846 var secondTitleEndIndex = b.title.indexOf("<", secondTitleStartIndex);
847 var secondTitle = b.title.substring(secondTitleStartIndex + 1, secondTitleEndIndex);
848 return ((firstTitle.toLowerCase() == secondTitle.toLowerCase()) ? 0 : ((firstTitle.toLowerCase() > secondTitle.toLowerCase()) ? 1 : -1));
849 });
850 for(var i = 0; i < _nearbyDocs.length; i++)
851 {
852 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>";
853 }
854 sortedTable += "</table>";
855
856 $("#nearbyDocuments").html(sortedTable);
857}
858
859function getDistanceQueryString(currentCoord, delta, precision, indexName, dirs)
860{
861 var query = "";
862 var coordFloat = parseFloat(currentCoord);
863
864 var newCoord = "" + (coordFloat + delta);
865 var beforeDec = newCoord.substring(0, newCoord.indexOf("."));
866
867 var dir = dirs[0];
868 if(coordFloat < 0)
869 {
870 dir = dirs[1];
871 beforeDec = beforeDec.substring(1);
872 }
873 beforeDec += dir;
874
875 var afterDec = newCoord.substring(newCoord.indexOf(".") + 1, newCoord.indexOf(".") + (precision) + 1);
876
877 return indexName + ":" + beforeDec + "+AND+" + indexName + ":" + afterDec;
878}
Note: See TracBrowser for help on using the repository browser.