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

Last change on this file since 33143 was 33143, checked in by wy59, 5 years ago

Bounds extends now works correctly for shapes so that all markers are displayed on the map. We have no way of calculating the correct zoom, though, and the zoom was never calculated before for a single marker (comments said it was randomly set to 18 back then as it looked good).

  • Property svn:executable set to *
File size: 33.9 KB
Line 
1//var newLat, newLng = 0;
2var _docList = new Array();
3_docList.ids = new Array();
4_docList.getDocByIndex = function(index)
5{
6 return _docList[_docList.ids[index]];
7};
8
9var _map;
10var _intervalHandle;
11var _baseURL = document.URL.substring(0, document.URL.indexOf("?") + 1);
12var _retrievedClassifiers = new Array();
13var _preventLoopingSingleMarker = false;
14var _searchRunning = false;
15var _nearbyDocs = new Array();
16var _scrollThroughDefault = true;
17
18function initializeMapScripts()
19{
20 modifyFunctions();
21 setUpMap();
22
23 var jsonNodeDiv = $("#jsonNodes");
24 if(jsonNodeDiv.length)
25 {
26 //console.log("@@@ JSON node div html: " + jsonNodeDiv.html());
27 var jsonNodes = eval(jsonNodeDiv.html());
28
29 if(jsonNodes && jsonNodes.length > 0)
30 {
31 for(var i = 0; i < jsonNodes.length; i++)
32 {
33 _docList[jsonNodes[i].nodeID] = jsonNodes[i];
34 _docList.ids.push(jsonNodes[i].nodeID);
35 createMarkers(jsonNodes[i], true);
36 }
37 updateMap();
38 }
39 else
40 {
41 //hiding the map
42 //$("#map_canvas").css({visibility:"hidden", height:"0px"});
43 $("#map_canvas").css({visibility:"hidden"}); // if you comment this out, add a log message saying "suppressing hiding map"
44 }
45 }
46
47 _docList.loopIndex = 0;
48
49 if(_docList.ids.length > 1)
50 {
51 var startStopCheckbox = $("<input>", {"type": "checkbox", "checked": _scrollThroughDefault, "id": "scrollCheckbox"});
52 startStopCheckbox.click(function()
53 {
54 // http://stackoverflow.com/questions/901712/how-to-check-if-a-checkbox-is-checked-in-jquery
55 // http://stackoverflow.com/questions/5270689/attrchecked-checked-does-not-work
56
57 if($('#scrollCheckbox').is(':checked')) // OR: if(document.getElementById('scrollCheckbox').checked)
58 {
59 if(_intervalHandle == null)
60 {
61 _intervalHandle = setInterval(loopThroughMarkers, 2000);
62 }
63 }
64 else
65 {
66 clearInterval(_intervalHandle);
67 _intervalHandle = null;
68 }
69 });
70
71 var label = $("<span>Scroll through places</span>");
72 var container = $("<div>", {"class": "ui-widget-header ui-corner-all", "style": "clear:right; float:right; padding:0px 5px 3px 0px;"});
73 container.append(startStopCheckbox);
74 container.append(label);
75
76 $(container).insertAfter("#map_canvas");
77
78 if (_scrollThroughDefault) {
79 _intervalHandle = setInterval(loopThroughMarkers, 2000);
80 }
81
82 }
83}
84
85function setUpMap()
86{
87 //alert("@@@@in map-scripts::setUpMap()");
88
89 var myOptions =
90 {
91 zoom: 2,
92 center: new google.maps.LatLng(0, 0),
93 mapTypeId: google.maps.MapTypeId.HYBRID
94 };
95 var $map_canvas = $("#map_canvas");
96
97 if ($map_canvas.length > 0) {
98 _map = new google.maps.Map($map_canvas[0], myOptions);
99 google.maps.event.addListener(_map, 'bounds_changed', performSearchForMarkers);
100 }
101}
102
103function performSearchForMarkers()
104{
105 if(_searchRunning)
106 {
107 return;
108 }
109
110
111
112 _searchRunning = true;
113
114 var bounds = _map.getBounds();
115
116 var neLat = bounds.getNorthEast().lat();
117 var neLng = bounds.getNorthEast().lng();
118 var swLat = bounds.getSouthWest().lat();
119 var swLng = bounds.getSouthWest().lng();
120
121 var latDistance = neLat - swLat;
122 var lngDistance = neLng - swLng;
123
124 //Check which increment to use for latitude (i.e. 0.001, 0.01, 0.1 or 1 degree increments)
125 var latDelta;
126 var latPrecision;
127 for(var i = 3; i >= 0; i--)
128 {
129 latDelta = (1 / Math.pow(10, i));
130 if((latDistance / latDelta) <= 5 || latDelta == 1)
131 {
132 latPrecision = i;
133 break;
134 }
135 }
136
137 //Check which increment to use for longitude (i.e. 0.001, 0.01, 0.1 or 1 degree increments)
138 var lngDelta;
139 for(var i = 3; i >= 0; i--)
140 {
141 lngDelta = (1 / Math.pow(10, i));
142 if((lngDistance / lngDelta) <= 5 || lngDelta == 1)
143 {
144 lngPrecision = i;
145 break;
146 }
147 }
148
149 if(latDelta == 0.1){latDelta = 1; latPrecision = 0; }
150 if(lngDelta == 0.1){lngDelta = 1; lngPrecision = 0; }
151
152 /*
153 var query = "";
154 for(var i = 0; i <= Math.floor(latDistance / latDelta) + 1; i++)
155 {
156 for(var j = 0; j <= Math.floor(lngDistance / lngDelta) + 1; j++)
157 {
158 //Some necessary variables
159 var newLat = neLat - (latDelta * i);
160 var newLatString = "" + newLat;
161 var newLatTrunc;
162 if(newLat < 0){newLatTrunc = Math.ceil(newLat);}
163 else{newLatTrunc = Math.floor(newLat);}
164
165 var newLng = neLng - (lngDelta * j);
166 var newLngString = "" + newLng;
167 var newLngTrunc;
168 if(newLng < 0){newLngTrunc = Math.ceil(newLng);}
169 else{newLngTrunc = Math.floor(newLng);}
170
171 //Construct query
172 query += "(";
173 query += "LA:" + coordToAbsDirected(newLatTrunc, "lat");
174 if(latDelta != 1)
175 {
176 query += "+AND+";
177 query += "LA:" + newLatString.substring(newLatString.indexOf(".") + 1, newLatString.indexOf(".") + latPrecision + 1);
178 }
179 query += "+AND+";
180 query += "LN:" + coordToAbsDirected(newLngTrunc, "lng");
181 if(lngDelta != 1)
182 {
183 query += "+AND+";
184 query += "LN:" + newLngString.substring(newLngString.indexOf(".") + 1, newLngString.indexOf(".") + lngPrecision + 1);
185 }
186 query += ")";
187
188 if(i != (Math.floor(latDistance / latDelta) + 1) || j != (Math.floor(lngDistance / lngDelta) + 1)){ query += "+OR+"; }
189 }
190 }
191 */
192 var query = "";
193 var iMax = Math.floor(latDistance / latDelta) + 1;
194 var jMax = Math.floor(lngDistance / lngDelta) + 1;;
195 for(var i = 0; i <= iMax; i++) //for(var i = 0; i <= Math.floor(latDistance / latDelta) + 1; i++)
196 {
197 for(var j = 0; j <= jMax; j++) //for(var j = 0; j <= Math.floor(lngDistance / lngDelta) + 1; j++)
198 {
199 //Some necessary variables
200 var newLat = neLat - (latDelta * i);
201 var newLatString = "" + newLat;
202 var newLatTrunc;
203 if(newLat < 0){newLatTrunc = Math.ceil(newLat);}
204 else{newLatTrunc = Math.floor(newLat);}
205
206 var newLng = neLng - (lngDelta * j);
207 var newLngString = "" + newLng;
208 var newLngTrunc;
209 if(newLng < 0){newLngTrunc = Math.ceil(newLng);}
210 else{newLngTrunc = Math.floor(newLng);}
211
212 //Construct query
213 query += "(";
214 query += "CS:\"" + coordToAbsDirected(newLatTrunc, "lat");
215 //query += "CS:\"" + coordToAbsDirected(newLatTrunc, "lat") + "\" \"" + coordToAbsDirected(newLngTrunc, "lng") + "\""; //query += "LA:" + coordToAbsDirected(newLatTrunc, "lat");
216 if(latDelta != 1)
217 {
218 query += newLatString.substring(newLatString.indexOf(".") + 1, newLatString.indexOf(".") + latPrecision + 1);
219 }
220 query += " ";
221 //query += "+AND+";
222
223 //query += "LN:" + coordToAbsDirected(newLngTrunc, "lng");
224 query += coordToAbsDirected(newLngTrunc, "lng");
225 if(lngDelta != 1)
226 {
227 query += newLngString.substring(newLngString.indexOf(".") + 1, newLngString.indexOf(".") + lngPrecision + 1);
228 }
229 query += "\"";
230 query += ")";
231
232 //if(i != (Math.floor(latDistance / latDelta) + 1) || j != (Math.floor(lngDistance / lngDelta) + 1)){ query += "+OR+"; }
233 if(i != iMax || j != jMax){ query += "+OR+"; }
234 }
235 }
236
237 // This works, why not from the double loop above?
238 //query = "(CS:\"" + coordToAbsDirected(newLatTrunc, "lat") + " " + coordToAbsDirected(newLngTrunc, "lng") + "\")";
239 //alert("@@@@in map-scripts::performSearchForMarkers() - query: " + query);
240
241 //var url = gs.xsltParams.library_name + "?a=q&s=RawQuery&rt=rd&c=" + gs.cgiParams.c + "&s1.rawquery=" + query + "&excerptid=jsonNodes";
242 var url = gs.xsltParams.library_name;
243 var data = "a=q&s=RawQuery&rt=rd&c=" + gs.cgiParams.c + "&s1.rawquery=" + query + "&excerptid=jsonNodes";
244 $.ajax({type:"POST", url:url, data:data})
245 .success(function(responseText)
246 {
247 //console.log("*** responseText (first 250) = " + responseText.substring(0,256));
248
249 if(responseText.search("id=\"jsonNodes") != -1)
250 {
251 var startIndex = responseText.indexOf(">");
252 var endIndex = responseText.indexOf("</");
253
254 //console.log("@@@@ performSearch, got response: " + responseText);
255
256 var jsonNodes = eval(responseText.substring(startIndex+1, endIndex));
257 if(jsonNodes && jsonNodes.length > 0)
258 {
259 for(var i = 0; i < jsonNodes.length; i++)
260 {
261 var doc = jsonNodes[i];
262
263 var found = false;
264 for(var j = 0; j < _docList.ids.length; j++){if(doc.nodeID == _docList.ids[j]){found = true; break;}}
265
266 if(!found)
267 {
268 _docList[doc.nodeID] = doc;
269 _docList.ids.push(doc.nodeID);
270
271 createMarkers(doc, false);
272 }
273 }
274 }
275 }
276 else
277 {
278 console.log("No JSON information received");
279 }
280
281 _searchRunning = false;
282 }).fail(function(responseText, textStatus, errorThrown) // fail() has replaced error(), http://api.jquery.com/jquery.ajax/
283 {
284 console.log("In map-scripts.performSearchForMarkers(): Got an error in ajax call");
285 _searchRunning = false;
286 });
287}
288
289function coordToAbsDirected(coord, type)
290{
291 var value = "" + coord;
292 if(coord < 0)
293 {
294 value = value.substring(1);
295 if(type == "lat")
296 {
297 value += "S";
298 }
299 else
300 {
301 value += "W";
302 }
303 }
304 else
305 {
306 if(type == "lat")
307 {
308 value += "N";
309 }
310 else
311 {
312 value += "E";
313 }
314 }
315
316 return value;
317}
318
319function updateMap()
320{
321 var markersOnMap = 0;
322 var bounds = new google.maps.LatLngBounds();
323 for(var i = 0; i < _docList.ids.length; i++)
324 {
325 var doc = _docList.getDocByIndex(i);
326 if(doc.parentCL && doc.parentCL.style.display == "none")
327 {
328 if(doc.shapes) {
329 for(var x = 0; x < doc.shapes.length; x++) {
330 doc.shapes[x].setVisible(false);
331 }
332 markersOnMap = doc.shapes.length;
333 } else {
334 doc.marker.setVisible(false);
335 }
336 continue;
337 }
338 else
339 {
340 if(doc.shapes) {
341 for(var x = 0; x < doc.shapes.length; x++) {
342 doc.shapes[x].setVisible(true);
343 }
344 markersOnMap = doc.shapes.length;
345 } else {
346 doc.marker.setVisible(true);
347 }
348 markersOnMap++; // TODO: what do we do with this when we have shapes. This variable may be connected with centring the map?
349 }
350
351
352 if(doc.coords) {
353 for(var x = 0; x < doc.coords.length; x++) {
354 var coord = doc.coords[x];
355 var coordInfo = getLatLngForCoord(doc.coords[x]);
356 bounds.extend(new google.maps.LatLng(coordInfo.lat, coordInfo.lng));
357 }
358 }
359 else {
360 bounds.extend(new google.maps.LatLng(doc.lat, doc.lng));
361 }
362 }
363
364 if(markersOnMap > 1)
365 {
366 //alert("@@@@ fitting bounds, current zoom is: " + _map.getZoom());
367 _map.fitBounds(bounds);
368 } else if (markersOnMap == 1) {
369 // sometimes a single point bounds are too small for the map to display, so use center and zoom instead of fitbounds.
370 _map.setCenter(bounds.getCenter());
371 _map.setZoom(18); // arbitrary value that looked nice for my example
372 }
373}
374
375function getLatLngForCoord(coord) {
376
377 // https://stackoverflow.com/questions/2559318/how-to-check-for-an-undefined-or-null-variable-in-javascript
378 if(!coord) {
379 // some_variable is either null, undefined, 0, NaN, false, or an empty string
380 console.log("@@@@ In map-scripts::getLatLngForCoord(): no or invalid coord info");
381 return null;
382 }
383
384 // coord is of the form: "37S77 157E53"
385 // lat will be 37S77, lng 157E53.
386 var indexOfSpace = coord.indexOf(" ");
387 if(indexOfSpace === -1) {
388 console.log("@@@@ In map-scripts::getLatLngForCoord(): bad format for coord " + coord);
389 return null;
390 }
391 var latitude = coord.substring(0, indexOfSpace);
392 var longitude = coord.substring(indexOfSpace+1);
393 return {lat: latitude, lng: longitude}; // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects
394}
395
396function loopThroughMarkers()
397{
398 if(_docList.ids.length == 0)
399 {
400 return;
401 }
402
403 var visibleMarkers = new Array();
404 for(var i = 0; i < _docList.ids.length; i++)
405 {
406 var doc = _docList.getDocByIndex(i);
407 if(doc.marker.getVisible())
408 {
409 visibleMarkers.push(doc);
410 }
411 }
412
413 if(visibleMarkers.length < 2)
414 {
415 clearAllInfoBoxes();
416 return;
417 }
418
419 clearAllInfoBoxes();
420
421 var elem = null;
422 while(!elem)
423 {
424 if(_docList.loopIndex >= visibleMarkers.length)
425 {
426 _docList.loopIndex = 0;
427 }
428
429 var doc = visibleMarkers[_docList.loopIndex];
430 var elem = gs.jqGet("div" + doc.nodeID);
431 if(elem.length)
432 {
433 elem.css("background", "#BBFFBB");
434 setTimeout(function(){elem.css("background", "");}, 2000);
435 }
436 _docList.loopIndex++;
437 }
438 doc.marker.markerInfo.open(_map, doc.marker);
439}
440
441// Unused at present, called by draggableCreateMarker
442// Map used to have editable markers. Now editable markers are restricted to the map-editor.
443function attachDraggableClickHandler(marker, nodeID)
444{
445 google.maps.event.addListener(marker, 'click', function()
446 {
447 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";
448
449 });
450
451 if (("docEdit" in gs.cgiParams) && (gs.cgiParams['docEdit'])) {
452 google.maps.event.addListener(marker, 'mouseup', function()
453 {
454 var lat = marker.getPosition().lat();
455 var lng = marker.getPosition().lng();
456 var collection = gs.cgiParams.c;
457 var site_name = gs.xsltParams.site_name;
458
459 if (nodeID == "") {
460 nodeID = gs.cgiParams.d;
461 }
462 console.log("GPS Click handler in collection:" + collection + " in site: " + site_name + " for Doc: " + nodeID + "(" + lat + "," + lng + ")");
463
464 var callbackFunction = function(){console.log("Completed saving metadata changes. You must rebuild the collection for the changes to take effect.");};
465
466 // set 5th parameter, metapos (metadata position) or 7th param prevMetaValue (previous metadata value) to non-null if you want metamode=override to work
467 // if neither of these 2 are set, then metamode is changed to 'accumulate' instead.
468 gs.functions.setArchivesMetadata(collection, site_name, nodeID, "Latitude", null, lat, null, "override", function(){callbackFunction();});
469 gs.functions.setArchivesMetadata(collection, site_name, nodeID, "Longitude", null, lng, null, "override", function(){callbackFunction();});
470 gs.functions.setArchivesMetadata(collection, site_name, nodeID, "Coordinate", null, lat + " " + lng, null, "override", function(){callbackFunction();});
471 console.log("NodeID: " + nodeID);
472 console.log("GPS Click handler in collection:" + collection + " in site: " + site_name + " for Doc: " + nodeID + "(" + lat + "," + lng + ")");
473 });
474 }
475}
476
477function focusDocument(id)
478{
479 var doc = _docList[id];
480 if(doc)
481 {
482 clearInterval(_intervalHandle);
483 _intervalHandle = null;
484 if(doc.coords) {
485 for(var x = 0; x < doc.coords.length; x++) {
486 var coord = doc.coords[x];
487 var coordInfo = getLatLngForCoord(doc.coords[x]);
488 _map.panTo(new google.maps.LatLng(coordInfo.lat, coordInfo.lng));
489 }
490 } else {
491 _map.panTo(new google.maps.LatLng(doc.lat, doc.lng));
492 }
493 clearAllInfoBoxes();
494 doc.marker.markerInfo.open(_map, doc.marker);
495 var scrollCheckbox = $("#scrollCheckbox");
496 if(scrollCheckbox.checked)
497 {
498 scrollCheckbox.checked = false;
499 }
500 }
501}
502
503function clearAllInfoBoxes()
504{
505 for(var i = 0; i < _docList.ids.length; i++)
506 {
507 var doc = _docList.getDocByIndex(i);
508 doc.marker.markerInfo.close();
509 }
510}
511
512function createMarkers(doc, mainMarker) {
513 if(doc.mapoverlay) {
514 //console.log("Have shapes: " + doc.mapoverlay.toString());
515 createShapes(doc, mainMarker);
516 } else { // backwards compatible to deal with Lat and Lng meta stored for doc
517 pos = new google.maps.LatLng(doc.lat,doc.lng);
518 createMarker(doc, pos, mainMarker);
519 }
520}
521
522function addInfoMarker(doc, shape) {
523
524 if(!shape.description) {
525 //console.log("@@@@ " + shape.type.toString() + " had no description/label");
526 return;
527 }
528
529 // else add an InfoWindow for this shape using the label (shape.description)
530
531 // https://developers.google.com/maps/documentation/javascript/infowindows
532 // An InfoWindow's "position contains the LatLng at which this info window is anchored.
533 // Note: An InfoWindow may be attached either to a Marker object (in which case its position is based on the marker's location)
534 // or on the map itself at a specified LatLng. Opening an info window on a marker will automatically update the position."
535 var infoWindow = new google.maps.InfoWindow({content:shape.description}); // NOTE: if not setting content or position properties
536 // inside this constructor, need to call setContent/setPosition to set them
537
538 if(shape.type === google.maps.drawing.OverlayType.MARKER) {
539 var marker = shape;
540 marker.addListener('mouseover', function() {
541 infoWindow.open(_map, marker);
542 });
543 marker.addListener('mouseout', function() {
544 infoWindow.close();
545 });
546 attachClickHandler(marker, doc.nodeID); // do what the original code used to do here
547 }
548 else {
549 var coord = ShapesUtil.getLabelCoordinate(shape);
550 console.log("Coord for " + shape.type.toString() + " is " + coord.toString());
551 infoWindow.setPosition(coord);
552 shape.addListener('mouseover', function() {
553 infoWindow.open(_map);
554 });
555 shape.addListener('mouseout', function() {
556 infoWindow.close();
557 });
558 attachClickHandler(shape, doc.nodeID); // as above
559 }
560}
561
562// This function will create Google Shapes/Overlays and markers out of a given doc JSONNode's doc.mapOverlay
563// (doc.mapOverlay shapes are stored as an array of JSON) and store the shapes/overlays in the doc.shapes array.
564// Note: doc.coords are just an array of all the coordinates in a doc, not indicating to which shapes they belong.
565// They're only **for searching** - for seaching which coords (hence docs) are in a map.
566// Param mainMarker: if set to true, marker is red. If false, marker is blue
567function createShapes(doc, mainMarker)
568{
569 // for doc.shapes: don't store JSON anymore, convert them to google Shapes overlays and store them instead
570 doc.shapes = [];
571 for (var i=0; i<doc.mapoverlay.length; i++) {
572 var shape = ShapesUtil.JSONToShape(doc.mapoverlay[i]);
573 doc.shapes[i] = shape;
574 shape.setMap(_map);
575 shape["title"] = doc.title;
576
577 // Unset editable and draggable properties of shape
578 // And for markers, which are initialised to clickable besides, undo the clickability
579 // and set them
580 if(shape.type === google.maps.drawing.OverlayType.MARKER) {
581 var marker = shape;
582 // mainMarkers should be red
583 if(!mainMarker) {
584 marker["icon"] = "interfaces/" + gs.xsltParams.interface_name + "/images/bluemarker.png";
585 }
586 marker.clickable = false; // only markers
587 }
588
589 shape.editable = false;
590 shape.draggable = false;
591
592
593
594 // doc[i]'s label = doc.shapes[i].description
595 addInfoMarker(doc, shape);
596 }
597
598 var docElement = gs.jqGet("div" + doc.nodeID);
599 var parent;
600 if(docElement)
601 {
602 parent = docElement.parentNode;
603 }
604
605 while(parent && parent.nodeName != "BODY")
606 {
607 if($(parent).attr("id") && $(parent).attr("id").search("divCL") != -1)
608 {
609 doc.parentCL = parent;
610 break;
611 }
612
613 parent = parent.parentNode;
614 }
615}
616
617// This method is only for backwards compatibility: for those collections with docs that only have Lat and Lng meta
618// and no GPS.mapOverlay (and hence Coordinate) meta.
619// Param mainMarker: if set to true, marker is red. If false, marker is blue
620function createMarker(doc, pos, mainMarker)
621{
622 var marker;
623 if(mainMarker)
624 {
625 marker = new google.maps.Marker
626 ({
627 position: pos,
628 title:doc.title,
629 map:_map
630 });
631 }
632 else
633 {
634 marker = new google.maps.Marker
635 ({
636 position: pos,
637 title:doc.title,
638 map:_map,
639 icon:"interfaces/" + gs.xsltParams.interface_name + "/images/bluemarker.png"
640 });
641 }
642
643 var docElement = gs.jqGet("div" + doc.nodeID);
644 var parent;
645 if(docElement)
646 {
647 parent = docElement.parentNode;
648 }
649
650 while(parent && parent.nodeName != "BODY")
651 {
652 if($(parent).attr("id") && $(parent).attr("id").search("divCL") != -1)
653 {
654 doc.parentCL = parent;
655 break;
656 }
657
658 parent = parent.parentNode;
659 }
660
661 var info = new google.maps.InfoWindow({content:doc.title});
662 marker.markerInfo = info;
663 doc.marker = marker;
664 attachClickHandler(marker, doc.nodeID);
665}
666
667// TODO: with the following, it seems that clicking on shape expands the entire document
668// Should it be that clicking on a shape should expand the doc section that contains that shape meta?
669function attachClickHandler(shapeOrMarker, nodeID)
670{
671 google.maps.event.addListener(shapeOrMarker, 'click', function()
672 {
673 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";
674 });
675}
676
677// TODO:
678// Version of createMarker function containing Zeddy's modifications (pre-mapeditor?) to make markers
679// on the public *map* (not on map-editor) draggable/editable and to save these edits/rebuild with them.
680// Do we want to continue supporting editing on the main map? I thought we weren't going to and that editing
681// was exclusive to the map-editor, with the public map only displaying the saved features?
682function draggableCreateMarker(doc, pos, mainMarker)
683{
684 var docEdit = (("docEdit" in gs.cgiParams) && (gs.cgiParams['docEdit']));
685 //var draggable_val = (docEdit) ? true : false;
686
687 // When user logs out, the very first page they're returned to has logout set
688 // If the user logged out when leaving docEdit on, then the very first page has docEdit=1 AND logout.
689 // In that case, don't allow editing. Subsequent pages in logged out mode have neither logout nor docEdit=1 set.
690 var loggedOutVar = ("logout" in gs.cgiParams);
691
692 // Don't allow dragging if either 1. docEdit not on OR 2. logout is in the cgiParams
693 var draggable_val = (!docEdit || loggedOutVar) ? false : true;
694
695 var marker;
696 if(mainMarker)
697 {
698 marker = new google.maps.Marker
699 ({
700 position: pos,
701 title:doc.title,
702 map:_map,
703 draggable: draggable_val
704 });
705 }
706 else
707 {
708 marker = new google.maps.Marker
709 ({
710 position: pos,
711 title:doc.title,
712 map:_map,
713 icon:"interfaces/" + gs.xsltParams.interface_name + "/images/bluemarker.png",
714 draggable: draggable_val
715 });
716 }
717
718 var docElement = gs.jqGet("div" + doc.nodeID);
719 var parent;
720 if(docElement)
721 {
722 parent = docElement.parentNode;
723 }
724
725 while(parent && parent.nodeName != "BODY")
726 {
727 if($(parent).attr("id") && $(parent).attr("id").search("divCL") != -1)
728 {
729 doc.parentCL = parent;
730 break;
731 }
732
733 parent = parent.parentNode;
734 }
735
736 var info = new google.maps.InfoWindow({content:doc.title});
737 marker.markerInfo = info;
738 doc.marker = marker;
739 attachDraggableClickHandler(marker, doc.nodeID);
740
741 ////////////////////////////////////////////////////// TEST
742
743 newLat = marker.getPosition().lat();
744 newLng = marker.getPosition().lng();
745 //console.log("Latitude " + newLat);
746 //console.log("Longitude " + newLng);
747 //NewLatLng(newLat, newLng);
748
749// // Define the LatLng coordinates for the polygon's path.
750// var triangleCoords = [
751// {lat: 18.774, lng: -80.190},
752// {lat: 18.466, lng: -64.600},
753// {lat: 32.321, lng: -64.757},
754// {lat: 32.300, lng: -80.190},
755// {lat: 28.300, lng: -90.190}
756// ];
757//
758// // Construct the polygon.
759// var bermudaTriangle = new google.maps.Polygon({
760// paths: triangleCoords,
761// strokeColor: '#FF0000',
762// strokeOpacity: 0.8,
763// strokeWeight: 2,
764// fillColor: '#FF0000',
765// fillOpacity: 0.35
766// });
767// bermudaTriangle.setMap(map);
768}
769
770function NewLatLng(lat, lng)
771{
772 console.log("Latitude " + lat);
773 console.log("Longitude " + lng);
774}
775
776function getSubClassifier(sectionID)
777{
778 var url = gs.xsltParams.library_name + "?a=b&rt=s&s=ClassifierBrowse&c=" + gs.cgiParams.c + "&cl=" + sectionID + "&excerptid=jsonNodes";
779 $.ajax(url)
780 .success(function(responseText)
781 {
782 var startIndex = responseText.indexOf(">");
783 var endIndex = responseText.indexOf("</");
784
785 var jsonNodes = eval(responseText.substring(startIndex+1, endIndex));
786 if(jsonNodes && jsonNodes.length > 0)
787 {
788 for(var i = 0; i < jsonNodes.length; i++)
789 {
790 var doc = jsonNodes[i];
791 _docList[doc.nodeID] = doc;
792 _docList.ids.push(doc.nodeID);
793
794 createMarkers(doc, false);
795 }
796
797 $("#map_canvas").css({"visibility": "visible", "height": ""});
798 }
799
800 updateMap();
801 })
802 .error(function()
803 {
804 console.log("Error getting subclassifiers");
805 return;
806 });
807}
808
809function performDistanceSearchWithCoordinates(id, coord, degrees)
810{
811 var coordInfo = getLatLngForCoord(coord);
812 if(!coordInfo) {
813 console.log("@@@ ERROR in map-scripts::performDistanceSearchWithCoordinates: coordInfo is null");
814 }
815 performDistanceSearch(id, coordInfo.lat, coordInfo.lng, degrees);
816}
817
818function performDistanceSearch(id, lat, lng, degrees)
819{
820 if(parseFloat(lat) > 180 || parseFloat(lat) < -180 || parseFloat(lng) > 180 || parseFloat(lat) < -180)
821 {
822 console.log("Latitude or longitude incorrectly formatted");
823 return;
824 }
825
826 if(lat.indexOf(".") == -1 || lng.indexOf(".") == -1 || (lat.indexOf(".") + 3) >= lat.length || (lng.indexOf(".") + 3) >= lng.length)
827 {
828 console.log("Latitude or longitude does not have the required precision for a distance search");
829 return;
830 }
831
832 var query = "";
833 for(var i = 0; i < degrees * 2; i++)
834 {
835 for (var j = 0; j < degrees * 2; j++)
836 {
837 var latDelta = (i - degrees) * 0.01;
838 var lngDelta = (j - degrees) * 0.01;
839
840 query += "(" + getDistanceQueryString(lat, latDelta, 2, "LA", ["N","S"]);
841 query += "+AND+";
842 query += getDistanceQueryString(lng, lngDelta, 2, "LN", ["E","W"]) + ")";
843
844 if(i != ((degrees * 2) - 1) || j != ((degrees * 2) - 1)){ query += "+OR+"; }
845 }
846 }
847
848 var inlineTemplate = '\
849 <xsl:template match="/" priority="5">\
850 <table id="nearbyDocs">\
851 <tr>\
852 <th><a href="javascript:sortByDistance();">Distance</a></th><th><a href="javascript:sortAlphabetically();">Document</a></th>\
853 </tr>\
854 <xsl:apply-templates select="//documentNode"/>\
855 </table>\
856 </xsl:template>\
857 \
858 <xsl:template match="documentNode" priority="5">\
859 <xsl:if test="@nodeID !=\''+id+'\'">\
860 <tr>\
861 <td>___<gsf:metadata name="Latitude"/>______<gsf:metadata name="Longitude"/>___</td>\
862 <td><gsf:link title="'+gs.text.doc.nearby_doc_tooltip+'" type="document"><gsf:metadata name="Title"/></gsf:link></td>\
863 </tr>\
864 </xsl:if>\
865 </xsl:template>';
866
867 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");
868 $.ajax(url)
869 .success(function(response)
870 {
871 response = response.replace(/<img src="[^"]*map_marker.png"[^>]*>/g, "");
872
873 var nearbyDocsArray = new Array();
874
875 var lats = new Array();
876 var lngs = new Array();
877 var matches = response.match(/___(-?[0-9\.]*)___/g);
878 for(var i = 0; i < matches.length; i += 2)
879 {
880 var matchLatFloat = parseFloat(matches[i].replace("___", ""));
881 var matchLngFloat = parseFloat(matches[i+1].replace("___", ""));
882
883 lats.push(matchLatFloat);
884 lngs.push(matchLngFloat);
885 var distance = Math.sqrt(Math.pow(matchLatFloat - parseFloat(lat), 2) + Math.pow(matchLngFloat - parseFloat(lng), 2)) * (40000.0/360.0);
886 var distanceString = "" + distance;
887 distanceString = distanceString.substring(0, 6);
888 response = response.replace(matches[i] + matches[i+1], distanceString);
889 }
890
891 var index = 0;
892 var i = 0;
893 while(true)
894 {
895 var distanceStart = response.indexOf("<td>", index);
896 if(distanceStart == -1)
897 {
898 break;
899 }
900 var distanceEnd = response.indexOf("</td>", distanceStart);
901
902 var docLinkStart = response.indexOf("<td>", distanceEnd);
903 var docLinkEnd = response.indexOf("</td>", docLinkStart);
904
905 var dist = response.substring(distanceStart + 4, distanceEnd);
906 var docLink = response.substring(docLinkStart + 4, docLinkEnd);
907
908 _nearbyDocs.push({title:docLink, distance:dist, lat:lats[i], lng:lngs[i++]});
909
910 index = docLinkEnd;
911 }
912
913 sortByDistance(lat,lng);
914
915 var toggle = $("#nearbyDocumentsToggle");
916 toggle.attr("src", gs.imageURLs.collapse);
917 gs.functions.makeToggle(toggle, $("#nearbyDocuments"));
918 });
919}
920
921var map_centering_timeout = null;
922function recenterMapF(lat, lng)
923{
924 return function() {
925 _map.setCenter(new google.maps.LatLng(lat, lng));
926 }
927}
928function recenterMap(lat, lng)
929{
930
931 _map.setCenter(new google.maps.LatLng(lat, lng));
932
933}
934function sortByDistance(base_lat,base_lng)
935{
936 var sortedTable = '<table id="nearbyDocs" onmouseleave="clearTimeout(map_centering_timeout); recenterMap('+base_lat+','+base_lng+');"><tr><th><a href="javascript:;">Distance</a></th><th><a href="javascript:sortAlphabetically('+base_lat+', '+base_lng+');">Document</a></th></tr>';
937 _nearbyDocs.sort(function(a, b){return (a.distance - b.distance);});
938 for(var i = 0; i < _nearbyDocs.length; i++)
939 {
940
941 sortedTable += "<tr><td>" + prettifyDistance(_nearbyDocs[i].distance) + '</td><td onmouseover="clearTimeout(map_centering_timeout); map_centering_timeout = setTimeout(recenterMapF(' + _nearbyDocs[i].lat + ',' + _nearbyDocs[i].lng + '), 900)" >' + _nearbyDocs[i].title + "</td></tr>";
942 }
943 sortedTable += "</table>";
944
945 $("#nearbyDocuments").html(sortedTable);
946}
947function prettifyDistance(distance) {
948
949 var new_distance;
950 if (distance < 1) {
951 new_distance = (distance * 1000);
952 // Round to nearest whole number - don't need to show points of metres..
953 new_distance = Math.round(new_distance);
954 new_distance += " m";
955 }
956 else {
957 new_distance = distance +" km";
958
959 }
960 return new_distance;
961}
962
963
964
965function sortAlphabetically(base_lat, base_lng)
966{
967 var sortedTable = '<table id="nearbyDocs" onmouseleave="clearTimeout(map_centering_timeout); recenterMap('+base_lat+','+base_lng+');"><tr><th><a href="javascript:sortByDistance('+base_lat+', '+base_lng+');">Distance</a></th><th><a href="javascript:;">Document</a></th></tr>';
968 _nearbyDocs.sort(function(a, b)
969 {
970 var firstTitleStartIndex = a.title.indexOf(">");
971 var firstTitleEndIndex = a.title.indexOf("<", firstTitleStartIndex);
972 var firstTitle = a.title.substring(firstTitleStartIndex + 1, firstTitleEndIndex);
973 var secondTitleStartIndex = b.title.indexOf(">");
974 var secondTitleEndIndex = b.title.indexOf("<", secondTitleStartIndex);
975 var secondTitle = b.title.substring(secondTitleStartIndex + 1, secondTitleEndIndex);
976 return ((firstTitle.toLowerCase() == secondTitle.toLowerCase()) ? 0 : ((firstTitle.toLowerCase() > secondTitle.toLowerCase()) ? 1 : -1));
977 });
978 for(var i = 0; i < _nearbyDocs.length; i++)
979 {
980 sortedTable += "<tr><td>" + _nearbyDocs[i].distance + '</td><td onmouseover="clearTimeout(map_centering_timeout); map_centering_timeout = setTimeout(recenterMapF(' + _nearbyDocs[i].lat + ',' + _nearbyDocs[i].lng + '), 900)">' + _nearbyDocs[i].title + "</td></tr>";
981 }
982 sortedTable += "</table>";
983
984 $("#nearbyDocuments").html(sortedTable);
985}
986
987function getDistanceQueryString(currentCoord, delta, precision, indexName, dirs)
988{
989 var query = "";
990 var coordFloat = parseFloat(currentCoord);
991
992 var newCoord = "" + (coordFloat + delta);
993 var beforeDec = newCoord.substring(0, newCoord.indexOf("."));
994
995 var dir = dirs[0];
996 if(coordFloat < 0)
997 {
998 dir = dirs[1];
999 beforeDec = beforeDec.substring(1);
1000 }
1001 beforeDec += dir;
1002
1003 var afterDec = newCoord.substring(newCoord.indexOf(".") + 1, newCoord.indexOf(".") + (precision) + 1);
1004
1005 return indexName + ":" + beforeDec + "+AND+" + indexName + ":" + afterDec;
1006}
1007
1008function modifyFunctions()
1009{
1010 // This function "overrides" toggleSection in both classifier_scripts.js and document_scripts.js
1011 // However, classifier_scripts.js::toggleSection() only took one parameter, sectionID, whereas
1012 // document_scripts.js::toggleSection() took 3 params (sectionID, callback, tocDisabled).
1013 // So to be compatible with both, need map-scripts::toggleSection() here to support all 3 in that order.
1014 toggleSection = function(sectionID, callback, tocDisabled)
1015 {
1016 _basicToggleSection(sectionID, callback, tocDisabled);
1017
1018 var section = gs.jqGet("div" + sectionID);
1019 var sectionToggle = gs.jqGet("toggle" + sectionID);
1020
1021 if(sectionToggle == undefined)
1022 {
1023 return;
1024 }
1025
1026 // Test if 'section' exists.
1027 // ==> Because we're using jQuery to do this we need to test the length of the object returned
1028 // http://stackoverflow.com/questions/920236/how-can-i-detect-if-a-selector-returns-null
1029 if(section.length !== 0)
1030 {
1031 if(isExpanded(sectionID))
1032 {
1033 section.css("display", "none");
1034 sectionToggle.attr("src", gs.imageURLs.expand);
1035
1036 if(openClassifiers[sectionID].length !== 0) //if(openClassifiers[sectionID] != undefined)
1037 {
1038 delete openClassifiers[sectionID];
1039 }
1040 }
1041 else
1042 {
1043 section.css("display", "block");
1044 sectionToggle.attr("src", gs.imageURLs.collapse);
1045 openClassifiers[sectionID] = true;
1046 }
1047 updateOpenClassifiers();
1048 updateMap();
1049 }
1050 else
1051 {
1052 httpRequest(sectionID);
1053 }
1054
1055 }
1056
1057 httpRequest = function(sectionID)
1058 {
1059 if(!inProgress[sectionID])
1060 {
1061 inProgress[sectionID] = true;
1062
1063 var sectionToggle = gs.jqGet("toggle" + sectionID);
1064 sectionToggle.attr("src", gs.imageURLs.loading);
1065
1066 var url = gs.xsltParams.library_name + "/collection/" + gs.cgiParams.c + "/browse/" + sectionID.replace(/\./g, "/") + "?excerptid=div" + sectionID;
1067
1068 if(gs.cgiParams.berrybasket == "on")
1069 {
1070 url = url + "&berrybasket=on";
1071 }
1072
1073 if(url.indexOf("#") != -1)
1074 {
1075 url = url.substring(0, url.indexOf("#"));
1076 }
1077
1078 $.ajax(url)
1079 .success(function(responseText)
1080 {
1081 var newDiv = $("<div>");
1082 var sibling = gs.jqGet("title" + sectionID);
1083 sibling.after(newDiv);
1084
1085 newDiv.html(responseText);
1086 sectionToggle.attr("src", gs.imageURLs.collapse);
1087 openClassifiers[sectionID] = true;
1088
1089 if(gs.cgiParams.berrybasket == "on")
1090 {
1091 checkout();
1092 }
1093 /*else if(gs.cgiParams.documentbasket == "on") // TODO: copied from classifier_scripts.js - should this else block be included here (and happen when mapEnabled) or not?
1094 {
1095 dmcheckout();
1096 }*/
1097 updateOpenClassifiers();
1098 getSubClassifier(sectionID);
1099 })
1100 .error(function()
1101 {
1102 sectionToggle.attr("src", gs.imageURLs.expand);
1103 })
1104 .complete(function()
1105 {
1106 inProgress[sectionID] = false;
1107 busy = false;
1108 });
1109 }
1110 }
1111}
Note: See TracBrowser for help on using the repository browser.