From f91d06abd5381d9dba0e4362ef2f93e3c4f6a49b Mon Sep 17 00:00:00 2001 From: James Bertouch Date: Sat, 27 Feb 2016 00:26:25 -0500 Subject: [PATCH 1/2] Fixed bounds, center and zoom handling Removed the requirement for bounds, center and zoom attributes on the ui-gmap-google-map directive. Now only the center or bounds attribute is required, and the zoom is optional (it defaults to 10). If only the bounds attribute is specified, the center lat/long is derived. Closes #1360. --- src/coffee/directives/api/map.coffee | 84 +++++++++++-------- .../directives/api/utils/gmap-util.coffee | 4 +- 2 files changed, 53 insertions(+), 35 deletions(-) diff --git a/src/coffee/directives/api/map.coffee b/src/coffee/directives/api/map.coffee index 14ede04d5..d62e3e401 100644 --- a/src/coffee/directives/api/map.coffee +++ b/src/coffee/directives/api/map.coffee @@ -39,15 +39,15 @@ angular.module('uiGmapgoogle-maps.directives.api')
""" scope: - center: '=' # required - zoom: '=' # required + center: '=' # either bounds or center is required + zoom: '=' # optional dragging: '=' # optional control: '=' # optional options: '=' # optional events: '=' # optional eventOpts: '=' # optional styles: '=' # optional - bounds: '=' + bounds: '=' # either bounds or center is required update: '=' # optional link: (scope, element, attrs) => @@ -59,12 +59,6 @@ angular.module('uiGmapgoogle-maps.directives.api') scope.map = null scope.idleAndZoomChanged = false - unless scope.center? - unbindCenterWatch = scope.$watch 'center', => - return unless scope.center - unbindCenterWatch() - @link scope, element, attrs #try again - return uiGmapGoogleMapApi.then (maps) => DEFAULTS = mapTypeId: maps.MapTypeId.ROADMAP @@ -74,23 +68,49 @@ angular.module('uiGmapgoogle-maps.directives.api') instance: spawned.instance map: _gMap - # Center property must be specified and provide lat & - # lng properties - if not @validateCoords(scope.center) - $log.error 'angular-google-maps: could not find a valid center property' + # Either a center or bounds lat/long property must be specified + if not angular.isDefined(scope.center) and not angular.isDefined(scope.bounds) + $log.error 'angular-google-maps: a center or bounds property is required' return - unless angular.isDefined(scope.zoom) - $log.error 'angular-google-maps: map zoom property not set' + + if angular.isDefined(scope.center) and not @validateCoords(scope.center) + $log.error 'angular-google-maps: the supplied center property (' + scope.center + ') is not valid' return + + if angular.isDefined(scope.bounds) + if !angular.isDefined(scope.bounds.northeast) + $log.error 'angular-google-maps: bounds.northeast property is not defined' + return + + if !angular.isDefined(scope.bounds.southwest) + $log.error 'angular-google-maps: bounds.southwest property is not defined' + return + + if not @validateCoords(scope.bounds.northeast) + $log.error 'angular-google-maps: bounds.northeast property (' + scope.bounds.northeast + ') is not valid' + return + + if not @validateCoords(scope.bounds.southwest) + $log.error 'angular-google-maps: bounds.southwest property (' + scope.bounds.southwest + ') is not valid' + return + + # If center is not set, calculate the center point from bounds + if !angular.isDefined(scope.center) + scope.center = new google.maps.LatLngBounds(@getCoords(scope.bounds.southwest), @getCoords(scope.bounds.northeast)).getCenter(); + + # If zoom is not set, use a default value + unless angular.isDefined(scope.zoom) + scope.zoom = 10; + el = angular.element(element) el.addClass 'angular-google-map' # Parse options opts = options: {} - opts.options = scope.options if attrs.options + opts.options = scope.options if attrs.options - opts.styles = scope.styles if attrs.styles + opts.styles = scope.styles if attrs.styles if attrs.type type = attrs.type.toUpperCase() if google.maps.MapTypeId.hasOwnProperty(type) @@ -120,7 +140,7 @@ angular.module('uiGmapgoogle-maps.directives.api') if attrs.events and scope.events?.blacklist? scope.events.blacklist else [] - if _.isString disabledEvents + if _.isString disabledEvents disabledEvents = [disabledEvents] maybeHookToEvent = (eventName, fn, prefn) -> @@ -141,14 +161,10 @@ angular.module('uiGmapgoogle-maps.directives.api') scope.$evalAsync (s) -> s.dragging = dragging if s.dragging? - updateCenter = (c = _gMap.center, s = scope) -> + updateCenter = (c = _gMap.center, s = scope) -> return if _.includes disabledEvents, 'center' - if angular.isDefined(s.center.type) - s.center.coordinates[1] = c.lat() if s.center.coordinates[1] isnt c.lat() - s.center.coordinates[0] = c.lng() if s.center.coordinates[0] isnt c.lng() - else - s.center.latitude = c.lat() if s.center.latitude isnt c.lat() - s.center.longitude = c.lng() if s.center.longitude isnt c.lng() + s.center.latitude = c.lat() if s.center.latitude isnt c.lat() + s.center.longitude = c.lng() if s.center.longitude isnt c.lng() settingFromDirective = false maybeHookToEvent 'idle', -> @@ -157,7 +173,7 @@ angular.module('uiGmapgoogle-maps.directives.api') sw = b.getSouthWest() settingFromDirective = true - scope.$evalAsync (s) -> + scope.$evalAsync (s) -> updateCenter() @@ -225,7 +241,7 @@ angular.module('uiGmapgoogle-maps.directives.api') scope.$watch 'center', (newValue, oldValue) => return if newValue == oldValue or settingFromDirective coords = @getCoords scope.center #get scope.center to make sure that newValue is not behind - return if coords.lat() is _gMap.center.lat() and coords.lng() is _gMap.center.lng() + return if coords.lat() is _gMap.center.lat() and coords.lng() is _gMap.center.lng() unless dragging if !@validateCoords(newValue) @@ -234,22 +250,22 @@ angular.module('uiGmapgoogle-maps.directives.api') _gMap.panTo coords else _gMap.setCenter coords - , true zoomPromise = null scope.$watch 'zoom', (newValue, oldValue) -> return unless newValue? - return if _.isEqual(newValue,oldValue) or _gMap?.getZoom() == scope?.zoom or settingFromDirective + return if _.isEqual(newValue,oldValue) or _gMap?.getZoom() == scope?.zoom or settingFromDirective #make this time out longer than zoom_changes because zoom_changed should be done first #being done first should make scopes equal $timeout.cancel(zoomPromise) if zoomPromise? - zoomPromise = $timeout -> + zoomPromise = $timeout -> _gMap.setZoom newValue - , scope.eventOpts?.debounce?.zoomMs + 20, false + , scope.eventOpts?.debounce?.zoomMs + 20 + , false scope.$watch 'bounds', (newValue, oldValue) -> - return if newValue is oldValue + return if newValue is oldValue if !newValue?.northeast?.latitude? or !newValue?.northeast?.longitude? or !newValue?.southwest?.latitude? or !newValue?.southwest?.longitude? $log.error "Invalid map bounds for new value: #{JSON.stringify newValue}" @@ -261,10 +277,10 @@ angular.module('uiGmapgoogle-maps.directives.api') ['options','styles'].forEach (toWatch) -> scope.$watch toWatch, (newValue,oldValue) -> - return if _.isEqual(newValue,oldValue) + return if _.isEqual(newValue,oldValue) if toWatch == 'options' opts.options = newValue else opts.options[toWatch] = newValue - _gMap.setOptions opts if _gMap? + _gMap.setOptions opts if _gMap? , true diff --git a/src/coffee/directives/api/utils/gmap-util.coffee b/src/coffee/directives/api/utils/gmap-util.coffee index 4549dc148..a9f56705d 100644 --- a/src/coffee/directives/api/utils/gmap-util.coffee +++ b/src/coffee/directives/api/utils/gmap-util.coffee @@ -26,7 +26,9 @@ angular.module('uiGmapgoogle-maps.directives.api.utils') getCoords = (value) -> return unless value - if Array.isArray(value) and value.length is 2 + if value instanceof google.maps.LatLng + return value + else if Array.isArray(value) and value.length is 2 new google.maps.LatLng(value[1], value[0]) else if angular.isDefined(value.type) and value.type is 'Point' new google.maps.LatLng(value.coordinates[1], value.coordinates[0]) From 55c0f617d6799e4326d650a7b1c385a9d58f2a88 Mon Sep 17 00:00:00 2001 From: James Bertouch Date: Wed, 2 Mar 2016 21:36:46 -0500 Subject: [PATCH 2/2] Removed validation checks Just revisited this branch - these validation check are too zealous. They are preventing the map directive from loading when the bounds or center properties are not populated until the Google maps API is ready (eg. with the supplied maps example). --- src/coffee/directives/api/map.coffee | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/src/coffee/directives/api/map.coffee b/src/coffee/directives/api/map.coffee index d62e3e401..aec553f0e 100644 --- a/src/coffee/directives/api/map.coffee +++ b/src/coffee/directives/api/map.coffee @@ -73,27 +73,6 @@ angular.module('uiGmapgoogle-maps.directives.api') $log.error 'angular-google-maps: a center or bounds property is required' return - if angular.isDefined(scope.center) and not @validateCoords(scope.center) - $log.error 'angular-google-maps: the supplied center property (' + scope.center + ') is not valid' - return - - if angular.isDefined(scope.bounds) - if !angular.isDefined(scope.bounds.northeast) - $log.error 'angular-google-maps: bounds.northeast property is not defined' - return - - if !angular.isDefined(scope.bounds.southwest) - $log.error 'angular-google-maps: bounds.southwest property is not defined' - return - - if not @validateCoords(scope.bounds.northeast) - $log.error 'angular-google-maps: bounds.northeast property (' + scope.bounds.northeast + ') is not valid' - return - - if not @validateCoords(scope.bounds.southwest) - $log.error 'angular-google-maps: bounds.southwest property (' + scope.bounds.southwest + ') is not valid' - return - # If center is not set, calculate the center point from bounds if !angular.isDefined(scope.center) scope.center = new google.maps.LatLngBounds(@getCoords(scope.bounds.southwest), @getCoords(scope.bounds.northeast)).getCenter();