update Ox.Map, remove non-async code path, deprecate non-standard options and events, change the API to allow for dynamic marker colors and sizes

This commit is contained in:
rolux 2012-04-03 15:25:41 +02:00
parent 1278e39759
commit 9f9c2df862

View file

@ -18,6 +18,9 @@ Ox.Map <function> Basic map object
editable <b|false> If true, places are editable editable <b|false> If true, places are editable
find <s|""> Initial query find <s|""> Initial query
findPlaceholder <s|"Find"> Placeholder text for the find input element findPlaceholder <s|"Find"> Placeholder text for the find input element
keys <a|[]> Additional place properties to be requested
markerColor <[n]|f|s|'auto'> Color of place markers ([r, g, b])
markerSize <n|f||s|'auto'> Size of place markers in px
maxMarkers <n|100> Maximum number of markers to be displayed maxMarkers <n|100> Maximum number of markers to be displayed
places <[o]|f|null> Array of, or function that returns, place objects places <[o]|f|null> Array of, or function that returns, place objects
countryCode <s> ISO 3166 country code countryCode <s> ISO 3166 country code
@ -26,8 +29,6 @@ Ox.Map <function> Basic map object
geoname <s> Geoname (like "Paris, Île-de-France, France") geoname <s> Geoname (like "Paris, Île-de-France, France")
lat <n> Latitude in degrees lat <n> Latitude in degrees
lng <n> Longitude in degrees lng <n> Longitude in degrees
markerColor <s|"red"> CSS color of the place marker
markerSize <n|16> size of the place marker in px
name <s> Name (like "Paris") name <s> Name (like "Paris")
north <n> Latitude of the northern boundary in degrees north <n> Latitude of the northern boundary in degrees
south <n> Latitude of the southern boundary in degrees south <n> Latitude of the southern boundary in degrees
@ -36,10 +37,9 @@ Ox.Map <function> Basic map object
selected <s|""> Id of the selected place selected <s|""> Id of the selected place
showControls <b|false> If true, show controls showControls <b|false> If true, show controls
showLabels <b|false> If true, show labels on the map showLabels <b|false> If true, show labels on the map
showTypes <b|false> If true, color markers according to place type showStatusbar <b|false> If true, the map has a statusbar
statusbar <b|false> If true, the map has a statusbar showToolbar <b|false> If true, the map has a toolbar
toolbar <b|false> If true, the map has a toolbar showZoombar <b|false> If true, the map has a zoombar
zoombar <b|false> If true, the map has a zoombar
zoomOnlyWhenFocused <b|false> If true, scroll-zoom only when focused zoomOnlyWhenFocused <b|false> If true, scroll-zoom only when focused
self <o|{}> Shared private variable self <o|{}> Shared private variable
# EVENTS ------------------------------------------------------------------- # EVENTS -------------------------------------------------------------------
@ -98,20 +98,22 @@ Ox.Map = function(options, self) {
self = self || {}; self = self || {};
var that = Ox.Element({}, self) var that = Ox.Element({}, self)
.defaults({ .defaults({
// fixme: isClickable? hasZoombar? // fixme: isClickable?
clickable: false, clickable: false,
editable: false, editable: false,
find: '', find: '',
findPlaceholder: 'Find', findPlaceholder: 'Find',
keys: [],
markerColor: 'auto',
markerSize: 'auto',
maxMarkers: 100, maxMarkers: 100,
places: null, places: null,
selected: '', selected: '',
showControls: false, showControls: false,
showLabels: false, showLabels: false,
showTypes: false, showStatusbar: false,
statusbar: false, // FIXME: showStatusbar showToolbar: false,
toolbar: false, // FIXME: showToolbar showZoombar: false,
zoombar: false, // FIXME: showZoombar
zoomOnlyWhenFocused: false zoomOnlyWhenFocused: false
// fixme: width, height // fixme: width, height
}) })
@ -192,15 +194,30 @@ Ox.Map = function(options, self) {
} }
}); });
self.isAsync = Ox.isFunction(self.options.places); // HANDLE DEPRECATED OPTIONS
['statusbar', 'toolbar', 'zoombar'].forEach(function(key) {
if (options[key]) {
self.options['show' + Ox.toTitleCase(key)] = options[key];
}
});
if (Ox.isArray(self.options.places)) {
self.options.places.forEach(function(place) {
if (Ox.isUndefined(place.id)) {
place.id = Ox.encodeBase32(Ox.uid());
}
});
self.options.places = Ox.api(self.options.places, {geo: true});
}
self.mapHeight = getMapHeight(); self.mapHeight = getMapHeight();
self.metaKey = false; self.metaKey = false;
self.minZoom = getMinZoom(); self.minZoom = getMinZoom();
self.placeKeys = [ self.placeKeys = Ox.merge([
'id', 'name', 'alternativeNames', 'geoname', 'countryCode', 'type', 'id', 'name', 'alternativeNames', 'geoname', 'countryCode', 'type',
'lat', 'lng', 'south', 'west', 'north', 'east', 'area', 'lat', 'lng', 'south', 'west', 'north', 'east', 'area',
'editable' 'editable'
]; ], self.options.keys);
self.resultPlace = null; self.resultPlace = null;
self.scaleMeters = [ self.scaleMeters = [
50000000, 20000000, 10000000, 50000000, 20000000, 10000000,
@ -213,7 +230,7 @@ Ox.Map = function(options, self) {
]; ];
self.shiftKey = false; self.shiftKey = false;
if (self.options.toolbar) { if (self.options.showToolbar) {
self.$toolbar = Ox.Bar({ self.$toolbar = Ox.Bar({
size: 24 size: 24
}) })
@ -275,23 +292,23 @@ Ox.Map = function(options, self) {
self.$map = Ox.Element() self.$map = Ox.Element()
.css({ .css({
left: 0, left: 0,
top: self.options.toolbar * 24 + 'px', top: self.options.showToolbar * 24 + 'px',
right: 0, right: 0,
bottom: self.options.zoombar * 16 + self.options.statusbar * 24 + 'px' bottom: self.options.showZoombar * 16 + self.options.showStatusbar * 24 + 'px'
}) })
.appendTo(that); .appendTo(that);
if (self.options.zoombar) { if (self.options.showZoombar) {
self.$zoombar = Ox.Bar({ self.$zoombar = Ox.Bar({
size: 16 size: 16
}) })
.css({ .css({
bottom: self.options.statusbar * 24 + 'px' bottom: self.options.showStatusbar * 24 + 'px'
}) })
.appendTo(that); .appendTo(that);
} }
if (self.options.statusbar) { if (self.options.showStatusbar) {
self.$statusbar = Ox.Bar({ self.$statusbar = Ox.Bar({
size: 24 size: 24
}) })
@ -438,14 +455,6 @@ Ox.Map = function(options, self) {
$placeControl.css({opacity: 0}).hide(); $placeControl.css({opacity: 0}).hide();
}); });
if (!self.isAsync) {
self.options.places.forEach(function(place) {
if (Ox.isUndefined(place.id)) {
place.id = Ox.encodeBase32(Ox.uid());
}
});
}
if (window.google) { if (window.google) {
initMap(); initMap();
} else if (window.googleCallback) { } else if (window.googleCallback) {
@ -471,6 +480,7 @@ Ox.Map = function(options, self) {
place.remove(); place.remove();
}); });
self.places = []; self.places = [];
/*
if (!self.isAsync) { if (!self.isAsync) {
self.options.places.forEach(function(place) { self.options.places.forEach(function(place) {
self.places.push(new Ox.MapPlace(Ox.extend({ self.places.push(new Ox.MapPlace(Ox.extend({
@ -478,6 +488,7 @@ Ox.Map = function(options, self) {
}, place))); }, place)));
}); });
} }
*/
} }
function addPlaceToMap(place) { function addPlaceToMap(place) {
@ -590,7 +601,7 @@ Ox.Map = function(options, self) {
} }
function constructZoomInput() { function constructZoomInput() {
if (self.options.zoombar) { if (self.options.showZoombar) {
self.$zoomInput && self.$zoomInput.remove(); self.$zoomInput && self.$zoomInput.remove();
self.$zoomInput = Ox.Range({ self.$zoomInput = Ox.Range({
arrows: true, arrows: true,
@ -634,31 +645,20 @@ Ox.Map = function(options, self) {
function getMapBounds(callback) { function getMapBounds(callback) {
// get initial map bounds // get initial map bounds
var mapBounds; self.options.places({}, function(result) {
if (!self.isAsync) { var area = result.data.area;
self.options.places.forEach(function(place, i) { callback(new google.maps.LatLngBounds(
var bounds = getBounds(place); new google.maps.LatLng(area.south, area.west),
mapBounds = i == 0 ? bounds : mapBounds.union(bounds); new google.maps.LatLng(area.north, area.east)
}); ));
callback(mapBounds); });
} else {
self.options.places({}, function(result) {
callback(getBounds(result.data.area));
});
}
function getBounds(place) {
return new google.maps.LatLngBounds(
new google.maps.LatLng(place.south, place.west),
new google.maps.LatLng(place.north, place.east)
);
}
} }
function getMapHeight() { function getMapHeight() {
return self.options.height return self.options.height
- self.options.statusbar * 24 - self.options.showStatusbar * 24
- self.options.toolbar * 24 - self.options.showToolbar * 24
- self.options.zoombar * 16; - self.options.showZoombar * 16;
} }
function getMapType() { function getMapType() {
@ -916,67 +916,47 @@ Ox.Map = function(options, self) {
west = southWest.lng(), west = southWest.lng(),
north = northEast.lat(), north = northEast.lat(),
east = northEast.lng(); east = northEast.lng();
if (!self.isAsync) { self.options.places({
self.places.sort(function(a, b) { keys: self.placeKeys,
var sort = { query: {
a: a.selected ? Infinity conditions: Ox.merge([
: bounds.contains(a.center) ? a.area {key: 'lat', value: [south, north], operator: '='}
: -Infinity, ], spansGlobe() ? [
b: b.selected ? Infinity {key: 'lng', value: [-180, 180], operator: '='}
: bounds.contains(b.center) ? b.area ] : crossesDateline() ? [
: -Infinity, {key: 'lng', value: [east, west], operator: '!='}
}; ] : [
return sort.b - sort.a; {key: 'lng', value: [west, east], operator: '='}
}).forEach(function(place, i) { ]),
if (i < self.options.maxMarkers && !place.visible) { operator: '&'
},
range: [0, self.options.maxMarkers],
sort: [{key: 'area', operator: '-'}]
}, function(result) {
Ox.Log('Map', 'RESULT', result)
var ids = [];
result.data.items.forEach(function(item, i) {
var place = getPlaceById(item.id);
if (!place) {
self.places.push(
new Ox.MapPlace(Ox.extend({
map: that
}, item)).add()
);
} else if (!place.visible) {
place.add(); place.add();
} else if (i >= self.options.maxMarkers && place.visible) { }
ids.push(item.id);
});
self.places.forEach(function(place) {
if (
!place.selected && place.visible
&& ids.indexOf(place.id) == -1
) {
place.remove(); place.remove();
} }
}); });
} else { });
self.options.places({
keys: self.placeKeys,
query: {
conditions: Ox.merge([
{key: 'lat', value: [south, north], operator: '='}
], spansGlobe() ? [
{key: 'lng', value: [-180, 180], operator: '='}
] : crossesDateline() ? [
{key: 'lng', value: [east, west], operator: '!='}
] : [
{key: 'lng', value: [west, east], operator: '='}
]),
operator: '&'
},
range: [0, self.options.maxMarkers],
sort: [{key: 'area', operator: '-'}]
}, function(result) {
Ox.Log('Map', 'RESULT', result)
var ids = [];
result.data.items.forEach(function(item, i) {
var place = getPlaceById(item.id);
if (!place) {
self.places.push(
new Ox.MapPlace(Ox.extend({
map: that
}, item)).add()
);
} else if (!place.visible) {
place.add();
}
ids.push(item.id);
});
self.places.forEach(function(place) {
if (
!place.selected && place.visible
&& ids.indexOf(place.id) == -1
) {
place.remove();
}
});
});
}
self.boundsChanged = false; self.boundsChanged = false;
} }
if (self.centerChanged) { if (self.centerChanged) {
@ -1189,13 +1169,12 @@ Ox.Map = function(options, self) {
} }
} }
function select() { function select() {
//Ox.print('select...', place)
place && place.select(); place && place.select();
self.options.selected = id; self.options.selected = id;
setPlaceControls(place); setPlaceControls(place);
setStatus(); setStatus();
that.triggerEvent('selectplace', place); that.triggerEvent('selectplace', place); // DEPRECATED
// FIXME: all these events should rather pass {place: place} that.triggerEvent('select', {place: place});
} }
}; };
@ -1222,8 +1201,9 @@ Ox.Map = function(options, self) {
function setScale() { function setScale() {
var metersPerPixel = getMetersPerPixel(); var metersPerPixel = getMetersPerPixel();
Ox.forEach(self.scaleMeters, function(meters) { Ox.forEach(self.scaleMeters, function(meters) {
var scaleWidth = Math.round(meters / metersPerPixel); var mapWidth = self.options.width || that.width(),
if (scaleWidth <= self.options.width / 2 - 4) { scaleWidth = Math.round(meters / metersPerPixel);
if (scaleWidth <= mapWidth / 2 - 4) {
self.$controls.scale self.$controls.scale
.options({ .options({
title: '\u2190 ' + ( title: '\u2190 ' + (
@ -1241,7 +1221,7 @@ Ox.Map = function(options, self) {
function setStatus() { function setStatus() {
//Ox.Log('Map', 'setStatus()', self.options.selected) //Ox.Log('Map', 'setStatus()', self.options.selected)
var code, country, disabled, place, title; var code, country, disabled, place, title;
if (self.options.statusbar) { if (self.options.showStatusbar) {
place = getSelectedPlace(); place = getSelectedPlace();
country = place ? Ox.getCountryByGeoname(place.geoname) : ''; country = place ? Ox.getCountryByGeoname(place.geoname) : '';
code = country ? country.code : 'NTHH'; code = country ? country.code : 'NTHH';
@ -1355,13 +1335,13 @@ Ox.Map = function(options, self) {
function updateFormElements() { function updateFormElements() {
var width = that.width(); var width = that.width();
if (self.options.zoombar) { if (self.options.showZoombar) {
getMaxZoom(function(zoom) { getMaxZoom(function(zoom) {
self.maxZoom = zoom; self.maxZoom = zoom;
constructZoomInput(); constructZoomInput();
}); });
} }
if (self.options.statusbar) { if (self.options.showStatusbar) {
self.$placeNameInput.options({ self.$placeNameInput.options({
width: Math.floor((width - 132) / 2) width: Math.floor((width - 132) / 2)
}); });
@ -1404,8 +1384,6 @@ Ox.Map = function(options, self) {
that.$element.css(key, value + 'px'); that.$element.css(key, value + 'px');
that.resizeMap(); that.resizeMap();
} else if (key == 'places') { } else if (key == 'places') {
// fixme: assumes !self.isAsync
//Ox.print('MAP SET OPTIONS PLACES', value);
addPlaces(); addPlaces();
getMapBounds(function(mapBounds) { getMapBounds(function(mapBounds) {
if (mapBounds) { if (mapBounds) {
@ -1483,8 +1461,8 @@ Ox.Map = function(options, self) {
that.resizeMap = function() { that.resizeMap = function() {
// keep center on resize has been commented out // keep center on resize has been commented out
// var center = self.map.getCenter(); // var center = self.map.getCenter();
self.options.height = that.$element.height(); self.options.height = that.height();
self.options.width = that.$element.width(); self.options.width = that.width();
// check if map has initialized // check if map has initialized
if (self.map) { if (self.map) {
self.mapHeight = getMapHeight(); self.mapHeight = getMapHeight();
@ -1496,7 +1474,7 @@ Ox.Map = function(options, self) {
height: self.mapHeight + 'px', height: self.mapHeight + 'px',
width: self.options.width + 'px' width: self.options.width + 'px'
}); });
self.options.zoombar && self.$zoomInput.options({ self.options.showZoombar && self.$zoomInput.options({
size: self.options.width size: self.options.width
}); });
updateFormElements(); updateFormElements();