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

Last change on this file was 38766, checked in by kjdon, 2 months ago

doc.shapes might not be defined

  • Property svn:executable set to *
File size: 41.4 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 if (doc.shapes) {
499 for(var i = 0; i < doc.shapes.length; i++) {
500 var shape = doc.shapes[i];
501 shape.setMap(null);
502 }
503 }
504}
505
506// Refer to https://developers.google.com/maps/documentation/javascript/reference/map#Map.fitBounds
507// In order for fitBounds() to work out a non-zero bounds, have to use visibility, not display when hiding/showing the map.
508// AND should not set height to 0px when using visibility hidden. But not setting height to 0 means an invisible map takes up space.
509// In order for the resulting invisible map, that still takes up space, to not break the flow of the visible items
510// on the page, need to swap map between position relative when map visible versus position absolute when the map is hidden.
511function showMap(callingFunction) {
512
513 //$("#map_canvas").css({display:"block"});
514 //$("#map_canvas").css({visibility:"visible", height:"100%"}); // not working in conjunction with hidden 0px
515 //$("#map_canvas").css({visibility:"visible", height: "400px"}); // but this works in conjunction with hidden 0px
516 $("#map_canvas").css({visibility:"visible", position: "relative"});
517
518 if(!_DEBUGGING_) return;
519
520 //var message = "map_canvas display BLOCK";
521 var message = "map_canvas visibility VISIBLE, position relative";
522 if(typeof callingFunction !== 'undefined') {
523 message = "showMap() called from" + callingFunction + ":" + message;
524 }
525 console.log("### " + message);
526}
527
528function hideMap(callingFunction) {
529 //$("#map_canvas").css({display:"none"});
530 //$("#map_canvas").css({visibility:"hidden", height:"0px"});
531 $("#map_canvas").css({visibility:"hidden", position:"absolute"});
532
533 if(!_DEBUGGING_) return;
534
535 //var message = "map_canvas display NONE";
536 var message = "map_canvas visibility HIDDEN, position absolute";
537 if(typeof callingFunction !== 'undefined') {
538 message = "hideMap() called from" + callingFunction + ":" + message;
539 }
540 console.log("### " + message);
541}
542
543function updateMap()
544{
545 //console.log("@@@ updateMap()");
546 var markersOnMap = 0;
547 var bounds = new google.maps.LatLngBounds();
548
549 for(var i = 0; i < _docList.ids.length; i++)
550 {
551 var doc = _docList.getDocByIndex(i);
552 if(doc.parentCL && doc.parentCL.style.display == "none")
553 {
554 if(doc.shapes) {
555 for(var x = 0; x < doc.shapes.length; x++) {
556 doc.shapes[x].setVisible(false);
557 }
558 } else {
559 doc.marker.setVisible(false);
560 }
561 continue;
562 }
563 else
564 {
565 if(doc.shapes) {
566 for(var x = 0; x < doc.shapes.length; x++) {
567 doc.shapes[x].setVisible(true);
568 markersOnMap += ShapesUtil.numberOfCoordinatesInBounds(doc.shapes[x]);
569 }
570 } else {
571 doc.marker.setVisible(true);
572 markersOnMap++;
573 }
574
575 }
576
577 if(doc.shapes) {
578 var docSection_overlay_bounds = ShapesUtil.overlayBounds(doc.shapes);
579 // We now have the current document or document subsection's bounds.
580 // Use this to extend the overall bounds (the cumulative bounds for all nearby documents,
581 // or at least the cumulative bounds for this document with all its subsections).
582 bounds.extend(docSection_overlay_bounds.getNorthEast());
583 bounds.extend(docSection_overlay_bounds.getSouthWest());
584 }
585 else {
586 var doc_latlng = new google.maps.LatLng(doc.lat, doc.lng);
587 bounds.extend(doc_latlng);
588 }
589 }
590
591 _debugPrintBounds(bounds, "@@@ UpdateMap():");
592
593
594 if(markersOnMap > 1)
595 {
596 _debugPrintBounds(_map.getBounds(), "@@@ UpdateMap() : BEFORE fitbounds, map");
597
598 _map.fitBounds(bounds);
599
600 _debugPrintBounds(_map.getBounds(), "@@@ UpdateMap() : AFTER fitbounds, map");
601 } else if (markersOnMap == 1) {
602 //console.log("@@@ updating bounds with " + markersOnMap + " markers on the map");
603 //console.log(bounds);
604
605 // sometimes a single point bounds are too small for the map to display, so use center and zoom instead of fitbounds.
606 _map.setCenter(bounds.getCenter());
607 _map.setZoom(18); // arbitrary value that looked nice for my example
608 }
609}
610
611
612// TODO: FUNCTION DUPLICATED IN panoramaViewer.js
613function getLatLngForCoord(coord) {
614
615 // https://stackoverflow.com/questions/2559318/how-to-check-for-an-undefined-or-null-variable-in-javascript
616 if(!coord) {
617 // some_variable is either null, undefined, 0, NaN, false, or an empty string
618 console.log("@@@@ In map-scripts::getLatLngForCoord(): no or invalid coord info");
619 return null;
620 }
621
622 // coord is of the form: "37S77 157E53"
623 // lat will be 37S77, lng 157E53.
624 var indexOfSpace = coord.indexOf(" ");
625 if(indexOfSpace === -1) {
626 console.log("@@@@ In map-scripts::getLatLngForCoord(): bad format for coord " + coord);
627 return null;
628 }
629 var latitude = coord.substring(0, indexOfSpace);
630 var longitude = coord.substring(indexOfSpace+1);
631 return {lat: latitude, lng: longitude}; // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects
632}
633
634function loopThroughMarkers()
635{
636 if(_docList.ids.length == 0)
637 {
638 return;
639 }
640
641 var doc;
642 var visibleMarkers = new Array();
643 for(var i = 0; i < _docList.ids.length; i++)
644 {
645 //var doc = _docList.getDocByIndex(i);
646 // NOTE: in JavaScript, "local" vars have function scope, not mere block level scope. Wherever declared inside a function, they get hoisted to function top.
647 // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var
648 // 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:
649 doc = _docList.getDocByIndex(i);
650 if(typeof doc.shapes !== 'undefined') {
651 for(var x = 0; x < doc.shapes.length; x++) {
652 var shape = doc.shapes[x];
653 if(shape.type === google.maps.drawing.OverlayType.MARKER && shape.getVisible())
654 {
655 visibleMarkers.push(doc);
656 }
657 }
658 }
659 if(doc.marker && doc.marker.getVisible())
660 {
661 visibleMarkers.push(doc);
662 }
663 }
664
665 if(visibleMarkers.length < 2)
666 {
667 clearAllInfoBoxes();
668 return;
669 }
670
671 clearAllInfoBoxes();
672
673 var elem = null;
674 while(!elem) // TODO: why redefine elem? Why does this work, and only this, but not while(true) or while(doc.marker) or while(!AnythingFalse)???
675 // Some clever behaviour here, but no documentation on the cleverness. Hard to understand
676 {
677 if(_docList.loopIndex >= visibleMarkers.length)
678 {
679 _docList.loopIndex = 0;
680 }
681
682 //var doc = visibleMarkers[_docList.loopIndex]; // See NOTE above.
683 doc = visibleMarkers[_docList.loopIndex];
684 elem = gs.jqGet("div" + doc.nodeID); // This used to redefine elem by doing var elem = <....>
685 // 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
686 if(elem.length)
687 {
688 elem.css("background", "#BBFFBB");
689 setTimeout(function(){elem.css("background", "");}, 2000);
690 }
691 _docList.loopIndex ++;
692 }
693
694 _gsDebug("@@@ loopThroughmarkers() - DOC:", doc);
695
696 if(doc.marker) {
697 doc.marker.markerInfo.open(_map, doc.marker); // TODO: how does doc have a value here? Where is the value set at this block level?
698 }
699
700 if(doc.shapes) {
701 for(var x = 0; x < doc.shapes.length; x++) {
702 var shape = doc.shapes[i];
703 if(typeof shape === 'undefined') { // happens just after map page has loaded when scrolling through markers. Why does this happen
704 console.log("shape at " + x + " not defined");
705 continue;
706 }
707 if(shape.type === google.maps.drawing.OverlayType.MARKER) {
708 shape.markerInfo.open(_map, shape);
709 } else {
710 shape.markerInfo.open(_map);
711 }
712 }
713 }
714}
715
716
717function focusDocument(id)
718{
719 var doc = _docList[id];
720 if(doc)
721 {
722 clearInterval(_intervalHandle);
723 _intervalHandle = null;
724
725 if(doc.shapes) {
726 var docShapesBounds = ShapesUtil.overlayBounds(doc.shapes);
727 _map.panToBounds(docShapesBounds); // https://developers.google.com/maps/documentation/javascript/reference/map#Map.panToBounds
728 } else {
729 _map.panTo(new google.maps.LatLng(doc.lat, doc.lng));
730 }
731
732 clearAllInfoBoxes();
733 if(doc.shapes) { // TODO
734 //console.log("Opening infowindow for doc " + doc.nodeID);
735 for(var x = 0; x < doc.shapes.length; x++) {
736 if(doc.shapes[x].markerInfo) {
737 doc.shapes[x].markerInfo.open(_map); // label
738 }
739 else {
740 console.log("No infowindow for doc " + doc.nodeID + "'s shape " + doc.shapes[x].type);
741 }
742 }
743 //openInfoBoxes(doc);
744 } else { // only Lat and Lng meta, so we have just one marker per doc, which will have the doc title not label
745 doc.marker.markerInfo.open(_map, doc.marker); // doc title
746 }
747 var scrollCheckbox = $("#scrollCheckbox");
748 if(scrollCheckbox.checked)
749 {
750 scrollCheckbox.checked = false;
751 }
752 }
753}
754
755function clearAllInfoBoxes()
756{
757 for(var i = 0; i < _docList.ids.length; i++)
758 {
759 var doc = _docList.getDocByIndex(i);
760
761 if(doc.shapes) {
762 for(var x = 0; x < doc.shapes.length; x++) {
763 if(doc.shapes[x].markerInfo) {
764 //console.log("Closing infowindow for doc " + _docList.ids[i]);
765 doc.shapes[x].markerInfo.close();
766 }
767 }
768 }
769 else { // only Lat and Lng meta, so we have just one marker per doc
770 doc.marker.markerInfo.close();
771 }
772 }
773}
774
775function createOverlayItems(doc, options) {
776 var loopCounter = 0;
777 if(doc.mapoverlay || doc.descendantsMapoverlays) {
778 if(doc.mapoverlay) {
779 // append any descendant section's mapoverlays onto doc.mapoverlay
780 if(doc.descendantsMapoverlays) {
781 for(loopCounter = 0; loopCounter < doc.descendantsMapoverlays.length; loopCounter++) {
782 //console.log("Pushing next descendant mapoverlay onto doc.mapoverlay: ", doc.descendantsMapoverlays[loopCounter]);
783 Array.prototype.push.apply(doc.mapoverlay, doc.descendantsMapoverlays[loopCounter]);
784 }
785 delete doc.descendantsMapoverlays; // served its purpose
786 }
787 } else if (doc.descendantsMapoverlays) { // no doc.mapoverlay
788 // construct doc.mapoverlay to contain each descendant section's mapoverlay
789 doc.mapoverlay = [];
790 for(loopCounter = 0; loopCounter < doc.descendantsMapoverlays.length; loopCounter++) {
791 //console.log("Pushing next descendant mapoverlay onto originally empty doc.mapoverlay: ", doc.descendantsMapoverlays[loopCounter]);
792 Array.prototype.push.apply(doc.mapoverlay, doc.descendantsMapoverlays[loopCounter]);
793 }
794 delete doc.descendantsMapoverlays; // no more use for this
795 }
796 //console.log("@@@@ Have shapes: ", doc.mapoverlay);
797 createShapes(doc, options);
798 } else { // backwards compatible to deal with Lat and Lng meta stored for doc
799 pos = new google.maps.LatLng(doc.lat,doc.lng);
800 createMarker(doc, pos, options);
801 }
802}
803
804function addInfoMarker(doc, shape) {
805
806 if(!shape.description) {
807 _gsInfo("#### " + shape.type.toString() + " had no description/label");
808 return;
809 }
810
811 // else add an InfoWindow for this shape using the label (shape.description)
812
813 // https://developers.google.com/maps/documentation/javascript/infowindows
814 // An InfoWindow's "position contains the LatLng at which this info window is anchored.
815 // Note: An InfoWindow may be attached either to a Marker object (in which case its position is based on the marker's location)
816 // or on the map itself at a specified LatLng. Opening an info window on a marker will automatically update the position."
817 var infoWindow = new google.maps.InfoWindow({content:shape.description}); // NOTE: if not setting content or position properties
818 // inside this constructor, need to call setContent/setPosition to set them
819
820 if(shape.type === google.maps.drawing.OverlayType.MARKER) {
821 var marker = shape;
822 _gsDebug("Coord for marker is " + marker.getPosition().toString());
823
824 marker.addListener('mouseover', function() {
825 infoWindow.open(_map, marker);
826 });
827 marker.addListener('mouseout', function() {
828 infoWindow.close();
829 });
830 attachClickHandler(marker, doc.nodeID); // do what the original code used to do here
831 }
832 else {
833 var coord = ShapesUtil.getLabelCoordinate(shape);
834 _gsDebug("Coord for " + shape.type.toString() + " is " + coord.toString());
835 infoWindow.setPosition(coord);
836 shape.addListener('mouseover', function() {
837 infoWindow.open(_map);
838 });
839 shape.addListener('mouseout', function() {
840 infoWindow.close();
841 });
842 attachClickHandler(shape, doc.nodeID); // as above
843 }
844 shape.markerInfo = infoWindow;
845 //console.log("######## Added markerInfo object to shape");
846}
847
848// This function will create Google Shapes/Overlays and markers out of a given doc JSONNode's doc.mapOverlay
849// (doc.mapOverlay shapes are stored as an array of JSON) and store the shapes/overlays in the doc.shapes array.
850function createShapes(doc, options)
851{
852 var isMainDoc = options["mainDoc"];
853
854 // for doc.shapes: don't store JSON anymore, convert them to google Shapes overlays and store them instead
855 doc.shapes = [];
856
857 for (var i=0; i<doc.mapoverlay.length; i++) {
858 //console.log("in: mapoverlay["+i+"] =" + JSON.stringify(doc.mapoverlay[i]));
859 var shape = ShapesUtil.JSONToShape(doc.mapoverlay[i]);
860 //console.log("out: shape = " + JSON.stringify(shape));
861
862 doc.shapes[i] = shape;
863 shape.setMap(_map);
864 //shape["title"] = doc.title; // TODO: Think on it some more.
865
866 // Unset editable and draggable properties of shape
867 // And for markers, which are initialised to clickable besides, undo the clickability
868 // and set them
869 if(shape.type === google.maps.drawing.OverlayType.MARKER) {
870 var marker = shape;
871 // markers of the main document should be red, else they'll be blue
872 if(!isMainDoc) {
873 marker["icon"] = "interfaces/" + gs.xsltParams.interface_name + "/images/bluemarker.png";
874 }
875 marker.clickable = false; // only markers
876 /*
877 console.log("@@@ map-scripts::addInfoMarker - marker.position");
878 console.log("Lat is " + typeof(marker.position.lat()));
879 console.log(marker.position.lat());
880 console.log("Long is " + typeof(marker.position.lng()));
881 console.log(marker.position.lng());
882 */
883 } else {
884 //console.log("Creating non-marker shape.");
885
886 if(!isMainDoc) {
887 ShapesUtil.setOpacity(shape, LOW_OPACITY);
888 } // else the shape will be drawn at its configured opacity
889 }
890
891 shape.editable = false;
892 shape.draggable = false;
893
894
895 // doc[i]'s label = doc.shapes[i].description
896 addInfoMarker(doc, shape);
897 }
898
899 var docElement = gs.jqGet("div" + doc.nodeID);
900 var parent;
901 if(docElement)
902 {
903 parent = docElement.parentNode;
904 }
905
906 while(parent && parent.nodeName != "BODY")
907 {
908 if($(parent).attr("id") && $(parent).attr("id").search("divCL") != -1)
909 {
910 doc.parentCL = parent;
911 break;
912 }
913
914 parent = parent.parentNode;
915 }
916}
917
918// This method is only for backwards compatibility: for those collections with docs that only have Lat and Lng meta
919// and no GPS.mapOverlay (and hence Coordinate) meta.
920function createMarker(doc, pos, options)
921{
922 var isMainMarker = options["mainDoc"];
923
924 var marker;
925 if(isMainMarker)
926 {
927 marker = new google.maps.Marker
928 ({
929 position: pos,
930 title:doc.title,
931 map:_map
932 });
933 }
934 else
935 {
936 marker = new google.maps.Marker
937 ({
938 position: pos,
939 title:doc.title,
940 map:_map,
941 icon:"interfaces/" + gs.xsltParams.interface_name + "/images/bluemarker.png"
942 });
943 }
944
945 var docElement = gs.jqGet("div" + doc.nodeID);
946 var parent;
947 if(docElement)
948 {
949 parent = docElement.parentNode;
950 }
951
952 while(parent && parent.nodeName != "BODY")
953 {
954 if($(parent).attr("id") && $(parent).attr("id").search("divCL") != -1)
955 {
956 doc.parentCL = parent;
957 break;
958 }
959
960 parent = parent.parentNode;
961 }
962
963 var info = new google.maps.InfoWindow({content:doc.title});
964 marker.markerInfo = info;
965 doc.marker = marker;
966 attachClickHandler(marker, doc.nodeID);
967}
968
969// TODO: with the following, it seems that clicking on shape expands the entire document
970// Should it be that clicking on a shape should expand the doc section that contains that shape meta?
971function attachClickHandler(shapeOrMarker, nodeID)
972{
973 google.maps.event.addListener(shapeOrMarker, 'click', function()
974 {
975 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";
976 });
977}
978
979function NewLatLng(lat, lng)
980{
981 console.log("Latitude " + lat);
982 console.log("Longitude " + lng);
983}
984
985function httpMapBrowseRequest(sectionID)
986{
987 // Make ajax call to retrieve jsonNodes for section ID, and draw shapes on the map.
988 var url = gs.xsltParams.library_name + "?a=b&rt=s&s=ClassifierBrowse&c=" + gs.cgiParams.c + "&cl=" + sectionID + "&excerptid=jsonNodes";
989 $.ajax(url)
990 .done(function(responseText)
991 {
992 var startIndex = responseText.indexOf(">");
993 var endIndex = responseText.indexOf("</");
994
995 var jsonNodesStr = responseText.substring(startIndex+1, endIndex);
996 var jsonNodes = eval(jsonNodesStr); //responseText.substring(startIndex+1, endIndex));
997 if(jsonNodes && jsonNodes.length > 0)
998 {
999
1000 mapEnabled = true;
1001 showMap("httpMapBrowseRequest");
1002
1003 for(var i = 0; i < jsonNodes.length; i++)
1004 {
1005 var doc = jsonNodes[i];
1006 _docList[doc.nodeID] = doc;
1007 _docList.ids.push(doc.nodeID);
1008
1009 var options = {
1010 "mainDoc": true // TODO: should this be true or false???
1011 };
1012 createOverlayItems(doc, options);
1013 }
1014
1015 ///var tmp = $("#title"+sectionID);
1016 ///console.log(tmp); // WRONG
1017 ///var tmp2 = document.getElementById("title"+sectionID);
1018 ///console.log(tmp2); // RIGHT, WHY?
1019
1020 // create data-* attribute to store this sectionID's JSON on the section's div
1021 //$("#title"+sectionID).attr("data-gps-map-json", "hello world"); // TODO: Doesn't work. Why?
1022 var titleClassifierEl = document.getElementById("title"+sectionID);
1023 titleClassifierEl.setAttribute("data-gps-map-json", jsonNodesStr);
1024 }
1025
1026 updateMap();
1027 //console.log("getSub Classifier -> updateMap()");
1028 })
1029 .fail(function()
1030 {
1031 //console.log("Error getting subclassifiers");
1032 return;
1033 });
1034}
1035
1036function performDistanceSearchWithCoordinates(id, coord, degrees)
1037{
1038 var coordInfo = getLatLngForCoord(coord);
1039 if(!coordInfo) {
1040 console.log("@@@ ERROR in map-scripts::performDistanceSearchWithCoordinates: coordInfo is null");
1041 }
1042 performDistanceSearch(id, coordInfo.lat, coordInfo.lng, degrees);
1043}
1044
1045function performDistanceSearch(id, lat, lng, degrees)
1046{
1047 if(parseFloat(lat) > 180 || parseFloat(lat) < -180 || parseFloat(lng) > 180 || parseFloat(lat) < -180)
1048 {
1049 console.log("Latitude or longitude incorrectly formatted");
1050 return;
1051 }
1052
1053 if(lat.indexOf(".") == -1 || lng.indexOf(".") == -1 || (lat.indexOf(".") + 3) >= lat.length || (lng.indexOf(".") + 3) >= lng.length)
1054 {
1055 console.log("Latitude or longitude does not have the required precision for a distance search");
1056 return;
1057 }
1058
1059 var query = "";
1060 for(var i = 0; i < degrees * 2; i++)
1061 {
1062 for (var j = 0; j < degrees * 2; j++)
1063 {
1064 var latDelta = (i - degrees) * 0.01;
1065 var lngDelta = (j - degrees) * 0.01;
1066
1067 //query += "(" + getDistanceQueryStringOldApproach(lat, latDelta, 2, "LA", ["N","S"]);
1068 //query += "+AND+";
1069 //query += getDistanceQueryStringOldApproach(lng, lngDelta, 2, "LN", ["E","W"]) + ")";
1070
1071 query += "(" + getDistanceQueryStringTerm(lat, lng, latDelta, lngDelta, 2, "CS") + ")";
1072
1073 if(i != ((degrees * 2) - 1) || j != ((degrees * 2) - 1)){ query += " OR "; }
1074 }
1075 }
1076
1077 var inlineTemplate = '\
1078 <xsl:template match="/" priority="5">\
1079 <table id="nearbyDocs">\
1080 <tr>\
1081 <th><a href="javascript:sortByDistance();">Distance</a></th><th><a href="javascript:sortAlphabetically();">Document</a></th>\
1082 </tr>\
1083 <xsl:apply-templates select="//documentNode"/>\
1084 </table>\
1085 </xsl:template>\
1086 \
1087 <xsl:template match="documentNode" priority="5">\
1088 <xsl:if test="@nodeID !=\''+id+'\'">\
1089 <tr>\
1090 <td>___<gsf:metadata name="Latitude"/>______<gsf:metadata name="Longitude"/>___</td>\
1091 <td><gsf:link title="'+gs.text.doc.nearby_doc_tooltip+'" type="document"><gsf:metadata name="Title"/></gsf:link></td>\
1092 </tr>\
1093 </xsl:if>\
1094 </xsl:template>';
1095
1096 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");
1097 $.ajax(url)
1098 .done(function(response)
1099 {
1100 response = response.replace(/<img src="[^"]*map_marker.png"[^>]*>/g, "");
1101
1102 var nearbyDocsArray = new Array();
1103
1104 var lats = new Array();
1105 var lngs = new Array();
1106 var matches = response.match(/___(-?[0-9\.]*)___/g);
1107 for(var i = 0; i < matches.length; i += 2)
1108 {
1109 var matchLatFloat = parseFloat(matches[i].replace("___", ""));
1110 var matchLngFloat = parseFloat(matches[i+1].replace("___", ""));
1111
1112 lats.push(matchLatFloat);
1113 lngs.push(matchLngFloat);
1114 var distance = Math.sqrt(Math.pow(matchLatFloat - parseFloat(lat), 2) + Math.pow(matchLngFloat - parseFloat(lng), 2)) * (40000.0/360.0);
1115 var distanceString = "" + distance;
1116 distanceString = distanceString.substring(0, 6);
1117 response = response.replace(matches[i] + matches[i+1], distanceString);
1118 }
1119
1120 var index = 0;
1121 var i = 0;
1122 while(true)
1123 {
1124 var distanceStart = response.indexOf("<td>", index);
1125 if(distanceStart == -1)
1126 {
1127 break;
1128 }
1129 var distanceEnd = response.indexOf("</td>", distanceStart);
1130
1131 var docLinkStart = response.indexOf("<td>", distanceEnd);
1132 var docLinkEnd = response.indexOf("</td>", docLinkStart);
1133
1134 var dist = response.substring(distanceStart + 4, distanceEnd);
1135 var docLink = response.substring(docLinkStart + 4, docLinkEnd);
1136
1137 _nearbyDocsByDistance.push({title:docLink, distance:dist, lat:lats[i], lng:lngs[i++]});
1138
1139 index = docLinkEnd;
1140 }
1141
1142 sortByDistance(lat,lng);
1143
1144 var toggle = $("#nearbyDocumentsToggle");
1145 toggle.attr("src", gs.imageURLs.collapse);
1146 gs.functions.makeToggle(toggle, $("#nearbyDocuments"));
1147 });
1148}
1149
1150var map_centering_timeout = null;
1151function recenterMapF(lat, lng)
1152{
1153 return function() {
1154 _map.setCenter(new google.maps.LatLng(lat, lng));
1155 }
1156}
1157function recenterMap(lat, lng)
1158{
1159
1160 _map.setCenter(new google.maps.LatLng(lat, lng));
1161
1162}
1163function sortByDistance(base_lat,base_lng)
1164{
1165 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>';
1166 _nearbyDocsByDistance.sort(function(a, b){return (a.distance - b.distance);});
1167 for(var i = 0; i < _nearbyDocsByDistance.length; i++)
1168 {
1169
1170 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>";
1171 }
1172 sortedTable += "</table>";
1173
1174 $("#nearbyDocuments").html(sortedTable);
1175}
1176function prettifyDistance(distance) {
1177
1178 var new_distance;
1179 if (distance < 1) {
1180 new_distance = (distance * 1000);
1181 // Round to nearest whole number - don't need to show points of metres..
1182 new_distance = Math.round(new_distance);
1183 new_distance += " m";
1184 }
1185 else {
1186 new_distance = distance +" km";
1187
1188 }
1189 return new_distance;
1190}
1191
1192
1193
1194function sortAlphabetically(base_lat, base_lng)
1195{
1196 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>';
1197 _nearbyDocsByDistance.sort(function(a, b)
1198 {
1199 var firstTitleStartIndex = a.title.indexOf(">");
1200 var firstTitleEndIndex = a.title.indexOf("<", firstTitleStartIndex);
1201 var firstTitle = a.title.substring(firstTitleStartIndex + 1, firstTitleEndIndex);
1202 var secondTitleStartIndex = b.title.indexOf(">");
1203 var secondTitleEndIndex = b.title.indexOf("<", secondTitleStartIndex);
1204 var secondTitle = b.title.substring(secondTitleStartIndex + 1, secondTitleEndIndex);
1205 return ((firstTitle.toLowerCase() == secondTitle.toLowerCase()) ? 0 : ((firstTitle.toLowerCase() > secondTitle.toLowerCase()) ? 1 : -1));
1206 });
1207 for(var i = 0; i < _nearbyDocsByDistance.length; i++)
1208 {
1209 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>";
1210 }
1211 sortedTable += "</table>";
1212
1213 $("#nearbyDocuments").html(sortedTable);
1214}
1215
1216function getDistanceQueryStringOldApproach(currentCoord, delta, precision, indexName, directions)
1217{
1218 console.error("**** Old Approach called!!!");
1219
1220 var query = "";
1221 var coordFloat = parseFloat(currentCoord);
1222
1223 var newCoord = "" + (coordFloat + delta);
1224 var beforeDec = newCoord.substring(0, newCoord.indexOf("."));
1225
1226 var direction = directions[0];
1227 if(coordFloat < 0)
1228 {
1229 // negative value
1230 direction = directions[1];
1231 beforeDec = beforeDec.substring(1); // skip over '-' at front
1232 }
1233 beforeDec += direction;
1234
1235 var afterDec = newCoord.substring(newCoord.indexOf(".") + 1, newCoord.indexOf(".") + (precision) + 1);
1236
1237 return indexName + ":" + beforeDec + "+AND+" + indexName + ":" + afterDec;
1238}
1239
1240function coordValToIndexToken(coordValStr, delta, precision, directions)
1241{
1242 var coordValFloat = parseFloat(coordValStr);
1243
1244 var deltaCoordValStr = "" + (coordValFloat + delta);
1245 var beforeDec = deltaCoordValStr.substring(0, deltaCoordValStr.indexOf("."));
1246
1247 var direction = directions[0];
1248 if(coordValFloat < 0)
1249 {
1250 // negative value
1251 direction = directions[1];
1252 beforeDec = beforeDec.substring(1); // skip over '-' at front
1253 }
1254
1255 var beforeDecWithDirection = beforeDec + direction;
1256
1257 var afterDecPrecision = deltaCoordValStr.substring(deltaCoordValStr.indexOf(".") + 1, deltaCoordValStr.indexOf(".") + (precision) + 1);
1258
1259 var indexToken = beforeDecWithDirection + afterDecPrecision;
1260
1261 return indexToken;
1262}
1263
1264function getDistanceQueryStringTerm(currentLat,currentLng, deltaLat, deltaLng, precision, indexName)
1265{
1266 var latToken = coordValToIndexToken(currentLat,deltaLat,precision,["N","S"]);
1267 var lngToken = coordValToIndexToken(currentLng,deltaLng,precision,["E","W"]);
1268
1269 var queryStringTerm = indexName + ":\"" + latToken + " " + lngToken + "\"";
1270
1271 return queryStringTerm;
1272}
1273
1274function _gsInfo(message, optObject) {
1275 console.log(message);
1276 if(typeof optObject !== 'undefined') {
1277 console.log(optObject);
1278 }
1279}
1280
1281function _gsDebug(message, optObject) {
1282 if(_DEBUGGING_) {
1283 _gsInfo(message, optObject);
1284 }
1285}
1286
1287
1288function _debugPrintDocList() {
1289 if(!_DEBUGGING_) return;
1290
1291 console.log("@@@@ printing docList:");
1292 for(var i = 0; i < _docList.ids.length; i++)
1293 {
1294 var doc = _docList.getDocByIndex(i);
1295 console.log(" At index = " + i + " ids[i]: " + _docList.ids[i]);
1296 console.log(" At index = " + i + " ids[i]: " + _docList.ids[i] + ", doc: " + doc.nodeID);
1297 }
1298}
1299
1300function _debugPrintBounds(bounds, message) {
1301 if(!_DEBUGGING_) return;
1302 if(typeof bounds === 'undefined') {
1303 console.log("Bounds undefined");
1304 return;
1305 }
1306 var ne = bounds.getNorthEast();
1307 var sw = bounds.getSouthWest();
1308 console.log(message + " bounds: ne = " + ne + ", sw = " + sw);
1309}
Note: See TracBrowser for help on using the repository browser.