Geowebcache + Openlayers3 with XYZ source: error by zooming the map - gis

I'm trying the do the same map as here:
Openlayers3: tile grid incorrect with pixelratio=3 using Geoserver/Geowebcache as backend
but using the TMS protocol instead of WMS.
The map works good but there is a little problem by zooming in, only by changing from zoom level 4 to zoom level 5: the map seems to "jump upwards". The problem occurs with all pixel ratio.
This is my source code. Any help is appreciated:
<!DOCTYPE html>
<html>
<head>
<title>WMS Tiles</title>
<link rel="stylesheet" href="https://openlayers.org/en/v3.19.1/css/ol.css" type="text/css">
<!-- The line below is only needed for old environments like Internet Explorer and Android 4.x -->
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>
<script src="https://openlayers.org/en/v3.19.1/build/ol.js"></script>
</head>
<style type="text/css">
body { font-family: sans-serif; font-weight: bold; font-size: .8em; }
body { border: 0px; margin: 0px; padding: 0px; }
</style>
<body>
<div id="map" class="map" style="width: 85%; height: 85%;border: 0px; padding: 0px"> </div>
<script>
console.log("DOMContentLoaded");
try {
var config = {
"bounds": {
"left" : 475279.2689196961,
"bottom" : 5473193.572300382,
"right" : 476655.1750108673,
"top" : 5474594.636365802
}
};
var bounds = [config.bounds.left, config.bounds.bottom, config.bounds.right, config.bounds.top];
var resolutions = [
1.4,
0.7,
0.35,
0.175,
0.0875,
0.04375,
];
var tilePixelRatio = 1;
if (ol.has.DEVICE_PIXEL_RATIO > 2.5) {
tilePixelRatio = 3;
} else if (ol.has.DEVICE_PIXEL_RATIO > 1.5) {
tilePixelRatio = 2;
}
var matrixSet = 'unihd15';
// available gridsets in backend: unihd15, unihd15_512 and unihd15_768
if (tilePixelRatio > 1){
matrixSet = matrixSet + '_' + (256 * tilePixelRatio).toString();
}
var res_length = resolutions.length;
var matrixIds = new Array(res_length );
for (var z = 0; z < res_length ; ++z) {
matrixIds[z] = matrixSet + ':'+ z;
}
console.log('matrixSet is: ' + matrixSet);
console.log(matrixIds);
console.log(matrixIds[0] + ' '+ resolutions[0]);
console.log('Center: ' + ol.extent.getCenter(bounds));
console.log('Pixel ratio: ' + window.devicePixelRatio);
console.log('Bounds: ' + bounds);
console.log('TopLeft: ' + ol.extent.getTopLeft(bounds));
var projection = new ol.proj.Projection({
code: 'EPSG:32632',
units: 'm',
extent: [166021.4431, 0.0000, 833978.5569, 9329005.1825]
});
var tileGrid = new ol.tilegrid.TileGrid({
extent: bounds,
resolutions: resolutions,
origin: ol.extent.getTopLeft(bounds),
tileSize: [256, 256]
});
var view = new ol.View({
extent: bounds,
zoom: 0,
center: ol.extent.getCenter(bounds),
projection: projection,
resolutions: resolutions
});
var layerName = 'unihd15:unihd15_0_basemap';
var tms_source = new ol.source.XYZ({
projection: projection,
tileGrid: tileGrid,
tilePixelRatio: tilePixelRatio,
url: 'http://ssp.deepmap.de/geo/gwc/service/tms/1.0.0/' + layerName + '#' + matrixSet + '#png/{z}/{x}/{-y}.png'
});
var layer = new ol.layer.Tile({
source: tms_source,
extent: bounds
});
var map = new ol.Map({
projection: projection,
controls: ol.control.defaults(
{
rotate: false,
attributionOptions: {
collapsible: false
}
}
),
view: view,
layers: [layer],
target: 'map'
});
console.log("no error");
} catch (error) {
console.log("error");
console.log(error);
}
</script>
</body>
</html>

Usually this kind of problem comes from an incorrect extent. To get the correct extent, go to http://ssp.deepmap.de/geo/gwc/service/tms/1.0.0/unihd15:unihd15_0_basemap#EPSG:32632#png (currently not working on your GeoServer, but that's the URL), and use the <BoundingBox> from there.

Related

konva.js transformer crop box behavior problem

Is there any way to do the same with the cropbox action in the link below?
I am using the latest version of konva, but it seems that the link does not work after version 4.
https://codepen.io/kade87/pen/vYavQMp?editors=1011
How can I use it to work like a link in the latest version?
We must solve this problem. Or is there a javascript crop library that supports both pc and mobile? If so, please recommend. However, most of the libraries didn't work the way we wanted.
<script src="https://unpkg.com/konva#^4/konva.min.js"></script>
<div id="container"></div>
<script>
// noprotect
const stage = new Konva.Stage({
container: 'container',
width: window.innerWidth,
height: window.innerHeight
});
const layer = new Konva.Layer();
stage.add(layer);
Konva.Image.fromURL('https://i.imgur.com/ktWThtZ.png', img => {
img.setAttrs({
width: stage.width(),
height: stage.height(),
opacity: 0.5
});
layer.add(img)
})
Konva.Image.fromURL('https://i.imgur.com/ktWThtZ.png', img => {
var group = new Konva.Group({
clipFunc: (ctx) => {
ctx.save();
ctx.translate(fakeShape.x(), fakeShape.y())
ctx.rotate(Konva.getAngle(fakeShape.rotation()))
ctx.rect(0, 0, fakeShape.width() * fakeShape.scaleX(), fakeShape.height() * fakeShape.scaleY());
ctx.restore()
}
})
layer.add(group);
img.setAttrs({
width: stage.width(),
height: stage.height(),
});
group.add(img);
var fakeShape = new Konva.Rect({
width: 100,
height: 100,
x: 100,
y: 100,
fill: 'rgba(0,0,0,0)',
draggable: true
})
layer.add(fakeShape);
var tr = new Konva.Transformer({
enabledAnchors: ['top-left', 'bottom-right'],
rotateEnabled: false,
keepRatio: false,
flipEnabled: true,
node: fakeShape,
boundBoxFunc: (oldBox, newBox) => {
if(newBox.width < 50) {
newBox.width = 50
// newBox.x = oldBox.x
}
if(newBox.height < 50) {
newBox.height = 50
// newBox.y = oldBox.y
}
return newBox
}
});
layer.add(tr);
layer.draw();
});
</script>

How can I display the global UTM grid on a map in openlayers?

