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

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

Some cleanup

  • 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[i];
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.