951 lines
28 KiB
JavaScript
951 lines
28 KiB
JavaScript
//vim: et:ts=4:sw=4:sts=4:ft=js
|
|
Ox.Map = function(options, self) {
|
|
|
|
var self = self || {}
|
|
that = new Ox.Element('div', self)
|
|
.defaults({
|
|
// fixme: isClickable? hasZoombar?
|
|
clickable: false,
|
|
editable: false,
|
|
findPlaceholder: 'Find',
|
|
labels: false,
|
|
markers: 100,
|
|
places: [],
|
|
selected: null,
|
|
statusbar: false,
|
|
toolbar: false,
|
|
zoombar: false
|
|
})
|
|
.options(options || {})
|
|
.addClass('OxMap')
|
|
.click(function(e) {
|
|
!$(e.target).is('input') && that.gainFocus();
|
|
})
|
|
.bindEvent({
|
|
key_0: function() {
|
|
that.panToPlace()
|
|
},
|
|
key_down: function() {
|
|
pan(0, 1);
|
|
},
|
|
key_enter: pressEnter,
|
|
key_escape: pressEscape,
|
|
key_equal: function() {
|
|
zoom(1);
|
|
},
|
|
key_l: toggleLabels,
|
|
key_left: function() {
|
|
pan(-1, 0);
|
|
},
|
|
key_meta: function() {
|
|
self.metaKey = true;
|
|
$(document).one({
|
|
keyup: function() {
|
|
self.metaKey = false;
|
|
}
|
|
});
|
|
},
|
|
key_minus: function() {
|
|
zoom(-1);
|
|
},
|
|
key_right: function() {
|
|
pan(1, 0);
|
|
},
|
|
key_shift: function() {
|
|
self.shiftKey = true;
|
|
$(document).one({
|
|
keyup: function() {
|
|
self.shiftKey = false;
|
|
}
|
|
});
|
|
},
|
|
key_shift_down: function() {
|
|
pan(0, 2);
|
|
},
|
|
key_shift_0: function() {
|
|
that.zoomToPlace();
|
|
},
|
|
key_shift_equal: function() {
|
|
zoom(2)
|
|
},
|
|
key_shift_left: function() {
|
|
pan(-2, 0);
|
|
},
|
|
key_shift_minus: function() {
|
|
zoom(-2);
|
|
},
|
|
key_shift_right: function() {
|
|
pan(2, 0);
|
|
},
|
|
key_shift_up: function() {
|
|
pan(0, -2);
|
|
},
|
|
key_up: function() {
|
|
pan(0, -1);
|
|
},
|
|
key_z: undo
|
|
});
|
|
|
|
self.mapHeight = getMapHeight();
|
|
self.minZoom = getMinZoom();
|
|
self.scaleMeters = [
|
|
50000000, 20000000, 10000000,
|
|
5000000, 2000000, 1000000,
|
|
500000, 200000, 100000,
|
|
50000, 20000, 10000,
|
|
5000, 2000, 1000,
|
|
500, 200, 100,
|
|
50, 20, 10
|
|
];
|
|
|
|
Ox.extend(self, {
|
|
metaKey: false,
|
|
resultPlace: null,
|
|
shiftKey: false
|
|
});
|
|
|
|
if (self.options.toolbar) {
|
|
self.$toolbar = new Ox.Bar({
|
|
size: 24
|
|
})
|
|
.appendTo(that);
|
|
self.$labelsButton = new Ox.Button({
|
|
title: 'Show Labels',
|
|
width: 96
|
|
})
|
|
.css({float: 'left', margin: '4px'})
|
|
.bindEvent({
|
|
click: toggleLabels
|
|
})
|
|
.appendTo(self.$toolbar)
|
|
self.$findInput = new Ox.Input({
|
|
clear: true,
|
|
placeholder: self.options.findPlaceholder,
|
|
width: 192
|
|
})
|
|
.css({float: 'right', margin: '4px'})
|
|
.bindEvent({
|
|
submit: submitFind
|
|
})
|
|
.appendTo(self.$toolbar)
|
|
}
|
|
|
|
self.$map = new Ox.Element('div')
|
|
.css({
|
|
left: 0,
|
|
top: self.options.toolbar * 24 + 'px',
|
|
right: 0,
|
|
bottom: self.options.zoombar * 16 + self.options.statusbar * 24 + 'px'
|
|
})
|
|
.appendTo(that);
|
|
|
|
if (self.options.zoombar) {
|
|
self.$zoombar = new Ox.Bar({
|
|
size: 16
|
|
})
|
|
.css({
|
|
bottom: self.options.statusbar * 24 + 'px'
|
|
})
|
|
.appendTo(that);
|
|
}
|
|
|
|
if (self.options.statusbar) {
|
|
self.$statusbar = new Ox.Bar({
|
|
size: 24
|
|
})
|
|
.css({
|
|
bottom: 0
|
|
})
|
|
.appendTo(that);
|
|
self.$placeNameInput = new Ox.Input({
|
|
placeholder: 'Name',
|
|
width: 96
|
|
})
|
|
//.css({position: 'absolute', left: 4, top: 4})
|
|
.css({float: 'left', margin: '4px 1px 4px 4px'})
|
|
.appendTo(self.$statusbar);
|
|
self.$placeGeonameInput = new Ox.Input({
|
|
placeholder: 'Geoname',
|
|
width: 96
|
|
})
|
|
//.css({position: 'absolute', left: 104, top: 4})
|
|
.css({float: 'left', margin: '4px 1px 4px 4px'})
|
|
.appendTo(self.$statusbar);
|
|
self.$placeButton = new Ox.Button({
|
|
title: 'New Place',
|
|
width: 96
|
|
})
|
|
.css({float: 'right', margin: '4px 4px 4px 2px'})
|
|
.bindEvent({
|
|
click: clickPlaceButton
|
|
})
|
|
.appendTo(self.$statusbar);
|
|
}
|
|
|
|
self.$navigationButtons = {
|
|
'center': new Ox.Button({
|
|
title: 'close',
|
|
type: 'image'
|
|
})
|
|
.addClass('OxMapButton')
|
|
.css({
|
|
left: '24px',
|
|
top: '24px'
|
|
}),
|
|
'east': new Ox.Button({
|
|
title: 'right',
|
|
type: 'image'
|
|
})
|
|
.addClass('OxMapButton')
|
|
.css({
|
|
left: '44px',
|
|
top: '24px',
|
|
}),
|
|
'north': new Ox.Button({
|
|
title: 'up',
|
|
type: 'image'
|
|
})
|
|
.addClass('OxMapButton')
|
|
.css({
|
|
left: '24px',
|
|
top: '4px',
|
|
}),
|
|
'south': new Ox.Button({
|
|
title: 'down',
|
|
type: 'image'
|
|
})
|
|
.addClass('OxMapButton')
|
|
.css({
|
|
left: '24px',
|
|
top: '44px',
|
|
}),
|
|
'west': new Ox.Button({
|
|
title: 'left',
|
|
type: 'image'
|
|
})
|
|
.addClass('OxMapButton')
|
|
.css({
|
|
left: '4px',
|
|
top: '24px',
|
|
})
|
|
};
|
|
|
|
self.$scaleLabel = new Ox.Label({
|
|
textAlign: 'center',
|
|
title: '...'
|
|
})
|
|
.addClass('OxMapLabel')
|
|
.css({
|
|
right: '4px',
|
|
top: '4px'
|
|
});
|
|
|
|
if (!window.googleCallback) {
|
|
window.googleCallback = function() {
|
|
delete window.googleCallback;
|
|
initMap();
|
|
};
|
|
$.getScript('http://maps.google.com/maps/api/js?callback=googleCallback&sensor=false');
|
|
} else {
|
|
(function interval() {
|
|
window.google ? initMap() : setTimeout(interval, 100);
|
|
}());
|
|
}
|
|
|
|
function addPlaceToMap(place) {
|
|
// via find, click, or new place button
|
|
var exists = false;
|
|
if (!place) {
|
|
var bounds = self.map.getBounds(),
|
|
center = self.map.getCenter(),
|
|
southwest = new google.maps.LatLngBounds(
|
|
bounds.getSouthWest(), center
|
|
).getCenter(),
|
|
northeast = new google.maps.LatLngBounds(
|
|
center, bounds.getNorthEast()
|
|
).getCenter(),
|
|
place = new Ox.MapPlace({
|
|
countryCode: '',
|
|
editable: true,
|
|
geoname: '',
|
|
id: '_' + Ox.uid(), // fixme: stupid
|
|
lat: center.lat(),
|
|
lng: center.lng(),
|
|
map: that,
|
|
name: '',
|
|
south: southwest.lat(),
|
|
west: southwest.lng(),
|
|
north: northeast.lat(),
|
|
east: northeast.lng()
|
|
});
|
|
}
|
|
Ox.forEach(self.places, function(p, i) {
|
|
if (place.bounds.equals(p.bounds)) {
|
|
place = p;
|
|
exists = true;
|
|
return false;
|
|
}
|
|
});
|
|
if (!exists) {
|
|
self.resultPlace && self.resultPlace.removeElement();
|
|
self.resultPlace = place;
|
|
place.add();
|
|
}
|
|
selectPlace(place.id);
|
|
}
|
|
|
|
function addPlaceToPlaces() {
|
|
var place = getSelectedPlace();
|
|
if (self.options.selected == place.id) {
|
|
self.options.selected = place.id.substr(1);
|
|
}
|
|
place.id = place.id.substr(1); // fixme: NOT SAFE!
|
|
place.name = self.$placeNameInput.value();
|
|
place.geoname = self.$placeGeonameInput.value();
|
|
place.countryCode = Ox.getCountryCode(place.geoname);
|
|
place.marker.update();
|
|
self.places.push(place);
|
|
self.resultPlace = null;
|
|
that.triggerEvent('addplace', place)
|
|
Ox.print('SSSS', self.options.selected)
|
|
}
|
|
|
|
function boundsChanged() {
|
|
setScale();
|
|
self.boundsChanged = true;
|
|
}
|
|
|
|
function canContain(outerBounds, innerBounds) {
|
|
var outerSpan = outerBounds.toSpan(),
|
|
innerSpan = innerBounds.toSpan();
|
|
return outerSpan.lat() > innerSpan.lat() &&
|
|
outerSpan.lng() > innerSpan.lng();
|
|
}
|
|
|
|
function centerChanged() {
|
|
self.center = self.map.getCenter();
|
|
self.centerChanged = true;
|
|
}
|
|
|
|
function changeZoom(event, data) {
|
|
self.map.setZoom(data.value);
|
|
}
|
|
|
|
function clickMap(event) {
|
|
Ox.print('Ox.Map clickMap')
|
|
if (self.options.clickable/* && !editing()*/) {
|
|
getPlaceByLatLng(event.latLng, self.map.getBounds(), function(place) {
|
|
if (place) {
|
|
addPlaceToMap(place);
|
|
//selectPlace(place.id);
|
|
} else {
|
|
selectPlace(null);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
function clickPlaceButton() {
|
|
var place = getSelectedPlace(),
|
|
title = self.$placeButton.options('title');
|
|
if (title == 'New Place') {
|
|
addPlaceToMap();
|
|
} else if (title == 'Add Place') {
|
|
addPlaceToPlaces();
|
|
} else if (title == 'Remove Place') {
|
|
|
|
}
|
|
}
|
|
|
|
function constructZoomInput() {
|
|
Ox.print('constructZoomInput', self.minZoom, self.maxZoom)
|
|
if (self.options.zoombar) {
|
|
self.$zoomInput && self.$zoomInput.removeElement();
|
|
self.$zoomInput = new Ox.Range({
|
|
arrows: true,
|
|
max: self.maxZoom,
|
|
min: self.minZoom,
|
|
size: that.width(),
|
|
thumbSize: 32,
|
|
thumbValue: true,
|
|
value: self.map.getZoom()
|
|
})
|
|
.bindEvent({
|
|
change: changeZoom
|
|
})
|
|
.appendTo(self.$zoombar);
|
|
}
|
|
}
|
|
|
|
function editing() {
|
|
var place = getSelectedPlace();
|
|
return place && place.editing;
|
|
}
|
|
|
|
function getElevation(point, callback) {
|
|
// fixme: unused
|
|
if (arguments.length == 1) {
|
|
callback = point;
|
|
point = self.map.getCenter();
|
|
}
|
|
self.elevationService.getElevationForLocations({
|
|
locations: [point]
|
|
}, function(data) {
|
|
callback(data.elevation);
|
|
});
|
|
}
|
|
|
|
function getMapHeight() {
|
|
return self.options.height -
|
|
self.options.statusbar * 24 -
|
|
self.options.toolbar * 24 -
|
|
self.options.zoombar * 16;
|
|
}
|
|
|
|
function getMapType() {
|
|
return self.options.labels ? 'HYBRID' : 'SATELLITE'
|
|
}
|
|
|
|
function getMaxZoom(point, callback) {
|
|
if (arguments.length == 1) {
|
|
callback = point;
|
|
point = self.map.getCenter();
|
|
}
|
|
self.maxZoomService.getMaxZoomAtLatLng(point, function(data) {
|
|
callback(data.status == 'OK' ? data.zoom : null);
|
|
});
|
|
}
|
|
|
|
function getMinZoom() {
|
|
return 0;
|
|
return Math.ceil(
|
|
Ox.log(self.mapHeight / Ox.MAP_TILE_SIZE, 2)
|
|
);
|
|
}
|
|
|
|
function getPlaceById(id) {
|
|
var place = Ox.getObjectById(self.places, id);
|
|
if (!place && self.resultPlace && self.resultPlace.id == id) {
|
|
place = self.resultPlace;
|
|
}
|
|
Ox.print('getPlaceById', id, place)
|
|
return place;
|
|
}
|
|
|
|
function getPlaceByLatLng(latlng, bounds, callback) {
|
|
Ox.print('ll b', latlng, bounds)
|
|
var callback = arguments.length == 3 ? callback : bounds,
|
|
bounds = arguments.length == 3 ? bounds : null;
|
|
self.geocoder.geocode({
|
|
latLng: latlng
|
|
}, function(results, status) {
|
|
Ox.print('results', results)
|
|
var length = results.length;
|
|
if (status == google.maps.GeocoderStatus.OK) {
|
|
if (status != google.maps.GeocoderStatus.ZERO_RESULTS) {
|
|
if (bounds) {
|
|
Ox.forEach(results.reverse(), function(result, i) {
|
|
if (
|
|
i == length - 1 ||
|
|
canContain(bounds, result.geometry.bounds || result.geometry.viewport)
|
|
) {
|
|
callback(new Ox.MapPlace(parseGeodata(results[i])));
|
|
return false;
|
|
}
|
|
});
|
|
} else {
|
|
callback(new Ox.MapPlace(parseGeodata(results[0])));
|
|
}
|
|
} else {
|
|
callback(null);
|
|
}
|
|
} else {
|
|
//Ox.print('geocode failed:', status);
|
|
callback(null);
|
|
}
|
|
});
|
|
}
|
|
|
|
function getPlaceByName(name, callback) {
|
|
self.geocoder.geocode({
|
|
address: name
|
|
}, function(results, status) {
|
|
if (status == google.maps.GeocoderStatus.OK) {
|
|
if (status != google.maps.GeocoderStatus.ZERO_RESULTS) {
|
|
Ox.print('GEOCODER RESULT', results[0])
|
|
callback(new Ox.MapPlace(parseGeodata(results[0])));
|
|
} else {
|
|
callback(null);
|
|
}
|
|
} else {
|
|
Ox.print('geocode failed:', status);
|
|
callback(null);
|
|
}
|
|
});
|
|
}
|
|
|
|
function getPositionByName(name) {
|
|
var position = -1;
|
|
Ox.forEach(self.options.places, function(place, i) {
|
|
if (place.name == name) {
|
|
position = i;
|
|
return false;
|
|
}
|
|
});
|
|
return position;
|
|
}
|
|
|
|
function getSelectedMarker() {
|
|
// needed in case self.options.selected
|
|
// is changed from outside
|
|
var id = null;
|
|
if (self.resultPlace && self.resultPlace.selected) {
|
|
id = self.resultPlace.id;
|
|
} else {
|
|
Ox.forEach(self.places, function(place) {
|
|
if (place.selected) {
|
|
id = place.id;
|
|
return false;
|
|
}
|
|
});
|
|
}
|
|
return id;
|
|
}
|
|
|
|
function getSelectedPlace() {
|
|
return self.options.selected ?
|
|
getPlaceById(self.options.selected) : null;
|
|
}
|
|
|
|
function initMap() {
|
|
var mapBounds;
|
|
|
|
updateFormElements();
|
|
|
|
self.elevationService = new google.maps.ElevationService();
|
|
self.geocoder = new google.maps.Geocoder();
|
|
self.maxZoomService = new google.maps.MaxZoomService();
|
|
self.places = [];
|
|
self.options.places.forEach(function(place, i) {
|
|
var bounds = new google.maps.LatLngBounds(
|
|
new google.maps.LatLng(place.south, place.west),
|
|
new google.maps.LatLng(place.north, place.east)
|
|
);
|
|
if (Ox.isUndefined(place.id)) {
|
|
place.id = Ox.uid();
|
|
}
|
|
mapBounds = i == 0 ? bounds : mapBounds.union(bounds);
|
|
});
|
|
self.center = mapBounds ? mapBounds.getCenter() : new google.maps.LatLng(0, 0);
|
|
self.zoom = 1; // fixme: should depend on height
|
|
that.map = self.map = new google.maps.Map(self.$map.$element[0], {
|
|
center: self.center,
|
|
disableDefaultUI: true,
|
|
disableDoubleClickZoom: true,
|
|
mapTypeId: google.maps.MapTypeId[getMapType()],
|
|
zoom: self.zoom
|
|
});
|
|
google.maps.event.addListener(self.map, 'bounds_changed', boundsChanged);
|
|
google.maps.event.addListener(self.map, 'center_changed', centerChanged);
|
|
google.maps.event.addListener(self.map, 'click', clickMap);
|
|
google.maps.event.addListener(self.map, 'idle', mapChanged);
|
|
google.maps.event.addListener(self.map, 'zoom_changed', zoomChanged);
|
|
google.maps.event.addListenerOnce(self.map, 'tilesloaded', tilesLoaded);
|
|
mapBounds && self.map.fitBounds(mapBounds);
|
|
/*
|
|
setTimeout(function() {
|
|
}, 1000);
|
|
*/
|
|
self.options.places.forEach(function(place, i) {
|
|
self.places[i] = new Ox.MapPlace(Ox.extend({
|
|
map: that
|
|
}, place))/*.add()*/;
|
|
});
|
|
google.maps.event.trigger(self.map, 'resize');
|
|
//that.gainFocus();
|
|
that.triggerEvent('load');
|
|
function tilesLoaded() {
|
|
// fixme: can add earlier, use don't replace map contents option
|
|
Ox.forEach(self.$navigationButtons, function(button) {
|
|
button.appendTo(self.$map);
|
|
});
|
|
self.$scaleLabel.appendTo(self.$map);
|
|
}
|
|
}
|
|
|
|
function mapChanged() {
|
|
// gets called after panning or zooming
|
|
Ox.print('mapChanged');
|
|
var bounds;
|
|
if (self.boundsChanged) {
|
|
bounds = self.map.getBounds();
|
|
self.places.sort(function(a, b) {
|
|
var sort = {
|
|
a: a.selected ? Infinity :
|
|
(bounds.contains(a.center) ? a.size : -Infinity),
|
|
b: b.selected ? Infinity :
|
|
(bounds.contains(b.center) ? b.size : -Infinity),
|
|
};
|
|
return sort.b - sort.a;
|
|
}).forEach(function(place, i) {
|
|
if (i < self.options.markers && !place.visible) {
|
|
place.add();
|
|
} else if (i >= self.options.markers && place.visible) {
|
|
place.remove();
|
|
}
|
|
});
|
|
self.boundsChanged = false;
|
|
}
|
|
if (self.centerChanged) {
|
|
getMaxZoom(function(zoom) {
|
|
if (zoom != self.maxZoom) {
|
|
self.maxZoom = zoom;
|
|
if (self.map.getZoom() > zoom) {
|
|
self.map.setZoom(zoom);
|
|
}
|
|
constructZoomInput();
|
|
}
|
|
});
|
|
self.centerChanged = false;
|
|
}
|
|
if (self.zoomChanged) {
|
|
self.zoomChanged = false;
|
|
}
|
|
}
|
|
|
|
function pan(x, y) {
|
|
self.map.panBy(x * self.$map.width() / 2, y * self.$map.height() / 2);
|
|
};
|
|
|
|
function parseGeodata(data) {
|
|
var bounds = data.geometry.bounds || data.geometry.viewport,
|
|
place = {
|
|
components: data.address_components,
|
|
countryCode: getCountryCode(data.address_components),
|
|
east: bounds.getNorthEast().lng(),
|
|
editable: self.options.editable,
|
|
fullGeoname: getFullGeoname(data.address_components),
|
|
geoname: data.formatted_address,
|
|
id: '_' + Ox.uid(),
|
|
map: that,
|
|
name: data.formatted_address.split(', ')[0],
|
|
north: bounds.getNorthEast().lat(),
|
|
south: bounds.getSouthWest().lat(),
|
|
types: data.types.map(function(type) {
|
|
return Ox.toTitleCase(type.replace(/_/g, ' '));
|
|
}),
|
|
west: bounds.getSouthWest().lng()
|
|
};
|
|
function getCountryCode(components) {
|
|
countryCode = '';
|
|
Ox.forEach(components, function(component) {
|
|
if (component.types.indexOf('country') > -1) {
|
|
countryCode = component.short_name;
|
|
return false;
|
|
}
|
|
});
|
|
return countryCode;
|
|
}
|
|
function getFullGeoname(components) {
|
|
var country = false;
|
|
return components.map(function(component, i) {
|
|
var name = component.long_name;
|
|
if (i && components[i - 1].types.indexOf('country') > -1) {
|
|
country = true;
|
|
}
|
|
return !country && (
|
|
i == 0 || name != components[i - 1].long_name
|
|
) ? name : null;
|
|
}).join(', ')
|
|
}
|
|
return place;
|
|
}
|
|
|
|
function pressEnter() {
|
|
var place = getSelectedPlace();
|
|
if (place) {
|
|
if (place.editing) {
|
|
place.submit();
|
|
} else {
|
|
place.edit();
|
|
}
|
|
} else if (self.resultPlace) {
|
|
selectPlace(self.resultPlace.id)
|
|
}
|
|
}
|
|
|
|
function pressEscape() {
|
|
var place = getSelectedPlace();
|
|
if (place) {
|
|
if (place.editing) {
|
|
place.cancel();
|
|
} else {
|
|
selectPlace(null);
|
|
}
|
|
} else if (self.resultPlace) {
|
|
self.resultPlace.remove();
|
|
self.resultPlace = null;
|
|
}
|
|
}
|
|
|
|
function removePlace(id) {
|
|
|
|
}
|
|
|
|
function reset() {
|
|
//Ox.print(self.map.getZoom(), self.zoom);
|
|
self.map.getZoom() == self.zoom ?
|
|
self.map.panTo(self.center) :
|
|
self.map.fitBounds(self.bounds);
|
|
}
|
|
|
|
function resizeMap() {
|
|
/*
|
|
Ox.print('resizeMap', self.options.width, self.options.height);
|
|
var center = self.map.getCenter();
|
|
self.mapHeight = getMapHeight();
|
|
self.minZoom = getMinZoom();
|
|
that.css({
|
|
height: self.options.height + 'px',
|
|
width: self.options.width + 'px'
|
|
});
|
|
self.$map.css({
|
|
height: self.mapHeight + 'px',
|
|
width: self.options.width + 'px'
|
|
});
|
|
google.maps.event.trigger(self.map, 'resize');
|
|
self.map.setCenter(center);
|
|
*/
|
|
}
|
|
|
|
function selectPlace(id) {
|
|
var place,
|
|
selected = getSelectedMarker();
|
|
Ox.print('Ox.Map selectPlace()', id, selected);
|
|
if (id != selected) {
|
|
place = getPlaceById(selected);
|
|
place && place.deselect();
|
|
place = getPlaceById(id);
|
|
place && place.select();
|
|
self.options.selected = id;
|
|
setStatus();
|
|
that.triggerEvent('selectplace', place);
|
|
}
|
|
};
|
|
|
|
function getMetersPerPixel() {
|
|
var mapWidth = self.$map.width(),
|
|
span = self.map.getBounds().toSpan().lng();
|
|
if (span >= 360) {
|
|
span = 360 * mapWidth / Ox.MAP_TILE_SIZE;
|
|
}
|
|
return span * Ox.getMetersPerDegree(self.map.getCenter().lat()) / mapWidth;
|
|
}
|
|
|
|
function setScale() {
|
|
var metersPerPixel = getMetersPerPixel();
|
|
Ox.forEach(self.scaleMeters, function(meters) {
|
|
var scaleWidth = Math.round(meters / metersPerPixel);
|
|
if (scaleWidth <= 256) {
|
|
self.$scaleLabel
|
|
.options({
|
|
title: '\u2190 ' + (
|
|
meters > 1000 ? Ox.formatNumber(meters / 1000) + ' k' : meters + ' '
|
|
) + 'm \u2192'
|
|
})
|
|
.css({
|
|
width: (scaleWidth - 10) + 'px'
|
|
})
|
|
return false;
|
|
}
|
|
});
|
|
}
|
|
|
|
function setStatus() {
|
|
Ox.print('setStatus()', self.options.selected)
|
|
var disabled, place, title;
|
|
if (self.options.statusbar) {
|
|
place = getSelectedPlace();
|
|
if (place) {
|
|
title = place.id[0] == '_' ? 'Add Place' : 'Remove Place';
|
|
} else {
|
|
title = 'New Place';
|
|
}
|
|
disabled = place && !place.editable;
|
|
self.$placeNameInput.options({
|
|
disabled: disabled,
|
|
value: place ? place.name : ''
|
|
});
|
|
self.$placeGeonameInput.options({
|
|
disabled: disabled,
|
|
value: place ? place.geoname : ''
|
|
});
|
|
self.$placeButton.options({
|
|
disabled: disabled,
|
|
title: title
|
|
});
|
|
}
|
|
Ox.print('STATUS DONE');
|
|
}
|
|
|
|
function submitFind(event, data) {
|
|
that.findPlace(data.value, function(place) {
|
|
setStatus(place);
|
|
});
|
|
}
|
|
|
|
function toggleLabels() {
|
|
self.options.labels = !self.options.labels
|
|
self.map.setMapTypeId(google.maps.MapTypeId[getMapType()]);
|
|
self.$labelsButton.options({
|
|
title: self.$labelsButton.options('title') == 'Show Labels' ?
|
|
'Hide Labels' : 'Show Labels'
|
|
});
|
|
}
|
|
|
|
function undo() {
|
|
Ox.print('Map undo')
|
|
var place = getSelectedPlace();
|
|
place.editing && place.undo();
|
|
}
|
|
|
|
function updateFormElements() {
|
|
var width = that.width();
|
|
self.$zoomInput && constructZoomInput();
|
|
self.$placeNameInput.options({
|
|
width: Math.floor((width - 112) / 2)
|
|
});
|
|
self.$placeGeonameInput.options({
|
|
width: Math.ceil((width - 112) / 2)
|
|
});
|
|
}
|
|
|
|
function zoom(z) {
|
|
self.map.setZoom(self.map.getZoom() + z);
|
|
}
|
|
|
|
function zoomChanged() {
|
|
var zoom = self.map.getZoom();
|
|
if (zoom < self.minZoom) {
|
|
self.map.setZoom(self.minZoom);
|
|
} else if (self.maxZoom && zoom > self.maxZoom) {
|
|
self.map.setZoom(self.maxZoom);
|
|
} else {
|
|
self.zoomChanged = true;
|
|
self.$zoomInput && self.$zoomInput.options({value: zoom});
|
|
that.triggerEvent('zoom', {
|
|
value: zoom
|
|
});
|
|
}
|
|
}
|
|
|
|
function zoomToPlace() {
|
|
Ox.print('zoomToPlace')
|
|
if (self.options.selected !== null) {
|
|
self.map.fitBounds(getPlaceById(self.options.selected).bounds);
|
|
}
|
|
}
|
|
|
|
self.onChange = function(key, value) {
|
|
/*if (key == 'height' || key == 'width') {
|
|
resizeMap();
|
|
} else */if (key == 'places') {
|
|
loadPlaces();
|
|
} else if (key == 'selected') {
|
|
selectPlace(value);
|
|
} else if (key == 'type') {
|
|
|
|
}
|
|
};
|
|
|
|
that.getKey = function() {
|
|
var key = null;
|
|
if (self.shiftKey) {
|
|
key = 'shift'
|
|
} else if (self.metaKey) {
|
|
key = 'meta'
|
|
}
|
|
return key;
|
|
}
|
|
|
|
that.editPlace = function() {
|
|
getPlaceById(self.options.selected).edit();
|
|
return that;
|
|
}
|
|
|
|
that.findPlace = function(name, callback) {
|
|
getPlaceByName(name, function(place) {
|
|
if (place) {
|
|
addPlaceToMap(place);
|
|
self.map.fitBounds(place.bounds);
|
|
}
|
|
callback(place);
|
|
});
|
|
};
|
|
|
|
that.panToPlace = function() {
|
|
Ox.print('panToPlace:', self.options.selected)
|
|
var place = getSelectedPlace();
|
|
place && self.map.panTo(place.center);
|
|
return that;
|
|
};
|
|
|
|
that.removePlace = function(id) {
|
|
return that;
|
|
};
|
|
|
|
that.resizeMap = function() {
|
|
|
|
/*
|
|
Ox.print('resizeMap', self.options.width, self.options.height);
|
|
var center = self.map.getCenter();
|
|
self.mapHeight = getMapHeight();
|
|
self.minZoom = getMinZoom();
|
|
that.css({
|
|
height: self.options.height + 'px',
|
|
width: self.options.width + 'px'
|
|
});
|
|
self.$map.css({
|
|
height: self.mapHeight + 'px',
|
|
width: self.options.width + 'px'
|
|
});
|
|
google.maps.event.trigger(self.map, 'resize');
|
|
self.map.setCenter(center);
|
|
*/
|
|
|
|
/*
|
|
Ox.print('Ox.Map.resizeMap()');
|
|
var center = self.map.getCenter();
|
|
self.options.height = that.$element.height();
|
|
self.options.width = that.$element.width();
|
|
Ox.print(self.options.width, self.options.height)
|
|
self.$map.css({
|
|
height: self.mapHeight + 'px',
|
|
width: self.options.width + 'px'
|
|
});
|
|
google.maps.event.trigger(self.map, 'resize');
|
|
self.map.setCenter(center);
|
|
self.options.zoombar && self.$zoomInput.options({
|
|
size: self.options.width
|
|
});
|
|
*/
|
|
updateFormElements();
|
|
google.maps.event.trigger(self.map, 'resize');
|
|
return that;
|
|
}
|
|
|
|
that.zoomToPlace = function() {
|
|
Ox.print('zoomToPlace')
|
|
var place = getSelectedPlace();
|
|
place && self.map.fitBounds(place.bounds);
|
|
return that;
|
|
};
|
|
|
|
that.zoom = function(value) {
|
|
self.map.setZoom(value);
|
|
return that;
|
|
};
|
|
|
|
return that;
|
|
|
|
};
|