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

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