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

Last change on this file since 33184 was 33184, checked in by wy59, 5 years ago
  1. Loop counter bugfix. 2. Not sure if there should be a scroll through markers option in doc view and if so, what it should do. For now, it's off by default in doc view but can be turned on, in which case it does not at the moment.
  • Property svn:executable set to *
File size: 30.7 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.shapes) {
370 console.log("@@@@ HERE IN doc.shapes");
371 bounds = ShapesUtil.overlayBounds(doc.shapes);
372 }
373 else {
374 var doc_latlng = new google.maps.LatLng(doc.lat, doc.lng);
375 bounds.extend(doc_latlng);
376 }
377 }
378
379 //console.log("@@@ UpdateMap() : bounds = " + bounds);
380 if(markersOnMap > 1)
381 {
382 _map.fitBounds(bounds);
383 } else if (markersOnMap == 1) {
384 //console.log("@@@ updating bounds with " + markersOnMap + " markers on the map");
385 //console.log(bounds);
386
387 // sometimes a single point bounds are too small for the map to display, so use center and zoom instead of fitbounds.
388 _map.setCenter(bounds.getCenter());
389 _map.setZoom(18); // arbitrary value that looked nice for my example
390 }
391}
392
393// TODO: FUNCTION DUPLICATED IN panoramaViewer.js
394function getLatLngForCoord(coord) {
395
396 // https://stackoverflow.com/questions/2559318/how-to-check-for-an-undefined-or-null-variable-in-javascript
397 if(!coord) {
398 // some_variable is either null, undefined, 0, NaN, false, or an empty string
399 console.log("@@@@ In map-scripts::getLatLngForCoord(): no or invalid coord info");
400 return null;
401 }
402
403 // coord is of the form: "37S77 157E53"
404 // lat will be 37S77, lng 157E53.
405 var indexOfSpace = coord.indexOf(" ");
406 if(indexOfSpace === -1) {
407 console.log("@@@@ In map-scripts::getLatLngForCoord(): bad format for coord " + coord);
408 return null;
409 }
410 var latitude = coord.substring(0, indexOfSpace);
411 var longitude = coord.substring(indexOfSpace+1);
412 return {lat: latitude, lng: longitude}; // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects
413}
414
415function loopThroughMarkers()
416{
417 if(_docList.ids.length == 0)
418 {
419 return;
420 }
421
422 var visibleMarkers = new Array();
423 for(var i = 0; i < _docList.ids.length; i++)
424 {
425 var doc = _docList.getDocByIndex(i);
426 if(typeof doc.shapes !== 'undefined') {
427 for(var x = 0; x < doc.shapes.length; x++) {
428 var shape = doc.shapes[x];
429 if(shape.type === google.maps.drawing.OverlayType.MARKER && shape.getVisible())
430 {
431 visibleMarkers.push(doc);
432 }
433 }
434 }
435 if(doc.marker && doc.marker.getVisible())
436 {
437 visibleMarkers.push(doc);
438 }
439 }
440
441 if(visibleMarkers.length < 2)
442 {
443 clearAllInfoBoxes();
444 return;
445 }
446
447 clearAllInfoBoxes();
448
449 var elem = null;
450 while(!elem) // TODO: why redefine elem? Why does this work, and only this, but not while(true) or while(doc.marker) or while(!AnythingFalse)???
451 // Some clever behaviour here, but no documentation on the cleverness. Hard to understand
452 {
453 if(_docList.loopIndex >= visibleMarkers.length)
454 {
455 _docList.loopIndex = 0;
456 }
457
458 var doc = visibleMarkers[_docList.loopIndex];
459 elem = gs.jqGet("div" + doc.nodeID); // TODO: this used to redefine elem by doing var elem = <....>
460 if(elem.length)
461 {
462 elem.css("background", "#BBFFBB");
463 setTimeout(function(){elem.css("background", "");}, 2000);
464 }
465 _docList.loopIndex ++;
466 }
467 //console.log("@@@@ DOC:");
468 //console.log(doc);
469
470 if(doc.marker) {
471 doc.marker.markerInfo.open(_map, doc.marker); // TODO: how does doc have a value here? Where is the value set at this block level?
472 }
473
474 if(doc.shapes) {
475 for(var x = 0; x < doc.shapes.length; x++) {
476 var shape = doc.shapes[i];
477 if(shape.type === google.maps.drawing.OverlayType.MARKER) {
478 shape.markerInfo.open(_map, shape);
479 } else {
480 shape.markerInfo.open(_map);
481 }
482 }
483 }
484}
485
486
487function focusDocument(id)
488{
489 var doc = _docList[id];
490 if(doc)
491 {
492 clearInterval(_intervalHandle);
493 _intervalHandle = null;
494
495 if(doc.shapes) {
496 var docShapesBounds = ShapesUtil.overlayBounds(doc.shapes);
497 _map.panToBounds(docShapesBounds); // https://developers.google.com/maps/documentation/javascript/reference/map#Map.panToBounds
498 } else {
499 _map.panTo(new google.maps.LatLng(doc.lat, doc.lng));
500 }
501
502 clearAllInfoBoxes();
503 if(doc.shapes) { // TODO
504 //console.log("Opening infowindow for doc " + doc.nodeID);
505 for(var x = 0; x < doc.shapes.length; x++) {
506 if(doc.shapes[x].markerInfo) {
507 doc.shapes[x].markerInfo.open(_map); // label
508 }
509 else {
510 console.log("No infowindow for doc " + doc.nodeID + "'s shape " + doc.shapes[x].type);
511 }
512 }
513 //openInfoBoxes(doc);
514 } else { // only Lat and Lng meta, so we have just one marker per doc, which will have the doc title not label
515 doc.marker.markerInfo.open(_map, doc.marker); // doc title
516 }
517 var scrollCheckbox = $("#scrollCheckbox");
518 if(scrollCheckbox.checked)
519 {
520 scrollCheckbox.checked = false;
521 }
522 }
523}
524
525function clearAllInfoBoxes()
526{
527 for(var i = 0; i < _docList.ids.length; i++)
528 {
529 var doc = _docList.getDocByIndex(i);
530
531 if(doc.shapes) {
532 for(var x = 0; x < doc.shapes.length; x++) {
533 if(doc.shapes[x].markerInfo) {
534 //console.log("Closing infowindow for doc " + _docList.ids[i]);
535 doc.shapes[x].markerInfo.close();
536 }
537 }
538 }
539 else { // only Lat and Lng meta, so we have just one marker per doc
540 doc.marker.markerInfo.close();
541 }
542 }
543}
544
545function createMarkers(doc, mainMarker) {
546 if(doc.mapoverlay) {
547 //console.log("Have shapes: " + doc.mapoverlay.toString());
548 createShapes(doc, mainMarker);
549 } else { // backwards compatible to deal with Lat and Lng meta stored for doc
550 pos = new google.maps.LatLng(doc.lat,doc.lng);
551 createMarker(doc, pos, mainMarker);
552 }
553}
554
555function addInfoMarker(doc, shape) {
556
557 if(!shape.description) {
558 console.log("@@@@ " + shape.type.toString() + " had no description/label");
559 return;
560 }
561
562 // else add an InfoWindow for this shape using the label (shape.description)
563
564 // https://developers.google.com/maps/documentation/javascript/infowindows
565 // An InfoWindow's "position contains the LatLng at which this info window is anchored.
566 // Note: An InfoWindow may be attached either to a Marker object (in which case its position is based on the marker's location)
567 // or on the map itself at a specified LatLng. Opening an info window on a marker will automatically update the position."
568 var infoWindow = new google.maps.InfoWindow({content:shape.description}); // NOTE: if not setting content or position properties
569 // inside this constructor, need to call setContent/setPosition to set them
570
571 if(shape.type === google.maps.drawing.OverlayType.MARKER) {
572 var marker = shape;
573 console.log("Coord for marker is " + coord.toString());
574
575 marker.addListener('mouseover', function() {
576 infoWindow.open(_map, marker);
577 });
578 marker.addListener('mouseout', function() {
579 infoWindow.close();
580 });
581 attachClickHandler(marker, doc.nodeID); // do what the original code used to do here
582 }
583 else {
584 var coord = ShapesUtil.getLabelCoordinate(shape);
585 console.log("Coord for " + shape.type.toString() + " is " + coord.toString());
586 infoWindow.setPosition(coord);
587 shape.addListener('mouseover', function() {
588 infoWindow.open(_map);
589 });
590 shape.addListener('mouseout', function() {
591 infoWindow.close();
592 });
593 attachClickHandler(shape, doc.nodeID); // as above
594 }
595 shape.markerInfo = infoWindow;
596 //console.log("######## Added markerInfo object to shape");
597}
598
599// This function will create Google Shapes/Overlays and markers out of a given doc JSONNode's doc.mapOverlay
600// (doc.mapOverlay shapes are stored as an array of JSON) and store the shapes/overlays in the doc.shapes array.
601// Param mainMarker: if set to true, marker is red. If false, marker is blue
602function createShapes(doc, mainMarker)
603{
604 // for doc.shapes: don't store JSON anymore, convert them to google Shapes overlays and store them instead
605 doc.shapes = [];
606
607 for (var i=0; i<doc.mapoverlay.length; i++) {
608 //console.log("in: mapoverlay["+i+"] =" + JSON.stringify(doc.mapoverlay[i]));
609 var shape = ShapesUtil.JSONToShape(doc.mapoverlay[i]);
610 //console.log("out: shape = " + JSON.stringify(shape));
611
612 doc.shapes[i] = shape;
613 shape.setMap(_map);
614 //shape["title"] = doc.title; // TODO: Think on it some more.
615
616 // Unset editable and draggable properties of shape
617 // And for markers, which are initialised to clickable besides, undo the clickability
618 // and set them
619 if(shape.type === google.maps.drawing.OverlayType.MARKER) {
620 var marker = shape;
621 // mainMarkers should be red
622 if(!mainMarker) {
623 marker["icon"] = "interfaces/" + gs.xsltParams.interface_name + "/images/bluemarker.png";
624 }
625 marker.clickable = false; // only markers
626 /*
627 console.log("@@@ map-scripts::addInfoMarker - marker.position");
628 console.log("Lat is " + typeof(marker.position.lat()));
629 console.log(marker.position.lat());
630 console.log("Long is " + typeof(marker.position.lng()));
631 console.log(marker.position.lng());
632 */
633 } else {
634 //console.log("Creating non-marker shape.");
635 }
636
637 shape.editable = false;
638 shape.draggable = false;
639
640 console.log("#### calling addInfoMarker");
641 // doc[i]'s label = doc.shapes[i].description
642 addInfoMarker(doc, shape);
643 }
644
645 var docElement = gs.jqGet("div" + doc.nodeID);
646 var parent;
647 if(docElement)
648 {
649 parent = docElement.parentNode;
650 }
651
652 while(parent && parent.nodeName != "BODY")
653 {
654 if($(parent).attr("id") && $(parent).attr("id").search("divCL") != -1)
655 {
656 doc.parentCL = parent;
657 break;
658 }
659
660 parent = parent.parentNode;
661 }
662}
663
664// This method is only for backwards compatibility: for those collections with docs that only have Lat and Lng meta
665// and no GPS.mapOverlay (and hence Coordinate) meta.
666// Param mainMarker: if set to true, marker is red. If false, marker is blue
667function createMarker(doc, pos, mainMarker)
668{
669 var marker;
670 if(mainMarker)
671 {
672 marker = new google.maps.Marker
673 ({
674 position: pos,
675 title:doc.title,
676 map:_map
677 });
678 }
679 else
680 {
681 marker = new google.maps.Marker
682 ({
683 position: pos,
684 title:doc.title,
685 map:_map,
686 icon:"interfaces/" + gs.xsltParams.interface_name + "/images/bluemarker.png"
687 });
688 }
689
690 var docElement = gs.jqGet("div" + doc.nodeID);
691 var parent;
692 if(docElement)
693 {
694 parent = docElement.parentNode;
695 }
696
697 while(parent && parent.nodeName != "BODY")
698 {
699 if($(parent).attr("id") && $(parent).attr("id").search("divCL") != -1)
700 {
701 doc.parentCL = parent;
702 break;
703 }
704
705 parent = parent.parentNode;
706 }
707
708 var info = new google.maps.InfoWindow({content:doc.title});
709 marker.markerInfo = info;
710 doc.marker = marker;
711 attachClickHandler(marker, doc.nodeID);
712}
713
714// TODO: with the following, it seems that clicking on shape expands the entire document
715// Should it be that clicking on a shape should expand the doc section that contains that shape meta?
716function attachClickHandler(shapeOrMarker, nodeID)
717{
718 google.maps.event.addListener(shapeOrMarker, 'click', function()
719 {
720 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";
721 });
722}
723
724function NewLatLng(lat, lng)
725{
726 console.log("Latitude " + lat);
727 console.log("Longitude " + lng);
728}
729
730function getSubClassifier(sectionID)
731{
732 var url = gs.xsltParams.library_name + "?a=b&rt=s&s=ClassifierBrowse&c=" + gs.cgiParams.c + "&cl=" + sectionID + "&excerptid=jsonNodes";
733 $.ajax(url)
734 .success(function(responseText)
735 {
736 var startIndex = responseText.indexOf(">");
737 var endIndex = responseText.indexOf("</");
738
739 var jsonNodes = eval(responseText.substring(startIndex+1, endIndex));
740 if(jsonNodes && jsonNodes.length > 0)
741 {
742 for(var i = 0; i < jsonNodes.length; i++)
743 {
744 var doc = jsonNodes[i];
745 _docList[doc.nodeID] = doc;
746 _docList.ids.push(doc.nodeID);
747
748 createMarkers(doc, true);
749 }
750
751 $("#map_canvas").css({"visibility": "visible", "height": ""});
752 }
753
754 updateMap();
755 //console.log("getSub Classifier -> updateMap()");
756 })
757 .error(function()
758 {
759 //console.log("Error getting subclassifiers");
760 return;
761 });
762}
763
764function performDistanceSearchWithCoordinates(id, coord, degrees)
765{
766 var coordInfo = getLatLngForCoord(coord);
767 if(!coordInfo) {
768 console.log("@@@ ERROR in map-scripts::performDistanceSearchWithCoordinates: coordInfo is null");
769 }
770 performDistanceSearch(id, coordInfo.lat, coordInfo.lng, degrees);
771}
772
773function performDistanceSearch(id, lat, lng, degrees)
774{
775 if(parseFloat(lat) > 180 || parseFloat(lat) < -180 || parseFloat(lng) > 180 || parseFloat(lat) < -180)
776 {
777 console.log("Latitude or longitude incorrectly formatted");
778 return;
779 }
780
781 if(lat.indexOf(".") == -1 || lng.indexOf(".") == -1 || (lat.indexOf(".") + 3) >= lat.length || (lng.indexOf(".") + 3) >= lng.length)
782 {
783 console.log("Latitude or longitude does not have the required precision for a distance search");
784 return;
785 }
786
787 var query = "";
788 for(var i = 0; i < degrees * 2; i++)
789 {
790 for (var j = 0; j < degrees * 2; j++)
791 {
792 var latDelta = (i - degrees) * 0.01;
793 var lngDelta = (j - degrees) * 0.01;
794
795 //query += "(" + getDistanceQueryStringOldApproach(lat, latDelta, 2, "LA", ["N","S"]);
796 //query += "+AND+";
797 //query += getDistanceQueryStringOldApproach(lng, lngDelta, 2, "LN", ["E","W"]) + ")";
798
799 query += "(" + getDistanceQueryStringTerm(lat, lng, latDelta, lngDelta, 2, "CS") + ")";
800
801 if(i != ((degrees * 2) - 1) || j != ((degrees * 2) - 1)){ query += "+OR+"; }
802 }
803 }
804
805 var inlineTemplate = '\
806 <xsl:template match="/" priority="5">\
807 <table id="nearbyDocs">\
808 <tr>\
809 <th><a href="javascript:sortByDistance();">Distance</a></th><th><a href="javascript:sortAlphabetically();">Document</a></th>\
810 </tr>\
811 <xsl:apply-templates select="//documentNode"/>\
812 </table>\
813 </xsl:template>\
814 \
815 <xsl:template match="documentNode" priority="5">\
816 <xsl:if test="@nodeID !=\''+id+'\'">\
817 <tr>\
818 <td>___<gsf:metadata name="Latitude"/>______<gsf:metadata name="Longitude"/>___</td>\
819 <td><gsf:link title="'+gs.text.doc.nearby_doc_tooltip+'" type="document"><gsf:metadata name="Title"/></gsf:link></td>\
820 </tr>\
821 </xsl:if>\
822 </xsl:template>';
823
824 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");
825 $.ajax(url)
826 .success(function(response)
827 {
828 response = response.replace(/<img src="[^"]*map_marker.png"[^>]*>/g, "");
829
830 var nearbyDocsArray = new Array();
831
832 var lats = new Array();
833 var lngs = new Array();
834 var matches = response.match(/___(-?[0-9\.]*)___/g);
835 for(var i = 0; i < matches.length; i += 2)
836 {
837 var matchLatFloat = parseFloat(matches[i].replace("___", ""));
838 var matchLngFloat = parseFloat(matches[i+1].replace("___", ""));
839
840 lats.push(matchLatFloat);
841 lngs.push(matchLngFloat);
842 var distance = Math.sqrt(Math.pow(matchLatFloat - parseFloat(lat), 2) + Math.pow(matchLngFloat - parseFloat(lng), 2)) * (40000.0/360.0);
843 var distanceString = "" + distance;
844 distanceString = distanceString.substring(0, 6);
845 response = response.replace(matches[i] + matches[i+1], distanceString);
846 }
847
848 var index = 0;
849 var i = 0;
850 while(true)
851 {
852 var distanceStart = response.indexOf("<td>", index);
853 if(distanceStart == -1)
854 {
855 break;
856 }
857 var distanceEnd = response.indexOf("</td>", distanceStart);
858
859 var docLinkStart = response.indexOf("<td>", distanceEnd);
860 var docLinkEnd = response.indexOf("</td>", docLinkStart);
861
862 var dist = response.substring(distanceStart + 4, distanceEnd);
863 var docLink = response.substring(docLinkStart + 4, docLinkEnd);
864
865 _nearbyDocs.push({title:docLink, distance:dist, lat:lats[i], lng:lngs[i++]});
866
867 index = docLinkEnd;
868 }
869
870 sortByDistance(lat,lng);
871
872 var toggle = $("#nearbyDocumentsToggle");
873 toggle.attr("src", gs.imageURLs.collapse);
874 gs.functions.makeToggle(toggle, $("#nearbyDocuments"));
875 });
876}
877
878var map_centering_timeout = null;
879function recenterMapF(lat, lng)
880{
881 return function() {
882 _map.setCenter(new google.maps.LatLng(lat, lng));
883 }
884}
885function recenterMap(lat, lng)
886{
887
888 _map.setCenter(new google.maps.LatLng(lat, lng));
889
890}
891function sortByDistance(base_lat,base_lng)
892{
893 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>';
894 _nearbyDocs.sort(function(a, b){return (a.distance - b.distance);});
895 for(var i = 0; i < _nearbyDocs.length; i++)
896 {
897
898 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>";
899 }
900 sortedTable += "</table>";
901
902 $("#nearbyDocuments").html(sortedTable);
903}
904function prettifyDistance(distance) {
905
906 var new_distance;
907 if (distance < 1) {
908 new_distance = (distance * 1000);
909 // Round to nearest whole number - don't need to show points of metres..
910 new_distance = Math.round(new_distance);
911 new_distance += " m";
912 }
913 else {
914 new_distance = distance +" km";
915
916 }
917 return new_distance;
918}
919
920
921
922function sortAlphabetically(base_lat, base_lng)
923{
924 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>';
925 _nearbyDocs.sort(function(a, b)
926 {
927 var firstTitleStartIndex = a.title.indexOf(">");
928 var firstTitleEndIndex = a.title.indexOf("<", firstTitleStartIndex);
929 var firstTitle = a.title.substring(firstTitleStartIndex + 1, firstTitleEndIndex);
930 var secondTitleStartIndex = b.title.indexOf(">");
931 var secondTitleEndIndex = b.title.indexOf("<", secondTitleStartIndex);
932 var secondTitle = b.title.substring(secondTitleStartIndex + 1, secondTitleEndIndex);
933 return ((firstTitle.toLowerCase() == secondTitle.toLowerCase()) ? 0 : ((firstTitle.toLowerCase() > secondTitle.toLowerCase()) ? 1 : -1));
934 });
935 for(var i = 0; i < _nearbyDocs.length; i++)
936 {
937 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>";
938 }
939 sortedTable += "</table>";
940
941 $("#nearbyDocuments").html(sortedTable);
942}
943
944function getDistanceQueryStringOldApproach(currentCoord, delta, precision, indexName, directions)
945{
946 console.error("**** Old Approach called!!!");
947
948 var query = "";
949 var coordFloat = parseFloat(currentCoord);
950
951 var newCoord = "" + (coordFloat + delta);
952 var beforeDec = newCoord.substring(0, newCoord.indexOf("."));
953
954 var direction = directions[0];
955 if(coordFloat < 0)
956 {
957 // negative value
958 direction = directions[1];
959 beforeDec = beforeDec.substring(1); // skip over '-' at front
960 }
961 beforeDec += direction;
962
963 var afterDec = newCoord.substring(newCoord.indexOf(".") + 1, newCoord.indexOf(".") + (precision) + 1);
964
965 return indexName + ":" + beforeDec + "+AND+" + indexName + ":" + afterDec;
966}
967
968function coordValToIndexToken(coordValStr, delta, precision, directions)
969{
970 var coordValFloat = parseFloat(coordValStr);
971
972 var deltaCoordValStr = "" + (coordValFloat + delta);
973 var beforeDec = deltaCoordValStr.substring(0, deltaCoordValStr.indexOf("."));
974
975 var direction = directions[0];
976 if(coordValFloat < 0)
977 {
978 // negative value
979 direction = directions[1];
980 beforeDec = beforeDec.substring(1); // skip over '-' at front
981 }
982
983 var beforeDecWithDirection = beforeDec + direction;
984
985 var afterDecPrecision = deltaCoordValStr.substring(deltaCoordValStr.indexOf(".") + 1, deltaCoordValStr.indexOf(".") + (precision) + 1);
986
987 var indexToken = beforeDecWithDirection + afterDecPrecision;
988
989 return indexToken;
990}
991
992function getDistanceQueryStringTerm(currentLat,currentLng, deltaLat, deltaLng, precision, indexName)
993{
994 var latToken = coordValToIndexToken(currentLat,deltaLat,precision,["N","S"]);
995 var lngToken = coordValToIndexToken(currentLng,deltaLng,precision,["E","W"]);
996
997 var queryStringTerm = indexName + ":\"" + latToken + " " + lngToken + "\"";
998
999 return queryStringTerm;
1000}
Note: See TracBrowser for help on using the repository browser.