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

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

Second part of commit. Previous part detected whether we were in the import or buildcol phase and now, instead of during import, it would now during buildcol write out Coordinate meta extracted from GPS.mapoverlay meta. The previous commit worked without duplicating Coordinate meta in the index and didn't require the hack of testing whether the doc at a sectionID already had Coordinate meta calculated for it. The current commit 1. phases out the doc.coords variable, both when this array is created in the transform\xsl files and when it's used in map-scripts.js. 2. focusDocument now works with doc.shapes, panning to the overall doc.shapes' bounds and then opening any infomarkers (labels) for the selected doc's shapes.

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