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

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