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

Last change on this file since 32127 was 30736, checked in by ak19, 8 years ago

Several bugfixes noticed in the Images-GPS tutorial collection: 1. Dr Bainbridge fixed the huge location URL string by having it passed by POST instead of GET. 2. Dr Bainbridge corrected a check for the existence of an object returned with jQuery. Also applied the same correction in another location where this test is used. This helped withb expanding and collapsing book shelves using the plus icon. 3. The bookshelf nodes would expand upwards instead of downwards. Corrected this too. 4. The Scroll Through Places checkbox was not functioning, as it would keep scrolling even when unchecked. Now fixed.

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