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

Last change on this file since 36287 was 36027, checked in by cstephen, 2 years ago

Migrate to using jQuery3 and jQuery-UI-1.13.2; and integrate cookie consent manager

  • Property svn:executable set to *
File size: 41.3 KB
Line 
1var mapEnabled = false; // variable to detect when map-scripts have been included into document_scripts.js and classifier_scripts.js,
2 // in which case this variable will be defined.
3 // It will be furthermore be set to true iff we have gps map data that the map can display, false if map-scripts imported but no map data.
4
5//var newLat, newLng = 0;
6var _docList = {};
7_docList.ids = [];
8
9_docList.getDocByIndex = function(index)
10{
11 return _docList[_docList.ids[index]];
12};
13
14var _nearbyDocListByProximity = [];
15
16var _map;
17var _intervalHandle;
18var _baseURL = document.URL.substring(0, document.URL.indexOf("?") + 1);
19var _retrievedClassifiers = [];
20var _preventLoopingSingleMarker = false;
21var _searchRunning = false;
22var _nearbyDocsByDistance = [];
23var _scrollThroughDefault = true; // TODO: default is true
24
25var LOW_OPACITY = 0.1; // make surrounding docs' opacity 10%
26var _DEBUGGING_ = false;
27
28function initializeMapScripts()
29{
30 //console.log("@@@@ initializeMapScripts()");
31
32 var jsonNodeDiv = $("#jsonNodes");
33 if(jsonNodeDiv.length)
34 {
35 //console.log("@@@ JSON node div html: " + jsonNodeDiv.html());
36 var jsonNodes = eval(jsonNodeDiv.html());
37
38 renderMap();
39 if(jsonNodes && jsonNodes.length > 0)
40 {
41 mapEnabled = true;
42 showMap("initializeMapScripts");
43
44 var resultsArea = $('#resultsArea');
45 if (resultsArea.length > 0){
46 resultsArea.css('min-height','500px');
47 }
48 for(var i = 0; i < jsonNodes.length; i++)
49 {
50 _docList[jsonNodes[i].nodeID] = jsonNodes[i];
51 _docList.ids.push(jsonNodes[i].nodeID);
52 var options = {
53 "mainDoc": true
54 };
55 //console.log("#### " + jsonNodes[i].nodeID + " is a main doc: ");
56 //console.log(jsonNodes[i]);
57 createOverlayItems(jsonNodes[i], options);
58 }
59
60 updateMap();
61 }
62 else
63 {
64 //hiding the map
65 mapEnabled = false;
66 hideMap("initializeMapScripts");
67 //return;
68 }
69 }
70 _docList.loopIndex = 0;
71
72 if(_docList.ids.length > 1)
73 {
74 var startStopCheckbox = $("<input>", {"type": "checkbox", "checked": _scrollThroughDefault, "id": "scrollCheckbox"});
75 startStopCheckbox.on("click", function()
76 {
77 // http://stackoverflow.com/questions/901712/how-to-check-if-a-checkbox-is-checked-in-jquery
78 // http://stackoverflow.com/questions/5270689/attrchecked-checked-does-not-work
79
80 if($('#scrollCheckbox').is(':checked')) // OR: if(document.getElementById('scrollCheckbox').checked)
81 {
82 if(_intervalHandle == null)
83 {
84 _intervalHandle = setInterval(loopThroughMarkers, 2000);
85 }
86 }
87 else
88 {
89 clearInterval(_intervalHandle);
90 _intervalHandle = null;
91 }
92 });
93
94 var label = $("<span>Scroll through places</span>");
95 var container = $("<div>", {"class": "ui-widget-header ui-corner-all", "style": "clear:right; float:right; padding:0px 5px 3px 0px;"});
96 container.append(startStopCheckbox);
97 container.append(label);
98
99 $(container).insertAfter("#map_canvas");
100
101 if (_scrollThroughDefault) {
102 _intervalHandle = setInterval(loopThroughMarkers, 2000);
103 }
104
105 }
106}
107
108function renderMap()
109{
110 //console.log("@@@@in map-scripts::renderMap()");
111 var myOptions =
112 {
113 zoom: 2,
114 center: new google.maps.LatLng(0, 0),
115 mapTypeId: google.maps.MapTypeId.HYBRID
116 };
117 var $map_canvas = $("#map_canvas");
118
119 if ($map_canvas.length > 0) {
120 //console.log("docList is " + _docList.toString());
121 _map = new google.maps.Map($map_canvas[0], myOptions);
122 //console.log("@@@ created Google _map");
123
124 google.maps.event.addListener(_map, 'bounds_changed', performProximitySearch);
125 }
126}
127
128function performProximitySearch()
129{
130 //console.log("@@@@ skipping proximity search for now");
131 //return;
132
133 _gsDebug("*** START OF performProximitySearch()");
134
135
136 if(typeof mapEnabled === 'undefined') return;
137 if(!mapEnabled){ return; }
138
139 _gsDebug("*** Got past mapEnabled test");
140
141
142 for(var i = 0 ; i < _nearbyDocListByProximity.length; i++) {
143 removeMarkersFromMap(_nearbyDocListByProximity[i]);
144 }
145 _nearbyDocListByProximity = [];
146
147
148 _debugPrintBounds(_map.getBounds(), "@@@ performProximitySearch():");
149
150
151 if(_searchRunning)
152 {
153 _gsInfo("*** performProximitySearch(): already running search => not initiating an additional search");
154 return;
155 }
156
157 _searchRunning = true;
158
159 var bounds = _map.getBounds();
160
161 var neLat = bounds.getNorthEast().lat();
162 var neLng = bounds.getNorthEast().lng();
163 var swLat = bounds.getSouthWest().lat();
164 var swLng = bounds.getSouthWest().lng();
165
166 var latDistance = neLat - swLat;
167 var lngDistance = neLng - swLng;
168
169 _gsDebug("****************START*****************");
170 _gsDebug("latDistance = " + latDistance);
171 _gsDebug("lngDistance = " + lngDistance);
172
173 //Check which increment to use for latitude (i.e. 0.001, 0.01, 0.1 or 1 degree increments)
174 var latDelta;
175 var latPrecision;
176 for(var i = 3; i >= 0; i--)
177 {
178 latDelta = (1 / Math.pow(10, i));
179 if((latDistance / latDelta) <= 5 || latDelta == 1)
180 {
181 latPrecision = i;
182 break;
183 }
184 }
185
186 //Check which increment to use for longitude (i.e. 0.001, 0.01, 0.1 or 1 degree increments)
187 var lngDelta;
188 var lngPrecision;
189 for(var i = 3; i >= 0; i--)
190 {
191 lngDelta = (1 / Math.pow(10, i));
192 // Want the grid superimposed on the map to be 5 or fewer steps,
193 // where delta is the grid size to make it so
194 // and precision is the number of decimal places.
195 if((lngDistance / lngDelta) <= 5 || lngDelta == 1)
196 {
197 lngPrecision = i;
198 break;
199 }
200 }
201
202 if(latDelta == 0.1){latDelta = 1; latPrecision = 0; }
203 if(lngDelta == 0.1){lngDelta = 1; lngPrecision = 0; }
204
205
206
207 _gsDebug("Proximity search: lat precision BEFORE = " + latPrecision);
208 _gsDebug("Proximity search: lng precision BEFORE = " + lngPrecision);
209
210 // Want consistent precision for both lat and lng.
211 // So we choose the most conservative (whichever is more zoomed out) for both
212 if(latPrecision < lngPrecision) {
213 lngPrecision = latPrecision;
214 } else if (lngPrecision < latPrecision) {
215 latPrecision = lngPrecision;
216 }
217
218 _gsDebug("Proximity search: lat precision AFTER = " + latPrecision);
219 _gsDebug("Proximity search: lng precision AFTER = " + lngPrecision);
220 _gsDebug("Proximity search with: latDelta = " + latDelta);
221 _gsDebug("Proximity search with: lngDelta = " + lngDelta);
222
223 var query = "";
224 var iMax = Math.floor(latDistance / latDelta) + 1;
225 var jMax = Math.floor(lngDistance / lngDelta) + 1;
226
227 _gsDebug("Proximity search with: iMax = " + iMax);
228 _gsDebug("Proximity search with: jMax = " + jMax);
229
230 _gsDebug("****************END*****************");
231
232 for(var i = 0; i <= iMax; i++) //for(var i = 0; i <= Math.floor(latDistance / latDelta) + 1; i++)
233 {
234 for(var j = 0; j <= jMax; j++) //for(var j = 0; j <= Math.floor(lngDistance / lngDelta) + 1; j++)
235 {
236 //Some necessary variables
237 var newLat = neLat - (latDelta * i);
238 var newLatString = "" + newLat;
239 var newLatTrunc;
240 if(newLat < 0){newLatTrunc = Math.ceil(newLat);}
241 else{newLatTrunc = Math.floor(newLat);}
242
243 var newLng = neLng - (lngDelta * j);
244 var newLngString = "" + newLng;
245 var newLngTrunc;
246 if(newLng < 0){newLngTrunc = Math.ceil(newLng);}
247 else{newLngTrunc = Math.floor(newLng);}
248
249 //Construct query
250 query += "(";
251 query += "CS:\"" + coordToAbsDirected(newLatTrunc, "lat");
252
253 if(latDelta != 1)
254 {
255 query += newLatString.substring(newLatString.indexOf(".") + 1, newLatString.indexOf(".") + latPrecision + 1);
256 }
257 query += " ";
258 query += coordToAbsDirected(newLngTrunc, "lng");
259 if(lngDelta != 1)
260 {
261 query += newLngString.substring(newLngString.indexOf(".") + 1, newLngString.indexOf(".") + lngPrecision + 1);
262 }
263 query += "\"";
264 query += ")";
265
266 if(i != iMax || j != jMax){ query += " OR "; } //if(i != (Math.floor(latDistance / latDelta) + 1) || j != (Math.floor(lngDistance / lngDelta) + 1)){ query += " OR "; }
267 }
268 }
269
270 // This works, why not from the double loop above?
271 //query = "(CS:\"" + coordToAbsDirected(newLatTrunc, "lat") + " " + coordToAbsDirected(newLngTrunc, "lng") + "\")";
272 //alert("@@@@in map-scripts::performProximitySearch() - query: " + query);
273
274 //var url = gs.xsltParams.library_name + "?a=q&s=RawQuery&rt=rd&c=" + gs.cgiParams.c + "&s1.rawquery=" + query + "&excerptid=jsonNodes";
275 var url = gs.xsltParams.library_name;
276 var data = "a=q&s=RawQuery&rt=rd&c=" + gs.cgiParams.c + "&s1.rawquery=" + query + "&excerptid=jsonNodes";
277 _gsDebug("*** performProximitySearch(): rawQuery query data = " + query);
278
279 $.ajax({type:"POST", url:url, data:data})
280 .done(function(responseText)
281 {
282 //console.log("*** responseText (first 250) = " + responseText.substring(0,256));
283
284 if(responseText.search("id=\"jsonNodes") != -1)
285 {
286 var startIndex = responseText.indexOf(">");
287 var endIndex = responseText.indexOf("</");
288
289 //console.log("@@@@ performSearch, got response: " + responseText);
290
291 var jsonNodes = eval(responseText.substring(startIndex+1, endIndex));
292 _gsDebug("@@@@ performProximitySearch - Number of matches returned from ajax rawQuery search = " + jsonNodes.length);
293 if(jsonNodes && jsonNodes.length > 0)
294 {
295 for(var i = 0; i < jsonNodes.length; i++)
296 {
297 var doc = jsonNodes[i];
298
299 var found = false;
300 for(var j = 0; j < _docList.ids.length; j++) {
301 if(doc.nodeID == _docList.ids[j]) {
302 found = true;
303 _gsDebug("performProximitySearch(): Found nearby ID " + doc.nodeID + " was already drawn:", jsonNodes[i]);
304 break;
305 }
306 }
307
308 if(!found)
309 {
310 _nearbyDocListByProximity.push(doc);
311 createOverlayItems(doc, {"mainDoc": false});
312 }
313
314 }
315 }
316 }
317 else
318 {
319 console.log("map-scripts::performProximitySearch(): No JSON information received");
320 }
321
322 _searchRunning = false;
323 }).fail(function(responseText, textStatus, errorThrown) // fail() has replaced error(), http://api.jquery.com/jquery.ajax/
324 {
325 console.log("In map-scripts.performProximitySearch(): Got an error in ajax call");
326 _searchRunning = false;
327 });
328}
329
330function coordToAbsDirected(coord, type)
331{
332 var value = "" + coord;
333 if(coord < 0)
334 {
335 value = value.substring(1);
336 if(type == "lat")
337 {
338 value += "S";
339 }
340 else
341 {
342 value += "W";
343 }
344 }
345 else
346 {
347 if(type == "lat")
348 {
349 value += "N";
350 }
351 else
352 {
353 value += "E";
354 }
355 }
356
357 return value;
358}
359
360function facetedMapSearch(facet_request_url) {
361 // ask for just the jsonNodes
362 facet_request_url += "excerptid=jsonNodes";
363
364 $.ajax(facet_request_url).done(function(responseText) {
365 var doc;
366 var nodeID;
367
368 //console.log("Sent off facetedMapSearch request to " + facet_request_url + ", got response: ");
369 //console.log(responseText);
370
371 if(responseText.search("id=\"jsonNodes") != -1) {
372 var startIndex = responseText.indexOf(">");
373 var endIndex = responseText.indexOf("</");
374 var jsonNodes = eval(responseText.substring(startIndex+1, endIndex));
375 //console.log(jsonNodes);
376
377 if(jsonNodes && jsonNodes.length > 0) {
378 //console.log("Faceted search got some nodes. Removing all markers first...");
379
380
381 mapEnabled = true;
382 showMap("initializeMapScripts");
383
384 // Remove all the markers/shapes from map
385 // and empty _docList.ids and the _docList of items
386 for(var j = 0; j < _docList.ids.length; j++) {
387 nodeID = _docList.ids[j];
388 doc = _docList.getDocByIndex(j);
389 removeMarkersFromMap(doc);
390 delete _docList[nodeID];
391 }
392 _docList.ids = [];
393
394 // repopulate _docList and _docList.ids and plot on map
395 for(var i = 0; i < jsonNodes.length; i++)
396 {
397 _docList[jsonNodes[i].nodeID] = jsonNodes[i];
398 _docList.ids.push(jsonNodes[i].nodeID);
399 var options = {
400 "mainDoc": true
401 };
402 createOverlayItems(jsonNodes[i], options);
403 }
404
405 // redo map bounds, which will also performProximitySearch
406 updateMap();
407 }
408 else
409 {
410 //hiding the map
411 mapEnabled = false;
412 hideMap("initializeMapScripts");
413 }
414 }
415 _docList.loopIndex = 0;
416
417 });
418
419}
420
421
422function toggleMapSection(options)
423{
424 var sectionID = options["nodeID"];
425
426 var titleClassifierEl = document.getElementById("title"+sectionID);
427 var jsonNodesStr = titleClassifierEl.getAttribute("data-gps-map-json");
428 //alert("@@@@ got jsonNodesStr |" + jsonNodesStr + "|");
429 var jsonNodes = JSON.parse(jsonNodesStr);
430
431 if(options["expand"]){
432 _gsDebug("expanding classifier - sectionID: " + sectionID);
433
434 if(jsonNodes && jsonNodes.length > 0)
435 {
436 for(var i = 0; i < jsonNodes.length; i++)
437 {
438 var doc = jsonNodes[i];
439 if(_docList[doc.nodeID]) continue; // already in list, don't add again
440
441 _docList[doc.nodeID] = doc;
442 _docList.ids.push(doc.nodeID);
443
444 var options = {
445 "mainDoc": true // TODO: should this be true or false???
446 };
447 createOverlayItems(doc, options);
448 }
449 }
450
451 } else { // closing the bookshelf
452 _gsDebug("closing classifier - sectionID: " + sectionID);
453 if(jsonNodes && jsonNodes.length > 0)
454 {
455 for(var i = 0; i < jsonNodes.length; i++)
456 {
457 // remove the doc from _docList and its id from _docList.ids
458 // and remove its markers/shapes from the map
459 var nodeID = jsonNodes[i].nodeID;
460 var doc = _docList[nodeID];
461 if(doc) {
462 removeMarkersFromMap(doc);
463
464 delete _docList[nodeID];
465
466 var filtered_ids_to_keep = [];
467 for(var j = 0; j < _docList.ids.length; j++) {
468 if(_docList.ids[j] !== nodeID) {
469 filtered_ids_to_keep.push(_docList.ids[j]);
470 }
471 }
472
473 _docList.ids = filtered_ids_to_keep;
474
475 } else {
476 console.log("**** In toggleMapSection: shouldn't happen - failed to find doc on closing node: " + nodeID);
477 }
478 }
479
480 }
481 }
482
483 _debugPrintDocList();
484
485 mapEnabled = (_docList.ids.length > 0);
486
487 if(mapEnabled) {
488 showMap("toggleMapSection");
489 } else {
490 hideMap("toggleMapSection");
491 }
492
493
494}
495
496/* Given a doc, removes all its shapes doc.shapes from the map _map */
497function removeMarkersFromMap(doc) {
498 for(var i = 0; i < doc.shapes.length; i++) {
499 var shape = doc.shapes[i];
500 shape.setMap(null);
501 }
502}
503
504// Refer to https://developers.google.com/maps/documentation/javascript/reference/map#Map.fitBounds
505// In order for fitBounds() to work out a non-zero bounds, have to use visibility, not display when hiding/showing the map.
506// AND should not set height to 0px when using visibility hidden. But not setting height to 0 means an invisible map takes up space.
507// In order for the resulting invisible map, that still takes up space, to not break the flow of the visible items
508// on the page, need to swap map between position relative when map visible versus position absolute when the map is hidden.
509function showMap(callingFunction) {
510
511 //$("#map_canvas").css({display:"block"});
512 //$("#map_canvas").css({visibility:"visible", height:"100%"}); // not working in conjunction with hidden 0px
513 //$("#map_canvas").css({visibility:"visible", height: "400px"}); // but this works in conjunction with hidden 0px
514 $("#map_canvas").css({visibility:"visible", position: "relative"});
515
516 if(!_DEBUGGING_) return;
517
518 //var message = "map_canvas display BLOCK";
519 var message = "map_canvas visibility VISIBLE, position relative";
520 if(typeof callingFunction !== 'undefined') {
521 message = "showMap() called from" + callingFunction + ":" + message;
522 }
523 console.log("### " + message);
524}
525
526function hideMap(callingFunction) {
527 //$("#map_canvas").css({display:"none"});
528 //$("#map_canvas").css({visibility:"hidden", height:"0px"});
529 $("#map_canvas").css({visibility:"hidden", position:"absolute"});
530
531 if(!_DEBUGGING_) return;
532
533 //var message = "map_canvas display NONE";
534 var message = "map_canvas visibility HIDDEN, position absolute";
535 if(typeof callingFunction !== 'undefined') {
536 message = "hideMap() called from" + callingFunction + ":" + message;
537 }
538 console.log("### " + message);
539}
540
541function updateMap()
542{
543 //console.log("@@@ updateMap()");
544 var markersOnMap = 0;
545 var bounds = new google.maps.LatLngBounds();
546
547 for(var i = 0; i < _docList.ids.length; i++)
548 {
549 var doc = _docList.getDocByIndex(i);
550 if(doc.parentCL && doc.parentCL.style.display == "none")
551 {
552 if(doc.shapes) {
553 for(var x = 0; x < doc.shapes.length; x++) {
554 doc.shapes[x].setVisible(false);
555 }
556 } else {
557 doc.marker.setVisible(false);
558 }
559 continue;
560 }
561 else
562 {
563 if(doc.shapes) {
564 for(var x = 0; x < doc.shapes.length; x++) {
565 doc.shapes[x].setVisible(true);
566 markersOnMap += ShapesUtil.numberOfCoordinatesInBounds(doc.shapes[x]);
567 }
568 } else {
569 doc.marker.setVisible(true);
570 markersOnMap++;
571 }
572
573 }
574
575 if(doc.shapes) {
576 var docSection_overlay_bounds = ShapesUtil.overlayBounds(doc.shapes);
577 // We now have the current document or document subsection's bounds.
578 // Use this to extend the overall bounds (the cumulative bounds for all nearby documents,
579 // or at least the cumulative bounds for this document with all its subsections).
580 bounds.extend(docSection_overlay_bounds.getNorthEast());
581 bounds.extend(docSection_overlay_bounds.getSouthWest());
582 }
583 else {
584 var doc_latlng = new google.maps.LatLng(doc.lat, doc.lng);
585 bounds.extend(doc_latlng);
586 }
587 }
588
589 _debugPrintBounds(bounds, "@@@ UpdateMap():");
590
591
592 if(markersOnMap > 1)
593 {
594 _debugPrintBounds(_map.getBounds(), "@@@ UpdateMap() : BEFORE fitbounds, map");
595
596 _map.fitBounds(bounds);
597
598 _debugPrintBounds(_map.getBounds(), "@@@ UpdateMap() : AFTER fitbounds, map");
599 } else if (markersOnMap == 1) {
600 //console.log("@@@ updating bounds with " + markersOnMap + " markers on the map");
601 //console.log(bounds);
602
603 // sometimes a single point bounds are too small for the map to display, so use center and zoom instead of fitbounds.
604 _map.setCenter(bounds.getCenter());
605 _map.setZoom(18); // arbitrary value that looked nice for my example
606 }
607}
608
609
610// TODO: FUNCTION DUPLICATED IN panoramaViewer.js
611function getLatLngForCoord(coord) {
612
613 // https://stackoverflow.com/questions/2559318/how-to-check-for-an-undefined-or-null-variable-in-javascript
614 if(!coord) {
615 // some_variable is either null, undefined, 0, NaN, false, or an empty string
616 console.log("@@@@ In map-scripts::getLatLngForCoord(): no or invalid coord info");
617 return null;
618 }
619
620 // coord is of the form: "37S77 157E53"
621 // lat will be 37S77, lng 157E53.
622 var indexOfSpace = coord.indexOf(" ");
623 if(indexOfSpace === -1) {
624 console.log("@@@@ In map-scripts::getLatLngForCoord(): bad format for coord " + coord);
625 return null;
626 }
627 var latitude = coord.substring(0, indexOfSpace);
628 var longitude = coord.substring(indexOfSpace+1);
629 return {lat: latitude, lng: longitude}; // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects
630}
631
632function loopThroughMarkers()
633{
634 if(_docList.ids.length == 0)
635 {
636 return;
637 }
638
639 var doc;
640 var visibleMarkers = new Array();
641 for(var i = 0; i < _docList.ids.length; i++)
642 {
643 //var doc = _docList.getDocByIndex(i);
644 // NOTE: in JavaScript, "local" vars have function scope, not mere block level scope. Wherever declared inside a function, they get hoisted to function top.
645 // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var
646 // But this feature is confusing, so have now declared var doc nearer to function top, at function level so outside current local block, and am assigning here:
647 doc = _docList.getDocByIndex(i);
648 if(typeof doc.shapes !== 'undefined') {
649 for(var x = 0; x < doc.shapes.length; x++) {
650 var shape = doc.shapes[x];
651 if(shape.type === google.maps.drawing.OverlayType.MARKER && shape.getVisible())
652 {
653 visibleMarkers.push(doc);
654 }
655 }
656 }
657 if(doc.marker && doc.marker.getVisible())
658 {
659 visibleMarkers.push(doc);
660 }
661 }
662
663 if(visibleMarkers.length < 2)
664 {
665 clearAllInfoBoxes();
666 return;
667 }
668
669 clearAllInfoBoxes();
670
671 var elem = null;
672 while(!elem) // TODO: why redefine elem? Why does this work, and only this, but not while(true) or while(doc.marker) or while(!AnythingFalse)???
673 // Some clever behaviour here, but no documentation on the cleverness. Hard to understand
674 {
675 if(_docList.loopIndex >= visibleMarkers.length)
676 {
677 _docList.loopIndex = 0;
678 }
679
680 //var doc = visibleMarkers[_docList.loopIndex]; // See NOTE above.
681 doc = visibleMarkers[_docList.loopIndex];
682 elem = gs.jqGet("div" + doc.nodeID); // This used to redefine elem by doing var elem = <....>
683 // This worked because "If you re-declare a JavaScript variable, it will not lose its value." See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var
684 if(elem.length)
685 {
686 elem.css("background", "#BBFFBB");
687 setTimeout(function(){elem.css("background", "");}, 2000);
688 }
689 _docList.loopIndex ++;
690 }
691
692 _gsDebug("@@@ loopThroughmarkers() - DOC:", doc);
693
694 if(doc.marker) {
695 doc.marker.markerInfo.open(_map, doc.marker); // TODO: how does doc have a value here? Where is the value set at this block level?
696 }
697
698 if(doc.shapes) {
699 for(var x = 0; x < doc.shapes.length; x++) {
700 var shape = doc.shapes[i];
701 if(typeof shape === 'undefined') { // happens just after map page has loaded when scrolling through markers. Why does this happen
702 console.log("shape at " + x + " not defined");
703 continue;
704 }
705 if(shape.type === google.maps.drawing.OverlayType.MARKER) {
706 shape.markerInfo.open(_map, shape);
707 } else {
708 shape.markerInfo.open(_map);
709 }
710 }
711 }
712}
713
714
715function focusDocument(id)
716{
717 var doc = _docList[id];
718 if(doc)
719 {
720 clearInterval(_intervalHandle);
721 _intervalHandle = null;
722
723 if(doc.shapes) {
724 var docShapesBounds = ShapesUtil.overlayBounds(doc.shapes);
725 _map.panToBounds(docShapesBounds); // https://developers.google.com/maps/documentation/javascript/reference/map#Map.panToBounds
726 } else {
727 _map.panTo(new google.maps.LatLng(doc.lat, doc.lng));
728 }
729
730 clearAllInfoBoxes();
731 if(doc.shapes) { // TODO
732 //console.log("Opening infowindow for doc " + doc.nodeID);
733 for(var x = 0; x < doc.shapes.length; x++) {
734 if(doc.shapes[x].markerInfo) {
735 doc.shapes[x].markerInfo.open(_map); // label
736 }
737 else {
738 console.log("No infowindow for doc " + doc.nodeID + "'s shape " + doc.shapes[x].type);
739 }
740 }
741 //openInfoBoxes(doc);
742 } else { // only Lat and Lng meta, so we have just one marker per doc, which will have the doc title not label
743 doc.marker.markerInfo.open(_map, doc.marker); // doc title
744 }
745 var scrollCheckbox = $("#scrollCheckbox");
746 if(scrollCheckbox.checked)
747 {
748 scrollCheckbox.checked = false;
749 }
750 }
751}
752
753function clearAllInfoBoxes()
754{
755 for(var i = 0; i < _docList.ids.length; i++)
756 {
757 var doc = _docList.getDocByIndex(i);
758
759 if(doc.shapes) {
760 for(var x = 0; x < doc.shapes.length; x++) {
761 if(doc.shapes[x].markerInfo) {
762 //console.log("Closing infowindow for doc " + _docList.ids[i]);
763 doc.shapes[x].markerInfo.close();
764 }
765 }
766 }
767 else { // only Lat and Lng meta, so we have just one marker per doc
768 doc.marker.markerInfo.close();
769 }
770 }
771}
772
773function createOverlayItems(doc, options) {
774 var loopCounter = 0;
775 if(doc.mapoverlay || doc.descendantsMapoverlays) {
776 if(doc.mapoverlay) {
777 // append any descendant section's mapoverlays onto doc.mapoverlay
778 if(doc.descendantsMapoverlays) {
779 for(loopCounter = 0; loopCounter < doc.descendantsMapoverlays.length; loopCounter++) {
780 //console.log("Pushing next descendant mapoverlay onto doc.mapoverlay: ", doc.descendantsMapoverlays[loopCounter]);
781 Array.prototype.push.apply(doc.mapoverlay, doc.descendantsMapoverlays[loopCounter]);
782 }
783 delete doc.descendantsMapoverlays; // served its purpose
784 }
785 } else if (doc.descendantsMapoverlays) { // no doc.mapoverlay
786 // construct doc.mapoverlay to contain each descendant section's mapoverlay
787 doc.mapoverlay = [];
788 for(loopCounter = 0; loopCounter < doc.descendantsMapoverlays.length; loopCounter++) {
789 //console.log("Pushing next descendant mapoverlay onto originally empty doc.mapoverlay: ", doc.descendantsMapoverlays[loopCounter]);
790 Array.prototype.push.apply(doc.mapoverlay, doc.descendantsMapoverlays[loopCounter]);
791 }
792 delete doc.descendantsMapoverlays; // no more use for this
793 }
794 //console.log("@@@@ Have shapes: ", doc.mapoverlay);
795 createShapes(doc, options);
796 } else { // backwards compatible to deal with Lat and Lng meta stored for doc
797 pos = new google.maps.LatLng(doc.lat,doc.lng);
798 createMarker(doc, pos, options);
799 }
800}
801
802function addInfoMarker(doc, shape) {
803
804 if(!shape.description) {
805 _gsInfo("#### " + shape.type.toString() + " had no description/label");
806 return;
807 }
808
809 // else add an InfoWindow for this shape using the label (shape.description)
810
811 // https://developers.google.com/maps/documentation/javascript/infowindows
812 // An InfoWindow's "position contains the LatLng at which this info window is anchored.
813 // Note: An InfoWindow may be attached either to a Marker object (in which case its position is based on the marker's location)
814 // or on the map itself at a specified LatLng. Opening an info window on a marker will automatically update the position."
815 var infoWindow = new google.maps.InfoWindow({content:shape.description}); // NOTE: if not setting content or position properties
816 // inside this constructor, need to call setContent/setPosition to set them
817
818 if(shape.type === google.maps.drawing.OverlayType.MARKER) {
819 var marker = shape;
820 _gsDebug("Coord for marker is " + marker.getPosition().toString());
821
822 marker.addListener('mouseover', function() {
823 infoWindow.open(_map, marker);
824 });
825 marker.addListener('mouseout', function() {
826 infoWindow.close();
827 });
828 attachClickHandler(marker, doc.nodeID); // do what the original code used to do here
829 }
830 else {
831 var coord = ShapesUtil.getLabelCoordinate(shape);
832 _gsDebug("Coord for " + shape.type.toString() + " is " + coord.toString());
833 infoWindow.setPosition(coord);
834 shape.addListener('mouseover', function() {
835 infoWindow.open(_map);
836 });
837 shape.addListener('mouseout', function() {
838 infoWindow.close();
839 });
840 attachClickHandler(shape, doc.nodeID); // as above
841 }
842 shape.markerInfo = infoWindow;
843 //console.log("######## Added markerInfo object to shape");
844}
845
846// This function will create Google Shapes/Overlays and markers out of a given doc JSONNode's doc.mapOverlay
847// (doc.mapOverlay shapes are stored as an array of JSON) and store the shapes/overlays in the doc.shapes array.
848function createShapes(doc, options)
849{
850 var isMainDoc = options["mainDoc"];
851
852 // for doc.shapes: don't store JSON anymore, convert them to google Shapes overlays and store them instead
853 doc.shapes = [];
854
855 for (var i=0; i<doc.mapoverlay.length; i++) {
856 //console.log("in: mapoverlay["+i+"] =" + JSON.stringify(doc.mapoverlay[i]));
857 var shape = ShapesUtil.JSONToShape(doc.mapoverlay[i]);
858 //console.log("out: shape = " + JSON.stringify(shape));
859
860 doc.shapes[i] = shape;
861 shape.setMap(_map);
862 //shape["title"] = doc.title; // TODO: Think on it some more.
863
864 // Unset editable and draggable properties of shape
865 // And for markers, which are initialised to clickable besides, undo the clickability
866 // and set them
867 if(shape.type === google.maps.drawing.OverlayType.MARKER) {
868 var marker = shape;
869 // markers of the main document should be red, else they'll be blue
870 if(!isMainDoc) {
871 marker["icon"] = "interfaces/" + gs.xsltParams.interface_name + "/images/bluemarker.png";
872 }
873 marker.clickable = false; // only markers
874 /*
875 console.log("@@@ map-scripts::addInfoMarker - marker.position");
876 console.log("Lat is " + typeof(marker.position.lat()));
877 console.log(marker.position.lat());
878 console.log("Long is " + typeof(marker.position.lng()));
879 console.log(marker.position.lng());
880 */
881 } else {
882 //console.log("Creating non-marker shape.");
883
884 if(!isMainDoc) {
885 ShapesUtil.setOpacity(shape, LOW_OPACITY);
886 } // else the shape will be drawn at its configured opacity
887 }
888
889 shape.editable = false;
890 shape.draggable = false;
891
892
893 // doc[i]'s label = doc.shapes[i].description
894 addInfoMarker(doc, shape);
895 }
896
897 var docElement = gs.jqGet("div" + doc.nodeID);
898 var parent;
899 if(docElement)
900 {
901 parent = docElement.parentNode;
902 }
903
904 while(parent && parent.nodeName != "BODY")
905 {
906 if($(parent).attr("id") && $(parent).attr("id").search("divCL") != -1)
907 {
908 doc.parentCL = parent;
909 break;
910 }
911
912 parent = parent.parentNode;
913 }
914}
915
916// This method is only for backwards compatibility: for those collections with docs that only have Lat and Lng meta
917// and no GPS.mapOverlay (and hence Coordinate) meta.
918function createMarker(doc, pos, options)
919{
920 var isMainMarker = options["mainDoc"];
921
922 var marker;
923 if(isMainMarker)
924 {
925 marker = new google.maps.Marker
926 ({
927 position: pos,
928 title:doc.title,
929 map:_map
930 });
931 }
932 else
933 {
934 marker = new google.maps.Marker
935 ({
936 position: pos,
937 title:doc.title,
938 map:_map,
939 icon:"interfaces/" + gs.xsltParams.interface_name + "/images/bluemarker.png"
940 });
941 }
942
943 var docElement = gs.jqGet("div" + doc.nodeID);
944 var parent;
945 if(docElement)
946 {
947 parent = docElement.parentNode;
948 }
949
950 while(parent && parent.nodeName != "BODY")
951 {
952 if($(parent).attr("id") && $(parent).attr("id").search("divCL") != -1)
953 {
954 doc.parentCL = parent;
955 break;
956 }
957
958 parent = parent.parentNode;
959 }
960
961 var info = new google.maps.InfoWindow({content:doc.title});
962 marker.markerInfo = info;
963 doc.marker = marker;
964 attachClickHandler(marker, doc.nodeID);
965}
966
967// TODO: with the following, it seems that clicking on shape expands the entire document
968// Should it be that clicking on a shape should expand the doc section that contains that shape meta?
969function attachClickHandler(shapeOrMarker, nodeID)
970{
971 google.maps.event.addListener(shapeOrMarker, 'click', function()
972 {
973 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";
974 });
975}
976
977function NewLatLng(lat, lng)
978{
979 console.log("Latitude " + lat);
980 console.log("Longitude " + lng);
981}
982
983function httpMapBrowseRequest(sectionID)
984{
985 // Make ajax call to retrieve jsonNodes for section ID, and draw shapes on the map.
986 var url = gs.xsltParams.library_name + "?a=b&rt=s&s=ClassifierBrowse&c=" + gs.cgiParams.c + "&cl=" + sectionID + "&excerptid=jsonNodes";
987 $.ajax(url)
988 .done(function(responseText)
989 {
990 var startIndex = responseText.indexOf(">");
991 var endIndex = responseText.indexOf("</");
992
993 var jsonNodesStr = responseText.substring(startIndex+1, endIndex);
994 var jsonNodes = eval(jsonNodesStr); //responseText.substring(startIndex+1, endIndex));
995 if(jsonNodes && jsonNodes.length > 0)
996 {
997
998 mapEnabled = true;
999 showMap("httpMapBrowseRequest");
1000
1001 for(var i = 0; i < jsonNodes.length; i++)
1002 {
1003 var doc = jsonNodes[i];
1004 _docList[doc.nodeID] = doc;
1005 _docList.ids.push(doc.nodeID);
1006
1007 var options = {
1008 "mainDoc": true // TODO: should this be true or false???
1009 };
1010 createOverlayItems(doc, options);
1011 }
1012
1013 ///var tmp = $("#title"+sectionID);
1014 ///console.log(tmp); // WRONG
1015 ///var tmp2 = document.getElementById("title"+sectionID);
1016 ///console.log(tmp2); // RIGHT, WHY?
1017
1018 // create data-* attribute to store this sectionID's JSON on the section's div
1019 //$("#title"+sectionID).attr("data-gps-map-json", "hello world"); // TODO: Doesn't work. Why?
1020 var titleClassifierEl = document.getElementById("title"+sectionID);
1021 titleClassifierEl.setAttribute("data-gps-map-json", jsonNodesStr);
1022 }
1023
1024 updateMap();
1025 //console.log("getSub Classifier -> updateMap()");
1026 })
1027 .fail(function()
1028 {
1029 //console.log("Error getting subclassifiers");
1030 return;
1031 });
1032}
1033
1034function performDistanceSearchWithCoordinates(id, coord, degrees)
1035{
1036 var coordInfo = getLatLngForCoord(coord);
1037 if(!coordInfo) {
1038 console.log("@@@ ERROR in map-scripts::performDistanceSearchWithCoordinates: coordInfo is null");
1039 }
1040 performDistanceSearch(id, coordInfo.lat, coordInfo.lng, degrees);
1041}
1042
1043function performDistanceSearch(id, lat, lng, degrees)
1044{
1045 if(parseFloat(lat) > 180 || parseFloat(lat) < -180 || parseFloat(lng) > 180 || parseFloat(lat) < -180)
1046 {
1047 console.log("Latitude or longitude incorrectly formatted");
1048 return;
1049 }
1050
1051 if(lat.indexOf(".") == -1 || lng.indexOf(".") == -1 || (lat.indexOf(".") + 3) >= lat.length || (lng.indexOf(".") + 3) >= lng.length)
1052 {
1053 console.log("Latitude or longitude does not have the required precision for a distance search");
1054 return;
1055 }
1056
1057 var query = "";
1058 for(var i = 0; i < degrees * 2; i++)
1059 {
1060 for (var j = 0; j < degrees * 2; j++)
1061 {
1062 var latDelta = (i - degrees) * 0.01;
1063 var lngDelta = (j - degrees) * 0.01;
1064
1065 //query += "(" + getDistanceQueryStringOldApproach(lat, latDelta, 2, "LA", ["N","S"]);
1066 //query += "+AND+";
1067 //query += getDistanceQueryStringOldApproach(lng, lngDelta, 2, "LN", ["E","W"]) + ")";
1068
1069 query += "(" + getDistanceQueryStringTerm(lat, lng, latDelta, lngDelta, 2, "CS") + ")";
1070
1071 if(i != ((degrees * 2) - 1) || j != ((degrees * 2) - 1)){ query += " OR "; }
1072 }
1073 }
1074
1075 var inlineTemplate = '\
1076 <xsl:template match="/" priority="5">\
1077 <table id="nearbyDocs">\
1078 <tr>\
1079 <th><a href="javascript:sortByDistance();">Distance</a></th><th><a href="javascript:sortAlphabetically();">Document</a></th>\
1080 </tr>\
1081 <xsl:apply-templates select="//documentNode"/>\
1082 </table>\
1083 </xsl:template>\
1084 \
1085 <xsl:template match="documentNode" priority="5">\
1086 <xsl:if test="@nodeID !=\''+id+'\'">\
1087 <tr>\
1088 <td>___<gsf:metadata name="Latitude"/>______<gsf:metadata name="Longitude"/>___</td>\
1089 <td><gsf:link title="'+gs.text.doc.nearby_doc_tooltip+'" type="document"><gsf:metadata name="Title"/></gsf:link></td>\
1090 </tr>\
1091 </xsl:if>\
1092 </xsl:template>';
1093
1094 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");
1095 $.ajax(url)
1096 .done(function(response)
1097 {
1098 response = response.replace(/<img src="[^"]*map_marker.png"[^>]*>/g, "");
1099
1100 var nearbyDocsArray = new Array();
1101
1102 var lats = new Array();
1103 var lngs = new Array();
1104 var matches = response.match(/___(-?[0-9\.]*)___/g);
1105 for(var i = 0; i < matches.length; i += 2)
1106 {
1107 var matchLatFloat = parseFloat(matches[i].replace("___", ""));
1108 var matchLngFloat = parseFloat(matches[i+1].replace("___", ""));
1109
1110 lats.push(matchLatFloat);
1111 lngs.push(matchLngFloat);
1112 var distance = Math.sqrt(Math.pow(matchLatFloat - parseFloat(lat), 2) + Math.pow(matchLngFloat - parseFloat(lng), 2)) * (40000.0/360.0);
1113 var distanceString = "" + distance;
1114 distanceString = distanceString.substring(0, 6);
1115 response = response.replace(matches[i] + matches[i+1], distanceString);
1116 }
1117
1118 var index = 0;
1119 var i = 0;
1120 while(true)
1121 {
1122 var distanceStart = response.indexOf("<td>", index);
1123 if(distanceStart == -1)
1124 {
1125 break;
1126 }
1127 var distanceEnd = response.indexOf("</td>", distanceStart);
1128
1129 var docLinkStart = response.indexOf("<td>", distanceEnd);
1130 var docLinkEnd = response.indexOf("</td>", docLinkStart);
1131
1132 var dist = response.substring(distanceStart + 4, distanceEnd);
1133 var docLink = response.substring(docLinkStart + 4, docLinkEnd);
1134
1135 _nearbyDocsByDistance.push({title:docLink, distance:dist, lat:lats[i], lng:lngs[i++]});
1136
1137 index = docLinkEnd;
1138 }
1139
1140 sortByDistance(lat,lng);
1141
1142 var toggle = $("#nearbyDocumentsToggle");
1143 toggle.attr("src", gs.imageURLs.collapse);
1144 gs.functions.makeToggle(toggle, $("#nearbyDocuments"));
1145 });
1146}
1147
1148var map_centering_timeout = null;
1149function recenterMapF(lat, lng)
1150{
1151 return function() {
1152 _map.setCenter(new google.maps.LatLng(lat, lng));
1153 }
1154}
1155function recenterMap(lat, lng)
1156{
1157
1158 _map.setCenter(new google.maps.LatLng(lat, lng));
1159
1160}
1161function sortByDistance(base_lat,base_lng)
1162{
1163 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>';
1164 _nearbyDocsByDistance.sort(function(a, b){return (a.distance - b.distance);});
1165 for(var i = 0; i < _nearbyDocsByDistance.length; i++)
1166 {
1167
1168 sortedTable += "<tr><td>" + prettifyDistance(_nearbyDocsByDistance[i].distance) + '</td><td onmouseover="clearTimeout(map_centering_timeout); map_centering_timeout = setTimeout(recenterMapF(' + _nearbyDocsByDistance[i].lat + ',' + _nearbyDocsByDistance[i].lng + '), 900)" >' + _nearbyDocsByDistance[i].title + "</td></tr>";
1169 }
1170 sortedTable += "</table>";
1171
1172 $("#nearbyDocuments").html(sortedTable);
1173}
1174function prettifyDistance(distance) {
1175
1176 var new_distance;
1177 if (distance < 1) {
1178 new_distance = (distance * 1000);
1179 // Round to nearest whole number - don't need to show points of metres..
1180 new_distance = Math.round(new_distance);
1181 new_distance += " m";
1182 }
1183 else {
1184 new_distance = distance +" km";
1185
1186 }
1187 return new_distance;
1188}
1189
1190
1191
1192function sortAlphabetically(base_lat, base_lng)
1193{
1194 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>';
1195 _nearbyDocsByDistance.sort(function(a, b)
1196 {
1197 var firstTitleStartIndex = a.title.indexOf(">");
1198 var firstTitleEndIndex = a.title.indexOf("<", firstTitleStartIndex);
1199 var firstTitle = a.title.substring(firstTitleStartIndex + 1, firstTitleEndIndex);
1200 var secondTitleStartIndex = b.title.indexOf(">");
1201 var secondTitleEndIndex = b.title.indexOf("<", secondTitleStartIndex);
1202 var secondTitle = b.title.substring(secondTitleStartIndex + 1, secondTitleEndIndex);
1203 return ((firstTitle.toLowerCase() == secondTitle.toLowerCase()) ? 0 : ((firstTitle.toLowerCase() > secondTitle.toLowerCase()) ? 1 : -1));
1204 });
1205 for(var i = 0; i < _nearbyDocsByDistance.length; i++)
1206 {
1207 sortedTable += "<tr><td>" + _nearbyDocsByDistance[i].distance + '</td><td onmouseover="clearTimeout(map_centering_timeout); map_centering_timeout = setTimeout(recenterMapF(' + _nearbyDocsByDistance[i].lat + ',' + _nearbyDocsByDistance[i].lng + '), 900)">' + _nearbyDocsByDistance[i].title + "</td></tr>";
1208 }
1209 sortedTable += "</table>";
1210
1211 $("#nearbyDocuments").html(sortedTable);
1212}
1213
1214function getDistanceQueryStringOldApproach(currentCoord, delta, precision, indexName, directions)
1215{
1216 console.error("**** Old Approach called!!!");
1217
1218 var query = "";
1219 var coordFloat = parseFloat(currentCoord);
1220
1221 var newCoord = "" + (coordFloat + delta);
1222 var beforeDec = newCoord.substring(0, newCoord.indexOf("."));
1223
1224 var direction = directions[0];
1225 if(coordFloat < 0)
1226 {
1227 // negative value
1228 direction = directions[1];
1229 beforeDec = beforeDec.substring(1); // skip over '-' at front
1230 }
1231 beforeDec += direction;
1232
1233 var afterDec = newCoord.substring(newCoord.indexOf(".") + 1, newCoord.indexOf(".") + (precision) + 1);
1234
1235 return indexName + ":" + beforeDec + "+AND+" + indexName + ":" + afterDec;
1236}
1237
1238function coordValToIndexToken(coordValStr, delta, precision, directions)
1239{
1240 var coordValFloat = parseFloat(coordValStr);
1241
1242 var deltaCoordValStr = "" + (coordValFloat + delta);
1243 var beforeDec = deltaCoordValStr.substring(0, deltaCoordValStr.indexOf("."));
1244
1245 var direction = directions[0];
1246 if(coordValFloat < 0)
1247 {
1248 // negative value
1249 direction = directions[1];
1250 beforeDec = beforeDec.substring(1); // skip over '-' at front
1251 }
1252
1253 var beforeDecWithDirection = beforeDec + direction;
1254
1255 var afterDecPrecision = deltaCoordValStr.substring(deltaCoordValStr.indexOf(".") + 1, deltaCoordValStr.indexOf(".") + (precision) + 1);
1256
1257 var indexToken = beforeDecWithDirection + afterDecPrecision;
1258
1259 return indexToken;
1260}
1261
1262function getDistanceQueryStringTerm(currentLat,currentLng, deltaLat, deltaLng, precision, indexName)
1263{
1264 var latToken = coordValToIndexToken(currentLat,deltaLat,precision,["N","S"]);
1265 var lngToken = coordValToIndexToken(currentLng,deltaLng,precision,["E","W"]);
1266
1267 var queryStringTerm = indexName + ":\"" + latToken + " " + lngToken + "\"";
1268
1269 return queryStringTerm;
1270}
1271
1272function _gsInfo(message, optObject) {
1273 console.log(message);
1274 if(typeof optObject !== 'undefined') {
1275 console.log(optObject);
1276 }
1277}
1278
1279function _gsDebug(message, optObject) {
1280 if(_DEBUGGING_) {
1281 _gsInfo(message, optObject);
1282 }
1283}
1284
1285
1286function _debugPrintDocList() {
1287 if(!_DEBUGGING_) return;
1288
1289 console.log("@@@@ printing docList:");
1290 for(var i = 0; i < _docList.ids.length; i++)
1291 {
1292 var doc = _docList.getDocByIndex(i);
1293 console.log(" At index = " + i + " ids[i]: " + _docList.ids[i]);
1294 console.log(" At index = " + i + " ids[i]: " + _docList.ids[i] + ", doc: " + doc.nodeID);
1295 }
1296}
1297
1298function _debugPrintBounds(bounds, message) {
1299 if(!_DEBUGGING_) return;
1300 if(typeof bounds === 'undefined') {
1301 console.log("Bounds undefined");
1302 return;
1303 }
1304 var ne = bounds.getNorthEast();
1305 var sw = bounds.getSouthWest();
1306 console.log(message + " bounds: ne = " + ne + ", sw = " + sw);
1307}
Note: See TracBrowser for help on using the repository browser.