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

Last change on this file since 32604 was 32604, checked in by kjdon, 5 years ago

made it easy to change whether you scroll through the places or not by default - change the _scrollThroughDefault value to true/false

  • Property svn:executable set to *
File size: 18.9 KB
Line 
1var _docList = new Array();
2_docList.ids = new Array();
3_docList.getDocByIndex = function(index)
4{
5 return _docList[_docList.ids[index]];
6};
7
8var _map;
9var _intervalHandle;
10var _baseURL = document.URL.substring(0, document.URL.indexOf("?") + 1);
11var _retrievedClassifiers = new Array();
12var _preventLoopingSingleMarker = false;
13var _searchRunning = false;
14var _nearbyDocs = new Array();
15var _scrollThroughDefault = true;
16
17function initializeMapScripts()
18{
19 modifyFunctions();
20 setUpMap();
21
22 var jsonNodeDiv = $("#jsonNodes");
23 if(jsonNodeDiv.length)
24 {
25 var jsonNodes = eval(jsonNodeDiv.html());
26 if(jsonNodes && jsonNodes.length > 0)
27 {
28 for(var i = 0; i < jsonNodes.length; i++)
29 {
30 _docList[jsonNodes[i].nodeID] = jsonNodes[i];
31 _docList.ids.push(jsonNodes[i].nodeID);
32 createMarker(jsonNodes[i], true);
33 }
34 updateMap();
35 }
36 else
37 {
38 //$("#map_canvas").css({visibility:"hidden", height:"0px"});
39 $("#map_canvas").css({visibility:"hidden"});
40 }
41 }
42
43 _docList.loopIndex = 0;
44
45 if(_docList.ids.length > 1)
46 {
47 var startStopCheckbox = $("<input>", {"type": "checkbox", "checked": _scrollThroughDefault, "id": "scrollCheckbox"});
48 startStopCheckbox.click(function()
49 {
50 // http://stackoverflow.com/questions/901712/how-to-check-if-a-checkbox-is-checked-in-jquery
51 // http://stackoverflow.com/questions/5270689/attrchecked-checked-does-not-work
52
53 if($('#scrollCheckbox').is(':checked')) // OR: if(document.getElementById('scrollCheckbox').checked)
54 {
55 if(_intervalHandle == null)
56 {
57 _intervalHandle = setInterval(loopThroughMarkers, 2000);
58 }
59 }
60 else
61 {
62 clearInterval(_intervalHandle);
63 _intervalHandle = null;
64 }
65 });
66
67 var label = $("<span>Scroll through places</span>");
68 var container = $("<div>", {"class": "ui-widget-header ui-corner-all", "style": "clear:right; float:right; padding:0px 5px 3px 0px;"});
69 container.append(startStopCheckbox);
70 container.append(label);
71
72 $(container).insertAfter("#map_canvas");
73
74 if (_scrollThroughDefault) {
75 _intervalHandle = setInterval(loopThroughMarkers, 2000);
76 }
77
78 }
79}
80
81function setUpMap()
82{
83 var myOptions =
84 {
85 zoom: 2,
86 center: new google.maps.LatLng(0, 0),
87 mapTypeId: google.maps.MapTypeId.HYBRID
88 };
89 _map = new google.maps.Map($("#map_canvas")[0], myOptions);
90 google.maps.event.addListener(_map, 'bounds_changed', performSearchForMarkers);
91}
92
93function performSearchForMarkers()
94{
95 if(_searchRunning)
96 {
97 return;
98 }
99
100 _searchRunning = true;
101
102 var bounds = _map.getBounds();
103
104 var neLat = bounds.getNorthEast().lat();
105 var neLng = bounds.getNorthEast().lng();
106 var swLat = bounds.getSouthWest().lat();
107 var swLng = bounds.getSouthWest().lng();
108
109 var latDistance = neLat - swLat;
110 var lngDistance = neLng - swLng;
111
112 console.log("neLat = " + neLat + " neLng = " + neLng + " swLat = " + swLat + " swLng = " + swLng + " latDistance = " + latDistance + " lngDistance = " + lngDistance);
113
114 //Check which increment to use for latitude (i.e. 0.001, 0.01, 0.1 or 1 degree increments)
115 var latDelta;
116 var latPrecision;
117 for(var i = 3; i >= 0; i--)
118 {
119 latDelta = (1 / Math.pow(10, i));
120 if((latDistance / latDelta) <= 5 || latDelta == 1)
121 {
122 latPrecision = i;
123 break;
124 }
125 }
126
127 //Check which increment to use for longitude (i.e. 0.001, 0.01, 0.1 or 1 degree increments)
128 var lngDelta;
129 for(var i = 3; i >= 0; i--)
130 {
131 lngDelta = (1 / Math.pow(10, i));
132 if((lngDistance / lngDelta) <= 5 || lngDelta == 1)
133 {
134 lngPrecision = i;
135 break;
136 }
137 }
138
139 if(latDelta == 0.1){latDelta = 1; latPrecision = 0;}
140 if(lngDelta == 0.1){lngDelta = 1; lngPrecision = 0;}
141
142 var query = "";
143 for(var i = 0; i <= Math.floor(latDistance / latDelta) + 1; i++)
144 {
145 for(var j = 0; j <= Math.floor(lngDistance / lngDelta) + 1; j++)
146 {
147 //Some necessary variables
148 var newLat = neLat - (latDelta * i);
149 var newLatString = "" + newLat;
150 var newLatTrunc;
151 if(newLat < 0){newLatTrunc = Math.ceil(newLat);}
152 else{newLatTrunc = Math.floor(newLat);}
153
154 var newLng = neLng - (lngDelta * j);
155 var newLngString = "" + newLng;
156 var newLngTrunc;
157 if(newLng < 0){newLngTrunc = Math.ceil(newLng);}
158 else{newLngTrunc = Math.floor(newLng);}
159
160 //Construct query
161 query += "(";
162 query += "LA:" + coordToAbsDirected(newLatTrunc, "lat");
163 if(latDelta != 1)
164 {
165 query += "+AND+";
166 query += "LA:" + newLatString.substring(newLatString.indexOf(".") + 1, newLatString.indexOf(".") + latPrecision + 1);
167 }
168 query += "+AND+";
169 query += "LN:" + coordToAbsDirected(newLngTrunc, "lng");
170 if(lngDelta != 1)
171 {
172 query += "+AND+";
173 query += "LN:" + newLngString.substring(newLngString.indexOf(".") + 1, newLngString.indexOf(".") + lngPrecision + 1);
174 }
175 query += ")";
176
177 if(i != (Math.floor(latDistance / latDelta) + 1) || j != (Math.floor(lngDistance / lngDelta) + 1)){ query += "+OR+"; }
178 }
179 }
180
181 //var url = gs.xsltParams.library_name + "?a=q&s=RawQuery&rt=rd&c=" + gs.cgiParams.c + "&s1.rawquery=" + query + "&excerptid=jsonNodes";
182 var url = gs.xsltParams.library_name;
183 var data = "a=q&s=RawQuery&rt=rd&c=" + gs.cgiParams.c + "&s1.rawquery=" + query + "&excerptid=jsonNodes";
184
185 $.ajax({type:"POST", url:url, data:data})
186 .success(function(responseText)
187 {
188 //console.log("*** responseText (first 250) = " + responseText.substring(0,256));
189
190 if(responseText.search("id=\"jsonNodes") != -1)
191 {
192 var startIndex = responseText.indexOf(">");
193 var endIndex = responseText.indexOf("</");
194
195 var jsonNodes = eval(responseText.substring(startIndex+1, endIndex));
196 if(jsonNodes && jsonNodes.length > 0)
197 {
198 for(var i = 0; i < jsonNodes.length; i++)
199 {
200 var doc = jsonNodes[i];
201
202 var found = false;
203 for(var j = 0; j < _docList.ids.length; j++){if(doc.nodeID == _docList.ids[j]){found = true; break;}}
204
205 if(!found)
206 {
207 _docList[doc.nodeID] = doc;
208 _docList.ids.push(doc.nodeID);
209
210 createMarker(doc, false);
211 }
212 }
213 }
214 }
215 else
216 {
217 console.log("No JSON information received");
218 }
219
220 _searchRunning = false;
221 }).fail(function(responseText, textStatus, errorThrown) // fail() has replaced error(), http://api.jquery.com/jquery.ajax/
222 {
223 console.log("In map-scripts.performSearchForMarkers(): Got an error in ajax call");
224 _searchRunning = false;
225 });
226}
227
228function coordToAbsDirected(coord, type)
229{
230 var value = "" + coord;
231 if(coord < 0)
232 {
233 value = value.substring(1);
234 if(type == "lat")
235 {
236 value += "S";
237 }
238 else
239 {
240 value += "W";
241 }
242 }
243 else
244 {
245 if(type == "lat")
246 {
247 value += "N";
248 }
249 else
250 {
251 value += "E";
252 }
253 }
254
255 return value;
256}
257
258function updateMap()
259{
260 var north = -180;
261 var east = -180;
262 var south = 180;
263 var west = 180;
264
265 var markersOnMap = 0;
266 for(var i = 0; i < _docList.ids.length; i++)
267 {
268 var doc = _docList.getDocByIndex(i);
269
270 if(doc.parentCL && doc.parentCL.style.display == "none")
271 {
272 doc.marker.setVisible(false);
273 continue;
274 }
275 else
276 {
277 doc.marker.setVisible(true);
278 markersOnMap++;
279 }
280
281 if(doc.lat > north)
282 {
283 north = doc.lat;
284 }
285 if(doc.lat < south)
286 {
287 south = doc.lat;
288 }
289 if(doc.lng > east)
290 {
291 east = doc.lng;
292 }
293 if(doc.lng < west)
294 {
295 west = doc.lng;
296 }
297 }
298
299 //As there is always 2 possible bounding boxes we want the smaller of the two
300 if(east - west > 180)
301 {
302 var temp = east;
303 east = west;
304 west = temp;
305 }
306
307 var bounds;
308 if(markersOnMap > 0)
309 {
310 bounds = new google.maps.LatLngBounds(new google.maps.LatLng(south, west), new google.maps.LatLng(north, east));
311 _map.fitBounds(bounds);
312 }
313}
314
315function loopThroughMarkers()
316{
317 if(_docList.ids.length == 0)
318 {
319 return;
320 }
321
322 var visibleMarkers = new Array();
323 for(var i = 0; i < _docList.ids.length; i++)
324 {
325 var doc = _docList.getDocByIndex(i);
326 if(doc.marker.getVisible())
327 {
328 visibleMarkers.push(doc);
329 }
330 }
331
332 if(visibleMarkers.length < 2)
333 {
334 clearAllInfoBoxes();
335 return;
336 }
337
338 clearAllInfoBoxes();
339
340 var elem = null;
341 while(!elem)
342 {
343 if(_docList.loopIndex >= visibleMarkers.length)
344 {
345 _docList.loopIndex = 0;
346 }
347
348 var doc = visibleMarkers[_docList.loopIndex];
349 var elem = gs.jqGet("div" + doc.nodeID);
350 if(elem.length)
351 {
352 elem.css("background", "#BBFFBB");
353 setTimeout(function(){elem.css("background", "");}, 2000);
354 }
355 _docList.loopIndex++;
356 }
357 doc.marker.markerInfo.open(_map, doc.marker);
358}
359
360function attachClickHandler(marker, nodeID)
361{
362 google.maps.event.addListener(marker, 'click', function()
363 {
364 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";
365 });
366}
367
368function focusDocument(id)
369{
370 var doc = _docList[id];
371 if(doc)
372 {
373 clearInterval(_intervalHandle);
374 _intervalHandle = null;
375 _map.panTo(new google.maps.LatLng(doc.lat, doc.lng));
376 clearAllInfoBoxes();
377 doc.marker.markerInfo.open(_map, doc.marker);
378 var scrollCheckbox = $("#scrollCheckbox");
379 if(scrollCheckbox.checked)
380 {
381 scrollCheckbox.checked = false;
382 }
383 }
384}
385
386function clearAllInfoBoxes()
387{
388 for(var i = 0; i < _docList.ids.length; i++)
389 {
390 var doc = _docList.getDocByIndex(i);
391 doc.marker.markerInfo.close();
392 }
393}
394
395function createMarker(doc, mainMarker)
396{
397 var pos = new google.maps.LatLng(doc.lat,doc.lng);
398 var marker
399 if(mainMarker)
400 {
401 marker = new google.maps.Marker
402 ({
403 position: pos,
404 title:doc.title,
405 map:_map
406 });
407 }
408 else
409 {
410 marker = new google.maps.Marker
411 ({
412 position: pos,
413 title:doc.title,
414 map:_map,
415 icon:"interfaces/" + gs.xsltParams.interface_name + "/images/bluemarker.png"
416 });
417 }
418
419 var docElement = gs.jqGet("div" + doc.nodeID);
420 var parent;
421 if(docElement)
422 {
423 parent = docElement.parentNode;
424 }
425
426 while(parent && parent.nodeName != "BODY")
427 {
428 if($(parent).attr("id") && $(parent).attr("id").search("divCL") != -1)
429 {
430 doc.parentCL = parent;
431 break;
432 }
433
434 parent = parent.parentNode;
435 }
436
437 var info = new google.maps.InfoWindow({content:doc.title});
438 marker.markerInfo = info;
439 doc.marker = marker;
440
441 attachClickHandler(marker, doc.nodeID);
442}
443
444function getSubClassifier(sectionID)
445{
446 var url = gs.xsltParams.library_name + "?a=b&rt=s&s=ClassifierBrowse&c=" + gs.cgiParams.c + "&cl=" + sectionID + "&excerptid=jsonNodes";
447 $.ajax(url)
448 .success(function(responseText)
449 {
450 var startIndex = responseText.indexOf(">");
451 var endIndex = responseText.indexOf("</");
452
453 var jsonNodes = eval(responseText.substring(startIndex+1, endIndex));
454 if(jsonNodes && jsonNodes.length > 0)
455 {
456 for(var i = 0; i < jsonNodes.length; i++)
457 {
458 var doc = jsonNodes[i];
459 _docList[doc.nodeID] = doc;
460 _docList.ids.push(doc.nodeID);
461
462 createMarker(doc, false);
463 }
464
465 $("#map_canvas").css({"visibility": "visible", "height": ""});
466 }
467
468 updateMap();
469 })
470 .error(function()
471 {
472 console.log("Error getting subclassifiers");
473 return;
474 });
475}
476
477function performDistanceSearch(id, lat, lng, degrees)
478{
479 if(parseFloat(lat) > 180 || parseFloat(lat) < -180 || parseFloat(lng) > 180 || parseFloat(lat) < -180)
480 {
481 console.log("Latitude or longitude incorrectly formatted");
482 return;
483 }
484
485 if(lat.indexOf(".") == -1 || lng.indexOf(".") == -1 || (lat.indexOf(".") + 3) >= lat.length || (lng.indexOf(".") + 3) >= lng.length)
486 {
487 console.log("Latitude or longitude does not have the required precision for a distance search");
488 return;
489 }
490
491 var query = "";
492 for(var i = 0; i < degrees * 2; i++)
493 {
494 for (var j = 0; j < degrees * 2; j++)
495 {
496 var latDelta = (i - degrees) * 0.01;
497 var lngDelta = (j - degrees) * 0.01;
498
499 query += "(" + getDistanceQueryString(lat, latDelta, 2, "LA", ["N","S"]);
500 query += "+AND+";
501 query += getDistanceQueryString(lng, lngDelta, 2, "LN", ["E","W"]) + ")";
502
503 if(i != ((degrees * 2) - 1) || j != ((degrees * 2) - 1)){ query += "+OR+"; }
504 }
505 }
506
507 var inlineTemplate = '\
508 <xsl:template match="/" priority="5">\
509 <table id="nearbyDocs">\
510 <tr>\
511 <th><a href="javascript:sortByDistance();">Distance (km)</a></th><th><a href="javascript:sortAlphabetically();">Document</a></th>\
512 </tr>\
513 <xsl:apply-templates select="//documentNode"/>\
514 </table>\
515 </xsl:template>\
516 \
517 <xsl:template match="documentNode" priority="5">\
518 <tr>\
519 <td>___<gsf:metadata name="Latitude"/>______<gsf:metadata name="Longitude"/>___</td>\
520 <td><gsf:link type="document"><gsf:metadata name="Title"/></gsf:link></td>\
521 </tr>\
522 </xsl:template>';
523
524 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");
525 $.ajax(url)
526 .success(function(response)
527 {
528 response = response.replace(/<img src="[^"]*map_marker.png"[^>]*>/g, "");
529
530 var nearbyDocsArray = new Array();
531
532 var lats = new Array();
533 var lngs = new Array();
534
535 var matches = response.match(/___(-?[0-9\.]*)___/g);
536 for(var i = 0; i < matches.length; i += 2)
537 {
538 var matchLatFloat = parseFloat(matches[i].replace("___", ""));
539 var matchLngFloat = parseFloat(matches[i+1].replace("___", ""));
540
541 lats.push(matchLatFloat);
542 lngs.push(matchLngFloat);
543
544 var distance = Math.sqrt(Math.pow(matchLatFloat - parseFloat(lat), 2) + Math.pow(matchLngFloat - parseFloat(lng), 2)) * (40000.0/360.0);
545 var distanceString = "" + distance;
546 distanceString = distanceString.substring(0, 6);
547
548 response = response.replace(matches[i] + matches[i+1], distanceString);
549 }
550
551 var index = 0;
552 var i = 0;
553 while(true)
554 {
555 var distanceStart = response.indexOf("<td>", index);
556 if(distanceStart == -1)
557 {
558 break;
559 }
560 var distanceEnd = response.indexOf("</td>", distanceStart);
561
562 var docLinkStart = response.indexOf("<td>", distanceEnd);
563 var docLinkEnd = response.indexOf("</td>", docLinkStart);
564
565 var dist = response.substring(distanceStart + 4, distanceEnd);
566 var docLink = response.substring(docLinkStart + 4, docLinkEnd);
567
568 _nearbyDocs.push({title:docLink, distance:dist, lat:lats[i], lng:lngs[i++]});
569
570 index = docLinkEnd;
571 }
572
573 sortByDistance();
574
575 var toggle = $("#nearbyDocumentsToggle");
576 toggle.attr("src", gs.imageURLs.collapse);
577 gs.functions.makeToggle(toggle, $("#nearbyDocuments"));
578 });
579}
580
581function sortByDistance()
582{
583 var sortedTable = '<table id="nearbyDocs"><tr><th><a href="javascript:;">Distance (km)</a></th><th><a href="javascript:sortAlphabetically();">Document</a></th></tr>';
584 _nearbyDocs.sort(function(a, b){return (a.distance - b.distance);});
585 for(var i = 0; i < _nearbyDocs.length; i++)
586 {
587 sortedTable += "<tr><td>" + _nearbyDocs[i].distance + '</td><td onmouseover="_map.setCenter(new google.maps.LatLng(' + _nearbyDocs[i].lat + ',' + _nearbyDocs[i].lng + '))">' + _nearbyDocs[i].title + "</td></tr>";
588 }
589 sortedTable += "</table>";
590
591 $("#nearbyDocuments").html(sortedTable);
592}
593
594function sortAlphabetically()
595{
596 var sortedTable = '<table id="nearbyDocs"><tr><th><a href="javascript:sortByDistance();">Distance (km)</a></th><th><a href="javascript:;">Document</a></th></tr>';
597 _nearbyDocs.sort(function(a, b)
598 {
599 var firstTitleStartIndex = a.title.indexOf(">");
600 var firstTitleEndIndex = a.title.indexOf("<", firstTitleStartIndex);
601 var firstTitle = a.title.substring(firstTitleStartIndex + 1, firstTitleEndIndex);
602 var secondTitleStartIndex = b.title.indexOf(">");
603 var secondTitleEndIndex = b.title.indexOf("<", secondTitleStartIndex);
604 var secondTitle = b.title.substring(secondTitleStartIndex + 1, secondTitleEndIndex);
605 return ((firstTitle.toLowerCase() == secondTitle.toLowerCase()) ? 0 : ((firstTitle.toLowerCase() > secondTitle.toLowerCase()) ? 1 : -1));
606 });
607 for(var i = 0; i < _nearbyDocs.length; i++)
608 {
609 sortedTable += "<tr><td>" + _nearbyDocs[i].distance + '</td><td onmouseover="_map.setCenter(new google.maps.LatLng(' + _nearbyDocs[i].lat + ',' + _nearbyDocs[i].lng + '))">' + _nearbyDocs[i].title + "</td></tr>";
610 }
611 sortedTable += "</table>";
612
613 $("#nearbyDocuments").html(sortedTable);
614}
615
616function getDistanceQueryString(currentCoord, delta, precision, indexName, dirs)
617{
618 var query = "";
619 var coordFloat = parseFloat(currentCoord);
620
621 var newCoord = "" + (coordFloat + delta);
622 var beforeDec = newCoord.substring(0, newCoord.indexOf("."));
623
624 var dir = dirs[0];
625 if(coordFloat < 0)
626 {
627 dir = dirs[1];
628 beforeDec = beforeDec.substring(1);
629 }
630 beforeDec += dir;
631
632 var afterDec = newCoord.substring(newCoord.indexOf(".") + 1, newCoord.indexOf(".") + (precision) + 1);
633
634 return indexName + ":" + beforeDec + "+AND+" + indexName + ":" + afterDec;
635}
636
637function modifyFunctions()
638{
639 toggleSection = function(sectionID)
640 {
641 var section = gs.jqGet("div" + sectionID);
642 var sectionToggle = gs.jqGet("toggle" + sectionID);
643
644 if(sectionToggle == undefined)
645 {
646 return;
647 }
648
649 // Test if 'section' exists.
650 // ==> Because we're using jQuery to do this we need to test the length of the object returned
651 // http://stackoverflow.com/questions/920236/how-can-i-detect-if-a-selector-returns-null
652 if(section.length !== 0)
653 {
654 if(isExpanded(sectionID))
655 {
656 section.css("display", "none");
657 sectionToggle.attr("src", gs.imageURLs.expand);
658
659 if(openClassifiers[sectionID].length !== 0) //if(openClassifiers[sectionID] != undefined)
660 {
661 delete openClassifiers[sectionID];
662 }
663 }
664 else
665 {
666 section.css("display", "block");
667 sectionToggle.attr("src", gs.imageURLs.collapse);
668 openClassifiers[sectionID] = true;
669 }
670 updateOpenClassifiers();
671 updateMap();
672 }
673 else
674 {
675 httpRequest(sectionID);
676 }
677 }
678
679 httpRequest = function(sectionID)
680 {
681 if(!inProgress[sectionID])
682 {
683 inProgress[sectionID] = true;
684
685 var sectionToggle = gs.jqGet("toggle" + sectionID);
686 sectionToggle.attr("src", gs.imageURLs.loading);
687
688 var url = gs.xsltParams.library_name + "/collection/" + gs.cgiParams.c + "/browse/" + sectionID.replace(/\./g, "/") + "?excerptid=div" + sectionID;
689
690 if(gs.cgiParams.berrybasket == "on")
691 {
692 url = url + "&berrybasket=on";
693 }
694
695 if(url.indexOf("#") != -1)
696 {
697 url = url.substring(0, url.indexOf("#"));
698 }
699
700 $.ajax(url)
701 .success(function(responseText)
702 {
703 var newDiv = $("<div>");
704 var sibling = gs.jqGet("title" + sectionID);
705 sibling.after(newDiv);
706
707 newDiv.html(responseText);
708 sectionToggle.attr("src", gs.imageURLs.collapse);
709 openClassifiers[sectionID] = true;
710
711 if(gs.cgiParams.berrybasket == "on")
712 {
713 checkout();
714 }
715 updateOpenClassifiers();
716 getSubClassifier(sectionID);
717 })
718 .error(function()
719 {
720 sectionToggle.attr("src", gs.imageURLs.expand);
721 })
722 .complete(function()
723 {
724 inProgress[sectionID] = false;
725 busy = false;
726 });
727 }
728 }
729}
Note: See TracBrowser for help on using the repository browser.