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

Last change on this file since 26141 was 26141, checked in by sjm84, 12 years ago

The map will be hidden when there is no Latitude and Longitude information

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