I want to display the global UTM Grid on a map in openlayers. There is no proj definition for the whole system, just the individual zones. For the projection of my map I want to use EPSG:3857.Im using the Ol-Ext graticule to use a different projection for map and grid as that is needed in my project. Is there any way to do this with the ol-ext graticule or do i have to develop a custom solution?
You could define a projection which combines all the UTM projections into one (e.g. by adding 1000000 to the x coordinate at each increase in zone) while still using the appropriate UTM transforms for the zone.
<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io#master/en/v6.6.1/css/ol.css" type="text/css">
<style>
html, body, .map {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
</style>
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io#master/en/v6.6.1/build/ol.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.7.5/proj4.js"></script>
<link rel="stylesheet" href="https://viglino.github.io/ol-ext/dist/ol-ext.css" type="text/css">
<script src="https://viglino.github.io/ol-ext/dist/ol-ext.js"></script>
</head>
<body>
<div id="map" class="map"></div>
<script type="text/javascript">
const utmProjs = [];
for (let zone = 1; zone <= 60; zone++) {
const code = "EPSG:" + (32600 + zone);
proj4.defs(code, "+proj=utm +zone=" + zone + " +ellps=WGS84 +datum=WGS84 +units=m +no_defs");
ol.proj.proj4.register(proj4);
utmProjs[zone] = ol.proj.get(code);
}
const llProj = ol.proj.get("EPSG:4326");
const midpointX = 500000;
const width = midpointX * 2;
function ll2utm(ll) {
const lon = (((ll[0] % 360) + 540) % 360) - 180; // normalise any wrapx
const lat = ll[1];
const zone = Math.floor((180 + lon) / 6) + 1;
const zoneCoord = ol.proj.transform([lon, lat], llProj, utmProjs[zone]);
return [zoneCoord[0] + (zone - 1) * width, zoneCoord[1]];
}
function utm2ll(coord) {
const zone = Math.floor(coord[0] / width) % 60 + 1;
const c0 = coord[0] % width;
const c1 = coord[1];
const ll = ol.proj.transform([c0, c1], utmProjs[zone], llProj);
if (Math.floor((180 + ll[0]) / 6) + 1 != zone) {
ll[0] = (zone - (c0 < midpointX ? 1 : 0)) * 6 - 180;
}
return ll;
}
const UTM = new ol.proj.Projection({
code: 'GlobalUTM',
units: 'm',
extent: [0, -10000000, 60 * width, 10000000]
});
ol.proj.addProjection(UTM);
ol.proj.addCoordinateTransforms(
llProj,
UTM,
ll2utm,
utm2ll
);
const map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
view: new ol.View({
center: ol.proj.fromLonLat([37.41, 8.82]),
zoom: 4
})
});
const viewProj = map.getView().getProjection();
ol.proj.addCoordinateTransforms(
viewProj,
UTM,
function(coord) {
return ll2utm(ol.proj.toLonLat(coord, viewProj));
},
function(coord) {
return ol.proj.fromLonLat(utm2ll(coord), viewProj);
},
);
map.addControl(
new ol.control.Graticule({
projection: UTM,
step: 1000,
stepCoord: 1
})
);
</script>
</body>
</html>
If the ol-ext graticule had an intervals option similar to that in the OpenLayers graticule instead of drawing lines at random multiples of the step setting using
intervals: [1000, 5000, 10000, 50000, 100000, 500000]
would make the zone boundaries clear while still showing details when zoomed in. In the absence of that option you could potentially use one graticule with a step setting of 1000km with a wider stroke to highlight and label the zones, and another with a step of 1km for detail within the zones. Unfortunately the ol-ext graticule simply draws straight lines between the intersection points instead of calculating the correct curve, so the 1000km y values lines which would also be produced would be misplaced relative to the more accurate 1km detail. It can however be used the show the labels, but because it lacks separate label formatters for x and y coordinates an extra x offset is needed to be able to distinguish between x and y coordinates. In an EPSG:3857 projection the zone boundary lines can be easily added in a separate vector layer.
<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io#master/en/v6.6.1/css/ol.css" type="text/css">
<style>
html, body, .map {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
</style>
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io#master/en/v6.6.1/build/ol.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.7.5/proj4.js"></script>
<link rel="stylesheet" href="https://viglino.github.io/ol-ext/dist/ol-ext.css" type="text/css">
<script src="https://viglino.github.io/ol-ext/dist/ol-ext.js"></script>
</head>
<body>
<div id="map" class="map"></div>
<script type="text/javascript">
const utmProjs = [];
for (let zone = 1; zone <= 60; zone++) {
const code = "EPSG:" + (32600 + zone);
proj4.defs(code, "+proj=utm +zone=" + zone + " +ellps=WGS84 +datum=WGS84 +units=m +no_defs");
ol.proj.proj4.register(proj4);
utmProjs[zone] = ol.proj.get(code);
}
const llProj = ol.proj.get("EPSG:4326");
const midpointX = 500000;
const width = midpointX * 2;
const xOffset = 100 * 60 * width;
function ll2utm(ll) {
//const world = Math.floor((ll[0] + 180) / 360);
const lon = (((ll[0] % 360) + 540) % 360) - 180; // normalise any wrapx
const lat = ll[1];
const zone = Math.floor((180 + lon) / 6) + 1;
const zoneCoord = ol.proj.transform([lon, lat], llProj, utmProjs[zone]);
const coord = [xOffset + zoneCoord[0] + (zone - 1) * width, zoneCoord[1]];
//coord[0] += world * 60 * width;
return coord;
}
function utm2ll(coord) {
//const world = Math.floor((coord[0] - xOffset) / (60 * width));
const zone = Math.floor(coord[0] / width) % 60 + 1;
const c0 = coord[0] % width;
const c1 = coord[1];
const ll = ol.proj.transform([c0, c1], utmProjs[zone], llProj);
if (Math.floor((180 + ll[0]) / 6) + 1 != zone) {
ll[0] = (zone - (c0 < midpointX ? 1 : 0)) * 6 - 180;
}
//ll[0] += world * 360;
return ll;
}
const UTM = new ol.proj.Projection({
code: 'GlobalUTM',
units: 'm',
extent: [xOffset, -10000000, xOffset + 60 * width, 10000000],
//global: true
});
ol.proj.addProjection(UTM);
ol.proj.addCoordinateTransforms(
llProj,
UTM,
ll2utm,
utm2ll
);
const map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
view: new ol.View({
center: ol.proj.fromLonLat([37.41, 8.82]),
zoom: 4
})
});
const viewProj = map.getView().getProjection();
ol.proj.addCoordinateTransforms(
viewProj,
UTM,
function(coord) {
return ll2utm(ol.proj.toLonLat(coord, viewProj));
},
function(coord) {
return ol.proj.fromLonLat(utm2ll(coord), viewProj);
},
);
const features = [
new ol.Feature(
new ol.geom.LineString([[-180, 0], [180, 0]]).transform(llProj, viewProj)
)
];
for (let i = -180; i <= 180; i += 6) {
features.push(
new ol.Feature(
new ol.geom.LineString([[i, -85], [i, 85]]).transform(llProj, viewProj)
)
);
};
map.addLayer(
new ol.layer.Vector({
source: new ol.source.Vector({
features: features
}),
style: new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'black',
width: 3
}),
})
})
);
map.addControl(
new ol.control.Graticule({
projection: UTM,
step: 1000,
stepCoord: 1,
formatCoord: function(coord) {
if (coord % width == 0) {
return '';
} else {
return (20000 + (coord % width) / 1000).toString().slice(2);
}
},
style: new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'black',
width: 1
}),
fill: new ol.style.Fill({
color: 'white'
}),
text: new ol.style.Text({
stroke: new ol.style.Stroke({
color: 'white',
width: 3
}),
fill: new ol.style.Fill({
color: 'black'
}),
font: 'bold 12px Arial, Helvetica, Helvetica, sans-serif',
})
})
})
);
map.addControl(
new ol.control.Graticule({
projection: UTM,
step: width,
stepCoord: 1,
formatCoord: function(coord) {
if (coord < 0) {
return 'S' + (20 + coord / width).toString().slice(1);
} else if (coord < xOffset) {
return 'N' + (20 + coord / width).toString().slice(1);
} else {
return 'Z' + (100 + Math.floor(coord / width) % 60 + 1).toString().slice(1);
}
},
style: new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'transparent',
width: 1
}),
fill: new ol.style.Fill({
color: 'transparent'
}),
text: new ol.style.Text({
stroke: new ol.style.Stroke({
color: 'white',
width: 3
}),
fill: new ol.style.Fill({
color: 'black'
}),
font: 'bold 15px Arial, Helvetica, Helvetica, sans-serif',
})
})
})
);
</script>
</body>
</html>

