diff --git a/demos/calendar/js/calendar.js b/demos/calendar/js/calendar.js index ef987f18..6dfd5580 100644 --- a/demos/calendar/js/calendar.js +++ b/demos/calendar/js/calendar.js @@ -378,7 +378,7 @@ Ox.load('UI', {debug: true, hideScreen: true, showScreen: true, theme: 'modern'} {name: 'Alfred Hitchcock', start: '1899-08-13', end: '1980-04-29', type: 'person'}, {name: 'Jorge Luis Borges', start: '1899-08-24', end: '1986-06-14', type: 'person'}, - {name: 'Luis Bunuel', start: '1900-02-22', end: '1983-07-29', type: 'person'}, + {name: 'Luis Buñuel', start: '1900-02-22', end: '1983-07-29', type: 'person'}, {name: 'Jan Oort', start: '1900-04-28', end: '1992-11-05', type: 'person'}, {name: 'Catherine Hessling', start: '1900-06-22', end: '1979-09-28', type: 'person'}, {name: 'Robert Siodmak', start: '1900-08-08', end: '1973-03-10', type: 'person'}, diff --git a/demos/map/js/map.js b/demos/map/js/map.js index b36d2db5..7f1e04f0 100644 --- a/demos/map/js/map.js +++ b/demos/map/js/map.js @@ -68,6 +68,7 @@ Ox.load('UI', {debug: true}, function() { Ox.print('DATA', data) panel.replaceElement(1, list = new Ox.TreeList({ data: Ox.isEmpty(data) ? [] : { + area: data.area, components: data.components, countryCode: data.countryCode, crossesDateline: data.crossesDateline(), @@ -78,7 +79,6 @@ Ox.load('UI', {debug: true}, function() { lng: data.lng, name: data.name, north: data.north, - size: data.size, sizeEastWest: data.sizeEastWest, sizeNorthSouth: data.sizeNorthSouth, south: data.south, diff --git a/source/Ox.UI/js/Map/Ox.ListMap.js b/source/Ox.UI/js/Map/Ox.ListMap.js index 3004b6e0..1c62d8d9 100644 --- a/source/Ox.UI/js/Map/Ox.ListMap.js +++ b/source/Ox.UI/js/Map/Ox.ListMap.js @@ -411,24 +411,24 @@ Ox.ListMap = function(options, self) { place.countryCode = country ? country.code : ''; self.selectedPlace = self.selectedPlace.substr(1); // fixme: safe? place.id = self.selectedPlace; - if (Ox.isArray(self.options.places)) { + //if (Ox.isArray(self.options.places)) { self.options.places.push(place); self.$list.options({ items: Ox.clone(self.options.places), selected: [place.id] }); setStatus(); - } + //} self.$map.addPlace(place); self.$placeButton.options({title: 'Remove Place'}); that.triggerEvent('addplace', {place: place}); } else if (title == 'Remove Place') { var index = Ox.getPositionById(self.options.places, self.selectedPlace); - if (Ox.isArray(self.options.places)) { + //if (Ox.isArray(self.options.places)) { self.options.places.splice(index, 1); self.$list.options({items: Ox.clone(self.options.places)}); setStatus(); - } + //} self.$map.removePlace(); self.$placeButton.options({title: 'Add Place'}); that.triggerEvent('removeplace', {place: place}); diff --git a/source/Ox.UI/js/Map/Ox.Map.js b/source/Ox.UI/js/Map/Ox.Map.js index e0b80b16..769f4f98 100644 --- a/source/Ox.UI/js/Map/Ox.Map.js +++ b/source/Ox.UI/js/Map/Ox.Map.js @@ -15,8 +15,8 @@ Ox.Map Basic map object clickable If true, clicking on the map finds a place editable If true, places are editable findPlaceholder Placeholder text for the find input element - markers Maximum number of markers to be displayed - places <[o]|[]> Array of place objects + maxMarkers Maximum number of markers to be displayed + places <[o]|f|null> Array of, or function that returns, place objects countryCode ISO 3166 country code east Longitude of the eastern boundary in degrees editable If true, the place is editable @@ -94,8 +94,8 @@ Ox.Map = function(options, self) { clickable: false, editable: false, findPlaceholder: 'Find', - markers: 100, - places: [], + maxMarkers: 100, + places: null, selected: null, showControls: false, showLabels: false, @@ -173,6 +173,7 @@ Ox.Map = function(options, self) { key_z: undo }); + self.isAsync = Ox.isFunction(self.options.places); self.mapHeight = getMapHeight(); self.minZoom = getMinZoom(); self.scaleMeters = [ @@ -352,6 +353,14 @@ Ox.Map = function(options, self) { .addClass('OxMapLabel') .css({right: '4px', top: '4px'}); + if (!self.isAsync) { + self.options.places.forEach(function(place) { + if (Ox.isUndefined(place.id)) { + place.id = Ox.encodeBase32(Ox.uid()); + } + }); + } + if (!window.googleCallback) { window.googleCallback = function() { delete window.googleCallback; @@ -507,6 +516,28 @@ Ox.Map = function(options, self) { }); } + function getMapBounds(callback) { + // get initial map bounds + var mapBounds; + if (!self.isAsync) { + self.options.places.forEach(function(place, i) { + var bounds = getBounds(place); + mapBounds = i == 0 ? bounds : mapBounds.union(bounds); + }); + callback(mapBounds); + } else { + self.options.places({}, function(result) { + callback(getBounds(result.data)); + }); + } + 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() { return self.options.height - self.options.statusbar * 24 - @@ -651,53 +682,48 @@ Ox.Map = function(options, self) { } function initMap() { - var mapBounds; - updateFormElements(); + getMapBounds(function(mapBounds) { - 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(); + Ox.print('init', mapBounds.getSouthWest(), mapBounds.getNorthEast(), mapBounds.getCenter()) + + updateFormElements(); + + self.elevationService = new google.maps.ElevationService(); + self.geocoder = new google.maps.Geocoder(); + self.maxZoomService = new google.maps.MaxZoomService(); + + 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); + + self.places = []; + if (!self.isAsync) { + self.options.places.forEach(function(place, i) { + self.places[i] = new Ox.MapPlace(Ox.extend({ + map: that + }, place)); + }); } - mapBounds = i == 0 ? bounds : mapBounds.union(bounds); + google.maps.event.trigger(self.map, 'resize'); + //that.gainFocus(); + that.triggerEvent('load'); + }); - //Ox.print('BOUNDS', mapBounds.getSouthWest(), mapBounds.getNorthEast(), mapBounds.getCenter()) - 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) { @@ -713,21 +739,57 @@ Ox.Map = function(options, self) { 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.area : -Infinity, - b: b.selected ? Infinity : - bounds.contains(b.center) ? b.area : -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(); - } - }); + if (!self.isAsync) { + self.places.sort(function(a, b) { + var sort = { + a: a.selected ? Infinity : + bounds.contains(a.center) ? a.area : -Infinity, + b: b.selected ? Infinity : + bounds.contains(b.center) ? b.area : -Infinity, + }; + return sort.b - sort.a; + }).forEach(function(place, i) { + if (i < self.options.maxMarkers && !place.visible) { + place.add(); + } else if (i >= self.options.maxMarkers && place.visible) { + place.remove(); + } + }); + } else { + self.options.places({ + area: { + south: bounds.getSouthWest().lat(), + west: bounds.getSouthWest().lng(), + north: bounds.getNorthEast().lat(), + east: bounds.getNorthEast().lng() + }, + range: [0, self.options.maxMarkers], + sort: [{key: 'area', operator: '+'}], + }, function(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; } if (self.centerChanged) {