source: main/trunk/greenstone3/web/interfaces/oran/js/map-scripts.js@ 25462

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

Fixes to map_scripts and also changed the on-page editing that it reloads the page with the expanded view. Later we will probably make the page reload unnecessary. Also fixed the preferences page.

  • 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 if(_docList.loopIndex >= visibleMarkers.length)
303 {
304 _docList.loopIndex = 0;
305 }
306
307 clearAllInfoBoxes();
308
309 var doc = visibleMarkers[_docList.loopIndex];
310 var elem = document.getElementById("div" + doc.nodeID);
311 if(elem)
312 {
313 elem.style.background = "#BBFFBB";
314 setTimeout(function(){elem.style.background = "";}, 2000);
315 }
316 doc.marker.markerInfo.open(_map, doc.marker);
317
318 _docList.loopIndex++;
319}
320
321function attachClickHandler(marker, nodeID)
322{
323 google.maps.event.addListener(marker, 'click', function()
324 {
325 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";
326 });
327}
328
329function focusDocument(id)
330{
331 var doc = _docList[id];
332 if(doc)
333 {
334 clearInterval(_intervalHandle);
335 _map.panTo(new google.maps.LatLng(doc.lat, doc.lng));
336 clearAllInfoBoxes();
337 doc.marker.markerInfo.open(_map, doc.marker);
338 }
339}
340
341function clearAllInfoBoxes()
342{
343 for(var i = 0; i < _docList.ids.length; i++)
344 {
345 var doc = _docList.getDocByIndex(i);
346 doc.marker.markerInfo.close();
347 }
348}
349
350function createMarker(doc, mainMarker)
351{
352 var pos = new google.maps.LatLng(doc.lat,doc.lng);
353 var marker
354 if(mainMarker)
355 {
356 marker = new google.maps.Marker
357 ({
358 position: pos,
359 title:doc.title,
360 map:_map,
361 icon:"interfaces/" + gs.xsltParams.interface_name + "/images/bluemarker.png"
362 });
363 }
364 else
365 {
366 marker = new google.maps.Marker
367 ({
368 position: pos,
369 title:doc.title,
370 map:_map
371 });
372 }
373
374 var docElement = document.getElementById("div" + doc.nodeID);
375 var parent;
376 if(docElement)
377 {
378 parent = docElement.parentNode;
379 }
380
381 while(parent && parent.nodeName != "BODY")
382 {
383 if(parent.getAttribute("id") && parent.getAttribute("id").search("divCL") != -1)
384 {
385 doc.parentCL = parent;
386 break;
387 }
388
389 parent = parent.parentNode;
390 }
391
392 var info = new google.maps.InfoWindow({content:doc.title});
393 marker.markerInfo = info;
394 doc.marker = marker;
395
396 attachClickHandler(marker, doc.nodeID);
397}
398
399function getSubClassifier(sectionID)
400{
401 var ajax = new gs.functions.ajaxRequest();
402 ajax.open("GET", gs.xsltParams.library_name + "?a=b&rt=s&s=ClassifierBrowse&c=" + gs.cgiParams.c + "&cl=" + sectionID + "&excerptid=jsonNodes", true);
403 ajax.onreadystatechange = function()
404 {
405 if(ajax.readyState == 4 && ajax.status == 200)
406 {
407 var startIndex = ajax.responseText.indexOf(">");
408 var endIndex = ajax.responseText.indexOf("</");
409
410 var jsonNodes = eval(ajax.responseText.substring(startIndex+1, endIndex));
411 if(jsonNodes && jsonNodes.length > 0)
412 {
413 for(var i = 0; i < jsonNodes.length; i++)
414 {
415 var doc = jsonNodes[i];
416 _docList[doc.nodeID] = doc;
417 _docList.ids.push(doc.nodeID);
418
419 createMarker(doc, false);
420 }
421
422 document.getElementById("map_canvas").style.visibility = "visible";
423 }
424
425 updateMap();
426 }
427 else if(ajax.readyState == 4)
428 {
429 console.log("Error getting subclassifiers");
430 return;
431 }
432 }
433 ajax.send();
434}
435
436function performDistanceSearch(id, lat, lng, degrees)
437{
438 if(parseFloat(lat) > 180 || parseFloat(lat) < -180 || parseFloat(lng) > 180 || parseFloat(lat) < -180)
439 {
440 console.log("Latitude or longitude incorrectly formatted");
441 return;
442 }
443
444 if(lat.indexOf(".") == -1 || lng.indexOf(".") == -1 || (lat.indexOf(".") + 3) >= lat.length || (lng.indexOf(".") + 3) >= lng.length)
445 {
446 console.log("Latitude or longitude does not have the required precision for a distance search");
447 return;
448 }
449
450 var query = "";
451 for(var i = 0; i < degrees * 2; i++)
452 {
453 for (var j = 0; j < degrees * 2; j++)
454 {
455 var latDelta = (i - degrees) * 0.01;
456 var lngDelta = (j - degrees) * 0.01;
457
458 query += "(" + getDistanceQueryString(lat, latDelta, 2, "LA", ["N","S"]);
459 query += "+AND+";
460 query += getDistanceQueryString(lng, lngDelta, 2, "LN", ["E","W"]) + ")";
461
462 if(i != ((degrees * 2) - 1) || j != ((degrees * 2) - 1)){ query += "+OR+"; }
463 }
464 }
465
466 var inlineTemplate = '\
467 <xsl:template match="/" priority="5">\
468 <table id="nearbyDocs">\
469 <tr>\
470 <th><a href="javascript:sortByDistance();">Distance (km)</a></th><th><a href="javascript:sortAlphabetically();">Document</a></th>\
471 </tr>\
472 <xsl:apply-templates select="//documentNode"/>\
473 </table>\
474 </xsl:template>\
475 \
476 <xsl:template match="documentNode" priority="5">\
477 <tr>\
478 <td>___<gsf:metadata name="Latitude"/>______<gsf:metadata name="Longitude"/>___</td>\
479 <td><gsf:link type="document"><gsf:metadata name="Title"/></gsf:link></td>\
480 </tr>\
481 </xsl:template>';
482
483 var ajax = new gs.functions.ajaxRequest();
484 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);
485 ajax.onreadystatechange = function()
486 {
487 if(ajax.readyState == 4 && ajax.status == 200)
488 {
489 var response = ajax.responseText;
490 response = response.replace(/<img src="[^"]*map_marker.png"[^>]*>/g, "");
491
492 console.log(ajax.responseText);
493
494 var nearbyDocsArray = new Array();
495
496 var lats = new Array();
497 var lngs = new Array();
498
499 var matches = response.match(/___(-?[0-9\.]*)___/g);
500 for(var i = 0; i < matches.length; i += 2)
501 {
502 var matchLatFloat = parseFloat(matches[i].replace("___", ""));
503 var matchLngFloat = parseFloat(matches[i+1].replace("___", ""));
504
505 lats.push(matchLatFloat);
506 lngs.push(matchLngFloat);
507
508 var distance = Math.sqrt(Math.pow(matchLatFloat - parseFloat(lat), 2) + Math.pow(matchLngFloat - parseFloat(lng), 2)) * (40000.0/360.0);
509 var distanceString = "" + distance;
510 distanceString = distanceString.substring(0, 6);
511
512 response = response.replace(matches[i] + matches[i+1], distanceString);
513 }
514
515 var index = 0;
516 var i = 0;
517 while(true)
518 {
519 var distanceStart = response.indexOf("<td>", index);
520 if(distanceStart == -1)
521 {
522 break;
523 }
524 var distanceEnd = response.indexOf("</td>", distanceStart);
525
526 var docLinkStart = response.indexOf("<td>", distanceEnd);
527 var docLinkEnd = response.indexOf("</td>", docLinkStart);
528
529 var dist = response.substring(distanceStart + 4, distanceEnd);
530 var docLink = response.substring(docLinkStart + 4, docLinkEnd);
531
532 _nearbyDocs.push({title:docLink, distance:dist, lat:lats[i], lng:lngs[i++]});
533
534 index = docLinkEnd;
535 }
536
537 sortByDistance();
538
539 var toggle = document.getElementById("nearbyDocumentsToggle");
540 toggle.setAttribute("src", gs.imageURLs.collapse);
541 gs.functions.makeToggle(toggle, document.getElementById("nearbyDocuments"));
542 }
543 }
544 ajax.send();
545}
546
547function sortByDistance()
548{
549 var sortedTable = '<table id="nearbyDocs"><tr><th><a href="javascript:;">Distance (km)</a></th><th><a href="javascript:sortAlphabetically();">Document</a></th></tr>';
550 _nearbyDocs.sort(function(a, b){return (a.distance - b.distance);});
551 for(var i = 0; i < _nearbyDocs.length; i++)
552 {
553 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>";
554 }
555 sortedTable += "</table>";
556
557 document.getElementById("nearbyDocuments").innerHTML = sortedTable;
558}
559
560function sortAlphabetically()
561{
562 var sortedTable = '<table id="nearbyDocs"><tr><th><a href="javascript:sortByDistance();">Distance (km)</a></th><th><a href="javascript:;">Document</a></th></tr>';
563 _nearbyDocs.sort(function(a, b)
564 {
565 var firstTitleStartIndex = a.title.indexOf(">");
566 var firstTitleEndIndex = a.title.indexOf("<", firstTitleStartIndex);
567 var firstTitle = a.title.substring(firstTitleStartIndex + 1, firstTitleEndIndex);
568 var secondTitleStartIndex = b.title.indexOf(">");
569 var secondTitleEndIndex = b.title.indexOf("<", secondTitleStartIndex);
570 var secondTitle = b.title.substring(secondTitleStartIndex + 1, secondTitleEndIndex);
571 return ((firstTitle.toLowerCase() == secondTitle.toLowerCase()) ? 0 : ((firstTitle.toLowerCase() > secondTitle.toLowerCase()) ? 1 : -1));
572 });
573 for(var i = 0; i < _nearbyDocs.length; i++)
574 {
575 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>";
576 }
577 sortedTable += "</table>";
578
579 document.getElementById("nearbyDocuments").innerHTML = sortedTable;
580}
581
582function getDistanceQueryString(currentCoord, delta, precision, indexName, dirs)
583{
584 var query = "";
585 var coordFloat = parseFloat(currentCoord);
586
587 var newCoord = "" + (coordFloat + delta);
588 var beforeDec = newCoord.substring(0, newCoord.indexOf("."));
589
590 var dir = dirs[0];
591 if(coordFloat < 0)
592 {
593 dir = dirs[1];
594 beforeDec = beforeDec.substring(1);
595 }
596 beforeDec += dir;
597
598 var afterDec = newCoord.substring(newCoord.indexOf(".") + 1, newCoord.indexOf(".") + (precision) + 1);
599
600 return indexName + ":" + beforeDec + "+AND+" + indexName + ":" + afterDec;
601}
602
603function modifyFunctions()
604{
605 toggleSection = function(sectionID)
606 {
607 var section = document.getElementById("div" + sectionID);
608 var sectionToggle = document.getElementById("toggle" + sectionID);
609
610 if(sectionToggle == undefined)
611 {
612 return;
613 }
614
615 if(section)
616 {
617 if(isExpanded(sectionID))
618 {
619 section.style.display = "none";
620 sectionToggle.setAttribute("src", gs.imageURLs.expand);
621
622 if(openClassifiers[sectionID] != undefined)
623 {
624 delete openClassifiers[sectionID];
625 }
626 }
627 else
628 {
629 section.style.display = "block";
630 sectionToggle.setAttribute("src", gs.imageURLs.collapse);
631 openClassifiers[sectionID] = true;
632 }
633 updateOpenClassifiers();
634 updateMap();
635 }
636 else
637 {
638 httpRequest(sectionID);
639 }
640 }
641
642 httpRequest = function(sectionID)
643 {
644 if(!inProgress[sectionID])
645 {
646 inProgress[sectionID] = true;
647 var httpRequest = new gs.functions.ajaxRequest();
648
649 var sectionToggle = document.getElementById("toggle" + sectionID);
650 sectionToggle.setAttribute("src", gs.imageURLs.loading);
651
652 var url = gs.xsltParams.library_name + "/collection/" + gs.cgiParams.c + "/browse/" + sectionID.replace(/\./g, "/") + "?excerptid=div" + sectionID;
653
654 if(gs.cgiParams.berryBasket == "on")
655 {
656 url = url + "&berrybasket=on";
657 }
658
659 if(url.indexOf("#") != -1)
660 {
661 url = url.substring(0, url.indexOf("#"));
662 }
663 httpRequest.open('GET', url, true);
664 httpRequest.onreadystatechange = function()
665 {
666 if (httpRequest.readyState == 4)
667 {
668 if (httpRequest.status == 200)
669 {
670 var newDiv = document.createElement("div");
671 var sibling = document.getElementById("title" + sectionID);
672 var parent = sibling.parentNode;
673 if(sibling.nextSibling)
674 {
675 parent.insertBefore(newDiv, sibling.nextSibling);
676 }
677 else
678 {
679 parent.appendChild(newDiv);
680 }
681
682 newDiv.innerHTML = httpRequest.responseText;
683 sectionToggle.setAttribute("src", gs.imageURLs.collapse);
684 openClassifiers[sectionID] = true;
685
686 if(gs.cgiParams.berryBasket == "on")
687 {
688 checkout();
689 }
690 updateOpenClassifiers();
691 getSubClassifier(sectionID);
692 }
693 else
694 {
695 sectionToggle.setAttribute("src", gs.imageURLs.expand);
696 }
697 inProgress[sectionID] = false;
698 busy = false;
699 }
700 }
701 httpRequest.send();
702 }
703 }
704}
Note: See TracBrowser for help on using the repository browser.