diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index ad37b3a..0000000 Binary files a/.DS_Store and /dev/null differ diff --git a/.gitignore b/.gitignore index 2421ac0..e773f31 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ node_modules .tmp .sass-cache bower_components +.DS_Store diff --git a/README.markdown b/README.markdown index 573b17a..80f0441 100644 --- a/README.markdown +++ b/README.markdown @@ -2,7 +2,7 @@ > AngularJS directives for Nokia Here Maps -For pull requests please see branching strategy below! +For pull requests please see branching strategy below! Master (1.2.6): [![Build Status](https://travis-ci.org/lukemarsh/angular-here-maps.svg?branch=master)](https://travis-ci.org/lukemarsh/angular-here-maps) @@ -60,7 +60,10 @@ Add some configuration settings: appCode: 'your Here Maps app code', libraries: 'ui,mapevents,pano', pixelRatio: 2, // Optional (Default: 1) - pixelPerInch: 320 // Optional (Default: 72) + pixelPerInch: 320, // Optional (Default: 72) + useHTTPS: true, + zoomMax: 16, + zoomMin: 13 }); }) ``` @@ -74,17 +77,116 @@ default center and zoom for the maps: ```js $scope.map = { zoom : 14, - center : { + center : { lng: -0.135559, lat: 51.513872 } }; ``` +You can choose the map type: default `normal` and `satellite`: + +```html + +``` + +```js +$scope.map = { + zoom : 14, + center : { + lng: -0.135559, + lat: 51.513872 + }, + type: 'satellite' +}; +``` + +### Map Events + +#### onLoad Map + +```html + +``` + +```js +$scope.mapOnLoad = function(platform, map){ + var center = map.getCenter(); +}; +``` + +#### onTap Map + +```html + +``` + +```js +$scope.mapEventOnTap = function(event, platform, map){ + // center map on tap + var coord = map.screenToGeo(event.currentPointer.viewportX, event.currentPointer.viewportY); + $scope.$apply(function(){ + $scope.map.center = coord; + }); +}; +``` + +#### onDoubleTap Map + +```html + +``` + +```js +$scope.mapEventOnDoubleTap = function(event, platform, map){ + // center map on double tap + var coord = map.screenToGeo(event.currentPointer.viewportX, event.currentPointer.viewportY); + $scope.$apply(function(){ + $scope.map.center = coord; + }); +}; +``` + +#### onDragStart Map + +```html + +``` + +```js +$scope.mapEventOnDragStart = function(event, platform, map){ + +}; +``` + +#### onDrag Map + +```html + +``` + +```js +$scope.mapEventOnDrag = function(event, platform, map){ + +}; +``` + +#### onDragEnd Map + +```html + +``` + +```js +$scope.mapEventOnDragEnd = function(event, platform, map){ + +}; +``` + If you plan to hack on the directives or want to run the example, first thing to do is to install NPM dependencies: ```shell -npm install #note bower install is run on post install +npm install #note bower install is run on post install ``` ### Building @@ -117,13 +219,13 @@ The various directives are documented at [official site](http://lukemarsh.github ### Contributing -Filing issues: +Filing issues: Prior to submiting an issue: - Search open/**closed** issues, src examples (./examples), and gitter! **Again please search!** - issues w/ plnkrs get attention quicker -Pull requests more than welcome! If you're adding new features, it would be appreciated if you would provide some docs about the feature. -This can be done either by adding a card to our [Waffle.io board](https://waffle.io/lukemarsh/angular-here-maps), forking the website +Pull requests more than welcome! If you're adding new features, it would be appreciated if you would provide some docs about the feature. +This can be done either by adding a card to our [Waffle.io board](https://waffle.io/lukemarsh/angular-here-maps), forking the website branch and issuing a PR with the updated documentation page, or by opening an issue for us to add the documentation to the site. ### Branching Scheme diff --git a/app/development/app.js b/app/development/app.js index 923e2f2..90f7d2d 100644 --- a/app/development/app.js +++ b/app/development/app.js @@ -10,6 +10,9 @@ angular appCode: 'WT6i13vXvx1JbFky92wqjg', libraries: 'ui,mapevents,pano', pixelRatio: 2, - pixelPerInch: 320 + pixelPerInch: 320, + useHTTPS: true, + zoomMax: 16, + zoomMin: 13 }); }); diff --git a/app/development/controllers/MapController.js b/app/development/controllers/MapController.js index e7bf248..d2a17d5 100644 --- a/app/development/controllers/MapController.js +++ b/app/development/controllers/MapController.js @@ -7,18 +7,20 @@ angular.module('angular-here-maps-development') $scope.windowContent = 'DEF'; $scope.map = { zoom : 14, - center : { + center : { lng: -0.135559, lat: 51.513872 - } + }, + animation: true, + typeMap: 'normal' // normal || satellite }; $scope.marker = { coordinates : { - lng: -0.14, + lng: -0.15, lat: 51.513872 }, icon: { - templateUrl: 'development/templates/icon test.html', + templateUrl: 'development/templates/icon.html', window: { template: 'hello' }, @@ -48,7 +50,7 @@ angular.module('angular-here-maps-development') lat: 51.513872 }, icon: { - template: '
new icon
' + template: '
new icon
' }, id: 1 }, @@ -71,4 +73,52 @@ angular.module('angular-here-maps-development') } } }; - }); \ No newline at end of file + + $scope.moveCenter = function(){ + $scope.map.center = { + lng: $scope.map.center.lng + (Math.random() / 100), + lat: $scope.map.center.lat + (Math.random() / 100) + }; + }; + + $scope.mapOnLoad = function(platform, map){ + $scope.platform = platform; + $scope.mapObj = map; + }; + + /** + * Example Center Map on Tap + */ + $scope.mapEventOnTap = function(event, platform, map){ + console.log('mapEventOnTap event', event, platform, map); + var coord = map.screenToGeo(event.currentPointer.viewportX, event.currentPointer.viewportY); + $scope.$apply(function(){ + $scope.map.center = coord; + }); + }; + + $scope.mapEventOnDoubleTap = function(event, platform, map){ + console.log('mapEventOnDoubleTap event', event, platform, map); + }; + + $scope.mapEventOnDragStart = function(event, platform, map){ + console.log('mapEventOnDragStart event', event, platform, map); + }; + + $scope.mapEventOnDrag = function(event, platform, map){ + console.log('mapEventOnDrag event', event, platform, map); + }; + + $scope.mapEventOnDragEnd = function(event, platform, map){ + console.log('mapEventOnDragEnd event', event, platform, map); + }; + + $scope.plusZoom = function(){ + $scope.map.zoom++; + }; + + $scope.minusZoom = function(){ + $scope.map.zoom--; + }; + + }); diff --git a/app/development/templates/icon.html b/app/development/templates/icon.html index 2e4b601..1b7d807 100644 --- a/app/development/templates/icon.html +++ b/app/development/templates/icon.html @@ -1 +1 @@ -
this is the icon {{id}} {{number}}
\ No newline at end of file +
this is the icon {{id}} {{number}}
diff --git a/app/index.html b/app/index.html index 93fe71a..e0e2f78 100644 --- a/app/index.html +++ b/app/index.html @@ -15,12 +15,16 @@ @@ -28,11 +32,32 @@ - - + +

Custom Buttons

+ + Map Type: + +
+ + Zoom: + +
+ + Move Center: +
diff --git a/app/scripts/directives/map.js b/app/scripts/directives/map.js index 47e3a87..18d4154 100644 --- a/app/scripts/directives/map.js +++ b/app/scripts/directives/map.js @@ -7,23 +7,39 @@ * # map */ angular.module('angular-here-maps') - .directive('map', function (MapConfig, $document, $compile) { + .directive('map', ['MapConfig', '$document', '$compile', '$window', function (MapConfig, $document, $compile, $window) { return { template: '
', restrict: 'EA', transclude: true, replace: true, - controller: function($scope, $element, $attrs) { - var defaultLayers, - modules, - behavior, - marker, - markerWindow, - group; - - $scope.zoom = $scope.helpers.useDotNotation($scope, $attrs.zoom); - $scope.center = $scope.helpers.useDotNotation($scope, $attrs.center); - $scope.bounds = $scope.helpers.useDotNotation($scope, $attrs.bounds); + scope: { + animation: '=', + bounds: '=', + center: '=', + draggable: '=', + onLoad: '=', + onTap: '=', + onDoubleTap: '=', + onDragStart: '=', + onDrag: '=', + onDragEnd: '=', + type: '=?', + layer: '=?', + wheelzoom: '=', + zoom: '=' + }, + controller: function($scope, $element) { + + var defaultLayers; + var modules; + var behavior; + var marker; + var markerWindow; + var group; + var animation = $scope.animation || false; + $scope.type = angular.isDefined($scope.type) ? $scope.type : 'normal'; + $scope.layer = angular.isDefined($scope.layer) ? $scope.layer : 'map'; if (MapConfig.libraries()) { modules = MapConfig.libraries().split(','); @@ -51,39 +67,55 @@ angular.module('angular-here-maps') $scope.mapObject = new H.Map( $element[0], - defaultLayers.normal.map, + defaultLayers[$scope.type][$scope.layer], { pixelRatio: MapConfig.pixelRatio() } ); - if ($scope.zoom) { - $scope.mapObject.setZoom($scope.zoom); - } + var zoomMax = MapConfig.zoomMax(); + var zoomMin = MapConfig.zoomMin(); - if ($scope.center) { - $scope.mapObject.setCenter($scope.center); - } + $scope.$watch('zoom', function(zoom){ + if (zoom) { + if (zoom > zoomMax){ + $scope.zoom = zoomMax; + return; + } + if (zoom < zoomMin){ + $scope.zoom = zoomMin; + return; + } + $scope.mapObject.setZoom(zoom, animation); + } + }); + + $scope.$watch('center', function(center){ + if (center) { + $scope.mapObject.setCenter(center, animation); + } + }); var setViewBounds = function(bounds) { var bbox = new H.geo.Rect(bounds[0], bounds[1], bounds[2], bounds[3]); $scope.mapObject.setViewBounds(bbox); }; - if ($scope.bounds) { - setViewBounds($scope.bounds); - } + $scope.$watch('bounds', function(bounds) { + if (bounds) { + setViewBounds(bounds); + } + }); - if ($attrs.bounds) { - $scope.$watch($attrs.bounds, function() { - if ($scope.bounds) { - $scope.bounds = $scope.helpers.useDotNotation($scope, $attrs.bounds); - setViewBounds($scope.bounds); - } - }); - } + $scope.$watchGroup(['type', 'layer'], function(newValues) { + var type = newValues[0]; + var layer = newValues[1]; + if (type && layer) { + $scope.mapObject.setBaseLayer(defaultLayers[type][layer]); + } + }); - window.addEventListener('resize', function () { + $window.addEventListener('resize', function () { $scope.mapObject.getViewPort().resize(); }.bind(this)); @@ -219,17 +251,52 @@ angular.module('angular-here-maps') this.createMapMarker(group, coordinates, icon, id); this.createMarkerWindows(group, coordinates, icon); - marker.setData(coordinates); - $scope.mapObject.addObject(group); if (marker) { + marker.setData(coordinates); group.addObject(marker); } }; $scope.mapObject.addEventListener('mapviewchangeend', function() { $scope.refreshMarkers(); + // $scope.zoom = $scope.mapObject.getZoom(); }); + + if (angular.isFunction($scope.onLoad)){ + $scope.onLoad(platform, $scope.mapObject); + } + + if (angular.isFunction($scope.onTap)){ + $scope.mapObject.addEventListener('tap', function(event) { + $scope.onTap(event, platform, $scope.mapObject); + }); + } + + if (angular.isFunction($scope.onDoubleTap)){ + $scope.mapObject.addEventListener('dbltap', function(event) { + $scope.onDoubleTap(event, platform, $scope.mapObject); + }); + } + + if (angular.isFunction($scope.onDragStart)){ + $scope.mapObject.addEventListener('dragstart', function(event) { + $scope.onDragStart(event, platform, $scope.mapObject); + }); + } + + if (angular.isFunction($scope.onDrag)){ + $scope.mapObject.addEventListener('drag', function(event) { + $scope.onDrag(event, platform, $scope.mapObject); + }); + } + + if (angular.isFunction($scope.onDragEnd)){ + $scope.mapObject.addEventListener('dragend', function(event) { + $scope.onDragEnd(event, platform, $scope.mapObject); + }); + } + } }; - }); + }]); diff --git a/app/scripts/directives/marker.js b/app/scripts/directives/marker.js index 32b39ee..1c2f198 100644 --- a/app/scripts/directives/marker.js +++ b/app/scripts/directives/marker.js @@ -11,22 +11,22 @@ angular.module('angular-here-maps') return { require: '^map', scope: { - coordinates: '=', - icon: '=' + coordinates: '=', + icon: '=', + zIndex: '=' }, restrict: 'E', link: function(scope, element, attrs, mapController) { var icon = scope.icon || ''; var coordinates; - - scope.addMarker = function() { + scope.addMarker = function() { if (scope.coordinates) { coordinates = scope.coordinates; mapController.addMarkerToMap(scope.coordinates, icon); } }; - scope.$watch('coordinates', function() { + scope.$watch('coordinates', function() { if (coordinates) { mapController.removeMarker(); } diff --git a/app/scripts/services/MapConfig.js b/app/scripts/services/MapConfig.js index fb7d9f1..40915ae 100644 --- a/app/scripts/services/MapConfig.js +++ b/app/scripts/services/MapConfig.js @@ -30,6 +30,15 @@ angular.module('angular-here-maps') }, libraries: function(libraries) { return mapOptions.libraries || libraries; + }, + useHTTPS: function(https) { + return mapOptions.useHTTPS || https; + }, + zoomMax: function() { + return mapOptions.zoomMax || 18; + }, + zoomMin: function() { + return mapOptions.zoomMin || 1; } }; }; diff --git a/examples/.DS_Store b/examples/.DS_Store deleted file mode 100644 index 24bc81d..0000000 Binary files a/examples/.DS_Store and /dev/null differ diff --git a/package.json b/package.json index e75b817..055b3d9 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "inherits": "^2.0.1" }, "devDependencies": { + "glob": "^7.0.3", "grunt": "^0.4.1", "grunt-autoprefixer": "^0.7.3", "grunt-bump": "^0.3.0", @@ -23,17 +24,21 @@ "grunt-contrib-watch": "^0.6.1", "grunt-filerev": "^0.2.1", "grunt-google-cdn": "^0.4.0", - "grunt-karma": "^0.10.1", + "grunt-karma": "^2.0.0", "grunt-newer": "^0.7.0", "grunt-ng-annotate": "^0.3.0", "grunt-svgmin": "^0.4.0", "grunt-usemin": "^2.1.1", "grunt-wiredep": "^1.7.0", + "jasmine-core": "^2.4.1", "jshint-stylish": "^0.2.0", + "karma": "^0.13.22", "karma-chrome-launcher": "^0.1.7", "karma-jasmine": "^0.3.5", - "karma-phantomjs-launcher": "^0.1.4", + "karma-phantomjs-launcher": "^1.0.0", "load-grunt-tasks": "^0.4.0", + "lodash": "^4.13.1", + "phantomjs-prebuilt": "^2.1.7", "time-grunt": "^0.3.1" }, "engines": { diff --git a/test/spec/directives/map.js b/test/spec/directives/map.js index d734c3d..4b018e4 100644 --- a/test/spec/directives/map.js +++ b/test/spec/directives/map.js @@ -8,10 +8,11 @@ describe('Directive: map', function () { var element, scope, compile, - mapController; + mapController, + isolateScope; - beforeEach(inject(function ($rootScope, _$compile_) { - scope = $rootScope.$new(); + beforeEach(inject(function (_$compile_, _$rootScope_) { + scope = _$rootScope_.$new(); compile = _$compile_; })); @@ -20,6 +21,7 @@ describe('Directive: map', function () { compile(element)(scope); scope.$digest(); mapController = element.controller('map'); + isolateScope = element.isolateScope(); } beforeEach(function() { @@ -28,10 +30,11 @@ describe('Directive: map', function () { lng: -0.13, lat: 51 }, - zoom: 14 + zoom: 14, + type: 'satellite' }; - element = ''; + element = ''; compileDirective(element); }); @@ -43,18 +46,24 @@ describe('Directive: map', function () { expect((element[0]).className).toContain('here-map'); }); - describe('Rendering the map with center and zoom values', function() { + describe('Rendering the map with center, zoom and type', function() { it('should have access to center', function() { - expect(element.scope().center).toBeDefined(); - expect(element.scope().center.lng).toEqual(-0.13); - expect(element.scope().center.lat).toEqual(51); + expect(isolateScope.center).toBeDefined(); + expect(isolateScope.center.lng).toEqual(-0.13); + expect(isolateScope.center.lat).toEqual(51); }); it('should have access to zoom', function() { - expect(element.scope().zoom).toBeDefined(); - expect(element.scope().zoom).toEqual(14); + expect(isolateScope.zoom).toBeDefined(); + expect(isolateScope.zoom).toEqual(14); }); + + it('should have access to type', function() { + expect(isolateScope.type).toBeDefined(); + expect(isolateScope.type).toEqual('satellite'); + }); + }); describe('Rendering the map without center values', function() { @@ -65,7 +74,7 @@ describe('Directive: map', function () { }); it('should not have access to center', function() { - expect(element.scope().center).toBeUndefined(); + expect(isolateScope.center).toBeUndefined(); }); }); @@ -77,7 +86,11 @@ describe('Directive: map', function () { }); it('should not have access to zoom', function() { - expect(element.scope().zoom).toBeUndefined(); + expect(isolateScope.zoom).toBeUndefined(); + }); + + it('should have default type normal', function() { + expect(isolateScope.type).toEqual('normal'); }); }); diff --git a/test/spec/services/MapConfig.js b/test/spec/services/MapConfig.js index 80a9168..4e85725 100644 --- a/test/spec/services/MapConfig.js +++ b/test/spec/services/MapConfig.js @@ -4,7 +4,7 @@ describe('Service: MapConfig', function () { beforeEach(module('angular-here-maps')); - var MapConfigProvider; + var MapConfigProvider, MapConfig; beforeEach(function() { angular.module('mockModule', []) @@ -12,11 +12,14 @@ describe('Service: MapConfig', function () { MapConfigProvider = _MapConfigProvider_; MapConfigProvider.setOptions({ - appId: 'Q4azLpJlFAp5pkcEbagu', - appCode: 'WT6i13vXvx1JbFky92wqjg', + appId: 'dEuIUI8oyzMGgrJVq4dz', + appCode: '_g3jrZwSCHmKTRFcrySZQw', libraries: 'ui,mapevents,pano', pixelRatio: 2, - pixelPerInch: 320 + pixelPerInch: 320, + useHTTPS: false, + zoomMax: 15, + zoomMin: 5 }); }); @@ -30,11 +33,11 @@ describe('Service: MapConfig', function () { }); it('appId() should return the appId provided', function () { - expect(MapConfigProvider.mapOptions.appId).toEqual('Q4azLpJlFAp5pkcEbagu'); + expect(MapConfigProvider.mapOptions.appId).toEqual('dEuIUI8oyzMGgrJVq4dz'); }); it('appCode() should return the appCode provided', function () { - expect(MapConfigProvider.mapOptions.appCode).toEqual('WT6i13vXvx1JbFky92wqjg'); + expect(MapConfigProvider.mapOptions.appCode).toEqual('_g3jrZwSCHmKTRFcrySZQw'); }); it('libraries() should return the libraries provided', function () { @@ -49,4 +52,54 @@ describe('Service: MapConfig', function () { expect(MapConfigProvider.mapOptions.pixelPerInch).toEqual(320); }); + it('zoomMax should return the zoomMax provided', function() { + expect(MapConfigProvider.mapOptions.zoomMax).toEqual(15); + }); + + it('zoomMin should return the zoomMin provided', function() { + expect(MapConfigProvider.mapOptions.zoomMin).toEqual(5); + }); + + it('useHTTPS should return the useHTTPS provided', function() { + expect(MapConfigProvider.mapOptions.useHTTPS).toEqual(false); + }); + + it('setOptions should update mapOptions', function() { + var fakeOptions = { + test: true + }; + MapConfigProvider.setOptions(fakeOptions); + expect(MapConfigProvider.mapOptions).toEqual(fakeOptions); + }); + + + describe('MapConfig default values', function() { + + beforeEach(function(){ + + MapConfigProvider.setOptions({ + appId: 'dEuIUI8oyzMGgrJVq4dz', + appCode: '_g3jrZwSCHmKTRFcrySZQw', + libraries: 'ui,mapevents,pano', + pixelRatio: 2, + pixelPerInch: 320 + }); + + inject(function(_MapConfig_) { + MapConfig = _MapConfig_; + }); + + }); + + it('MapConfig.zoomMax() should return the default value 18', function() { + expect(MapConfig.zoomMax()).toEqual(18); + }); + + it('MapConfig.zoomMin() should return the default value 1', function() { + expect(MapConfig.zoomMin()).toEqual(1); + }); + + }); + + });