How to merge multiple intersecting polygons

I'm trying to merge or group polygons using turfjs.
The following illustration shows what it looks like before and how it should look like after the merge.
I'm working with Openlayers and Typescript and both have Polygons hence the alias TurfPolygon etc.
I'm convert my OpenLayers Polygons to Turfjs Polygons first, so I can use Turf functions.
const mergedIds: number[] = [];
const t0 = performance.now();
for (const object of arrayTurfObjects) {
if (mergedIds.find(x => x === object.properties.mergedId)) {
continue;
}
let mergeResultPolygon: TurfFeature<TurfPolygon> | null = null;
for (let indexNested = 0; indexNested < arrayTurfObjects.length; indexNested++) {
const nestedObject = arrayTurfObjects[indexNested];
if(nestedObject === object){
continue;
}
if(mergedIds.find(x => x === nestedObject.properties.mergedId)){
continue;
}
if(mergeResultPolygon){
if(booleanIntersects(mergeResultPolygon, nestedObject)){
mergeResultPolygon = TurfUnion(mergeResultPolygon, nestedObject) as TurfFeature<TurfPolygon, any>;
mergedIds.push(nestedObject.properties.mergedId);
indexNested = 0;
}
} else {
if(booleanIntersects(object, nestedObject)){
mergeResultPolygon = TurfUnion(object, nestedObject) as TurfFeature<TurfPolygon, any>;
mergedIds.push(nestedObject.properties.mergedId);
indexNested = 0;
}
}
}
if (mergeResultPolygon) {
const polygon = new Polygon(mergeResultPolygon.geometry.coordinates);
const feature = new Feature(polygon);
feature.setStyle(new Style({
stroke: new Stroke({
color: ColorCode.BLACK,
width: 5,
}),
fill: new Fill({
color: 'rgba(255,0,0, 0.6)',
}),
}));
//Here is an function to add the mergeResultPolygon to the map to check if it's correct
}
}
const t1 = performance.now();
console.log((t1 - t0) + ' milliseconds.');
I'm iterating over the same array, which contains the polygons twice.
First I check if the polygon is already merged, so I can skip, and I'm declaring my merge result polygon.
Then comes the nested loop where I skip the polygon, if it's the same as the polygon in my outer loop and if its already merged.
To start my merging process I'm looking for the first polygon that intersects the current outer loop polygon, so I can set a value for my mergeResultPolygon.
After that I just merge more polygons to that variable.
As you can see I have to reset the nested loop, so I can iterate again.
I'm doing this, because I don't have any kind of order, so the previous polygon could intersect the merge Result Polygon.
My problem is that I'm doing this on the client side and the performance is not that great.
Is there a better solution for this problem?
Demonstration of getting merged polygons from a union of all polygons
<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io#master/en/v6.5.0/css/ol.css" type="text/css">
<style>
html, body, .map {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
</style>
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io#master/en/v6.5.0/build/ol.js"></script>
<script src="https://unpkg.com/#turf/turf#6.3.0/turf.min.js"></script>
</head>
<body>
<div id="map" class="map"></div>
<script type="text/javascript">
var count = 200;
var features = new Array(count);
var e = 4500000;
for (var i = 0; i < count; ++i) {
var coordinates = [2 * e * Math.random() - e, 2 * e * Math.random() - e];
features[i] = new ol.Feature(new ol.geom.Polygon.fromExtent(ol.extent.buffer(coordinates.concat(coordinates), 200000)));
}
var source = new ol.source.Vector({
features: features,
});
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
new ol.layer.Vector({
source: source
})
],
view: new ol.View({
center: [0, 0],
zoom: 2
})
});
var result;
format = new ol.format.GeoJSON();
source.forEachFeature(function(feature) {
var turfPolygon = format.writeFeatureObject(feature);
if (!result) {
result = turfPolygon;
} else {
result = turf.union(result, turfPolygon);
}
});
var results = [];
var olResult = format.readFeature(result);
if (olResult.getGeometry().getType() === 'MultiPolygon') {
olResult.getGeometry().getPolygons().forEach(function(polygon) {
results.push(new ol.Feature(polygon));
});
} else {
results.push(olResult);
}
map.addLayer(
new ol.layer.Vector({
source: new ol.source.Vector({
features: results,
}),
style: new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'red',
width: 2
})
})
})
);
</script>
</body>
</html>

Google Street View with deviceorientation (Full Tilt)

