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

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

The loop that displays the names of the places above the markers will now only loop through the documents on the page, rather than all the pages on the map

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