Skip to content
This repository has been archived by the owner on Dec 1, 2020. It is now read-only.

Commit

Permalink
Merge pull request #71 from Esri/feature/mapOptions-#65
Browse files Browse the repository at this point in the history
Feature/map options #65

resolves #65
resolves #70 (and then some)
  • Loading branch information
tomwayson committed Aug 27, 2015
2 parents 9a52bbd + 1e4615c commit 0dde574
Show file tree
Hide file tree
Showing 17 changed files with 384 additions and 419 deletions.
213 changes: 77 additions & 136 deletions dist/angular-esri-map.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,14 +159,6 @@
});

})(angular);
/*
Changes made by Edwin Sheldon (eas604@github) per Apache license:
Added support for the following ESRI JavaScript API attributes for the map constructor:
attributionWidth, autoResize, displayGraphicsOnPan, fadeOnZoom, fitExtent, force3DTransforms,
logo, maxScale, maxZoom, minScale, minZoom, nav, navigationMode, optimizePanAnimation,
resizeDelay, scale, showAttribution, showInfoWindowOnClick, slider, sliderOrientation,
sliderPosition, sliderStyle, smartNavigation, wrapAround180
*/
(function(angular) {
'use strict';

Expand All @@ -187,7 +179,11 @@
basemap: '@',
// function binding for event handlers
load: '&',
extentChange: '&'
extentChange: '&',
// function binding for reading object hash from attribute string
// or from scope object property
// see Example 7 here: https://gist.github.com/CMCDragonkai/6282750
mapOptions: '&'
},

// replace tag with div with same id
Expand All @@ -201,8 +197,7 @@
// since we are using compile we need to return our linker function
// the 'link' function handles how our directive responds to changes in $scope
/*jshint unused: false*/
return function(scope, element, attrs, controller) {
};
return function(scope, element, attrs, controller) {};
},

// directive api
Expand All @@ -212,19 +207,37 @@
var mapDeferred = $q.defer();

