├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── dist
├── angular-heremaps.js
└── angular-heremaps.min.js
├── example
├── app.module.js
└── marker.svg
├── gulpfile.js
├── index.html
├── karma.conf.js
├── package.json
└── src
├── heremaps.directive.js
├── heremaps.directive.spec.js
├── index.js
└── providers
├── api.service.js
├── consts.js
├── map-modules
├── events
│ ├── events.js
│ └── infobubble.js
├── index.js
└── ui
│ └── ui.js
├── mapconfig.provider.js
├── maputils.service.js
├── markers
├── default.marker.js
├── dom.marker.js
├── index.js
├── marker.js
├── markers.service.js
└── svg.marker.js
└── routes
├── index.js
└── routes.service.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/*
2 | .idea/*
3 | coverage/
4 | .DS_Store
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | before_install:
2 | - npm install -g codeclimate-test-reporter
3 | install:
4 | - npm i
5 | language: node_js
6 | node_js:
7 | - "4.2.4"
8 | script:
9 | - ./node_modules/.bin/gulp build
10 | - npm test
11 | after_script:
12 | - codeclimate-test-reporter < ./coverage/**/lcov.info
13 | addons:
14 | code_climate:
15 | repo_token: c7535f88a3e1a0d9d2c8450a4e35e3c87fdf21251a7123957fbd34071a3cb545
16 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Dmytro Verbovyi
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/dverbovyi/angular-heremaps)
2 | [](https://codeclimate.com/github/dverbovyi/angular-heremaps)
3 | [](https://badge.fury.io/js/angular-heremaps)
4 |
5 |
6 | # angular-heremaps
7 | *Live demo* **https://dverbovyi.github.io/angular-heremaps/**
8 |
9 | AngularJS directive for working with Here Maps
10 |
11 | ### 0.1.9 latest release
12 | [see release notes](https://github.com/dverbovyi/angular-heremaps/releases/tag/v0.1.9)
13 |
14 | ### Install guide:
15 |
16 | npm install angular-heremaps
17 |
18 | ##### include angular-heremaps file
19 |
20 | ```html
21 |
22 | ```
23 |
24 | ##### add dependency in your angular application
25 |
26 | ```javascript
27 | angular.module('exampleModule', ['heremaps'])
28 | ```
29 |
30 | ##### add config provider:
31 | Before, you should register [here](https://developer.here.com/plans/api/consumer-mapping) and get your app id. Then pass it below
32 |
33 | ```javascript
34 | angular.module('exampleModule')
35 | .config(["HereMapsConfigProvider", function(HereMapsConfigProvider) {
36 | HereMapsConfigProvider.setOptions({
37 | 'app_id': 'your_app_id_here',
38 | 'app_code': 'your_app_code_here',
39 | 'useHTTPS': true
40 | });
41 | }]);
42 | ```
43 |
44 | #### Simple directive initialization with default options.
45 |
46 | ```html
47 |
48 | ```
49 |
50 | See details on [wiki pages](https://github.com/dverbovyi/angular-heremaps/wiki)
51 |
52 | Please report, any issue [here](https://github.com/dverbovyi/angular-heremaps/issues)
53 |
54 |
55 | ### To Contribute
56 |
57 | #### Fork and clone the project
58 | git clone https://github.com/{{username}}/angular-heremaps.git
59 |
60 | and make pull request
61 |
62 | #### Install dependencies
63 | cd angular-heremaps
64 |
65 | npm i
66 |
67 | #### Start dev-server
68 |
69 | gulp serve
70 |
71 | #### Build resources
72 |
73 | gulp build
74 |
75 |
--------------------------------------------------------------------------------
/dist/angular-heremaps.min.js:
--------------------------------------------------------------------------------
1 | !function e(t,r,n){function o(a,s){if(!r[a]){if(!t[a]){var u="function"==typeof require&&require;if(!s&&u)return u(a,!0);if(i)return i(a,!0);var c=new Error("Cannot find module '"+a+"'");throw c.code="MODULE_NOT_FOUND",c}var p=r[a]={exports:{}};t[a][0].call(p.exports,function(e){var r=t[a][1][e];return o(r||e)},p,p.exports,e,t,r,n)}return r[a].exports}for(var i="function"==typeof require&&require,a=0;a",replace:!0,scope:{opts:"&options",places:"&",onMapReady:"&mapReady",events:"&"},controller:l}}t.exports=n,n.$inject=["$timeout","$window","$rootScope","$filter","HereMapsConfig","HereMapsAPIService","HereMapsUtilsService","HereMapsMarkerService","HereMapsRoutesService","HereMapsCONSTS","HereMapsEventsFactory","HereMapsUiFactory"]},{}],2:[function(e,t,r){e("./providers/markers"),e("./providers/map-modules"),e("./providers/routes"),t.exports=angular.module("heremaps",["heremaps-markers-module","heremaps-routes-module","heremaps-map-modules"]).provider("HereMapsConfig",e("./providers/mapconfig.provider")).service("HereMapsUtilsService",e("./providers/maputils.service")).service("HereMapsAPIService",e("./providers/api.service")).constant("HereMapsCONSTS",e("./providers/consts")).directive("heremaps",e("./heremaps.directive"))},{"./heremaps.directive":1,"./providers/api.service":3,"./providers/consts":4,"./providers/map-modules":7,"./providers/mapconfig.provider":9,"./providers/maputils.service":10,"./providers/markers":13,"./providers/routes":17}],3:[function(e,t,r){function n(e,t,r,n,o){function i(){return h(O.CORE).then(function(){return h(O.SERVICE)})}function a(e,t){for(var r in t)if(t.hasOwnProperty(r)&&e[r]){var n=l(r);n().then(t[r])}}function s(t){var r=e.defer();return t&&n.isValidCoords(t.coords)?r.resolve({coords:t.coords}):navigator.geolocation.getCurrentPosition(function(e){r.resolve(e)},function(e){r.reject(e)},t),r.promise}function u(t,r){if(!r.coords)return console.error("Missed required coords");var n=t.getGeocodingService(),o=e.defer(),i={prox:[r.coords.lat,r.coords.lng,r.radius||250].join(","),mode:"retrieveAddresses",maxresults:"1",gen:"8",language:r.lang||"en-gb"};return n.reverseGeocode(i,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise}function c(t,r){if(!r)return console.error("Missed required parameters");var n=t.getGeocodingService(),o=e.defer(),i={gen:8};for(var a in r)i[a]=r[a];return n.geocode(i,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise}function p(n){if(!n)return console.error("Missing required parameters");var o=T+O.AUTOCOMPLETE_URL,i=e.defer(),a={query:"",beginHighlight:"",endHighlight:"",maxresults:"5"};for(var s in a)angular.isDefined(n[s])&&(a[s]=n[s]);return a.app_id=r.app_id,a.app_code=r.app_code,t.get(o,{params:a}).success(function(e){i.resolve(e)}).error(function(e){i.reject(e)}),i.promise}function d(n){if(!n)return console.error("Missing Location Identifier");var o=T+O.LOCATION_URL,i=e.defer(),a={locationid:n,gen:9,app_id:r.app_id,app_code:r.app_code};return t.get(o,{params:a}).success(function(e){i.resolve(e)}).error(function(e){i.reject(e)}),i.promise}function l(e){var t;switch(e){case o.MODULES.UI:t=f;break;case o.MODULES.EVENTS:t=m;break;default:throw new Error("Unknown module",e)}return t}function f(){if(!v(O.UI.src)){var e=n.createLinkTag({rel:"stylesheet",type:"text/css",href:g(O.UI.href)});e&&I.appendChild(e)}return h(O.UI.src)}function m(){return h(O.EVENTS)}function g(e){return[T,O.BASE,H.V,"/",H.SUB,"/",e].join("")}function h(t){var r,o,i=e.defer();return v(t)?i.resolve():(r=g(t),o=n.createScriptTag({src:r}),o&&I.appendChild(o),x[t].push(i),o.onload=k.bind(null,t),o.onerror=b.bind(null,t)),i.promise}function v(e){var t=null;switch(e){case O.CORE:t=E;break;case O.SERVICE:t=M;break;case O.UI.src:t=S;break;case O.EVENTS:t=w;break;default:t=function(){return!1}}return t()}function E(){return!!window.H}function M(){return!(!window.H||!window.H.service)}function S(){return!(!window.H||!window.H.ui)}function w(){return!(!window.H||!window.H.mapevents)}function k(e){for(var t=x[e],r=0,n=t.length;r',onStateChange:function(o){i.getState()!==H.ui.base.Button.State.DOWN&&e.getPosition().then(function(e){var o={lng:e.coords.longitude,lat:e.coords.latitude};if(n.map.setCenter(o),r.zoom(n.map,17,.08),n.userMarker)return void n.userMarker.setPosition(o);n.userMarker=t.addUserMarker(n.map,{pos:o})})}});return o.addChild(i),o}function s(e){if(o.isValidAlignment(this.alignment))for(var t in e){var r=this.ui.getControl(e[t]);e.hasOwnProperty(t)&&r&&r.setAlignment(this.alignment)}}function u(e){return!!(n.CONTROLS.POSITIONS.indexOf(e)+1)}o.isValidAlignment=u;var c=o.prototype;return c.setupControls=i,c.createUserControl=a,c.setControlsAlignment=s,{start:function(e){if(!(e.platform.map instanceof H.Map||e.platform.layers))return console.error("Missed ui module dependencies");new o(e.platform,e.alignment)}}}t.exports=n,n.$inject=["HereMapsAPIService","HereMapsMarkerService","HereMapsUtilsService","HereMapsCONSTS"]},{}],9:[function(e,t,r){t.exports=function(){var e={};this.$get=function(){return{app_id:e.app_id,app_code:e.app_code,apiVersion:e.apiVersion||"3.0",useHTTPS:e.useHTTPS,useCIT:!!e.useCIT,mapTileConfig:e.mapTileConfig}},this.setOptions=function(t){e=t}}},{}],10:[function(e,t,r){function n(e,t,r){function n(e,r){var n=null;return function(){t&&t.cancel(n),n=t(e,r)}}function o(e,t,r,n){e.addEventListener(t,r,!!n)}function i(e,t){return!(!e.$root||"$apply"===e.$root.$$phase||"$digest"===e.$root.$$phase)&&(e.$digest(t||angular.noop),!0)}function a(e){var t=document.getElementById(e.src);return!t&&(t=document.createElement("script"),t.type="text/javascript",t.id=e.src,f(t,e),t)}function s(e){var t=document.getElementById(e.href);return!t&&(t=document.createElement("link"),t.id=e.href,f(t,e),t)}function u(e){return e&&("string"==typeof e.latitude||"number"==typeof e.latitude)&&("string"==typeof e.longitude||"number"==typeof e.longitude)}function c(e,t,n){var o=e.getZoom(),i=(n||r.ANIMATION_ZOOM_STEP,o>=t?-1:1),a=n*i;return function r(){if(!n||Math.floor(o)===Math.floor(t))return void e.setZoom(t);o+=a,e.setZoom(o),requestAnimationFrame(r)}()}function p(){return H}function d(e,t){return H.geo.Rect.fromPoints(e,t,!0)}function l(){var e=/[xy]/g,t=(new Date).getTime();return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(e,function(e){var r=(t+16*Math.random())%16|0;return t=Math.floor(t/16),("x"==e?r:3&r|8).toString(16)})}function f(e,t){if(!e||!t)throw new Error("Missed attributes");for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])}return{throttle:n,createScriptTag:a,createLinkTag:s,runScopeDigestIfNeed:i,isValidCoords:u,addEventListener:o,zoom:c,getBoundsRectFromPoints:d,generateId:l,getMapFactory:p}}t.exports=n,n.$inject=["$rootScope","$timeout","HereMapsCONSTS"]},{}],11:[function(e,t,r){function n(e){function t(e){this.place=e,this.setCoords()}function r(){var e=new H.map.Marker(this.coords);return this.addInfoBubble(e),e}var n=t.prototype=new e;return n.constructor=t,n.create=r,t}t.exports=n,n.$inject=["HereMapsMarkerInterface"]},{}],12:[function(e,t,r){function n(e){function t(e){this.place=e,this.setCoords()}function r(){var e=new H.map.DomMarker(this.coords,{icon:this.getIcon()});return this.addInfoBubble(e),e}function n(){var e=this.place.markup;if(!e)throw new Error("markup missed");return new H.map.DomIcon(e)}function o(e,t,r){var n=r?"removeEventListener":"addEventListener";for(var o in t)t.hasOwnProperty(o)&&e[n].call(null,o,t[o])}var i=t.prototype=new e;return i.constructor=t,i.create=r,i.getIcon=n,i.setupEvents=o,t}t.exports=n,n.$inject=["HereMapsMarkerInterface"]},{}],13:[function(e,t,r){t.exports=angular.module("heremaps-markers-module",[]).factory("HereMapsMarkerInterface",e("./marker.js")).factory("HereMapsDefaultMarker",e("./default.marker.js")).factory("HereMapsDOMMarker",e("./dom.marker.js")).factory("HereMapsSVGMarker",e("./svg.marker.js")).service("HereMapsMarkerService",e("./markers.service.js"))},{"./default.marker.js":11,"./dom.marker.js":12,"./marker.js":14,"./markers.service.js":15,"./svg.marker.js":16}],14:[function(e,t,r){t.exports=function(){function e(){throw new Error("Abstract class! The Instance should be created")}function t(){}function r(){throw new Error("create:: not implemented")}function n(){this.coords={lat:this.place.pos.lat,lng:this.place.pos.lng}}function o(e){this.place.popup&&e.setData(this.place.popup)}var i=e.prototype;return i.create=r,i.setCoords=n,i.addInfoBubble=o,t.prototype=i,t}},{}],15:[function(e,t,r){function n(e,t,r,n){function o(e){return e instanceof H.map.Marker||e instanceof H.map.DomMarker}function i(e,t){return e.userMarker?e.userMarker:(t.markup='',e.userMarker=new r(t).create(),e.addObject(e.userMarker),e.userMarker)}function a(e,t,r){if(t&&t.length){if(!(e instanceof H.Map))throw new Error("Unsupported map instance");e.markersGroup||(e.markersGroup=new H.map.Group),t.forEach(function(t,r){var n=c(t),o=t.draggable?p(n.create()):n.create();e.markersGroup.addObject(o)}),e.addObject(e.markersGroup),r&&s(e,e.markersGroup.getBounds())}}function s(e,t,r){e.setViewBounds(t,!!r)}function u(e,t,r){e.markersGroup&&(e.markersGroup.removeAll(),e.removeObject(e.markersGroup),e.markersGroup=null),a.apply(null,arguments)}function c(n){var o;switch(n.type?n.type.toUpperCase():null){case d.DOM:o=t;break;case d.SVG:o=r;break;default:o=e}return new o(n)}function p(e){return e.draggable=!0,e}var d=n.MARKER_TYPES;return{addMarkersToMap:a,addUserMarker:i,updateMarkers:u,isMarkerInstance:o,setViewBounds:s}}t.exports=n,n.$inject=["HereMapsDefaultMarker","HereMapsDOMMarker","HereMapsSVGMarker","HereMapsCONSTS"]},{}],16:[function(e,t,r){function n(e){function t(e){this.place=e,this.setCoords()}function r(){var e=new H.map.Marker(this.coords,{icon:this.getIcon()});return this.addInfoBubble(e),e}function n(){var e=this.place.markup;if(!e)throw new Error("markup missed");return new H.map.Icon(e)}var o=t.prototype=new e;return o.constructor=t,o.create=r,o.getIcon=n,t}t.exports=n,n.$inject=["HereMapsMarkerInterface"]},{}],17:[function(e,t,r){t.exports=angular.module("heremaps-routes-module",[]).service("HereMapsRoutesService",e("./routes.service.js"))},{"./routes.service.js":18}],18:[function(e,t,r){function n(e,t){function r(t,r){var n=t.platform,o=(t.map,n.getRoutingService()),a=r.direction,s=a.waypoints,u="{{MODE}};{{VECHILE}}".replace(/{{MODE}}/,a.mode||"fastest").replace(/{{VECHILE}}/,r.driveType),c={mode:u,representation:a.representation||"display",language:a.language||"en-gb"};s.forEach(function(e,t){c["waypoint"+t]=[e.lat,e.lng].join(",")}),i(c,a.attrs);var p=e.defer();return o.calculateRoute(c,function(e){p.resolve(e)},function(e){p.reject(e)}),p.promise}function n(e){var t=e.routesGroup;t&&(t.removeAll(),e.removeObject(t),e.routesGroup=null)}function o(e,r,o){o&&n(e);var i=r.route;if(e&&i&&i.shape){var a=new H.geo.Strip,s=null;i.shape.forEach(function(e){var t=e.split(",");a.pushLatLngAlt(t[0],t[1])});var u=r.style||{};s=new H.map.Polyline(a,{style:{lineWidth:u.lineWidth||4,strokeColor:u.color||"rgba(0, 128, 255, 0.7)"}});var c=e.routesGroup;c||(c=e.routesGroup=new H.map.Group,e.addObject(c)),c.addObject(s),r.zoomToBounds&&t.setViewBounds(e,s.getBounds(),!0)}}function i(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r+"attributes"]=t[r])}return{calculateRoute:r,addRouteToMap:o,cleanRoutes:n}}t.exports=n,n.$inject=["$q","HereMapsMarkerService"]},{}]},{},[2]);
--------------------------------------------------------------------------------
/example/app.module.js:
--------------------------------------------------------------------------------
1 |
2 | (function () {
3 |
4 | 'use strict';
5 |
6 | angular
7 | .module('demoModule', ['heremaps'])
8 | .config(["HereMapsConfigProvider", function (HereMapsConfigProvider) {
9 | HereMapsConfigProvider.setOptions({
10 | 'app_id': 'DemoAppId01082013GAL',
11 | 'app_code': 'AJKnXv84fjrb0KIHawS0Tg',
12 | 'useHTTPS': true,
13 | 'useCIT': true,
14 | 'mapTileConfig': {
15 | metadataQueryParams: {
16 | 'lg2': 'ara'
17 | }
18 | }
19 | });
20 | }]);
21 |
22 | angular.module('demoModule')
23 | .controller('DemoCtrl', ['$scope', DemoCtrl]);
24 |
25 | function DemoCtrl($scope) {
26 | $scope.mapOptions = {
27 | height: 640,
28 | width: 480,
29 | zoom: 13,
30 | draggable: true,
31 | resize: true,
32 | coords: {
33 | longitude: 55.1021576,
34 | latitude: 25.064732
35 | }
36 | };
37 |
38 | $scope.onMapReady = function (heremaps) {
39 | $scope.heremaps = heremaps;
40 |
41 | heremaps.setCenter({
42 | lat: 25.1075831, lng: 55.159061
43 | });
44 |
45 | heremaps.setZoom(13);
46 |
47 | heremaps.calculateRoute('car', {
48 | mode: 'fastest',
49 | waypoints: [
50 | { lat: 25.1075831, lng: 55.1461 },
51 | { lat: 25.1075831, lng: 55.179061 }
52 | ]
53 | }).then(function(result){
54 | if(!result.response)
55 | return;
56 |
57 | heremaps.addRouteToMap({
58 | zoomToBounds: false,
59 | route: result.response.route[0],
60 | style: {
61 | lineWidth: 5,
62 | color: 'rgba(0, 128, 255, 1)'
63 | }
64 | });
65 | }).catch(handleError);
66 | };
67 |
68 | $scope.markers = [
69 | {
70 | pos: { lat: 25.1075831, lng: 55.1461 },
71 | popup: {
72 | display: 'onHover',
73 | markup: 'Default Marker
'
74 | }
75 | },
76 | {
77 | pos: { lat: 25.1075831, lng: 55.179061 }
78 | },
79 | {
80 | pos: { lat: 25.1075831, lng: 55.079061 },
81 | type: 'DOM',
82 | markup: 'DOM Marker
(Click me)
',
83 | popup: {
84 | display: 'onClick',
85 | markup: 'View on GitHub'
86 | }
87 | },
88 | {
89 | pos: { lat: 25.1075831, lng: 55.2 },
90 | type: 'SVG',
91 | draggable: true,
92 | markup: './example/marker.svg'
93 | }
94 | ];
95 |
96 | $scope.listeners = {
97 | 'click': function () {
98 | console.info('click');
99 | },
100 | 'mapviewchangeend': function () {
101 | console.info('mapviewchangeend');
102 | }
103 | };
104 |
105 | function handleError(e) {
106 | console.error(e);
107 | }
108 | }
109 | })();
--------------------------------------------------------------------------------
/example/marker.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Dmytro on 3/27/2016.
3 | */
4 | var browserify = require('browserify'),
5 | gulp = require('gulp'),
6 | source = require('vinyl-source-stream'),
7 | minify = require('gulp-minify'),
8 | buffer = require('vinyl-buffer'),
9 | config = require('./package.json'),
10 | argv = require('yargs').argv,
11 | browserSync = require("browser-sync").create();
12 |
13 | /* pathConfig*/
14 | var entryPoint = './src/index.js',
15 | browserDir = './',
16 | jsWatchPath = './src/**/*.js';
17 | /**/
18 |
19 | gulp.task('browser-sync', function () {
20 | browserSync.init({
21 | server: {
22 | baseDir: browserDir
23 | }
24 | });
25 | });
26 |
27 | gulp.task('build', function () {
28 | return browserify(entryPoint, { debug: true })
29 | .bundle()
30 | .pipe(source('angular-heremaps.js'))
31 | .pipe(buffer())
32 | .pipe(minify({
33 | ext: {
34 | min: '.min.js'
35 | },
36 | }))
37 | .pipe(gulp.dest('./dist/'))
38 | .pipe(browserSync.reload({ stream: true }));
39 | });
40 |
41 | gulp.task('serve', ['build', 'browser-sync'], function () {
42 | gulp.watch(jsWatchPath, ['build']).on('change', browserSync.reload);
43 | gulp.watch("index.html").on('change', browserSync.reload);
44 | })
45 |
46 | gulp.task('default', ['build']);
47 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Title
7 |
8 |
9 |
10 |
11 |
12 |
13 |
53 |
54 |
55 |
56 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Dmytro on 4/26/2016.
3 | */
4 | var istanbul = require('browserify-istanbul');
5 |
6 | module.exports = function (config) {
7 | config.set({
8 | basePath: '',
9 | frameworks: ['browserify', 'jasmine'],
10 |
11 | files: [
12 | './node_modules/angular/angular.js',
13 | './node_modules/angular-mocks/angular-mocks.js',
14 | './src/**/*.js',
15 | './src/**/*spec.js'
16 | ],
17 |
18 | preprocessors: {
19 | './src/**/*.js': ['browserify']
20 | },
21 |
22 | browserify: {
23 | debug: true,
24 | transform: ['browserify-istanbul']
25 | },
26 |
27 | colors: true,
28 | logLevel: config.LOG_INFO,
29 |
30 | plugins : [
31 | 'karma-browserify',
32 | 'karma-jasmine',
33 | 'karma-mocha-reporter',
34 | 'karma-phantomjs-launcher',
35 | 'karma-chrome-launcher',
36 | 'karma-coverage'
37 | ],
38 |
39 | reporters: ['mocha', 'progress', 'coverage'],
40 |
41 | coverageReporter: {
42 | reporters: [{
43 | type: 'lcov',
44 | dir: 'coverage/'
45 | }, {
46 | type: 'text-summary'
47 | }]
48 | },
49 |
50 | browsers: ['PhantomJS'],
51 | // browsers: ['Chrome'],
52 |
53 | autoWatch: false,
54 | singleRun: true
55 | });
56 | };
57 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-heremaps",
3 | "version": "0.1.9",
4 | "description": "Angular directive for working with HereMaps",
5 | "source-folder": "/dist",
6 | "main": "angular-heremaps.js",
7 | "output": "angular-heremaps.js",
8 | "scripts": {
9 | "test": "karma start",
10 | "build": "./node_modules/.bin/gulp build"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "git+https://github.com/dverbovyi/angular-heremaps.git"
15 | },
16 | "keywords": [
17 | "heremaps",
18 | "here maps",
19 | "javascript",
20 | "angular",
21 | "angularjs"
22 | ],
23 | "author": "Dmytro Verbovyi: https://github.com/dverbovyi, Andrii Vandakurov: https://github.com/toastman",
24 | "license": "MIT",
25 | "bugs": {
26 | "url": "https://github.com/dverbovyi/angular-heremaps/issues"
27 | },
28 | "homepage": "https://dverbovyi.github.io/angular-heremaps/",
29 | "dependencies": {
30 | "angular": "^1.5.6"
31 | },
32 | "devDependencies": {
33 | "angular-mocks": "^1.5.6",
34 | "browser-sync": "^2.16.0",
35 | "browserify": "^13.0.1",
36 | "browserify-istanbul": "^2.0.0",
37 | "gulp": "^3.9.1",
38 | "gulp-minify": "0.0.14",
39 | "gulp-sourcemaps": "^1.6.0",
40 | "istanbul": "^0.4.3",
41 | "jasmine": "^2.4.1",
42 | "karma": "^0.13.22",
43 | "karma-browserify": "^5.0.5",
44 | "karma-chrome-launcher": "^1.0.1",
45 | "karma-coverage": "^1.0.0",
46 | "karma-jasmine": "^1.0.2",
47 | "karma-mocha-reporter": "^2.0.3",
48 | "karma-phantomjs-launcher": "^1.0.0",
49 | "phantomjs-prebuilt": "^2.1.7",
50 | "vinyl-buffer": "^1.0.0",
51 | "vinyl-source-stream": "^1.1.0",
52 | "watchify": "^3.7.0",
53 | "yargs": "^4.7.1"
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/heremaps.directive.js:
--------------------------------------------------------------------------------
1 | module.exports = HereMapsDirective;
2 |
3 | HereMapsDirective.$inject = [
4 | '$timeout',
5 | '$window',
6 | '$rootScope',
7 | '$filter',
8 | 'HereMapsConfig',
9 | 'HereMapsAPIService',
10 | 'HereMapsUtilsService',
11 | 'HereMapsMarkerService',
12 | 'HereMapsRoutesService',
13 | 'HereMapsCONSTS',
14 | 'HereMapsEventsFactory',
15 | 'HereMapsUiFactory'
16 | ];
17 | function HereMapsDirective(
18 | $timeout,
19 | $window,
20 | $rootScope,
21 | $filter,
22 | HereMapsConfig,
23 | HereMapsAPIService,
24 | HereMapsUtilsService,
25 | HereMapsMarkerService,
26 | HereMapsRoutesService,
27 | HereMapsCONSTS,
28 | HereMapsEventsFactory,
29 | HereMapsUiFactory) {
30 |
31 | HereMapsDirectiveCtrl.$inject = ['$scope', '$element', '$attrs'];
32 |
33 | return {
34 | restrict: 'EA',
35 | template: "",
36 | replace: true,
37 | scope: {
38 | opts: '&options',
39 | places: '&',
40 | onMapReady: "&mapReady",
41 | events: '&'
42 | },
43 | controller: HereMapsDirectiveCtrl
44 | }
45 |
46 | function HereMapsDirectiveCtrl($scope, $element, $attrs) {
47 | var CONTROL_NAMES = HereMapsCONSTS.CONTROLS.NAMES,
48 | places = $scope.places(),
49 | opts = $scope.opts(),
50 | listeners = $scope.events();
51 |
52 | var options = angular.extend({}, HereMapsCONSTS.DEFAULT_MAP_OPTIONS, opts),
53 | position = HereMapsUtilsService.isValidCoords(options.coords) ?
54 | options.coords : HereMapsCONSTS.DEFAULT_MAP_OPTIONS.coords;
55 |
56 | var heremaps = { id: HereMapsUtilsService.generateId() },
57 | mapReady = $scope.onMapReady(),
58 | _onResizeMap = null;
59 |
60 | $timeout(function () {
61 | return _setMapSize();
62 | }).then(function () {
63 | HereMapsAPIService.loadApi().then(_apiReady);
64 | });
65 |
66 | options.resize && addOnResizeListener();
67 |
68 | $scope.$on('$destroy', function () {
69 | $window.removeEventListener('resize', _onResizeMap);
70 | });
71 |
72 | function addOnResizeListener() {
73 | _onResizeMap = HereMapsUtilsService.throttle(_resizeHandler, HereMapsCONSTS.UPDATE_MAP_RESIZE_TIMEOUT);
74 | $window.addEventListener('resize', _onResizeMap);
75 | }
76 |
77 | function _apiReady() {
78 | _setupMapPlatform();
79 | _setupMap();
80 | }
81 |
82 | function _setupMapPlatform() {
83 | if (!HereMapsConfig.app_id || !HereMapsConfig.app_code)
84 | throw new Error('app_id or app_code were missed. Please specify their in HereMapsConfig');
85 |
86 | heremaps.platform = new H.service.Platform(HereMapsConfig);
87 | heremaps.layers = heremaps.platform.createDefaultLayers();
88 | }
89 |
90 | function _getLocation(enableHighAccuracy, maximumAge) {
91 | var _enableHighAccuracy = !!enableHighAccuracy,
92 | _maximumAge = maximumAge || 0;
93 |
94 | return HereMapsAPIService.getPosition({
95 | enableHighAccuracy: _enableHighAccuracy,
96 | maximumAge: _maximumAge
97 | });
98 | }
99 |
100 | function _locationFailure() {
101 | console.error('Can not get a geo position');
102 | }
103 |
104 | function _setupMap() {
105 | _initMap(function () {
106 | HereMapsAPIService.loadModules($attrs.$attr, {
107 | "controls": _uiModuleReady,
108 | "events": _eventsModuleReady
109 | });
110 | });
111 | }
112 |
113 | function _initMap(cb) {
114 | var map = heremaps.map = new H.Map($element[0], heremaps.layers.normal.map, {
115 | zoom: HereMapsUtilsService.isValidCoords(position) ? options.zoom : options.maxZoom,
116 | center: new H.geo.Point(position.latitude, position.longitude)
117 | });
118 |
119 | HereMapsMarkerService.addMarkersToMap(map, places, true);
120 |
121 | if (HereMapsConfig.mapTileConfig)
122 | _setCustomMapStyles(map, HereMapsConfig.mapTileConfig);
123 |
124 | mapReady && mapReady(MapProxy());
125 |
126 | cb && cb();
127 |
128 | }
129 |
130 | function _uiModuleReady() {
131 | HereMapsUiFactory.start({
132 | platform: heremaps,
133 | alignment: $attrs.controls
134 | });
135 | }
136 |
137 | function _eventsModuleReady() {
138 | HereMapsEventsFactory.start({
139 | platform: heremaps,
140 | listeners: listeners,
141 | options: options,
142 | injector: _moduleInjector
143 | });
144 | }
145 |
146 | function _moduleInjector() {
147 | return function (id) {
148 | return heremaps[id];
149 | }
150 | }
151 |
152 | function _resizeHandler(height, width) {
153 | _setMapSize.apply(null, arguments);
154 |
155 | heremaps.map.getViewPort().resize();
156 | }
157 |
158 | function _setMapSize(height, width) {
159 | var height = height || $element[0].parentNode.offsetHeight || options.height,
160 | width = width || $element[0].parentNode.offsetWidth || options.width;
161 |
162 | $scope.mapHeight = height + 'px';
163 | $scope.mapWidth = width + 'px';
164 |
165 | HereMapsUtilsService.runScopeDigestIfNeed($scope);
166 | }
167 |
168 | function _setCustomMapStyles(map, config) {
169 | // Create a MapTileService instance to request base tiles (i.e. base.map.api.here.com):
170 | var mapTileService = heremaps.platform.getMapTileService({ 'type': 'base' });
171 |
172 | // Create a tile layer which requests map tiles
173 | var newStyleLayer = mapTileService.createTileLayer(
174 | 'maptile',
175 | config.scheme || 'normal.day',
176 | config.size || 256,
177 | config.format || 'png8',
178 | config.metadataQueryParams || {}
179 | );
180 |
181 | // Set new style layer as a base layer on the map:
182 | map.setBaseLayer(newStyleLayer);
183 | }
184 |
185 | function MapProxy() {
186 | return {
187 | refresh: function () {
188 | var currentBounds = this.getViewBounds();
189 |
190 | this.setMapSizes();
191 | this.setViewBounds(currentBounds);
192 | },
193 | setMapSizes: function (height, width) {
194 | _resizeHandler.apply(null, arguments);
195 | },
196 | getPlatform: function () {
197 | return heremaps;
198 | },
199 | calculateRoute: function (driveType, direction) {
200 | return HereMapsRoutesService.calculateRoute(heremaps, {
201 | driveType: driveType,
202 | direction: direction
203 | });
204 | },
205 | addRouteToMap: function (routeData, clean) {
206 | HereMapsRoutesService.addRouteToMap(heremaps.map, routeData, clean);
207 | },
208 | setZoom: function (zoom, step) {
209 | HereMapsUtilsService.zoom(heremaps.map, zoom || 10, step);
210 | },
211 | getZoom: function () {
212 | return heremaps.map.getZoom();
213 | },
214 | getCenter: function () {
215 | return heremaps.map.getCenter();
216 | },
217 | getViewBounds: function () {
218 | return heremaps.map.getViewBounds();
219 | },
220 | setViewBounds: function (boundingRect, opt_animate) {
221 | HereMapsMarkerService.setViewBounds(heremaps.map, boundingRect, opt_animate);
222 | },
223 | getBoundsRectFromPoints: function (topLeft, bottomRight) {
224 | return HereMapsUtilsService.getBoundsRectFromPoints.apply(null, arguments);
225 | },
226 | setCenter: function (coords, opt_animate) {
227 | if (!coords) {
228 | return console.error('coords are not specified!');
229 | }
230 |
231 | heremaps.map.setCenter(coords, opt_animate);
232 | },
233 | cleanRoutes: function () {
234 | HereMapsRoutesService.cleanRoutes(heremaps.map);
235 | },
236 |
237 | /**
238 | * @param {Boolean} enableHighAccuracy
239 | * @param {Number} maximumAge - the maximum age in milliseconds of a possible cached position that is acceptable to return. If set to 0, it means that the device cannot use a cached position and must attempt to retrieve the real current position
240 | * @return {Promise}
241 | */
242 | getUserLocation: function (enableHighAccuracy, maximumAge) {
243 | return _getLocation.apply(null, arguments).then(function (position) {
244 | var coords = position.coords;
245 |
246 | return {
247 | lat: coords.latitude,
248 | lng: coords.longitude
249 | };
250 | })
251 | },
252 | geocodePosition: function (coords, options) {
253 | return HereMapsAPIService.geocodePosition(heremaps.platform, {
254 | coords: coords,
255 | radius: options && options.radius,
256 | lang: options && options.lang
257 | });
258 | },
259 | geocodeAddress: function (address) {
260 | return HereMapsAPIService.geocodeAddress(heremaps.platform, {
261 | searchtext: address && address.searchtext,
262 | country: address && address.country,
263 | city: address && address.city,
264 | street: address && address.street,
265 | housenumber: address && address.housenumber
266 | });
267 | },
268 | geocodeAutocomplete: function (query, options) {
269 | return HereMapsAPIService.geocodeAutocomplete({
270 | query: query,
271 | beginHighlight: options && options.beginHighlight,
272 | endHighlight: options && options.endHighlight,
273 | maxresults: options && options.maxresults
274 | });
275 | },
276 | findLocationById: function (locationId) {
277 | return HereMapsAPIService.findLocationById(locationId);
278 | },
279 | updateMarkers: function (places, refreshViewbounds) {
280 | HereMapsMarkerService.updateMarkers(heremaps.map, places, refreshViewbounds);
281 | },
282 | getMapFactory: function (){
283 | return HereMapsUtilsService.getMapFactory();
284 | }
285 | }
286 | }
287 |
288 | }
289 | };
290 |
--------------------------------------------------------------------------------
/src/heremaps.directive.spec.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Dmytro on 4/11/2016.
3 | */
4 |
5 | describe('Here Maps directive', function () {
6 | var scope, $compile, $rootScope, $timeout,
7 | template = angular.element('');
8 |
9 |
10 | beforeEach(function(){
11 | angular.mock.module('heremaps');
12 |
13 | inject(function (_$compile_, _$rootScope_, _$timeout_) {
14 | $compile = _$compile_;
15 | $timeout = _$timeout_;
16 | $rootScope = _$rootScope_;
17 | $scope = $rootScope.$new();
18 | })
19 |
20 | });
21 |
22 | it('Should compile a directive', function () {
23 | var result = $compile(template)($scope);
24 | $timeout.flush();
25 | $scope.$digest();
26 | expect(result[0].outerHTML).toBe('');
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | require('./providers/markers');
2 | require('./providers/map-modules');
3 | require('./providers/routes');
4 |
5 | module.exports = angular.module('heremaps', [
6 | 'heremaps-markers-module',
7 | 'heremaps-routes-module',
8 | 'heremaps-map-modules'
9 | ])
10 | .provider('HereMapsConfig', require('./providers/mapconfig.provider'))
11 | .service('HereMapsUtilsService', require('./providers/maputils.service'))
12 | .service('HereMapsAPIService', require('./providers/api.service'))
13 | .constant('HereMapsCONSTS', require('./providers/consts'))
14 | .directive('heremaps', require('./heremaps.directive'));
15 |
--------------------------------------------------------------------------------
/src/providers/api.service.js:
--------------------------------------------------------------------------------
1 | module.exports = HereMapsAPIService;
2 |
3 | HereMapsAPIService.$inject = [
4 | '$q',
5 | '$http',
6 | 'HereMapsConfig',
7 | 'HereMapsUtilsService',
8 | 'HereMapsCONSTS'
9 | ];
10 | function HereMapsAPIService($q, $http, HereMapsConfig, HereMapsUtilsService, HereMapsCONSTS) {
11 | var version = HereMapsConfig.apiVersion,
12 | protocol = HereMapsConfig.useHTTPS ? 'https' : 'http';
13 |
14 | var API_VERSION = {
15 | V: parseInt(version),
16 | SUB: version
17 | };
18 |
19 | var CONFIG = {
20 | BASE: "://js.api.here.com/v",
21 | CORE: "mapsjs-core.js",
22 | SERVICE: "mapsjs-service.js",
23 | UI: {
24 | src: "mapsjs-ui.js",
25 | href: "mapsjs-ui.css"
26 | },
27 | EVENTS: "mapsjs-mapevents.js",
28 | AUTOCOMPLETE_URL: "://autocomplete.geocoder.cit.api.here.com/6.2/suggest.json",
29 | LOCATION_URL: "://geocoder.cit.api.here.com/6.2/geocode.json"
30 | };
31 |
32 | var API_DEFERSQueue = {};
33 |
34 | API_DEFERSQueue[CONFIG.CORE] = [];
35 | API_DEFERSQueue[CONFIG.SERVICE] = [];
36 | API_DEFERSQueue[CONFIG.UI.src] = [];
37 | API_DEFERSQueue[CONFIG.PANO] = [];
38 | API_DEFERSQueue[CONFIG.EVENTS] = [];
39 |
40 | var head = document.getElementsByTagName('head')[0];
41 |
42 | return {
43 | loadApi: loadApi,
44 | loadModules: loadModules,
45 | getPosition: getPosition,
46 | geocodePosition: geocodePosition,
47 | geocodeAddress: geocodeAddress,
48 | geocodeAutocomplete: geocodeAutocomplete,
49 | findLocationById: findLocationById
50 | };
51 |
52 | //#region PUBLIC
53 | function loadApi() {
54 | return _getLoader(CONFIG.CORE)
55 | .then(function () {
56 | return _getLoader(CONFIG.SERVICE);
57 | });
58 | }
59 |
60 | function loadModules(attrs, handlers) {
61 | for (var key in handlers) {
62 | if (!handlers.hasOwnProperty(key) || !attrs[key])
63 | continue;
64 |
65 | var loader = _getLoaderByAttr(key);
66 |
67 | loader()
68 | .then(handlers[key]);
69 | }
70 | }
71 |
72 | function getPosition(options) {
73 | var deferred = $q.defer();
74 |
75 | if (options && HereMapsUtilsService.isValidCoords(options.coords)) {
76 | deferred.resolve({ coords: options.coords });
77 | } else {
78 | navigator.geolocation.getCurrentPosition(function (response) {
79 | deferred.resolve(response);
80 | }, function (error) {
81 | deferred.reject(error);
82 | }, options);
83 | }
84 |
85 | return deferred.promise;
86 | }
87 |
88 | function geocodePosition(platform, params) {
89 | if (!params.coords)
90 | return console.error('Missed required coords');
91 |
92 | var geocoder = platform.getGeocodingService(),
93 | deferred = $q.defer(),
94 | _params = {
95 | prox: [params.coords.lat, params.coords.lng, params.radius || 250].join(','),
96 | mode: 'retrieveAddresses',
97 | maxresults: '1',
98 | gen: '8',
99 | language: params.lang || 'en-gb'
100 | };
101 |
102 | geocoder.reverseGeocode(_params, function (response) {
103 | deferred.resolve(response)
104 | }, function (error) {
105 | deferred.reject(error)
106 | });
107 |
108 | return deferred.promise;
109 | }
110 |
111 | function geocodeAddress(platform, params) {
112 | if (!params)
113 | return console.error('Missed required parameters');
114 |
115 | var geocoder = platform.getGeocodingService(),
116 | deferred = $q.defer(),
117 | _params = { gen: 8 };
118 |
119 | for (var key in params) { _params[key] = params[key]; }
120 |
121 | geocoder.geocode(_params, function (response) {
122 | deferred.resolve(response)
123 | }, function (error) {
124 | deferred.reject(error)
125 | });
126 |
127 | return deferred.promise;
128 | }
129 |
130 | function geocodeAutocomplete(params) {
131 | if (!params)
132 | return console.error('Missing required parameters');
133 |
134 | var autocompleteUrl = protocol + CONFIG.AUTOCOMPLETE_URL,
135 | deferred = $q.defer(),
136 | _params = {
137 | query: "",
138 | beginHighlight: "",
139 | endHighlight: "",
140 | maxresults: "5"
141 | };
142 |
143 | for (var key in _params) {
144 | if (angular.isDefined(params[key])) {
145 | _params[key] = params[key];
146 | }
147 | }
148 |
149 | _params.app_id = HereMapsConfig.app_id;
150 | _params.app_code = HereMapsConfig.app_code;
151 |
152 | $http.get(autocompleteUrl, { params: _params })
153 | .success(function(response) {
154 | deferred.resolve(response);
155 | })
156 | .error(function(error) {
157 | deferred.reject(error);
158 | });
159 |
160 | return deferred.promise;
161 | }
162 |
163 | /**
164 | * Finds location by HERE Maps Location identifier.
165 | */
166 | function findLocationById(locationId) {
167 | if (!locationId)
168 | return console.error('Missing Location Identifier');
169 |
170 | var locationUrl = protocol + CONFIG.LOCATION_URL,
171 | deferred = $q.defer(),
172 | _params = {
173 | locationid: locationId,
174 | gen: 9,
175 | app_id: HereMapsConfig.app_id,
176 | app_code: HereMapsConfig.app_code
177 | };
178 |
179 | $http.get(locationUrl, { params: _params })
180 | .success(function(response) {
181 | deferred.resolve(response);
182 | })
183 | .error(function(error) {
184 | deferred.reject(error);
185 | });
186 |
187 | return deferred.promise;
188 | }
189 |
190 | //#endregion PUBLIC
191 |
192 | function _getLoaderByAttr(attr) {
193 | var loader;
194 |
195 | switch (attr) {
196 | case HereMapsCONSTS.MODULES.UI:
197 | loader = _loadUIModule;
198 | break;
199 | case HereMapsCONSTS.MODULES.EVENTS:
200 | loader = _loadEventsModule;
201 | break;
202 | default:
203 | throw new Error('Unknown module', attr);
204 | }
205 |
206 | return loader;
207 | }
208 |
209 | function _loadUIModule() {
210 | if (!_isLoaded(CONFIG.UI.src)) {
211 | var link = HereMapsUtilsService.createLinkTag({
212 | rel: 'stylesheet',
213 | type: 'text/css',
214 | href: _getURL(CONFIG.UI.href)
215 | });
216 |
217 | link && head.appendChild(link);
218 | }
219 |
220 | return _getLoader(CONFIG.UI.src);
221 | }
222 |
223 | function _loadEventsModule() {
224 | return _getLoader(CONFIG.EVENTS);
225 | }
226 |
227 | /**
228 | * @param {String} sourceName
229 | * return {String} e.g http://js.api.here.com/v{VER}/{SUBVERSION}/{SOURCE}
230 | */
231 | function _getURL(sourceName) {
232 | return [
233 | protocol,
234 | CONFIG.BASE,
235 | API_VERSION.V,
236 | "/",
237 | API_VERSION.SUB,
238 | "/",
239 | sourceName
240 | ].join("");
241 | }
242 |
243 | function _getLoader(sourceName) {
244 | var defer = $q.defer(), src, script;
245 |
246 | if (_isLoaded(sourceName)) {
247 | defer.resolve();
248 | } else {
249 | src = _getURL(sourceName);
250 | script = HereMapsUtilsService.createScriptTag({ src: src });
251 |
252 | script && head.appendChild(script);
253 |
254 | API_DEFERSQueue[sourceName].push(defer);
255 |
256 | script.onload = _onLoad.bind(null, sourceName);
257 | script.onerror = _onError.bind(null, sourceName);
258 | }
259 |
260 | return defer.promise;
261 | }
262 |
263 | function _isLoaded(sourceName) {
264 | var checker = null;
265 |
266 | switch (sourceName) {
267 | case CONFIG.CORE:
268 | checker = _isCoreLoaded;
269 | break;
270 | case CONFIG.SERVICE:
271 | checker = _isServiceLoaded;
272 | break;
273 | case CONFIG.UI.src:
274 | checker = _isUILoaded;
275 | break;
276 | case CONFIG.EVENTS:
277 | checker = _isEventsLoaded;
278 | break;
279 | default:
280 | checker = function () { return false };
281 | }
282 |
283 | return checker();
284 | }
285 |
286 | function _isCoreLoaded() {
287 | return !!window.H;
288 | }
289 |
290 | function _isServiceLoaded() {
291 | return !!(window.H && window.H.service);
292 | }
293 |
294 | function _isUILoaded() {
295 | return !!(window.H && window.H.ui);
296 | }
297 |
298 | function _isEventsLoaded() {
299 | return !!(window.H && window.H.mapevents);
300 | }
301 |
302 | function _onLoad(sourceName) {
303 | var deferQueue = API_DEFERSQueue[sourceName];
304 | for (var i = 0, l = deferQueue.length; i < l; ++i) {
305 | var defer = deferQueue[i];
306 | defer.resolve();
307 | }
308 |
309 | API_DEFERSQueue[sourceName] = [];
310 | }
311 |
312 | function _onError(sourceName) {
313 | var deferQueue = API_DEFERSQueue[sourceName];
314 | for (var i = 0, l = deferQueue.length; i < l; ++i) {
315 | var defer = deferQueue[i];
316 | defer.reject();
317 | }
318 |
319 | API_DEFERSQueue[sourceName] = [];
320 | }
321 | };
322 |
--------------------------------------------------------------------------------
/src/providers/consts.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | UPDATE_MAP_RESIZE_TIMEOUT: 500,
3 | ANIMATION_ZOOM_STEP: .05,
4 | MODULES: {
5 | UI: 'controls',
6 | EVENTS: 'events',
7 | PANO: 'pano'
8 | },
9 | DEFAULT_MAP_OPTIONS: {
10 | height: 480,
11 | width: 640,
12 | zoom: 12,
13 | maxZoom: 2,
14 | resize: false,
15 | draggable: false,
16 | coords: {
17 | longitude: 0,
18 | latitude: 0
19 | }
20 | },
21 | MARKER_TYPES: {
22 | DOM: "DOM",
23 | SVG: "SVG"
24 | },
25 | CONTROLS: {
26 | NAMES: {
27 | SCALE: 'scalebar',
28 | SETTINGS: 'mapsettings',
29 | ZOOM: 'zoom',
30 | USER: 'userposition'
31 | },
32 | POSITIONS: [
33 | 'top-right',
34 | 'top-center',
35 | 'top-left',
36 | 'left-top',
37 | 'left-middle',
38 | 'left-bottom',
39 | 'right-top',
40 | 'right-middle',
41 | 'right-bottom',
42 | 'bottom-right',
43 | 'bottom-center',
44 | 'bottom-left'
45 | ]
46 | },
47 | INFOBUBBLE: {
48 | STATE: {
49 | OPEN: 'open',
50 | CLOSED: 'closed'
51 | },
52 | DISPLAY_EVENT: {
53 | pointermove: 'onHover',
54 | tap: 'onClick'
55 | }
56 | },
57 | USER_EVENTS: {
58 | tap: 'click',
59 | pointermove: 'mousemove',
60 | pointerleave: 'mouseleave',
61 | pointerenter: 'mouseenter',
62 | drag: 'drag',
63 | dragstart: 'dragstart',
64 | dragend: 'dragend',
65 | mapviewchange: 'mapviewchange',
66 | mapviewchangestart: 'mapviewchangestart',
67 | mapviewchangeend: 'mapviewchangeend'
68 | }
69 | }
--------------------------------------------------------------------------------
/src/providers/map-modules/events/events.js:
--------------------------------------------------------------------------------
1 | module.exports = HereMapsEventsFactory;
2 |
3 | HereMapsEventsFactory.$inject = [
4 | 'HereMapsUtilsService',
5 | 'HereMapsMarkerService',
6 | 'HereMapsCONSTS',
7 | 'HereMapsInfoBubbleFactory'
8 | ];
9 | function HereMapsEventsFactory(HereMapsUtilsService, HereMapsMarkerService, HereMapsCONSTS, HereMapsInfoBubbleFactory) {
10 | function Events(platform, Injector, listeners) {
11 | this.map = platform.map;
12 | this.listeners = listeners;
13 | this.inject = new Injector();
14 | this.events = platform.events = new H.mapevents.MapEvents(this.map);
15 | this.behavior = platform.behavior = new H.mapevents.Behavior(this.events);
16 | this.bubble = HereMapsInfoBubbleFactory.create();
17 |
18 | this.setupEventListeners();
19 | }
20 |
21 | var proto = Events.prototype;
22 |
23 | proto.setupEventListeners = setupEventListeners;
24 | proto.setupOptions = setupOptions;
25 | proto.triggerUserListener = triggerUserListener;
26 | proto.infoBubbleHandler = infoBubbleHandler;
27 |
28 | return {
29 | start: function(args) {
30 | if (!(args.platform.map instanceof H.Map))
31 | return console.error('Missed required map instance');
32 |
33 | var events = new Events(args.platform, args.injector, args.listeners);
34 |
35 | args.options && events.setupOptions(args.options);
36 | }
37 | }
38 |
39 | function setupEventListeners() {
40 | var self = this;
41 |
42 | HereMapsUtilsService.addEventListener(this.map, 'tap', this.infoBubbleHandler.bind(this));
43 |
44 | HereMapsUtilsService.addEventListener(this.map, 'pointermove', this.infoBubbleHandler.bind(this));
45 |
46 | HereMapsUtilsService.addEventListener(this.map, 'dragstart', function(e) {
47 | if (HereMapsMarkerService.isMarkerInstance(e.target)) {
48 | self.behavior.disable();
49 | }
50 |
51 | self.triggerUserListener(HereMapsCONSTS.USER_EVENTS[e.type], e);
52 | });
53 |
54 | HereMapsUtilsService.addEventListener(this.map, 'drag', function(e) {
55 | var pointer = e.currentPointer,
56 | target = e.target;
57 |
58 | if (HereMapsMarkerService.isMarkerInstance(target)) {
59 | target.setPosition(self.map.screenToGeo(pointer.viewportX, pointer.viewportY));
60 | }
61 |
62 | self.triggerUserListener(HereMapsCONSTS.USER_EVENTS[e.type], e);
63 | });
64 |
65 | HereMapsUtilsService.addEventListener(this.map, 'dragend', function(e) {
66 | if (HereMapsMarkerService.isMarkerInstance(e.target)) {
67 | self.behavior.enable();
68 | }
69 |
70 | self.triggerUserListener(HereMapsCONSTS.USER_EVENTS[e.type], e);
71 | });
72 |
73 | HereMapsUtilsService.addEventListener(this.map, 'mapviewchangestart', function(e) {
74 | self.triggerUserListener(HereMapsCONSTS.USER_EVENTS[e.type], e);
75 | });
76 |
77 | HereMapsUtilsService.addEventListener(this.map, 'mapviewchange', function(e) {
78 | self.triggerUserListener(HereMapsCONSTS.USER_EVENTS[e.type], e);
79 | });
80 |
81 | HereMapsUtilsService.addEventListener(this.map, 'mapviewchangeend', function(e) {
82 | self.triggerUserListener(HereMapsCONSTS.USER_EVENTS[e.type], e);
83 | });
84 | }
85 |
86 | function setupOptions(options) {
87 | if (!options)
88 | return;
89 |
90 | this.map.draggable = !!options.draggable;
91 | }
92 |
93 | function triggerUserListener(eventName, e) {
94 | if (!this.listeners)
95 | return;
96 |
97 | var callback = this.listeners[eventName];
98 |
99 | callback && callback(e);
100 | }
101 |
102 | function infoBubbleHandler(e){
103 | var ui = this.inject('ui');
104 |
105 | if(ui)
106 | this.bubble.toggle(e, ui);
107 |
108 | this.triggerUserListener(HereMapsCONSTS.USER_EVENTS[e.type], e);
109 | }
110 |
111 | };
--------------------------------------------------------------------------------
/src/providers/map-modules/events/infobubble.js:
--------------------------------------------------------------------------------
1 | module.exports = HereMapsInfoBubbleFactory;
2 |
3 | HereMapsInfoBubbleFactory.$inject = [
4 | 'HereMapsMarkerService',
5 | 'HereMapsUtilsService',
6 | 'HereMapsCONSTS'
7 | ];
8 | function HereMapsInfoBubbleFactory(HereMapsMarkerService, HereMapsUtilsService, HereMapsCONSTS) {
9 | function InfoBubble() {}
10 |
11 | var proto = InfoBubble.prototype;
12 |
13 | proto.create = create;
14 | proto.update = update;
15 | proto.toggle = toggle;
16 | proto.show = show;
17 | proto.close = close;
18 |
19 | return {
20 | create: function(){
21 | return new InfoBubble();
22 | }
23 | }
24 |
25 | function toggle(e, ui) {
26 | if (HereMapsMarkerService.isMarkerInstance(e.target))
27 | this.show(e, ui);
28 | else
29 | this.close(e, ui);
30 | }
31 |
32 | function update(bubble, data) {
33 | bubble.display = data.display;
34 |
35 | bubble.setPosition(data.position);
36 | bubble.setContent(data.markup);
37 |
38 | bubble.setState(HereMapsCONSTS.INFOBUBBLE.STATE.OPEN);
39 | }
40 |
41 | function create(source) {
42 | var bubble = new H.ui.InfoBubble(source.position, {
43 | content: source.markup
44 | });
45 |
46 | bubble.display = source.display;
47 | bubble.addClass(HereMapsCONSTS.INFOBUBBLE.STATE.OPEN)
48 |
49 | HereMapsUtilsService.addEventListener(bubble, 'statechange', function(e) {
50 | var state = this.getState(),
51 | el = this.getElement();
52 | if (state === HereMapsCONSTS.INFOBUBBLE.STATE.CLOSED) {
53 | el.classList.remove(HereMapsCONSTS.INFOBUBBLE.STATE.OPEN);
54 | } else
55 | this.addClass(state)
56 | });
57 |
58 | return bubble;
59 | }
60 |
61 | function show(e, ui, data) {
62 | var target = e.target,
63 | data = target.getData(),
64 | el = null;
65 |
66 | if (!data || !data.display || !data.markup || data.display !== HereMapsCONSTS.INFOBUBBLE.DISPLAY_EVENT[e.type])
67 | return;
68 |
69 | var source = {
70 | position: target.getPosition(),
71 | markup: data.markup,
72 | display: data.display
73 | };
74 |
75 | if (!ui.bubble) {
76 | ui.bubble = this.create(source);
77 | ui.addBubble(ui.bubble);
78 |
79 | return;
80 | }
81 |
82 | this.update(ui.bubble, source);
83 | }
84 |
85 | function close(e, ui) {
86 | if (!ui.bubble || ui.bubble.display !== HereMapsCONSTS.INFOBUBBLE.DISPLAY_EVENT[e.type]) {
87 | return;
88 | }
89 |
90 | ui.bubble.setState(HereMapsCONSTS.INFOBUBBLE.STATE.CLOSED);
91 | }
92 | }
--------------------------------------------------------------------------------
/src/providers/map-modules/index.js:
--------------------------------------------------------------------------------
1 | angular.module('heremaps-events-module', [])
2 | .factory('HereMapsEventsFactory', require('./events/events.js'))
3 | .factory('HereMapsInfoBubbleFactory', require('./events/infobubble.js'));
4 |
5 | angular.module('heremaps-ui-module', [])
6 | .factory('HereMapsUiFactory', require('./ui/ui.js'))
7 |
8 | module.exports = angular.module('heremaps-map-modules', [
9 | 'heremaps-events-module',
10 | 'heremaps-ui-module'
11 | ]);
--------------------------------------------------------------------------------
/src/providers/map-modules/ui/ui.js:
--------------------------------------------------------------------------------
1 | module.exports = HereMapsUiFactory;
2 |
3 | HereMapsUiFactory.$inject = [
4 | 'HereMapsAPIService',
5 | 'HereMapsMarkerService',
6 | 'HereMapsUtilsService',
7 | 'HereMapsCONSTS'
8 | ];
9 | function HereMapsUiFactory(HereMapsAPIService, HereMapsMarkerService, HereMapsUtilsService, HereMapsCONSTS) {
10 | function UI(platform, alignment) {
11 | this.map = platform.map;
12 | this.layers = platform.layers;
13 | this.alignment = alignment;
14 | this.ui = platform.ui = H.ui.UI.createDefault(this.map, this.layers);
15 |
16 | this.setupControls();
17 | }
18 |
19 | UI.isValidAlignment = isValidAlignment;
20 |
21 | var proto = UI.prototype;
22 |
23 | proto.setupControls = setupControls;
24 | proto.createUserControl = createUserControl;
25 | proto.setControlsAlignment = setControlsAlignment;
26 |
27 | return {
28 | start: function(args) {
29 | if (!(args.platform.map instanceof H.Map) && !(args.platform.layers))
30 | return console.error('Missed ui module dependencies');
31 |
32 | var ui = new UI(args.platform, args.alignment);
33 | }
34 | }
35 |
36 | function setupControls() {
37 | var NAMES = HereMapsCONSTS.CONTROLS.NAMES,
38 | userControl = this.createUserControl();
39 |
40 | this.ui.getControl(NAMES.SETTINGS).setIncidentsLayer(false);
41 | this.ui.addControl(NAMES.USER, userControl);
42 | this.setControlsAlignment(NAMES);
43 | }
44 |
45 | function createUserControl() {
46 | var self = this,
47 | userControl = new H.ui.Control(),
48 | markup = '';
49 |
50 | var userControlButton = new H.ui.base.Button({
51 | label: markup,
52 | onStateChange: function(evt) {
53 | if (userControlButton.getState() === H.ui.base.Button.State.DOWN)
54 | return;
55 |
56 | HereMapsAPIService.getPosition().then(function(response) {
57 | var position = {
58 | lng: response.coords.longitude,
59 | lat: response.coords.latitude
60 | };
61 |
62 | self.map.setCenter(position);
63 |
64 | HereMapsUtilsService.zoom(self.map, 17, .08);
65 |
66 | if (self.userMarker) {
67 | self.userMarker.setPosition(position);
68 | return;
69 | }
70 |
71 | self.userMarker = HereMapsMarkerService.addUserMarker(self.map, {
72 | pos: position
73 | });
74 | });
75 | }
76 | });
77 |
78 | userControl.addChild(userControlButton);
79 |
80 | return userControl;
81 | }
82 |
83 | function setControlsAlignment(NAMES) {
84 | if (!UI.isValidAlignment(this.alignment))
85 | return;
86 |
87 | for (var id in NAMES) {
88 | var control = this.ui.getControl(NAMES[id]);
89 |
90 | if (!NAMES.hasOwnProperty(id) || !control)
91 | continue;
92 |
93 | control.setAlignment(this.alignment);
94 | }
95 | }
96 |
97 | function isValidAlignment(alignment) {
98 | return !!(HereMapsCONSTS.CONTROLS.POSITIONS.indexOf(alignment) + 1);
99 | }
100 |
101 | };
--------------------------------------------------------------------------------
/src/providers/mapconfig.provider.js:
--------------------------------------------------------------------------------
1 | module.exports = function() {
2 | var options = {};
3 | var DEFAULT_API_VERSION = "3.0";
4 |
5 | this.$get = function(){
6 | return {
7 | app_id: options.app_id,
8 | app_code: options.app_code,
9 | apiVersion: options.apiVersion || DEFAULT_API_VERSION,
10 | useHTTPS: options.useHTTPS,
11 | useCIT: !!options.useCIT,
12 | mapTileConfig: options.mapTileConfig
13 | }
14 | };
15 |
16 | this.setOptions = function(opts){
17 | options = opts;
18 | };
19 | };
--------------------------------------------------------------------------------
/src/providers/maputils.service.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = HereMapsUtilsService;
3 |
4 | HereMapsUtilsService.$inject = [
5 | '$rootScope',
6 | '$timeout',
7 | 'HereMapsCONSTS'
8 | ];
9 | function HereMapsUtilsService($rootScope, $timeout, HereMapsCONSTS) {
10 | return {
11 | throttle: throttle,
12 | createScriptTag: createScriptTag,
13 | createLinkTag: createLinkTag,
14 | runScopeDigestIfNeed: runScopeDigestIfNeed,
15 | isValidCoords: isValidCoords,
16 | addEventListener: addEventListener,
17 | zoom: zoom,
18 | getBoundsRectFromPoints: getBoundsRectFromPoints,
19 | generateId: generateId,
20 | getMapFactory: getMapFactory
21 | };
22 |
23 | //#region PUBLIC
24 | function throttle(fn, period) {
25 | var timeout = null;
26 |
27 | return function () {
28 | if ($timeout)
29 | $timeout.cancel(timeout);
30 |
31 | timeout = $timeout(fn, period);
32 | }
33 | }
34 |
35 | function addEventListener(obj, eventName, listener, useCapture) {
36 | obj.addEventListener(eventName, listener, !!useCapture);
37 | }
38 |
39 | function runScopeDigestIfNeed(scope, cb) {
40 | if (scope.$root && scope.$root.$$phase !== '$apply' && scope.$root.$$phase !== '$digest') {
41 | scope.$digest(cb || angular.noop);
42 | return true;
43 | }
44 | return false;
45 | }
46 |
47 | function createScriptTag(attrs) {
48 | var script = document.getElementById(attrs.src);
49 |
50 | if (script)
51 | return false;
52 |
53 | script = document.createElement('script');
54 | script.type = 'text/javascript';
55 | script.id = attrs.src;
56 | _setAttrs(script, attrs);
57 |
58 | return script;
59 | }
60 |
61 | function createLinkTag(attrs) {
62 | var link = document.getElementById(attrs.href);
63 |
64 | if (link)
65 | return false;
66 |
67 | link = document.createElement('link');
68 | link.id = attrs.href;
69 | _setAttrs(link, attrs);
70 |
71 | return link;
72 | }
73 |
74 | function isValidCoords(coords) {
75 | return coords &&
76 | (typeof coords.latitude === 'string' || typeof coords.latitude === 'number') &&
77 | (typeof coords.longitude === 'string' || typeof coords.longitude === 'number')
78 | }
79 |
80 | function zoom(map, value, step) {
81 | var currentZoom = map.getZoom(),
82 | _step = step || HereMapsCONSTS.ANIMATION_ZOOM_STEP,
83 | factor = currentZoom >= value ? -1 : 1,
84 | increment = step * factor;
85 |
86 | return (function zoom() {
87 | if (!step || Math.floor(currentZoom) === Math.floor(value)) {
88 | map.setZoom(value);
89 | return;
90 | }
91 |
92 | currentZoom += increment;
93 | map.setZoom(currentZoom);
94 |
95 | requestAnimationFrame(zoom);
96 | })();
97 | }
98 |
99 | function getMapFactory(){
100 | return H;
101 | }
102 |
103 | /**
104 | * @method getBoundsRectFromPoints
105 | *
106 | * @param {Object} topLeft
107 | * @property {Number|String} lat
108 | * @property {Number|String} lng
109 | * @param {Object} bottomRight
110 | * @property {Number|String} lat
111 | * @property {Number|String} lng
112 | *
113 | * @return {H.geo.Rect}
114 | */
115 | function getBoundsRectFromPoints(topLeft, bottomRight) {
116 | return H.geo.Rect.fromPoints(topLeft, bottomRight, true);
117 | }
118 |
119 | function generateId() {
120 | var mask = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx',
121 | regexp = /[xy]/g,
122 | d = new Date().getTime(),
123 | uuid = mask.replace(regexp, function (c) {
124 | var r = (d + Math.random() * 16) % 16 | 0;
125 | d = Math.floor(d / 16);
126 | return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16);
127 | });
128 |
129 | return uuid;
130 | }
131 |
132 | //#endregion PUBLIC
133 |
134 | function _setAttrs(el, attrs) {
135 | if (!el || !attrs)
136 | throw new Error('Missed attributes');
137 |
138 | for (var key in attrs) {
139 | if (!attrs.hasOwnProperty(key))
140 | continue;
141 |
142 | el[key] = attrs[key];
143 | }
144 | }
145 | };
--------------------------------------------------------------------------------
/src/providers/markers/default.marker.js:
--------------------------------------------------------------------------------
1 | module.exports = HereMapsDefaultMarker;
2 |
3 | HereMapsDefaultMarker.$inject = ['HereMapsMarkerInterface'];
4 | function HereMapsDefaultMarker(HereMapsMarkerInterface){
5 | function DefaultMarker(place){
6 | this.place = place;
7 | this.setCoords();
8 | }
9 |
10 | var proto = DefaultMarker.prototype = new HereMapsMarkerInterface();
11 | proto.constructor = DefaultMarker;
12 |
13 | proto.create = create;
14 |
15 | return DefaultMarker;
16 |
17 | function create(){
18 | var marker = new H.map.Marker(this.coords);
19 |
20 | this.addInfoBubble(marker);
21 |
22 | return marker;
23 | }
24 | }
--------------------------------------------------------------------------------
/src/providers/markers/dom.marker.js:
--------------------------------------------------------------------------------
1 | module.exports = HereMapsDOMMarker;
2 |
3 | HereMapsDOMMarker.$inject = ['HereMapsMarkerInterface'];
4 | function HereMapsDOMMarker(HereMapsMarkerInterface){
5 | function DOMMarker(place){
6 | this.place = place;
7 | this.setCoords();
8 | }
9 |
10 | var proto = DOMMarker.prototype = new HereMapsMarkerInterface();
11 | proto.constructor = DOMMarker;
12 |
13 | proto.create = create;
14 | proto.getIcon = getIcon;
15 | proto.setupEvents = setupEvents;
16 |
17 | return DOMMarker;
18 |
19 | function create(){
20 | var marker = new H.map.DomMarker(this.coords, {
21 | icon: this.getIcon()
22 | });
23 |
24 | this.addInfoBubble(marker);
25 |
26 | return marker;
27 | }
28 |
29 | function getIcon(){
30 | var icon = this.place.markup;
31 | if(!icon)
32 | throw new Error('markup missed');
33 |
34 | return new H.map.DomIcon(icon);
35 | }
36 |
37 | function setupEvents(el, events, remove){
38 | var method = remove ? 'removeEventListener' : 'addEventListener';
39 |
40 | for(var key in events) {
41 | if(!events.hasOwnProperty(key))
42 | continue;
43 |
44 | el[method].call(null, key, events[key]);
45 | }
46 | }
47 | }
--------------------------------------------------------------------------------
/src/providers/markers/index.js:
--------------------------------------------------------------------------------
1 | module.exports = angular.module('heremaps-markers-module', [])
2 | .factory('HereMapsMarkerInterface', require('./marker.js'))
3 | .factory('HereMapsDefaultMarker', require('./default.marker.js'))
4 | .factory('HereMapsDOMMarker', require('./dom.marker.js'))
5 | .factory('HereMapsSVGMarker', require('./svg.marker.js'))
6 | .service('HereMapsMarkerService', require('./markers.service.js'));
--------------------------------------------------------------------------------
/src/providers/markers/marker.js:
--------------------------------------------------------------------------------
1 | module.exports = function(){
2 | function MarkerInterface(){
3 | throw new Error('Abstract class! The Instance should be created');
4 | }
5 |
6 | var proto = MarkerInterface.prototype;
7 |
8 | proto.create = create;
9 | proto.setCoords = setCoords;
10 | proto.addInfoBubble = addInfoBubble;
11 |
12 | function Marker(){}
13 |
14 | Marker.prototype = proto;
15 |
16 | return Marker;
17 |
18 | function create(){
19 | throw new Error('create:: not implemented');
20 | }
21 |
22 | function setCoords(){
23 | this.coords = {
24 | lat: this.place.pos.lat,
25 | lng: this.place.pos.lng
26 | }
27 | }
28 |
29 | function addInfoBubble(marker){
30 | if(!this.place.popup)
31 | return;
32 |
33 | marker.setData(this.place.popup)
34 | }
35 | }
--------------------------------------------------------------------------------
/src/providers/markers/markers.service.js:
--------------------------------------------------------------------------------
1 | module.exports = HereMapsMarkerService;
2 |
3 | HereMapsMarkerService.$inject = [
4 | 'HereMapsDefaultMarker',
5 | 'HereMapsDOMMarker',
6 | 'HereMapsSVGMarker',
7 | 'HereMapsCONSTS'
8 | ];
9 | function HereMapsMarkerService(HereMapsDefaultMarker, HereMapsDOMMarker, HereMapsSVGMarker, HereMapsCONSTS) {
10 | var MARKER_TYPES = HereMapsCONSTS.MARKER_TYPES;
11 |
12 | return {
13 | addMarkersToMap: addMarkersToMap,
14 | addUserMarker: addUserMarker,
15 | updateMarkers: updateMarkers,
16 | isMarkerInstance: isMarkerInstance,
17 | setViewBounds: setViewBounds
18 | }
19 |
20 | function isMarkerInstance(target) {
21 | return target instanceof H.map.Marker || target instanceof H.map.DomMarker;
22 | }
23 |
24 | function addUserMarker(map, place) {
25 | if (map.userMarker)
26 | return map.userMarker;
27 |
28 | place.markup = '';
37 |
38 | map.userMarker = new HereMapsSVGMarker(place).create();
39 |
40 | map.addObject(map.userMarker);
41 |
42 | return map.userMarker;
43 | }
44 |
45 | function addMarkersToMap(map, places, refreshViewbounds) {
46 | if (!places || !places.length)
47 | return;
48 |
49 | if (!(map instanceof H.Map))
50 | throw new Error('Unsupported map instance');
51 |
52 | if (!map.markersGroup)
53 | map.markersGroup = new H.map.Group();
54 |
55 | places.forEach(function (place, i) {
56 | var creator = _getMarkerCreator(place),
57 | marker = place.draggable ? _draggableMarkerMixin(creator.create()) : creator.create();
58 |
59 | map.markersGroup.addObject(marker);
60 | });
61 |
62 | map.addObject(map.markersGroup);
63 |
64 | if (refreshViewbounds) {
65 | setViewBounds(map, map.markersGroup.getBounds());
66 | }
67 | }
68 |
69 | function setViewBounds(map, bounds, opt_animate) {
70 | map.setViewBounds(bounds, !!opt_animate);
71 | }
72 |
73 | function updateMarkers(map, places, refreshViewbounds) {
74 | if (map.markersGroup) {
75 | map.markersGroup.removeAll();
76 | map.removeObject(map.markersGroup);
77 | map.markersGroup = null;
78 | }
79 |
80 | addMarkersToMap.apply(null, arguments);
81 | }
82 |
83 | function _getMarkerCreator(place) {
84 | var ConcreteMarker,
85 | type = place.type ? place.type.toUpperCase() : null;
86 |
87 | switch (type) {
88 | case MARKER_TYPES.DOM:
89 | ConcreteMarker = HereMapsDOMMarker;
90 | break;
91 | case MARKER_TYPES.SVG:
92 | ConcreteMarker = HereMapsSVGMarker;
93 | break;
94 | default:
95 | ConcreteMarker = HereMapsDefaultMarker;
96 | }
97 |
98 | return new ConcreteMarker(place);
99 | }
100 |
101 | function _draggableMarkerMixin(marker) {
102 | marker.draggable = true;
103 |
104 | return marker;
105 | }
106 | };
107 |
--------------------------------------------------------------------------------
/src/providers/markers/svg.marker.js:
--------------------------------------------------------------------------------
1 | module.exports = HereMapsSVGMarker;
2 |
3 | HereMapsSVGMarker.$inject = ['HereMapsMarkerInterface'];
4 | function HereMapsSVGMarker(HereMapsMarkerInterface){
5 | function SVGMarker(place){
6 | this.place = place;
7 | this.setCoords();
8 | }
9 |
10 | var proto = SVGMarker.prototype = new HereMapsMarkerInterface();
11 | proto.constructor = SVGMarker;
12 |
13 | proto.create = create;
14 | proto.getIcon = getIcon;
15 |
16 | return SVGMarker;
17 |
18 | function create(){
19 | var marker = new H.map.Marker(this.coords, {
20 | icon: this.getIcon(),
21 | });
22 |
23 | this.addInfoBubble(marker);
24 |
25 | return marker;
26 | }
27 |
28 | function getIcon(){
29 | var icon = this.place.markup;
30 | if(!icon)
31 | throw new Error('markup missed');
32 |
33 | return new H.map.Icon(icon);
34 | }
35 | }
--------------------------------------------------------------------------------
/src/providers/routes/index.js:
--------------------------------------------------------------------------------
1 | module.exports = angular.module('heremaps-routes-module', [])
2 | .service('HereMapsRoutesService', require('./routes.service.js'));
--------------------------------------------------------------------------------
/src/providers/routes/routes.service.js:
--------------------------------------------------------------------------------
1 | module.exports = HereMapsRoutesService;
2 |
3 | HereMapsRoutesService.$inject = ['$q', 'HereMapsMarkerService'];
4 | function HereMapsRoutesService($q, HereMapsMarkerService) {
5 | return {
6 | calculateRoute: calculateRoute,
7 | addRouteToMap: addRouteToMap,
8 | cleanRoutes: cleanRoutes
9 | }
10 |
11 | function calculateRoute(heremaps, config) {
12 | var platform = heremaps.platform,
13 | map = heremaps.map,
14 | router = platform.getRoutingService(),
15 | dir = config.direction,
16 | waypoints = dir.waypoints;
17 |
18 | var mode = '{{MODE}};{{VECHILE}}'
19 | .replace(/{{MODE}}/, dir.mode || 'fastest')
20 | .replace(/{{VECHILE}}/, config.driveType);
21 |
22 | var routeRequestParams = {
23 | mode: mode,
24 | representation: dir.representation || 'display',
25 | language: dir.language || 'en-gb'
26 | };
27 |
28 | waypoints.forEach(function (waypoint, i) {
29 | routeRequestParams["waypoint" + i] = [waypoint.lat, waypoint.lng].join(',');
30 | });
31 |
32 | _setAttributes(routeRequestParams, dir.attrs);
33 |
34 | var deferred = $q.defer();
35 |
36 | router.calculateRoute(routeRequestParams, function (result) {
37 | deferred.resolve(result);
38 | }, function (error) {
39 | deferred.reject(error);
40 | });
41 |
42 | return deferred.promise;
43 | }
44 |
45 | function cleanRoutes(map) {
46 | var group = map.routesGroup;
47 |
48 | if (!group)
49 | return;
50 |
51 | group.removeAll();
52 | map.removeObject(group);
53 | map.routesGroup = null;
54 | }
55 |
56 | function addRouteToMap(map, routeData, clean) {
57 | if (clean)
58 | cleanRoutes(map);
59 |
60 | var route = routeData.route;
61 |
62 | if (!map || !route || !route.shape)
63 | return;
64 |
65 | var strip = new H.geo.Strip(), polyline = null;
66 |
67 | route.shape.forEach(function (point) {
68 | var parts = point.split(',');
69 | strip.pushLatLngAlt(parts[0], parts[1]);
70 | });
71 |
72 | var style = routeData.style || {};
73 |
74 | polyline = new H.map.Polyline(strip, {
75 | style: {
76 | lineWidth: style.lineWidth || 4,
77 | strokeColor: style.color || 'rgba(0, 128, 255, 0.7)'
78 | }
79 | });
80 |
81 | var group = map.routesGroup;
82 |
83 | if (!group) {
84 | group = map.routesGroup = new H.map.Group();
85 | map.addObject(group);
86 | }
87 |
88 | group.addObject(polyline);
89 |
90 | if(routeData.zoomToBounds) {
91 | HereMapsMarkerService.setViewBounds(map, polyline.getBounds(), true);
92 | }
93 | }
94 |
95 | //#region PRIVATE
96 |
97 | function _setAttributes(params, attrs) {
98 | var _key = 'attributes';
99 | for (var key in attrs) {
100 | if (!attrs.hasOwnProperty(key))
101 | continue;
102 |
103 | params[key + _key] = attrs[key];
104 | }
105 | }
106 |
107 | /**
108 | * Creates a series of H.map.Marker points from the route and adds them to the map.
109 | * @param {Object} route A route as received from the H.service.RoutingService
110 | */
111 | function addManueversToMap(map, route) {
112 | var svgMarkup = '',
117 | dotIcon = new H.map.Icon(svgMarkup, { anchor: { x: 8, y: 8 } }),
118 | group = new H.map.Group(), i, j;
119 |
120 | // Add a marker for each maneuver
121 | for (i = 0; i < route.leg.length; i += 1) {
122 | for (j = 0; j < route.leg[i].maneuver.length; j += 1) {
123 | // Get the next maneuver.
124 | maneuver = route.leg[i].maneuver[j];
125 | // Add a marker to the maneuvers group
126 | var marker = new H.map.Marker({
127 | lat: maneuver.position.latitude,
128 | lng: maneuver.position.longitude
129 | },
130 | { icon: dotIcon }
131 | );
132 |
133 | marker.instruction = maneuver.instruction;
134 | group.addObject(marker);
135 | }
136 | }
137 |
138 | group.addEventListener('tap', function (evt) {
139 | map.setCenter(evt.target.getPosition());
140 | openBubble(evt.target.getPosition(), evt.target.instruction);
141 | }, false);
142 |
143 | // Add the maneuvers group to the map
144 | map.addObject(group);
145 | }
146 |
147 |
148 | /**
149 | * Creates a series of H.map.Marker points from the route and adds them to the map.
150 | * @param {Object} route A route as received from the H.service.RoutingService
151 | */
152 | function addWaypointsToPanel(waypoints) {
153 | var nodeH3 = document.createElement('h3'),
154 | waypointLabels = [],
155 | i;
156 |
157 | for (i = 0; i < waypoints.length; i += 1) {
158 | waypointLabels.push(waypoints[i].label)
159 | }
160 |
161 | nodeH3.textContent = waypointLabels.join(' - ');
162 |
163 | routeInstructionsContainer.innerHTML = '';
164 | routeInstructionsContainer.appendChild(nodeH3);
165 | }
166 |
167 | /**
168 | * Creates a series of H.map.Marker points from the route and adds them to the map.
169 | * @param {Object} route A route as received from the H.service.RoutingService
170 | */
171 | function addSummaryToPanel(summary) {
172 | var summaryDiv = document.createElement('div'),
173 | content = '';
174 |
175 | content += 'Total distance: ' + summary.distance + 'm.
';
176 | content += 'Travel Time: ' + summary.travelTime.toMMSS() + ' (in current traffic)';
177 |
178 |
179 | summaryDiv.style.fontSize = 'small';
180 | summaryDiv.style.marginLeft = '5%';
181 | summaryDiv.style.marginRight = '5%';
182 | summaryDiv.innerHTML = content;
183 | routeInstructionsContainer.appendChild(summaryDiv);
184 | }
185 |
186 | /**
187 | * Creates a series of H.map.Marker points from the route and adds them to the map.
188 | * @param {Object} route A route as received from the H.service.RoutingService
189 | */
190 | function addManueversToPanel(route) {
191 | var nodeOL = document.createElement('ol'), i, j;
192 |
193 | nodeOL.style.fontSize = 'small';
194 | nodeOL.style.marginLeft = '5%';
195 | nodeOL.style.marginRight = '5%';
196 | nodeOL.className = 'directions';
197 |
198 | // Add a marker for each maneuver
199 | for (i = 0; i < route.leg.length; i += 1) {
200 | for (j = 0; j < route.leg[i].maneuver.length; j += 1) {
201 | // Get the next maneuver.
202 | maneuver = route.leg[i].maneuver[j];
203 |
204 | var li = document.createElement('li'),
205 | spanArrow = document.createElement('span'),
206 | spanInstruction = document.createElement('span');
207 |
208 | spanArrow.className = 'arrow ' + maneuver.action;
209 | spanInstruction.innerHTML = maneuver.instruction;
210 | li.appendChild(spanArrow);
211 | li.appendChild(spanInstruction);
212 |
213 | nodeOL.appendChild(li);
214 | }
215 | }
216 |
217 | routeInstructionsContainer.appendChild(nodeOL);
218 | }
219 |
220 | };
221 |
--------------------------------------------------------------------------------