I am trying to create a Google Street View that can be controlled via a devices orientation.
I am using Full Tilt to normalize devices / OS and it seems to be doing a really good job. In fact, it seems very close indeed to the solution I'm after.
However, at various positions, the view seems to jump rapidly (although it seems to resolve to the correct location) and is not as smooth as I would like. This seems particularly obvious if the device is held at around 90 degrees (upright) and rotated slightly to the left or right.
JS Fiddle has an example and would need to be viewed on a mobile device or tablet to see the effect. Following the link further down will only work if you can get to the edit mode where the deviceorientation is allowed to work.
Any ideas if there is a way to resolve this? Or if I'm on to a loser here?
var map;
google.maps.event.addDomListener(window, "load", function () {
// Set up map
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 9,
// Initial
center:{
lat: 35.6735408,
lng: 139.570305,
},
disableDefaultUI: true,
streetViewControl: true,
});
// Set up street view
google.maps.streetViewViewer = 'photosphere';
var street_view = new google.maps.StreetViewPanorama(document.getElementById('street-view'), {
addressControl: false,
fullscreenControl: false,
zoomControl: false,
});
street_view.setPano('2qVB_HA94-kQCAzwffO44g');
// When street view ready, update map position and pov
street_view.addListener('status_changed', function(){
var position = street_view.getPosition();
if( map ){
map.setCenter(position);
map.setStreetView(street_view);
}
});
// FULL TILT ORIENTATION
var promise = new FULLTILT.getDeviceOrientation({ 'type': 'world' });
var deviceOrientation;
promise
.then(function(controller) {
deviceOrientation = controller;
})
.catch(function(message) {
console.error(message);
});
(function draw() {
if (deviceOrientation) {
var euler = deviceOrientation.getScreenAdjustedEuler();
// debug
console.log('alpha: %d, beta: %d, gamma: %d', euler.alpha, euler.beta, euler.gamma);
document.getElementById('alpha').innerHTML = euler.alpha.toFixed(2);
document.getElementById('beta').innerHTML = euler.beta.toFixed(2);
document.getElementById('gamma').innerHTML = euler.gamma.toFixed(2);
// Set POV
if( euler.alpha != 0 && euler.beta != 0 && euler.gamma !=0 ){
street_view.setPov({
heading: euler.alpha*-1,
pitch: euler.beta-90,
});
}
}
requestAnimationFrame(draw);
})();
});
/*! Full Tilt v0.5.2 / http://github.com/richtr/Full-Tilt */
!function(a){function b(a){return a=+a,0===a||isNaN(a)?a:a>0?1:-1}function c(a){var b=new Promise(function(b,c){var d=function(e){setTimeout(function(){a&&a.data?b():e>=20?c():d(++e)},50)};d(0)});return b}function d(){o=n?(a.screen.orientation.angle||0)*j:(a.orientation||0)*j}function e(a){l.orientation.data=a;for(var b in l.orientation.callbacks)l.orientation.callbacks[b].call(this)}function f(a){l.motion.data=a;for(var b in l.motion.callbacks)l.motion.callbacks[b].call(this)}if(void 0===a.FULLTILT||null===a.FULLTILT){var g=Math.PI,h=g/2,i=2*g,j=g/180,k=180/g,l={orientation:{active:!1,callbacks:[],data:void 0},motion:{active:!1,callbacks:[],data:void 0}},m=!1,n=a.screen&&a.screen.orientation&&void 0!==a.screen.orientation.angle&&null!==a.screen.orientation.angle?!0:!1,o=(n?a.screen.orientation.angle:a.orientation||0)*j,p=h,q=g,r=i/3,s=-h,t={};t.version="0.5.2",t.getDeviceOrientation=function(a){var b=new Promise(function(b,d){var e=new t.DeviceOrientation(a);e.start();var f=new c(l.orientation);f.then(function(){e._alphaAvailable=l.orientation.data.alpha&&null!==l.orientation.data.alpha,e._betaAvailable=l.orientation.data.beta&&null!==l.orientation.data.beta,e._gammaAvailable=l.orientation.data.gamma&&null!==l.orientation.data.gamma,b(e)}).catch(function(){e.stop(),d("DeviceOrientation is not supported")})});return b},t.getDeviceMotion=function(a){var b=new Promise(function(b,d){var e=new t.DeviceMotion(a);e.start();var f=new c(l.motion);f.then(function(){e._accelerationXAvailable=l.motion.data.acceleration&&l.motion.data.acceleration.x,e._accelerationYAvailable=l.motion.data.acceleration&&l.motion.data.acceleration.y,e._accelerationZAvailable=l.motion.data.acceleration&&l.motion.data.acceleration.z,e._accelerationIncludingGravityXAvailable=l.motion.data.accelerationIncludingGravity&&l.motion.data.accelerationIncludingGravity.x,e._accelerationIncludingGravityYAvailable=l.motion.data.accelerationIncludingGravity&&l.motion.data.accelerationIncludingGravity.y,e._accelerationIncludingGravityZAvailable=l.motion.data.accelerationIncludingGravity&&l.motion.data.accelerationIncludingGravity.z,e._rotationRateAlphaAvailable=l.motion.data.rotationRate&&l.motion.data.rotationRate.alpha,e._rotationRateBetaAvailable=l.motion.data.rotationRate&&l.motion.data.rotationRate.beta,e._rotationRateGammaAvailable=l.motion.data.rotationRate&&l.motion.data.rotationRate.gamma,b(e)}).catch(function(){e.stop(),d("DeviceMotion is not supported")})});return b},t.Quaternion=function(a,c,d,e){var f;this.set=function(a,b,c,d){this.x=a||0,this.y=b||0,this.z=c||0,this.w=d||1},this.copy=function(a){this.x=a.x,this.y=a.y,this.z=a.z,this.w=a.w},this.setFromEuler=function(){var a,b,c,d,e,f,g,h,i,k,l,m;return function(n){return n=n||{},c=(n.alpha||0)*j,a=(n.beta||0)*j,b=(n.gamma||0)*j,f=c/2,d=a/2,e=b/2,g=Math.cos(d),h=Math.cos(e),i=Math.cos(f),k=Math.sin(d),l=Math.sin(e),m=Math.sin(f),this.set(k*h*i-g*l*m,g*l*i+k*h*m,g*h*m+k*l*i,g*h*i-k*l*m),this.normalize(),this}}(),this.setFromRotationMatrix=function(){var a;return function(c){return a=c.elements,this.set(.5*Math.sqrt(1+a[0]-a[4]-a[8])*b(a[7]-a[5]),.5*Math.sqrt(1-a[0]+a[4]-a[8])*b(a[2]-a[6]),.5*Math.sqrt(1-a[0]-a[4]+a[8])*b(a[3]-a[1]),.5*Math.sqrt(1+a[0]+a[4]+a[8])),this}}(),this.multiply=function(a){return f=t.Quaternion.prototype.multiplyQuaternions(this,a),this.copy(f),this},this.rotateX=function(a){return f=t.Quaternion.prototype.rotateByAxisAngle(this,[1,0,0],a),this.copy(f),this},this.rotateY=function(a){return f=t.Quaternion.prototype.rotateByAxisAngle(this,[0,1,0],a),this.copy(f),this},this.rotateZ=function(a){return f=t.Quaternion.prototype.rotateByAxisAngle(this,[0,0,1],a),this.copy(f),this},this.normalize=function(){return t.Quaternion.prototype.normalize(this)},this.set(a,c,d,e)},t.Quaternion.prototype={constructor:t.Quaternion,multiplyQuaternions:function(){var a=new t.Quaternion;return function(b,c){var d=b.x,e=b.y,f=b.z,g=b.w,h=c.x,i=c.y,j=c.z,k=c.w;return a.set(d*k+g*h+e*j-f*i,e*k+g*i+f*h-d*j,f*k+g*j+d*i-e*h,g*k-d*h-e*i-f*j),a}}(),normalize:function(a){var b=Math.sqrt(a.x*a.x+a.y*a.y+a.z*a.z+a.w*a.w);return 0===b?(a.x=0,a.y=0,a.z=0,a.w=1):(b=1/b,a.x*=b,a.y*=b,a.z*=b,a.w*=b),a},rotateByAxisAngle:function(){var a,b,c=new t.Quaternion,d=new t.Quaternion;return function(e,f,g){return a=(g||0)/2,b=Math.sin(a),d.set((f[0]||0)*b,(f[1]||0)*b,(f[2]||0)*b,Math.cos(a)),c=t.Quaternion.prototype.multiplyQuaternions(e,d),t.Quaternion.prototype.normalize(c)}}()},t.RotationMatrix=function(a,b,c,d,e,f,g,h,i){var k;this.elements=new Float32Array(9),this.identity=function(){return this.set(1,0,0,0,1,0,0,0,1),this},this.set=function(a,b,c,d,e,f,g,h,i){this.elements[0]=a||1,this.elements[1]=b||0,this.elements[2]=c||0,this.elements[3]=d||0,this.elements[4]=e||1,this.elements[5]=f||0,this.elements[6]=g||0,this.elements[7]=h||0,this.elements[8]=i||1},this.copy=function(a){this.elements[0]=a.elements[0],this.elements[1]=a.elements[1],this.elements[2]=a.elements[2],this.elements[3]=a.elements[3],this.elements[4]=a.elements[4],this.elements[5]=a.elements[5],this.elements[6]=a.elements[6],this.elements[7]=a.elements[7],this.elements[8]=a.elements[8]},this.setFromEuler=function(){var a,b,c,d,e,f,g,h,i;return function(k){return k=k||{},c=(k.alpha||0)*j,a=(k.beta||0)*j,b=(k.gamma||0)*j,d=Math.cos(a),e=Math.cos(b),f=Math.cos(c),g=Math.sin(a),h=Math.sin(b),i=Math.sin(c),this.set(f*e-i*g*h,-d*i,e*i*g+f*h,e*i+f*g*h,f*d,i*h-f*e*g,-d*h,g,d*e),this.normalize(),this}}(),this.setFromQuaternion=function(){var a,b,c,d;return function(e){return a=e.w*e.w,b=e.x*e.x,c=e.y*e.y,d=e.z*e.z,this.set(a+b-c-d,2*(e.x*e.y-e.w*e.z),2*(e.x*e.z+e.w*e.y),2*(e.x*e.y+e.w*e.z),a-b+c-d,2*(e.y*e.z-e.w*e.x),2*(e.x*e.z-e.w*e.y),2*(e.y*e.z+e.w*e.x),a-b-c+d),this}}(),this.multiply=function(a){return k=t.RotationMatrix.prototype.multiplyMatrices(this,a),this.copy(k),this},this.rotateX=function(a){return k=t.RotationMatrix.prototype.rotateByAxisAngle(this,[1,0,0],a),this.copy(k),this},this.rotateY=function(a){return k=t.RotationMatrix.prototype.rotateByAxisAngle(this,[0,1,0],a),this.copy(k),this},this.rotateZ=function(a){return k=t.RotationMatrix.prototype.rotateByAxisAngle(this,[0,0,1],a),this.copy(k),this},this.normalize=function(){return t.RotationMatrix.prototype.normalize(this)},this.set(a,b,c,d,e,f,g,h,i)},t.RotationMatrix.prototype={constructor:t.RotationMatrix,multiplyMatrices:function(){var a,b,c=new t.RotationMatrix;return function(d,e){return a=d.elements,b=e.elements,c.set(a[0]*b[0]+a[1]*b[3]+a[2]*b[6],a[0]*b[1]+a[1]*b[4]+a[2]*b[7],a[0]*b[2]+a[1]*b[5]+a[2]*b[8],a[3]*b[0]+a[4]*b[3]+a[5]*b[6],a[3]*b[1]+a[4]*b[4]+a[5]*b[7],a[3]*b[2]+a[4]*b[5]+a[5]*b[8],a[6]*b[0]+a[7]*b[3]+a[8]*b[6],a[6]*b[1]+a[7]*b[4]+a[8]*b[7],a[6]*b[2]+a[7]*b[5]+a[8]*b[8]),c}}(),normalize:function(a){var b=a.elements,c=b[0]*b[4]*b[8]-b[0]*b[5]*b[7]-b[1]*b[3]*b[8]+b[1]*b[5]*b[6]+b[2]*b[3]*b[7]-b[2]*b[4]*b[6];return b[0]/=c,b[1]/=c,b[2]/=c,b[3]/=c,b[4]/=c,b[5]/=c,b[6]/=c,b[7]/=c,b[8]/=c,a.elements=b,a},rotateByAxisAngle:function(){var a,b,c=new t.RotationMatrix,d=new t.RotationMatrix,e=!1;return function(f,g,h){return d.identity(),e=!1,a=Math.sin(h),b=Math.cos(h),1===g[0]&&0===g[1]&&0===g[2]?(e=!0,d.elements[4]=b,d.elements[5]=-a,d.elements[7]=a,d.elements[8]=b):1===g[1]&&0===g[0]&&0===g[2]?(e=!0,d.elements[0]=b,d.elements[2]=a,d.elements[6]=-a,d.elements[8]=b):1===g[2]&&0===g[0]&&0===g[1]&&(e=!0,d.elements[0]=b,d.elements[1]=-a,d.elements[3]=a,d.elements[4]=b),e?(c=t.RotationMatrix.prototype.multiplyMatrices(f,d),c=t.RotationMatrix.prototype.normalize(c)):c=f,c}}()},t.Euler=function(a,b,c){this.set=function(a,b,c){this.alpha=a||0,this.beta=b||0,this.gamma=c||0},this.copy=function(a){this.alpha=a.alpha,this.beta=a.beta,this.gamma=a.gamma},this.setFromRotationMatrix=function(){var a,b,c,d;return function(e){a=e.elements,a[8]>0?(b=Math.atan2(-a[1],a[4]),c=Math.asin(a[7]),d=Math.atan2(-a[6],a[8])):a[8]<0?(b=Math.atan2(a[1],-a[4]),c=-Math.asin(a[7]),c+=c>=0?-g:g,d=Math.atan2(a[6],-a[8])):a[6]>0?(b=Math.atan2(-a[1],a[4]),c=Math.asin(a[7]),d=-h):a[6]<0?(b=Math.atan2(a[1],-a[4]),c=-Math.asin(a[7]),c+=c>=0?-g:g,d=-h):(b=Math.atan2(a[3],a[0]),c=a[7]>0?h:-h,d=0),0>b&&(b+=i),b*=k,c*=k,d*=k,this.set(b,c,d)}}(),this.setFromQuaternion=function(){var a,b,c;return function(d){var e=d.w*d.w,f=d.x*d.x,j=d.y*d.y,l=d.z*d.z,m=e+f+j+l,n=d.w*d.x+d.y*d.z,o=1e-6;if(n>(.5-o)*m)a=2*Math.atan2(d.y,d.w),b=h,c=0;else if((-.5+o)*m>n)a=-2*Math.atan2(d.y,d.w),b=-h,c=0;else{var p=e-f+j-l,q=2*(d.w*d.z-d.x*d.y),r=e-f-j+l,s=2*(d.w*d.y-d.x*d.z);r>0?(a=Math.atan2(q,p),b=Math.asin(2*n/m),c=Math.atan2(s,r)):(a=Math.atan2(-q,-p),b=-Math.asin(2*n/m),b+=0>b?g:-g,c=Math.atan2(-s,-r))}0>a&&(a+=i),a*=k,b*=k,c*=k,this.set(a,b,c)}}(),this.rotateX=function(a){return t.Euler.prototype.rotateByAxisAngle(this,[1,0,0],a),this},this.rotateY=function(a){return t.Euler.prototype.rotateByAxisAngle(this,[0,1,0],a),this},this.rotateZ=function(a){return t.Euler.prototype.rotateByAxisAngle(this,[0,0,1],a),this},this.set(a,b,c)},t.Euler.prototype={constructor:t.Euler,rotateByAxisAngle:function(){var a=new t.RotationMatrix;return function(b,c,d){return a.setFromEuler(b),a=t.RotationMatrix.prototype.rotateByAxisAngle(a,c,d),b.setFromRotationMatrix(a),b}}()},t.DeviceOrientation=function(b){this.options=b||{};var c=0,d=200,e=0,f=10;if(this.alphaOffsetScreen=0,this.alphaOffsetDevice=void 0,"game"===this.options.type){var g=function(b){return null!==b.alpha&&(this.alphaOffsetDevice=new t.Euler(b.alpha,0,0),this.alphaOffsetDevice.rotateZ(-o),++e>=f)?void a.removeEventListener("deviceorientation",g,!1):void(++c>=d&&a.removeEventListener("deviceorientation",g,!1))}.bind(this);a.addEventListener("deviceorientation",g,!1)}else if("world"===this.options.type){var h=function(b){return b.absolute!==!0&&void 0!==b.webkitCompassAccuracy&&null!==b.webkitCompassAccuracy&&+b.webkitCompassAccuracy>=0&&+b.webkitCompassAccuracy<50&&(this.alphaOffsetDevice=new t.Euler(b.webkitCompassHeading,0,0),this.alphaOffsetDevice.rotateZ(o),this.alphaOffsetScreen=o,++e>=f)?void a.removeEventListener("deviceorientation",h,!1):void(++c>=d&&a.removeEventListener("deviceorientation",h,!1))}.bind(this);a.addEventListener("deviceorientation",h,!1)}},t.DeviceOrientation.prototype={constructor:t.DeviceOrientation,start:function(b){b&&"[object Function]"==Object.prototype.toString.call(b)&&l.orientation.callbacks.push(b),m||(n?a.screen.orientation.addEventListener("change",d,!1):a.addEventListener("orientationchange",d,!1)),l.orientation.active||(a.addEventListener("deviceorientation",e,!1),l.orientation.active=!0)},stop:function(){l.orientation.active&&(a.removeEventListener("deviceorientation",e,!1),l.orientation.active=!1)},listen:function(a){this.start(a)},getFixedFrameQuaternion:function(){var a=new t.Euler,b=new t.RotationMatrix,c=new t.Quaternion;return function(){var d=l.orientation.data||{alpha:0,beta:0,gamma:0},e=d.alpha;return this.alphaOffsetDevice&&(b.setFromEuler(this.alphaOffsetDevice),b.rotateZ(-this.alphaOffsetScreen),a.setFromRotationMatrix(b),a.alpha<0&&(a.alpha+=360),e-=a.alpha),a.set(e,d.beta,d.gamma),c.setFromEuler(a),c}}(),getScreenAdjustedQuaternion:function(){var a;return function(){return a=this.getFixedFrameQuaternion(),a.rotateZ(-o),a}}(),getFixedFrameMatrix:function(){var a=new t.Euler,b=new t.RotationMatrix;return function(){var c=l.orientation.data||{alpha:0,beta:0,gamma:0},d=c.alpha;return this.alphaOffsetDevice&&(b.setFromEuler(this.alphaOffsetDevice),b.rotateZ(-this.alphaOffsetScreen),a.setFromRotationMatrix(b),a.alpha<0&&(a.alpha+=360),d-=a.alpha),a.set(d,c.beta,c.gamma),b.setFromEuler(a),b}}(),getScreenAdjustedMatrix:function(){var a;return function(){return a=this.getFixedFrameMatrix(),a.rotateZ(-o),a}}(),getFixedFrameEuler:function(){var a,b=new t.Euler;return function(){return a=this.getFixedFrameMatrix(),b.setFromRotationMatrix(a),b}}(),getScreenAdjustedEuler:function(){var a,b=new t.Euler;return function(){return a=this.getScreenAdjustedMatrix(),b.setFromRotationMatrix(a),b}}(),isAbsolute:function(){return l.orientation.data&&l.orientation.data.absolute===!0?!0:!1},getLastRawEventData:function(){return l.orientation.data||{}},_alphaAvailable:!1,_betaAvailable:!1,_gammaAvailable:!1,isAvailable:function(a){switch(a){case this.ALPHA:return this._alphaAvailable;case this.BETA:return this._betaAvailable;case this.GAMMA:return this._gammaAvailable}},ALPHA:"alpha",BETA:"beta",GAMMA:"gamma"},t.DeviceMotion=function(a){this.options=a||{}},t.DeviceMotion.prototype={constructor:t.DeviceMotion,start:function(b){b&&"[object Function]"==Object.prototype.toString.call(b)&&l.motion.callbacks.push(b),m||(n?a.screen.orientation.addEventListener("change",d,!1):a.addEventListener("orientationchange",d,!1)),l.motion.active||(a.addEventListener("devicemotion",f,!1),l.motion.active=!0)},stop:function(){l.motion.active&&(a.removeEventListener("devicemotion",f,!1),l.motion.active=!1)},listen:function(a){this.start(a)},getScreenAdjustedAcceleration:function(){var a=l.motion.data&&l.motion.data.acceleration?l.motion.data.acceleration:{x:0,y:0,z:0},b={};switch(o){case p:b.x=-a.y,b.y=a.x;break;case q:b.x=-a.x,b.y=-a.y;break;case r:case s:b.x=a.y,b.y=-a.x;break;default:b.x=a.x,b.y=a.y}return b.z=a.z,b},getScreenAdjustedAccelerationIncludingGravity:function(){var a=l.motion.data&&l.motion.data.accelerationIncludingGravity?l.motion.data.accelerationIncludingGravity:{x:0,y:0,z:0},b={};switch(o){case p:b.x=-a.y,b.y=a.x;break;case q:b.x=-a.x,b.y=-a.y;break;case r:case s:b.x=a.y,b.y=-a.x;break;default:b.x=a.x,b.y=a.y}return b.z=a.z,b},getScreenAdjustedRotationRate:function(){var a=l.motion.data&&l.motion.data.rotationRate?l.motion.data.rotationRate:{alpha:0,beta:0,gamma:0},b={};switch(o){case p:b.beta=-a.gamma,b.gamma=a.beta;break;case q:b.beta=-a.beta,b.gamma=-a.gamma;break;case r:case s:b.beta=a.gamma,b.gamma=-a.beta;break;default:b.beta=a.beta,b.gamma=a.gamma}return b.alpha=a.alpha,b},getLastRawEventData:function(){return l.motion.data||{}},_accelerationXAvailable:!1,_accelerationYAvailable:!1,_accelerationZAvailable:!1,_accelerationIncludingGravityXAvailable:!1,_accelerationIncludingGravityYAvailable:!1,_accelerationIncludingGravityZAvailable:!1,_rotationRateAlphaAvailable:!1,_rotationRateBetaAvailable:!1,_rotationRateGammaAvailable:!1,isAvailable:function(a){switch(a){case this.ACCELERATION_X:return this._accelerationXAvailable;case this.ACCELERATION_Y:return this._accelerationYAvailable;case this.ACCELERATION_Z:return this._accelerationZAvailable;case this.ACCELERATION_INCLUDING_GRAVITY_X:return this._accelerationIncludingGravityXAvailable;case this.ACCELERATION_INCLUDING_GRAVITY_Y:return this._accelerationIncludingGravityYAvailable;case this.ACCELERATION_INCLUDING_GRAVITY_Z:return this._accelerationIncludingGravityZAvailable;case this.ROTATION_RATE_ALPHA:return this._rotationRateAlphaAvailable;case this.ROTATION_RATE_BETA:return this._rotationRateBetaAvailable;case this.ROTATION_RATE_GAMMA:return this._rotationRateGammaAvailable}},ACCELERATION_X:"accelerationX",ACCELERATION_Y:"accelerationY",ACCELERATION_Z:"accelerationZ",ACCELERATION_INCLUDING_GRAVITY_X:"accelerationIncludingGravityX",ACCELERATION_INCLUDING_GRAVITY_Y:"accelerationIncludingGravityY",ACCELERATION_INCLUDING_GRAVITY_Z:"accelerationIncludingGravityZ",ROTATION_RATE_ALPHA:"rotationRateAlpha",ROTATION_RATE_BETA:"rotationRateBeta",ROTATION_RATE_GAMMA:"rotationRateGamma"},a.FULLTILT=t}}(window);
#map{
width: 200px; height: 200px; position: absolute; right: 20px; bottom: 20px;
}
#street-view{
width: 100%; height: 100%; position: absolute; top: 0; left: 0;
}
#debug{
position: absolute; top: 0; left: 0; padding: 10px; border: 1px solid white; color: white;
}
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js"></script>
<div id="street-view"></div>
<div id="map"></div>
<div id="debug">
alpha: <span id="alpha"></span> |
beta: <span id="beta"></span> |
gamma: <span id="gamma"></span>
</div>