// add this map to the registry
if($attrs.registerAs){
if ($attrs.registerAs) {
var deregister = esriRegistry._register($attrs.registerAs, mapDeferred);

// remove this from the registry when the scope is destroyed
$scope.$on('$destroy', deregister);
}

require(['esri/map','esri/arcgis/utils'], function(Map, arcgisUtils)
{
if($attrs.webmapId)
{
arcgisUtils.createMap($attrs.webmapId,$attrs.id).then(function(response)
{
require(['esri/map', 'esri/arcgis/utils', 'esri/geometry/Extent', 'esri/dijit/Popup'], function(Map, arcgisUtils, Extent, Popup) {
// setup our mapOptions based on object hash from attribute string
// or from scope object property
var mapOptions = $scope.mapOptions() || {};

// construct optional Extent for mapOptions
if (mapOptions.hasOwnProperty('extent')) {
// construct if parent controller isn'tsupplying a valid and already constructed Extent
// e.g. if the controller or HTML view are only providing JSON
if (mapOptions.extent.declaredClass !== 'esri.geometry.Extent') {
mapOptions.extent = new Extent(mapOptions.extent);
}
}

// construct optional infoWindow from mapOptions
// default to a new Popup dijit for now
if (mapOptions.hasOwnProperty('infoWindow')) {
mapOptions.infoWindow = new Popup(mapOptions.infoWindow.options, mapOptions.infoWindow.srcNodeRef);
}

if ($attrs.webmapId) {
arcgisUtils.createMap($attrs.webmapId, $attrs.id, {
mapOptions: mapOptions
}).then(function(response) {
mapDeferred.resolve(response.map);

var geoCenter = response.map.geographicExtent.getCenter();
Expand All @@ -233,98 +246,34 @@
$scope.zoom = response.map.getZoom();
$scope.itemInfo = response.itemInfo;
});
}
else
{
// setup our map options based on the attributes and scope
var mapOptions = {};

} else {
// center/zoom/extent
// check for convenience extent attribute
// check for mapOptions extent property
// otherwise get from scope center/zoom
if ($attrs.extent) {
mapOptions.extent = $scope[$attrs.extent];
} else {
if ($scope.center.lng && $scope.center.lat) {
mapOptions.center = [$scope.center.lng, $scope.center.lat];
} else if ($scope.center) {
mapOptions.center = $scope.center;
// if (!mapOptions.extent) {
if ($scope.center) {
if ($scope.center.lng && $scope.center.lat) {
mapOptions.center = [$scope.center.lng, $scope.center.lat];
} else {
mapOptions.center = $scope.center;
}
}
if ($scope.zoom) {
mapOptions.zoom = $scope.zoom;
}
}
// }

// basemap
// $scope.basemap takes precedence over $scope.mapOptions.basemap
if ($scope.basemap) {
mapOptions.basemap = $scope.basemap;
}

// strings
if ($attrs.navigationMode) {
if ($attrs.navigationMode !== 'css-transforms' && $attrs.navigationMode !== 'classic') {
throw new Error('navigationMode must be \'css-transforms\' or \'classic\'.');
} else {
mapOptions.navigationMode = $attrs.navigationMode;
}
}

if ($attrs.sliderOrientation) {
if ($attrs.sliderOrientation !== 'horizontal' && $attrs.sliderOrientation !== 'vertical') {
throw new Error('sliderOrientation must be \'horizontal\' or \'vertical\'.');
} else {
mapOptions.sliderOrientation = $attrs.sliderOrientation;
}
}

if ($attrs.sliderPosition) {
var allowed = ['top-left', 'top-right', 'bottom-left', 'bottom-right'];
if (allowed.indexOf($attrs.sliderPosition) < 0) {
throw new Error('sliderPosition must be in ' + allowed);
} else {
mapOptions.sliderPosition = $attrs.sliderPosition;
}
}

// This attribute does not seem to have any effect on the underlying map slider.
// Not sure if it is being passed to the API correctly.
if ($attrs.sliderStyle) {
if ($attrs.sliderStyle !== 'large' && $attrs.sliderStyle !== 'small') {
throw new Error('sliderStyle must be \'large\' or \'small\'.');
} else {
mapOptions.sliderStyle = $attrs.sliderStyle;
}
}

// booleans
var bools = [
'autoResize', 'displayGraphicsOnPan', 'fadeOnZoom', 'fitExtent', 'force3DTransforms',
'logo', 'nav', 'optimizePanAnimation', 'showAttribution', 'showInfoWindowOnClick',
'slider', 'smartNavigation', 'wrapAround180'
];
angular.forEach(bools, function (key) {
if (typeof $attrs[key] !== 'undefined') {
mapOptions[key] = $attrs[key].toString() === 'true';
}
});

// numeric attributes
var numeric = [
'attributionWidth', 'maxScale', 'maxZoom', 'minScale', 'minZoom', 'resizeDelay', 'scale'
];
angular.forEach(numeric, function (key) {
if ($attrs[key]) {
mapOptions[key] = $attrs[key];
}
});

// initialize map and resolve the deferred
var map = new Map($attrs.id, mapOptions);
mapDeferred.resolve(map);
}

mapDeferred.promise.then(function(map)
{
mapDeferred.promise.then(function(map) {
// make a reference to the map object available
// to the controller once it is loaded.
map.on('load', function() {
Expand All @@ -336,70 +285,62 @@
});
});

// listen for changes to scope and update map
// listen for changes to $scope.basemap and update map
$scope.$watch('basemap', function(newBasemap, oldBasemap) {
if (map.loaded && newBasemap !== oldBasemap) {
map.setBasemap(newBasemap);
}
});

// listen for changes to $scope.center and $scope.zoom and update map
$scope.inUpdateCycle = false;
if (!angular.isUndefined($scope.center) || !angular.isUndefined($scope.zoom)) {
$scope.$watchGroup(['center.lng', 'center.lat', 'zoom'], function(newCenterZoom/*, oldCenterZoom*/) {
if ($scope.inUpdateCycle) {
return;
}
if (newCenterZoom[0] !== '' && newCenterZoom[1] !== '' && newCenterZoom[2] !== '') {
$scope.inUpdateCycle = true; // prevent circular updates between $watch and $apply
map.centerAndZoom([newCenterZoom[0], newCenterZoom[1]], newCenterZoom[2]).then(function() {
$scope.inUpdateCycle = false;
});
}
});
}

$scope.$watch(function(scope){ return [scope.center.lng,scope.center.lat, scope.zoom].join(',');}, function(newCenterZoom,oldCenterZoom)
// $scope.$watchGroup(['center.lng','center.lat', 'zoom'], function(newCenterZoom,oldCenterZoom) // supported starting at Angular 1.3
{
if( $scope.inUpdateCycle ) {
return;
}

console.log('center/zoom changed', newCenterZoom, oldCenterZoom);
newCenterZoom = newCenterZoom.split(',');
if( newCenterZoom[0] !== '' && newCenterZoom[1] !== '' && newCenterZoom[2] !== '' )
{
$scope.inUpdateCycle = true; // prevent circular updates between $watch and $apply
map.centerAndZoom([newCenterZoom[0], newCenterZoom[1]], newCenterZoom[2]).then(function()
{
console.log('after centerAndZoom()');
$scope.inUpdateCycle = false;
});
}
});

map.on('extent-change', function(e)
{
if( $scope.inUpdateCycle ) {
// listen for changes to map extent and then
// update $scope.center and $scope.zoom
// and call extent-change handler (if any)
map.on('extent-change', function(e) {
if ($scope.inUpdateCycle) {
return;
}

$scope.inUpdateCycle = true; // prevent circular updates between $watch and $apply

console.log('extent-change geo', map.geographicExtent);

$scope.$apply(function()
{
var geoCenter = map.geographicExtent.getCenter();

$scope.center.lng = geoCenter.x;
$scope.center.lat = geoCenter.y;
$scope.zoom = map.getZoom();
$scope.inUpdateCycle = true; // prevent circular updates between $watch and $apply
$scope.$apply(function() {
if (e.extent.spatialReference.wkid === 4326 || e.extent.spatialReference.isWebMercator()) {
var geoCenter = map.geographicExtent.getCenter();
$scope.center = {
lat: geoCenter.y,
lng: geoCenter.x
};
$scope.zoom = map.getZoom();
}

// we might want to execute event handler even if $scope.inUpdateCycle is true
if( $attrs.extentChange ) {
if ($attrs.extentChange) {
$scope.extentChange()(e);
}

$timeout(function(){
$timeout(function() {
// this will be executed after the $digest cycle
console.log('after apply()');
$scope.inUpdateCycle = false;
},0);
}, 0);
});
});

// clean up
$scope.$on('$destroy', function () {
$scope.$on('$destroy', function() {
map.destroy();
// TODO: anything else?
});
});
});
Expand Down
Loading

0 comments on commit 0dde574

Please sign in to comment.