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

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

When a place is clicked the "Scroll through places" checkbox becomes unchecked

  • Property svn:executable set to *
File size: 19.4 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 setUpMap();
20
21 var jsonNodeDiv = document.getElementById("jsonNodes");
22 if(jsonNodeDiv)
23 {
24 var jsonNodes = eval(jsonNodeDiv.innerHTML);
25 if(jsonNodes && jsonNodes.length > 0)
26 {
27 for(var i = 0; i < jsonNodes.length; i++)
28 {
29 _docList[jsonNodes[i].nodeID] = jsonNodes[i];
30 _docList.ids.push(jsonNodes[i].nodeID);
31 createMarker(jsonNodes[i], true);
32 }
33 updateMap();
34 }
35 else
36 {
37 document.getElementById("map_canvas").style.visibility = "hidden";
38 document.getElementById("map_canvas").style.height = "0px";
39 }
40 }
41
42 _docList.loopIndex = 0;
43
44 if(_docList.ids.length > 1)
45 {
46 var startStopCheckbox = document.createElement("input");
47 startStopCheckbox.setAttribute("type", "checkbox");
48 startStopCheckbox.setAttribute("checked", "true");
49 startStopCheckbox.setAttribute("id", "scrollCheckbox");
50 startStopCheckbox.onclick = function()
51 {
52 if(startStopCheckbox.checked)
53 {
54 if(_intervalHandle == null)
55 {
56 _intervalHandle = setInterval(loopThroughMarkers, 2000);
57 }
58 }
59 else
60 {
61 clearInterval(_intervalHandle);
62 _intervalHandle = null;
63 }
64 };
65
66 var label = document.createElement("span");
67 label.innerHTML = "Scroll through places";
68
69 var container = document.createElement("DIV");
70 container.appendChild(startStopCheckbox);
71 container.appendChild(label);
72 container.setAttribute("class", "ui-widget-header ui-corner-all");
73 container.setAttribute("style", "clear:right; float:right; padding:0px 5px 3px 0px;");
74
75 $(container).insertAfter("#map_canvas");
76
77 _intervalHandle = setInterval(loopThroughMarkers, 2000);
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(document.getElementById("map_canvas"), 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 ajax = new gs.functions.ajaxRequest();
182 ajax.open("GET", gs.xsltParams.library_name + "?a=q&s=RawQuery&rt=rd&c=" + gs.cgiParams.c + "&s1.rawquery=" + query + "&excerptid=jsonNodes", true);
183 ajax.onreadystatechange = function()
184 {
185 if(ajax.readyState == 4 && ajax.status == 200)
186 {
187 if(ajax.responseText.search("id=\"jsonNodes") != -1)
188 {
189 var startIndex = ajax.responseText.indexOf(">");
190 var endIndex = ajax.responseText.indexOf("</");
191
192 var jsonNodes = eval(ajax.responseText.substring(startIndex+1, endIndex));
193 if(jsonNodes && jsonNodes.length > 0)
194 {
195 for(var i = 0; i < jsonNodes.length; i++)
196 {
197 var doc = jsonNodes[i];
198
199 var found = false;
200 for(var j = 0; j < _docList.ids.length; j++){if(doc.nodeID == _docList.ids[j]){found = true; break;}}
201
202 if(!found)
203 {
204 _docList[doc.nodeID] = doc;
205 _docList.ids.push(doc.nodeID);
206
207 createMarker(doc, false);
208 }
209 }
210 }
211 }
212 else
213 {
214 console.log("No JSON information received");
215 }
216
217 _searchRunning = false;
218 }
219 }
220 ajax.send();
221}
222
223function coordToAbsDirected(coord, type)
224{
225 var value = "" + coord;
226 if(coord < 0)
227 {
228 value = value.substring(1);
229 if(type == "lat")
230 {
231 value += "S";
232 }
233 else
234 {
235 value += "W";
236 }
237 }
238 else
239 {
240 if(type == "lat")
241 {
242 value += "N";
243 }
244 else
245 {
246 value += "E";
247 }
248 }
249
250 return value;
251}
252
253function updateMap()
254{
255 var north = -180;
256 var east = -180;
257 var south = 180;
258 var west = 180;
259
260 var markersOnMap = 0;
261 for(var i = 0; i < _docList.ids.length; i++)
262 {
263 var doc = _docList.getDocByIndex(i);
264
265 if(doc.parentCL && doc.parentCL.style.display == "none")
266 {
267 doc.marker.setVisible(false);
268 continue;
269 }
270 else
271 {
272 doc.marker.setVisible(true);
273 markersOnMap++;
274 }
275
276 if(doc.lat > north)
277 {
278 north = doc.lat;
279 }
280 if(doc.lat < south)
281 {
282 south = doc.lat;
283 }
284 if(doc.lng > east)
285 {
286 east = doc.lng;
287 }
288 if(doc.lng < west)
289 {
290 west = doc.lng;
291 }
292 }
293
294 //As there is always 2 possible bounding boxes we want the smaller of the two
295 if(east - west > 180)
296 {
297 var temp = east;
298 east = west;
299 west = temp;
300 }
301
302 var bounds;
303 if(markersOnMap > 0)
304 {
305 bounds = new google.maps.LatLngBounds(new google.maps.LatLng(south, west), new google.maps.LatLng(north, east));
306 _map.fitBounds(bounds);
307 }
308}
309
310function loopThroughMarkers()
311{
312 if(_docList.ids.length == 0)
313 {
314 return;
315 }
316
317 var visibleMarkers = new Array();
318 for(var i = 0; i < _docList.ids.length; i++)
319 {
320 var doc = _docList.getDocByIndex(i);
321 if(doc.marker.getVisible())
322 {
323 visibleMarkers.push(doc);
324 }
325 }
326
327 if(visibleMarkers.length < 2)
328 {
329 clearAllInfoBoxes();
330 return;
331 }
332
333 clearAllInfoBoxes();
334
335 var elem = null;
336 while(!elem)
337 {
338 if(_docList.loopIndex >= visibleMarkers.length)
339 {
340 _docList.loopIndex = 0;
341 }
342
343 var doc = visibleMarkers[_docList.loopIndex];
344 var elem = document.getElementById("div" + doc.nodeID);
345 if(elem)
346 {
347 elem.style.background = "#BBFFBB";
348 setTimeout(function(){elem.style.background = "";}, 2000);
349 }
350 _docList.loopIndex++;
351 }
352 doc.marker.markerInfo.open(_map, doc.marker);
353}
354
355function attachClickHandler(marker, nodeID)
356{
357 google.maps.event.addListener(marker, 'click', function()
358 {
359 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";
360 });
361}
362
363function focusDocument(id)
364{
365 var doc = _docList[id];
366 if(doc)
367 {
368 clearInterval(_intervalHandle);
369 _intervalHandle = null;
370 _map.panTo(new google.maps.LatLng(doc.lat, doc.lng));
371 clearAllInfoBoxes();
372 doc.marker.markerInfo.open(_map, doc.marker);
373 var scrollCheckbox = document.getElementById("scrollCheckbox");
374 if(scrollCheckbox.checked)
375 {
376 scrollCheckbox.checked = false;
377 }
378 }
379}
380
381function clearAllInfoBoxes()
382{
383 for(var i = 0; i < _docList.ids.length; i++)
384 {
385 var doc = _docList.getDocByIndex(i);
386 doc.marker.markerInfo.close();
387 }
388}
389
390function createMarker(doc, mainMarker)
391{
392 var pos = new google.maps.LatLng(doc.lat,doc.lng);
393 var marker
394 if(mainMarker)
395 {
396 marker = new google.maps.Marker
397 ({
398 position: pos,
399 title:doc.title,
400 map:_map
401 });
402 }
403 else
404 {
405 marker = new google.maps.Marker
406 ({
407 position: pos,
408 title:doc.title,
409 map:_map,
410 icon:"interfaces/" + gs.xsltParams.interface_name + "/images/bluemarker.png"
411 });
412 }
413
414 var docElement = document.getElementById("div" + doc.nodeID);
415 var parent;
416 if(docElement)
417 {
418 parent = docElement.parentNode;
419 }
420
421 while(parent && parent.nodeName != "BODY")
422 {
423 if(parent.getAttribute("id") && parent.getAttribute("id").search("divCL") != -1)
424 {
425 doc.parentCL = parent;
426 break;
427 }
428
429 parent = parent.parentNode;
430 }
431
432 var info = new google.maps.InfoWindow({content:doc.title});
433 marker.markerInfo = info;
434 doc.marker = marker;
435
436 attachClickHandler(marker, doc.nodeID);
437}
438
439function getSubClassifier(sectionID)
440{
441 var ajax = new gs.functions.ajaxRequest();
442 ajax.open("GET", gs.xsltParams.library_name + "?a=b&rt=s&s=ClassifierBrowse&c=" + gs.cgiParams.c + "&cl=" + sectionID + "&excerptid=jsonNodes", true);
443 ajax.onreadystatechange = function()
444 {
445 if(ajax.readyState == 4 && ajax.status == 200)
446 {
447 var startIndex = ajax.responseText.indexOf(">");
448 var endIndex = ajax.responseText.indexOf("</");
449
450 var jsonNodes = eval(ajax.responseText.substring(startIndex+1, endIndex));
451 if(jsonNodes && jsonNodes.length > 0)
452 {
453 for(var i = 0; i < jsonNodes.length; i++)
454 {
455 var doc = jsonNodes[i];
456 _docList[doc.nodeID] = doc;
457 _docList.ids.push(doc.nodeID);
458
459 createMarker(doc, false);
460 }
461
462 document.getElementById("map_canvas").style.visibility = "visible";
463 document.getElementById("map_canvas").style.height = undefined;
464 }
465
466 updateMap();
467 }
468 else if(ajax.readyState == 4)
469 {
470 console.log("Error getting subclassifiers");
471 return;
472 }
473 }
474 ajax.send();
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 ajax = new gs.functions.ajaxRequest();
525 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);
526 ajax.onreadystatechange = function()
527 {
528 if(ajax.readyState == 4 && ajax.status == 200)
529 {
530 var response = ajax.responseText;
531 response = response.replace(/<img src="[^"]*map_marker.png"[^>]*>/g, "");
532
533 console.log(ajax.responseText);
534
535 var nearbyDocsArray = new Array();
536
537 var lats = new Array();
538 var lngs = new Array();
539
540 var matches = response.match(/___(-?[0-9\.]*)___/g);
541 for(var i = 0; i < matches.length; i += 2)
542 {
543 var matchLatFloat = parseFloat(matches[i].replace("___", ""));
544 var matchLngFloat = parseFloat(matches[i+1].replace("___", ""));
545
546 lats.push(matchLatFloat);
547 lngs.push(matchLngFloat);
548
549 var distance = Math.sqrt(Math.pow(matchLatFloat - parseFloat(lat), 2) + Math.pow(matchLngFloat - parseFloat(lng), 2)) * (40000.0/360.0);
550 var distanceString = "" + distance;
551 distanceString = distanceString.substring(0, 6);
552
553 response = response.replace(matches[i] + matches[i+1], distanceString);
554 }
555
556 var index = 0;
557 var i = 0;
558 while(true)
559 {
560 var distanceStart = response.indexOf("<td>", index);
561 if(distanceStart == -1)
562 {
563 break;
564 }
565 var distanceEnd = response.indexOf("</td>", distanceStart);
566
567 var docLinkStart = response.indexOf("<td>", distanceEnd);
568 var docLinkEnd = response.indexOf("</td>", docLinkStart);
569
570 var dist = response.substring(distanceStart + 4, distanceEnd);
571 var docLink = response.substring(docLinkStart + 4, docLinkEnd);
572
573 _nearbyDocs.push({title:docLink, distance:dist, lat:lats[i], lng:lngs[i++]});
574
575 index = docLinkEnd;
576 }
577
578 sortByDistance();
579
580 var toggle = document.getElementById("nearbyDocumentsToggle");
581 toggle.setAttribute("src", gs.imageURLs.collapse);
582 gs.functions.makeToggle(toggle, document.getElementById("nearbyDocuments"));
583 }
584 }
585 ajax.send();
586}
587
588function sortByDistance()
589{
590 var sortedTable = '<table id="nearbyDocs"><tr><th><a href="javascript:;">Distance (km)</a></th><th><a href="javascript:sortAlphabetically();">Document</a></th></tr>';
591 _nearbyDocs.sort(function(a, b){return (a.distance - b.distance);});
592 for(var i = 0; i < _nearbyDocs.length; i++)
593 {
594 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>";
595 }
596 sortedTable += "</table>";
597
598 document.getElementById("nearbyDocuments").innerHTML = sortedTable;
599}
600
601function sortAlphabetically()
602{
603 var sortedTable = '<table id="nearbyDocs"><tr><th><a href="javascript:sortByDistance();">Distance (km)</a></th><th><a href="javascript:;">Document</a></th></tr>';
604 _nearbyDocs.sort(function(a, b)
605 {
606 var firstTitleStartIndex = a.title.indexOf(">");
607 var firstTitleEndIndex = a.title.indexOf("<", firstTitleStartIndex);
608 var firstTitle = a.title.substring(firstTitleStartIndex + 1, firstTitleEndIndex);
609 var secondTitleStartIndex = b.title.indexOf(">");
610 var secondTitleEndIndex = b.title.indexOf("<", secondTitleStartIndex);
611 var secondTitle = b.title.substring(secondTitleStartIndex + 1, secondTitleEndIndex);
612 return ((firstTitle.toLowerCase() == secondTitle.toLowerCase()) ? 0 : ((firstTitle.toLowerCase() > secondTitle.toLowerCase()) ? 1 : -1));
613 });
614 for(var i = 0; i < _nearbyDocs.length; i++)
615 {
616 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>";
617 }
618 sortedTable += "</table>";
619
620 document.getElementById("nearbyDocuments").innerHTML = sortedTable;
621}
622
623function getDistanceQueryString(currentCoord, delta, precision, indexName, dirs)
624{
625 var query = "";
626 var coordFloat = parseFloat(currentCoord);
627
628 var newCoord = "" + (coordFloat + delta);
629 var beforeDec = newCoord.substring(0, newCoord.indexOf("."));
630
631 var dir = dirs[0];
632 if(coordFloat < 0)
633 {
634 dir = dirs[1];
635 beforeDec = beforeDec.substring(1);
636 }
637 beforeDec += dir;
638
639 var afterDec = newCoord.substring(newCoord.indexOf(".") + 1, newCoord.indexOf(".") + (precision) + 1);
640
641 return indexName + ":" + beforeDec + "+AND+" + indexName + ":" + afterDec;
642}
643
644function modifyFunctions()
645{
646 toggleSection = function(sectionID)
647 {
648 var section = document.getElementById("div" + sectionID);
649 var sectionToggle = document.getElementById("toggle" + sectionID);
650
651 if(sectionToggle == undefined)
652 {
653 return;
654 }
655
656 if(section)
657 {
658 if(isExpanded(sectionID))
659 {
660 section.style.display = "none";
661 sectionToggle.setAttribute("src", gs.imageURLs.expand);
662
663 if(openClassifiers[sectionID] != undefined)
664 {
665 delete openClassifiers[sectionID];
666 }
667 }
668 else
669 {
670 section.style.display = "block";
671 sectionToggle.setAttribute("src", gs.imageURLs.collapse);
672 openClassifiers[sectionID] = true;
673 }
674 updateOpenClassifiers();
675 updateMap();
676 }
677 else
678 {
679 httpRequest(sectionID);
680 }
681 }
682
683 httpRequest = function(sectionID)
684 {
685 if(!inProgress[sectionID])
686 {
687 inProgress[sectionID] = true;
688 var httpRequest = new gs.functions.ajaxRequest();
689
690 var sectionToggle = document.getElementById("toggle" + sectionID);
691 sectionToggle.setAttribute("src", gs.imageURLs.loading);
692
693 var url = gs.xsltParams.library_name + "/collection/" + gs.cgiParams.c + "/browse/" + sectionID.replace(/\./g, "/") + "?excerptid=div" + sectionID;
694
695 if(gs.cgiParams.berryBasket == "on")
696 {
697 url = url + "&berrybasket=on";
698 }
699
700 if(url.indexOf("#") != -1)
701 {
702 url = url.substring(0, url.indexOf("#"));
703 }
704 httpRequest.open('GET', url, true);
705 httpRequest.onreadystatechange = function()
706 {
707 if (httpRequest.readyState == 4)
708 {
709 if (httpRequest.status == 200)
710 {
711 var newDiv = document.createElement("div");
712 var sibling = document.getElementById("title" + sectionID);
713 var parent = sibling.parentNode;
714 if(sibling.nextSibling)
715 {
716 parent.insertBefore(newDiv, sibling.nextSibling);
717 }
718 else
719 {
720 parent.appendChild(newDiv);
721 }
722
723 newDiv.innerHTML = httpRequest.responseText;
724 sectionToggle.setAttribute("src", gs.imageURLs.collapse);
725 openClassifiers[sectionID] = true;
726
727 if(gs.cgiParams.berryBasket == "on")
728 {
729 checkout();
730 }
731 updateOpenClassifiers();
732 getSubClassifier(sectionID);
733 }
734 else
735 {
736 sectionToggle.setAttribute("src", gs.imageURLs.expand);
737 }
738 inProgress[sectionID] = false;
739 busy = false;
740 }
741 }
742 httpRequest.send();
743 }
744 }
745}
Note: See TracBrowser for help on using the repository browser.