Google is undefined in infobox.js

I have a Google map html page. It works fine in development under localhost but when I try to put in online, I get Google undefined in the infobox.js file, with this line:
this.extend(InfoBubble, google.maps.OverlayView);
I have the api key loaded and it's called before I load the infobox.js file. I added the callback=initialize to see if it would work, but it doesn't work with it or without it. Here is the code for the html file:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Activities</title>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAVVx45quD8ozW5SJZw-Lk_8QvVsXdWi2Y&sensor=false""></script>
<script type="text/javascript" src="GoogleMaps/Scripts/downloadxml.js"></script>
<script type="text/javascript" src="GoogleMaps/Scripts/infobubble_tabs.js"></script>
<style type="text/css">
html, body { height: 100%; }
.style1
{
width: 758px;
}
.style2
{
width: 349px;
}
#side_bar
{
height: 550px;
width: 349px;
overflow:scroll;
}
</style>
<script type="text/javascript">
//<![CDATA[
// this variable will collect the html which will eventually be placed in the side_bar
var side_bar_html = "";
var gmarkers = [];
var gicons = [];
var map = null;
var InfoBubble = new InfoBubble({
maxWidth: 300
});
//defines icon if there is none stated
gicons["red"] = new google.maps.MarkerImage("http://maps.gstatic.com/mapfiles/ridefinder-images/mm_20_red.png",
new google.maps.Size(20, 34),
new google.maps.Point(0, 0),
new google.maps.Point(9, 9));
// Marker sizes are expressed as a Size of X,Y
// where the origin of the image (0,0) is located
// in the top left of the image.
// Origins, anchor positions and coordinates of the marker
// increase in the X direction to the right and in
// the Y direction down.
var iconImage = new google.maps.MarkerImage('http://maps.gstatic.com/mapfiles/ridefinder-images/mm_20_red.png',
new google.maps.Size(20, 34),
new google.maps.Point(0, 0),
new google.maps.Point(9, 9));
var iconShadow = new google.maps.MarkerImage('http://www.google.com/mapfiles/shadow50.png',
new google.maps.Size(37, 34),
new google.maps.Point(0, 0),
new google.maps.Point(9, 9));
// Shapes define the clickable region of the icon.
// The type defines an HTML <area> element 'poly' which traces out a polygon as a series of X,Y points. The final coordinate closes
//the poly by connecting to the first coordinate.
var iconShape = {
coord: [9, 0, 6, 1, 4, 2, 2, 4, 0, 8, 0, 12, 1, 14, 2, 16, 5, 19, 7, 23, 8, 26, 9, 30, 9, 34, 11, 34, 11, 30, 12, 26, 13, 24, 14, 21, 16, 18, 18, 16, 20, 12, 20, 8, 18, 4, 16, 2, 15, 1, 13, 0],
type: 'poly'
};
//determines icon based on category
//if no icon is defined
function getMarkerImage(iconColor) {
if ((typeof (iconColor) == "undefined") || (iconColor == null)) {
iconColor = "red";
}
if (!gicons[iconColor]) {
gicons[iconColor] = new google.maps.MarkerImage(iconColor,
new google.maps.Size(20, 34),
new google.maps.Point(0, 0),
new google.maps.Point(9, 9));
}
return gicons[iconColor];
}
function category2icon(category) {
var color = "red";
switch (category) {
case "Hike": color = "GoogleMaps/Images/HikingIcon.jpg";
break;
case "KML": color = "GoogleMaps/Images/kml.gif";
break;
case "Camping": color = "GoogleMaps/Images/camping.gif";
break;
case "StatePark": color = "GoogleMaps/Images/statepark.jpg";
break;
case "NationalPark": color = "GoogleMaps/Images/NationalPark_icon.png";
break;
case "PointsofInterest": color = "GoogleMaps/Images/POI.png";
break;
case "CountyPark": color = "GoogleMaps/Images/CountyPark_Icon.png";
break;
case "Biking": color = "GoogleMaps/Images/Bike_icon.jpg";
break;
case "FishWildlifeService": color = "GoogleMaps/Images/FishWildlife_icon.gif";
break;
case "Kayak": color = "GoogleMaps/Images/kayaking.png";
break;
case "Shelter": color = "GoogleMaps/Images/Shelter_Icon.png";
break;
case "Parking": color = "GoogleMaps/Images/Parking_Lot_Icon.png";
break;
default: color = "red";
break;
}
return color;
}
gicons["Hike"] = getMarkerImage(category2icon("Hike"));
gicons["KML"] = getMarkerImage(category2icon("KML"));
gicons["Camping"] = getMarkerImage(category2icon("Camping"));
gicons["StatePark"] = getMarkerImage(category2icon("StatePark"));
gicons["NationalPark"] = getMarkerImage(category2icon("NationalPark"));
gicons["PointsofInterest"] = getMarkerImage(category2icon("PointsofInterest"));
gicons["CountyPark"] = getMarkerImage(category2icon("CountyPark"));
gicons["Biking"] = getMarkerImage(category2icon("Biking"));
gicons["FishWildlifeService"] = getMarkerImage(category2icon("FishWildlifeService"));
gicons["Kayak"] = getMarkerImage(category2icon("Kayak"));
gicons["Shelter"] = getMarkerImage(category2icon("Shelter"));
gicons["Parking"] = getMarkerImage(category2icon("Parking"));
// A function to create the marker and set up the event window
function createMarker(latlng, name, url, detail_tab, notes_tab, map_tab, hiking_detail_tab, camping_detail_tab, category, state) {
var contentString_detail = detail_tab;
var contentString_notes = notes_tab;
var contentString_maps = map_tab;
var contentString_hiking_detail = hiking_detail_tab;
var contentString_camping_detail = camping_detail_tab;
var marker = new google.maps.Marker({
position: latlng,
icon: gicons[category],
shadow: iconShadow,
map: map,
title: name,
zIndex: Math.round(latlng.lat() * -100000) << 5
});
// === Store the category and name info as a marker properties ===
marker.mycategory = category;
marker.mystate = state;
marker.myname = name;
gmarkers.push(marker);
// to open the info bubbles
google.maps.event.addListener(marker, 'click', function () {
InfoBubble.open(map, marker);
InfoBubble.removeTab(4);
InfoBubble.removeTab(3);
InfoBubble.removeTab(2);
InfoBubble.removeTab(1);
InfoBubble.removeTab(0);
if (category == "KML") {
window.open("" + url);
}
if (!category == "KML") {
InfoBubble.addTab('Details', contentString_detail);
}
if (!notes_tab == "") {
InfoBubble.addTab('Notes', contentString_notes);
}
if (!map_tab == "") {
switch (category) {
case "Camping": InfoBubble.addTab('Campsite Map', contentString_maps);
break;
case "Hike": InfoBubble.addTab('Trail Map', contentString_maps);
break;
}
}
if (!hiking_detail_tab == "") {
InfoBubble.addTab('Trail Notes', contentString_hiking_detail);
}
if (!camping_detail_tab == "") {
InfoBubble.addTab('Campsite Notes', contentString_camping_detail);
}
});
}
// == shows all markers of a particular category, and ensures the checkbox is checked ==
function show(category) {
for (var i = 0; i < gmarkers.length; i++) {
if (gmarkers[i].mycategory == category) {
gmarkers[i].setVisible(true);
}
}
// == check the checkbox ==
document.getElementById(category + "box").checked = true;
}
// == hides all markers of a particular category, and ensures the checkbox is cleared ==
function hide(category) {
for (var i = 0; i < gmarkers.length; i++) {
if (gmarkers[i].mycategory == category) {
gmarkers[i].setVisible(false);
}
}
// == clear the checkbox ==
document.getElementById(category + "box").checked = false;
// == close the info window, in case its open on a marker that we just hid
InfoBubble.close();
}
// == a checkbox has been clicked ==
function boxclick(box, category) {
if (box.checked) {
show(category);
} else {
hide(category);
}
// == rebuild the side bar
makeSidebar();
}
function myclick(i) {
google.maps.event.trigger(gmarkers[i], "click");
}
// == rebuilds the sidebar to match the markers currently displayed ==
function makeSidebar() {
var html = "";
for (var i = 0; i < gmarkers.length; i++) {
if (gmarkers[i].getVisible()) {
html += '<a href="javascript:myclick(' + i + ')">' + gmarkers[i].myname + '<\/a><br>';
}
}
document.getElementById("side_bar").innerHTML = html;
}
function initialize() {
var myOptions = {
zoom: 8,
center: new google.maps.LatLng(39.364032, -77.182159),
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map"), myOptions);
// Closes any open bubbles before opening new one
google.maps.event.addListener(map, 'click', function () {
InfoBubble.close();
});
//Downloads the data from xml file
// Reads the data the creates each tab
downloadUrl("GoogleMaps/categories.xml", function (doc) {
var xml = xmlParse(doc);
var markers = xml.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
// obtain the attribues of each marker
var lat = parseFloat(markers[i].getAttribute("lat"));
var lng = parseFloat(markers[i].getAttribute("lng"));
var point = new google.maps.LatLng(lat, lng);
var address = markers[i].getAttribute("address");
var city = markers[i].getAttribute("city");
var state = markers[i].getAttribute("state");
var zip = markers[i].getAttribute("zip");
var name = markers[i].getAttribute("name");
var notes = markers[i].getAttribute("notes");
var url = markers[i].getAttribute("url");
var hike_distance = markers[i].getAttribute("hike_distance");
var hike_trail_skill_level = markers[i].getAttribute("hike_trail_skill_level");
var hike_points_of_interest = markers[i].getAttribute("hike_points_of_interest");
var Camping_Amenities = markers[i].getAttribute("Camping_Amenities");
var Camping_Best_Sites = markers[i].getAttribute("Camping_Best_Sites");
var Camping_Notes = markers[i].getAttribute("Camping_Notes");
var image = markers[i].getAttribute("image");
var category = markers[i].getAttribute("category");
//Creates data for Detail Tab
var detail_tab = "";
detail_tab += "<b>" + name + "<\/b><p>";
detail_tab += address + "</br>";
detail_tab += city + ", " + state + " " + zip + "</br>";
detail_tab += '<br><a target="_blank" href="' + url + '">' + url + '</a>' + "</br>";
//Creates data for Notes Tab
var notes_tab = notes;
//Creates data for Maps Tab
var map_tab = "";
if (image) {
map_tab += '<br><a target="_blank" href="' + image + '">' + image + '</a>' + "</br>";
}
//Creates data for Hiking Detail Tab
var hiking_detail_tab = "";
if (hike_distance) {
hiking_detail_tab += "<b>Trail Distance: </b>" + hike_distance + " miles</br>";
hiking_detail_tab += "<b>Trail Skill Level: </b>" + hike_trail_skill_level + "</br>";
hiking_detail_tab += "<b>Points of Interest: </b>" + hike_points_of_interest + "</br>";
}
//Creates data for Camping Detail Tab
var camping_detail_tab = "";
if (Camping_Notes) {
camping_detail_tab += "<b>Amenities: </b>" + Camping_Amenities + "</br>";
camping_detail_tab += "<b>Best Sites: </b>" + Camping_Best_Sites + "</br>";
camping_detail_tab += "<b>Notes: </b>" + Camping_Notes + "</br>";
}
// var kml_tab = "";
// if (category=="KML) {
// create the marker
var marker = createMarker(point, name, url, detail_tab, notes_tab, map_tab, hiking_detail_tab, camping_detail_tab, category);
}
// == show or hide the categories initially ==
show("Hike");
show("KML");
hide("Camping");
hide("StatePark");
hide("NationalPark");
hide("PointsofInterest");
hide("CountyPark");
hide("Biking");
hide("FishWildlifeService");
hide("Kayak");
hide("Shelter");
hide("Parking");
// == create the initial sidebar ==
makeSidebar();
});
}
//]]>
</script>
</head>
<body style="margin:0px; padding:0px;" onload="initialize()">
<table border="1" >
<tr>
<td class="style1">
<div id="map" style="width:978px; height: 596px"></div>
</td>
<td valign="top" style="text-decoration: underline; color: #4444ff;"
class="style2">
<h4>To view a topo map, click map in the top left corner and select terrain from drop down menu</h4>
<div id="side_bar"></div>
</td>
</tr>
</table>
<form action="#">
Hiking: <input type="checkbox" id="Hikebox" onclick="boxclick(this,'Hike')" />
Full Trail Map: <input type="checkbox" id="KMLbox" onclick="boxclick(this,'KML')" />
Trail Shelters: <input type="checkbox" id="Shelterbox" onclick="boxclick(this,'Shelter')" />
Trail Parking: <input type="checkbox" id="Parkingbox" onclick="boxclick(this,'Parking')" />
Camping: <input type="checkbox" id="Campingbox" onclick="boxclick(this,'Camping')" />
Biking: <input type="checkbox" id="Bikingbox" onclick="boxclick(this,'Biking')" />
Kayaking: <input type="checkbox" id="Kayakbox" onclick="boxclick(this,'Kayak')" />
<br />
State Parks: <input type="checkbox" id="StateParkbox" onclick="boxclick(this,'StatePark')" />
National Parks: <input type="checkbox" id="NationalParkbox" onclick="boxclick(this,'NationalPark')" />
County Park: <input type="checkbox" id="CountyParkbox" onclick="boxclick(this,'CountyPark')" />
<br />
Points of Interest: <input type="checkbox" id="PointsofInterestbox" onclick="boxclick(this,'PointsofInterest')" />
Fish and Wildlife Service: <input type="checkbox" id="FishWildlifeServicebox" onclick="boxclick(this,'FishWildlifeService')" />
<br />
</form>
<noscript><b>JavaScript must be enabled in order for you to use Google Maps.</b>
However, it seems JavaScript is either disabled or not supported by your browser.
To view Google Maps, enable JavaScript by changing your browser options, and then
try again.
</noscript>
</body>
</html>
Remove the callback-parameter. When you use the callback-parameter the asynchronous version of the maps-API will be loaded.
You can't use the asynchronous version of the API here because infobox.js only works when the maps-API has already been loaded(what may happen with the asynchronous version, but must not).
In this special case the API never will be loaded, because the body-element is still unknown (but it must be available, because the script tries to inject another script-element into the body).
When you say that it also doesn't work without the callback-parameter there must be another issue that will not be exposed by the code, please post more code or a demo/link.