angular-heremaps
Version:
Angular directive for working with Nokia Here Maps
1,599 lines (1,297 loc) • 136 kB
JavaScript
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
module.exports = HereMapsDirective;
HereMapsDirective.$inject = [
'$timeout',
'$window',
'$rootScope',
'$filter',
'HereMapsConfig',
'HereMapsAPIService',
'HereMapsUtilsService',
'HereMapsMarkerService',
'HereMapsRoutesService',
'HereMapsCONSTS',
'HereMapsEventsFactory',
'HereMapsUiFactory'
];
function HereMapsDirective(
$timeout,
$window,
$rootScope,
$filter,
HereMapsConfig,
HereMapsAPIService,
HereMapsUtilsService,
HereMapsMarkerService,
HereMapsRoutesService,
HereMapsCONSTS,
HereMapsEventsFactory,
HereMapsUiFactory) {
HereMapsDirectiveCtrl.$inject = ['$scope', '$element', '$attrs'];
return {
restrict: 'EA',
template: "<div ng-style=\"{'width': mapWidth, 'height': mapHeight}\"></div>",
replace: true,
scope: {
opts: '&options',
places: '&',
onMapReady: "&mapReady",
events: '&'
},
controller: HereMapsDirectiveCtrl
}
function HereMapsDirectiveCtrl($scope, $element, $attrs) {
var CONTROL_NAMES = HereMapsCONSTS.CONTROLS.NAMES,
places = $scope.places(),
opts = $scope.opts(),
listeners = $scope.events();
var options = angular.extend({}, HereMapsCONSTS.DEFAULT_MAP_OPTIONS, opts),
position = HereMapsUtilsService.isValidCoords(options.coords) ?
options.coords : HereMapsCONSTS.DEFAULT_MAP_OPTIONS.coords;
var heremaps = { id: HereMapsUtilsService.generateId() },
mapReady = $scope.onMapReady(),
_onResizeMap = null;
$timeout(function () {
return _setMapSize();
}).then(function () {
HereMapsAPIService.loadApi().then(_apiReady);
});
options.resize && addOnResizeListener();
$scope.$on('$destroy', function () {
$window.removeEventListener('resize', _onResizeMap);
});
function addOnResizeListener() {
_onResizeMap = HereMapsUtilsService.throttle(_resizeHandler, HereMapsCONSTS.UPDATE_MAP_RESIZE_TIMEOUT);
$window.addEventListener('resize', _onResizeMap);
}
function _apiReady() {
_setupMapPlatform();
_setupMap();
}
function _setupMapPlatform() {
if (!HereMapsConfig.app_id || !HereMapsConfig.app_code)
throw new Error('app_id or app_code were missed. Please specify their in HereMapsConfig');
heremaps.platform = new H.service.Platform(HereMapsConfig);
heremaps.layers = heremaps.platform.createDefaultLayers();
}
function _getLocation(enableHighAccuracy, maximumAge) {
var _enableHighAccuracy = !!enableHighAccuracy,
_maximumAge = maximumAge || 0;
return HereMapsAPIService.getPosition({
enableHighAccuracy: _enableHighAccuracy,
maximumAge: _maximumAge
});
}
function _locationFailure() {
console.error('Can not get a geo position');
}
function _setupMap() {
_initMap(function () {
HereMapsAPIService.loadModules($attrs.$attr, {
"controls": _uiModuleReady,
"events": _eventsModuleReady
});
});
}
function _initMap(cb) {
var map = heremaps.map = new H.Map($element[0], heremaps.layers.normal.map, {
zoom: HereMapsUtilsService.isValidCoords(position) ? options.zoom : options.maxZoom,
center: new H.geo.Point(position.latitude, position.longitude)
});
HereMapsMarkerService.addMarkersToMap(map, places, true);
if (HereMapsConfig.mapTileConfig)
_setCustomMapStyles(map, HereMapsConfig.mapTileConfig);
mapReady && mapReady(MapProxy());
cb && cb();
}
function _uiModuleReady() {
HereMapsUiFactory.start({
platform: heremaps,
alignment: $attrs.controls
});
}
function _eventsModuleReady() {
HereMapsEventsFactory.start({
platform: heremaps,
listeners: listeners,
options: options,
injector: _moduleInjector
});
}
function _moduleInjector() {
return function (id) {
return heremaps[id];
}
}
function _resizeHandler(height, width) {
_setMapSize.apply(null, arguments);
heremaps.map.getViewPort().resize();
}
function _setMapSize(height, width) {
var height = height || $element[0].parentNode.offsetHeight || options.height,
width = width || $element[0].parentNode.offsetWidth || options.width;
$scope.mapHeight = height + 'px';
$scope.mapWidth = width + 'px';
HereMapsUtilsService.runScopeDigestIfNeed($scope);
}
function _setCustomMapStyles(map, config) {
// Create a MapTileService instance to request base tiles (i.e. base.map.api.here.com):
var mapTileService = heremaps.platform.getMapTileService({ 'type': 'base' });
// Create a tile layer which requests map tiles
var newStyleLayer = mapTileService.createTileLayer(
'maptile',
config.scheme || 'normal.day',
config.size || 256,
config.format || 'png8',
config.metadataQueryParams || {}
);
// Set new style layer as a base layer on the map:
map.setBaseLayer(newStyleLayer);
}
function MapProxy() {
return {
refresh: function () {
var currentBounds = this.getViewBounds();
this.setMapSizes();
this.setViewBounds(currentBounds);
},
setMapSizes: function (height, width) {
_resizeHandler.apply(null, arguments);
},
getPlatform: function () {
return heremaps;
},
calculateRoute: function (driveType, direction) {
return HereMapsRoutesService.calculateRoute(heremaps, {
driveType: driveType,
direction: direction
});
},
addRouteToMap: function (routeData, clean) {
HereMapsRoutesService.addRouteToMap(heremaps.map, routeData, clean);
},
setZoom: function (zoom, step) {
HereMapsUtilsService.zoom(heremaps.map, zoom || 10, step);
},
getZoom: function () {
return heremaps.map.getZoom();
},
getCenter: function () {
return heremaps.map.getCenter();
},
getViewBounds: function () {
return heremaps.map.getViewBounds();
},
setViewBounds: function (boundingRect, opt_animate) {
HereMapsMarkerService.setViewBounds(heremaps.map, boundingRect, opt_animate);
},
getBoundsRectFromPoints: function (topLeft, bottomRight) {
return HereMapsUtilsService.getBoundsRectFromPoints.apply(null, arguments);
},
setCenter: function (coords) {
if (!coords) {
return console.error('coords are not specified!');
}
heremaps.map.setCenter(coords);
},
cleanRoutes: function () {
HereMapsRoutesService.cleanRoutes(heremaps.map);
},
/**
* @param {Boolean} enableHighAccuracy
* @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
* @return {Promise}
*/
getUserLocation: function (enableHighAccuracy, maximumAge) {
return _getLocation.apply(null, arguments).then(function (position) {
var coords = position.coords;
return {
lat: coords.latitude,
lng: coords.longitude
};
})
},
geocodePosition: function (coords, options) {
return HereMapsAPIService.geocodePosition(heremaps.platform, {
coords: coords,
radius: options && options.radius,
lang: options && options.lang
});
},
geocodeAddress: function (address) {
return HereMapsAPIService.geocodeAddress(heremaps.platform, {
searchtext: address && address.searchtext,
country: address && address.country,
city: address && address.city,
street: address && address.street,
housenumber: address && address.housenumber
});
},
geocodeAutocomplete: function (query, options) {
return HereMapsAPIService.geocodeAutocomplete({
query: query,
beginHighlight: options && options.beginHighlight,
endHighlight: options && options.endHighlight,
maxresults: options && options.maxresults
});
},
findLocationById: function (locationId) {
return HereMapsAPIService.findLocationById(locationId);
},
updateMarkers: function (places, refreshViewbounds) {
HereMapsMarkerService.updateMarkers(heremaps.map, places, refreshViewbounds);
},
getMapFactory: function (){
return HereMapsUtilsService.getMapFactory();
}
}
}
}
};
},{}],2:[function(require,module,exports){
require('./providers/markers');
require('./providers/map-modules');
require('./providers/routes');
module.exports = angular.module('heremaps', [
'heremaps-markers-module',
'heremaps-routes-module',
'heremaps-map-modules'
])
.provider('HereMapsConfig', require('./providers/mapconfig.provider'))
.service('HereMapsUtilsService', require('./providers/maputils.service'))
.service('HereMapsAPIService', require('./providers/api.service'))
.constant('HereMapsCONSTS', require('./providers/consts'))
.directive('heremaps', require('./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(require,module,exports){
module.exports = HereMapsAPIService;
HereMapsAPIService.$inject = [
'$q',
'$http',
'HereMapsConfig',
'HereMapsUtilsService',
'HereMapsCONSTS'
];
function HereMapsAPIService($q, $http, HereMapsConfig, HereMapsUtilsService, HereMapsCONSTS) {
var version = HereMapsConfig.apiVersion,
protocol = HereMapsConfig.useHTTPS ? 'https' : 'http';
var API_VERSION = {
V: parseInt(version),
SUB: version
};
var CONFIG = {
BASE: "://js.api.here.com/v",
CORE: "mapsjs-core.js",
SERVICE: "mapsjs-service.js",
UI: {
src: "mapsjs-ui.js",
href: "mapsjs-ui.css"
},
EVENTS: "mapsjs-mapevents.js",
AUTOCOMPLETE_URL: "://autocomplete.geocoder.cit.api.here.com/6.2/suggest.json",
LOCATION_URL: "://geocoder.cit.api.here.com/6.2/geocode.json"
};
var API_DEFERSQueue = {};
API_DEFERSQueue[CONFIG.CORE] = [];
API_DEFERSQueue[CONFIG.SERVICE] = [];
API_DEFERSQueue[CONFIG.UI.src] = [];
API_DEFERSQueue[CONFIG.PANO] = [];
API_DEFERSQueue[CONFIG.EVENTS] = [];
var head = document.getElementsByTagName('head')[0];
return {
loadApi: loadApi,
loadModules: loadModules,
getPosition: getPosition,
geocodePosition: geocodePosition,
geocodeAddress: geocodeAddress,
geocodeAutocomplete: geocodeAutocomplete,
findLocationById: findLocationById
};
//#region PUBLIC
function loadApi() {
return _getLoader(CONFIG.CORE)
.then(function () {
return _getLoader(CONFIG.SERVICE);
});
}
function loadModules(attrs, handlers) {
for (var key in handlers) {
if (!handlers.hasOwnProperty(key) || !attrs[key])
continue;
var loader = _getLoaderByAttr(key);
loader()
.then(handlers[key]);
}
}
function getPosition(options) {
var deferred = $q.defer();
if (options && HereMapsUtilsService.isValidCoords(options.coords)) {
deferred.resolve({ coords: options.coords });
} else {
navigator.geolocation.getCurrentPosition(function (response) {
deferred.resolve(response);
}, function (error) {
deferred.reject(error);
}, options);
}
return deferred.promise;
}
function geocodePosition(platform, params) {
if (!params.coords)
return console.error('Missed required coords');
var geocoder = platform.getGeocodingService(),
deferred = $q.defer(),
_params = {
prox: [params.coords.lat, params.coords.lng, params.radius || 250].join(','),
mode: 'retrieveAddresses',
maxresults: '1',
gen: '8',
language: params.lang || 'en-gb'
};
geocoder.reverseGeocode(_params, function (response) {
deferred.resolve(response)
}, function (error) {
deferred.reject(error)
});
return deferred.promise;
}
function geocodeAddress(platform, params) {
if (!params)
return console.error('Missed required parameters');
var geocoder = platform.getGeocodingService(),
deferred = $q.defer(),
_params = { gen: 8 };
for (var key in params) { _params[key] = params[key]; }
geocoder.geocode(_params, function (response) {
deferred.resolve(response)
}, function (error) {
deferred.reject(error)
});
return deferred.promise;
}
function geocodeAutocomplete(params) {
if (!params)
return console.error('Missing required parameters');
var autocompleteUrl = protocol + CONFIG.AUTOCOMPLETE_URL,
deferred = $q.defer(),
_params = {
query: "",
beginHighlight: "<mark>",
endHighlight: "</mark>",
maxresults: "5"
};
for (var key in _params) {
if (angular.isDefined(params[key])) {
_params[key] = params[key];
}
}
_params.app_id = HereMapsConfig.app_id;
_params.app_code = HereMapsConfig.app_code;
$http.get(autocompleteUrl, { params: _params })
.success(function(response) {
deferred.resolve(response);
})
.error(function(error) {
deferred.reject(error);
});
return deferred.promise;
}
/**
* Finds location by HERE Maps Location identifier.
*/
function findLocationById(locationId) {
if (!locationId)
return console.error('Missing Location Identifier');
var locationUrl = protocol + CONFIG.LOCATION_URL,
deferred = $q.defer(),
_params = {
locationid: locationId,
gen: 9,
app_id: HereMapsConfig.app_id,
app_code: HereMapsConfig.app_code
};
$http.get(locationUrl, { params: _params })
.success(function(response) {
deferred.resolve(response);
})
.error(function(error) {
deferred.reject(error);
});
return deferred.promise;
}
//#endregion PUBLIC
function _getLoaderByAttr(attr) {
var loader;
switch (attr) {
case HereMapsCONSTS.MODULES.UI:
loader = _loadUIModule;
break;
case HereMapsCONSTS.MODULES.EVENTS:
loader = _loadEventsModule;
break;
default:
throw new Error('Unknown module', attr);
}
return loader;
}
function _loadUIModule() {
if (!_isLoaded(CONFIG.UI.src)) {
var link = HereMapsUtilsService.createLinkTag({
rel: 'stylesheet',
type: 'text/css',
href: _getURL(CONFIG.UI.href)
});
link && head.appendChild(link);
}
return _getLoader(CONFIG.UI.src);
}
function _loadEventsModule() {
return _getLoader(CONFIG.EVENTS);
}
/**
* @param {String} sourceName
* return {String} e.g http://js.api.here.com/v{VER}/{SUBVERSION}/{SOURCE}
*/
function _getURL(sourceName) {
return [
protocol,
CONFIG.BASE,
API_VERSION.V,
"/",
API_VERSION.SUB,
"/",
sourceName
].join("");
}
function _getLoader(sourceName) {
var defer = $q.defer(), src, script;
if (_isLoaded(sourceName)) {
defer.resolve();
} else {
src = _getURL(sourceName);
script = HereMapsUtilsService.createScriptTag({ src: src });
script && head.appendChild(script);
API_DEFERSQueue[sourceName].push(defer);
script.onload = _onLoad.bind(null, sourceName);
script.onerror = _onError.bind(null, sourceName);
}
return defer.promise;
}
function _isLoaded(sourceName) {
var checker = null;
switch (sourceName) {
case CONFIG.CORE:
checker = _isCoreLoaded;
break;
case CONFIG.SERVICE:
checker = _isServiceLoaded;
break;
case CONFIG.UI.src:
checker = _isUILoaded;
break;
case CONFIG.EVENTS:
checker = _isEventsLoaded;
break;
default:
checker = function () { return false };
}
return checker();
}
function _isCoreLoaded() {
return !!window.H;
}
function _isServiceLoaded() {
return !!(window.H && window.H.service);
}
function _isUILoaded() {
return !!(window.H && window.H.ui);
}
function _isEventsLoaded() {
return !!(window.H && window.H.mapevents);
}
function _onLoad(sourceName) {
var deferQueue = API_DEFERSQueue[sourceName];
for (var i = 0, l = deferQueue.length; i < l; ++i) {
var defer = deferQueue[i];
defer.resolve();
}
API_DEFERSQueue[sourceName] = [];
}
function _onError(sourceName) {
var deferQueue = API_DEFERSQueue[sourceName];
for (var i = 0, l = deferQueue.length; i < l; ++i) {
var defer = deferQueue[i];
defer.reject();
}
API_DEFERSQueue[sourceName] = [];
}
};
},{}],4:[function(require,module,exports){
module.exports = {
UPDATE_MAP_RESIZE_TIMEOUT: 500,
ANIMATION_ZOOM_STEP: .05,
MODULES: {
UI: 'controls',
EVENTS: 'events',
PANO: 'pano'
},
DEFAULT_MAP_OPTIONS: {
height: 480,
width: 640,
zoom: 12,
maxZoom: 2,
resize: false,
draggable: false,
coords: {
longitude: 0,
latitude: 0
}
},
MARKER_TYPES: {
DOM: "DOM",
SVG: "SVG"
},
CONTROLS: {
NAMES: {
SCALE: 'scalebar',
SETTINGS: 'mapsettings',
ZOOM: 'zoom',
USER: 'userposition'
},
POSITIONS: [
'top-right',
'top-center',
'top-left',
'left-top',
'left-middle',
'left-bottom',
'right-top',
'right-middle',
'right-bottom',
'bottom-right',
'bottom-center',
'bottom-left'
]
},
INFOBUBBLE: {
STATE: {
OPEN: 'open',
CLOSED: 'closed'
},
DISPLAY_EVENT: {
pointermove: 'onHover',
tap: 'onClick'
}
},
USER_EVENTS: {
tap: 'click',
pointermove: 'mousemove',
pointerleave: 'mouseleave',
pointerenter: 'mouseenter',
drag: 'drag',
dragstart: 'dragstart',
dragend: 'dragend',
mapviewchange: 'mapviewchange',
mapviewchangestart: 'mapviewchangestart',
mapviewchangeend: 'mapviewchangeend'
}
}
},{}],5:[function(require,module,exports){
module.exports = HereMapsEventsFactory;
HereMapsEventsFactory.$inject = [
'HereMapsUtilsService',
'HereMapsMarkerService',
'HereMapsCONSTS',
'HereMapsInfoBubbleFactory'
];
function HereMapsEventsFactory(HereMapsUtilsService, HereMapsMarkerService, HereMapsCONSTS, HereMapsInfoBubbleFactory) {
function Events(platform, Injector, listeners) {
this.map = platform.map;
this.listeners = listeners;
this.inject = new Injector();
this.events = platform.events = new H.mapevents.MapEvents(this.map);
this.behavior = platform.behavior = new H.mapevents.Behavior(this.events);
this.bubble = HereMapsInfoBubbleFactory.create();
this.setupEventListeners();
}
var proto = Events.prototype;
proto.setupEventListeners = setupEventListeners;
proto.setupOptions = setupOptions;
proto.triggerUserListener = triggerUserListener;
proto.infoBubbleHandler = infoBubbleHandler;
return {
start: function(args) {
if (!(args.platform.map instanceof H.Map))
return console.error('Missed required map instance');
var events = new Events(args.platform, args.injector, args.listeners);
args.options && events.setupOptions(args.options);
}
}
function setupEventListeners() {
var self = this;
HereMapsUtilsService.addEventListener(this.map, 'tap', this.infoBubbleHandler.bind(this));
HereMapsUtilsService.addEventListener(this.map, 'pointermove', this.infoBubbleHandler.bind(this));
HereMapsUtilsService.addEventListener(this.map, 'dragstart', function(e) {
if (HereMapsMarkerService.isMarkerInstance(e.target)) {
self.behavior.disable();
}
self.triggerUserListener(HereMapsCONSTS.USER_EVENTS[e.type], e);
});
HereMapsUtilsService.addEventListener(this.map, 'drag', function(e) {
var pointer = e.currentPointer,
target = e.target;
if (HereMapsMarkerService.isMarkerInstance(target)) {
target.setPosition(self.map.screenToGeo(pointer.viewportX, pointer.viewportY));
}
self.triggerUserListener(HereMapsCONSTS.USER_EVENTS[e.type], e);
});
HereMapsUtilsService.addEventListener(this.map, 'dragend', function(e) {
if (HereMapsMarkerService.isMarkerInstance(e.target)) {
self.behavior.enable();
}
self.triggerUserListener(HereMapsCONSTS.USER_EVENTS[e.type], e);
});
HereMapsUtilsService.addEventListener(this.map, 'mapviewchangestart', function(e) {
self.triggerUserListener(HereMapsCONSTS.USER_EVENTS[e.type], e);
});
HereMapsUtilsService.addEventListener(this.map, 'mapviewchange', function(e) {
self.triggerUserListener(HereMapsCONSTS.USER_EVENTS[e.type], e);
});
HereMapsUtilsService.addEventListener(this.map, 'mapviewchangeend', function(e) {
self.triggerUserListener(HereMapsCONSTS.USER_EVENTS[e.type], e);
});
}
function setupOptions(options) {
if (!options)
return;
this.map.draggable = !!options.draggable;
}
function triggerUserListener(eventName, e) {
if (!this.listeners)
return;
var callback = this.listeners[eventName];
callback && callback(e);
}
function infoBubbleHandler(e){
var ui = this.inject('ui');
if(ui)
this.bubble.toggle(e, ui);
this.triggerUserListener(HereMapsCONSTS.USER_EVENTS[e.type], e);
}
};
},{}],6:[function(require,module,exports){
module.exports = HereMapsInfoBubbleFactory;
HereMapsInfoBubbleFactory.$inject = [
'HereMapsMarkerService',
'HereMapsUtilsService',
'HereMapsCONSTS'
];
function HereMapsInfoBubbleFactory(HereMapsMarkerService, HereMapsUtilsService, HereMapsCONSTS) {
function InfoBubble() {}
var proto = InfoBubble.prototype;
proto.create = create;
proto.update = update;
proto.toggle = toggle;
proto.show = show;
proto.close = close;
return {
create: function(){
return new InfoBubble();
}
}
function toggle(e, ui) {
if (HereMapsMarkerService.isMarkerInstance(e.target))
this.show(e, ui);
else
this.close(e, ui);
}
function update(bubble, data) {
bubble.display = data.display;
bubble.setPosition(data.position);
bubble.setContent(data.markup);
bubble.setState(HereMapsCONSTS.INFOBUBBLE.STATE.OPEN);
}
function create(source) {
var bubble = new H.ui.InfoBubble(source.position, {
content: source.markup
});
bubble.display = source.display;
bubble.addClass(HereMapsCONSTS.INFOBUBBLE.STATE.OPEN)
HereMapsUtilsService.addEventListener(bubble, 'statechange', function(e) {
var state = this.getState(),
el = this.getElement();
if (state === HereMapsCONSTS.INFOBUBBLE.STATE.CLOSED) {
el.classList.remove(HereMapsCONSTS.INFOBUBBLE.STATE.OPEN);
} else
this.addClass(state)
});
return bubble;
}
function show(e, ui, data) {
var target = e.target,
data = target.getData(),
el = null;
if (!data || !data.display || !data.markup || data.display !== HereMapsCONSTS.INFOBUBBLE.DISPLAY_EVENT[e.type])
return;
var source = {
position: target.getPosition(),
markup: data.markup,
display: data.display
};
if (!ui.bubble) {
ui.bubble = this.create(source);
ui.addBubble(ui.bubble);
return;
}
this.update(ui.bubble, source);
}
function close(e, ui) {
if (!ui.bubble || ui.bubble.display !== HereMapsCONSTS.INFOBUBBLE.DISPLAY_EVENT[e.type]) {
return;
}
ui.bubble.setState(HereMapsCONSTS.INFOBUBBLE.STATE.CLOSED);
}
}
},{}],7:[function(require,module,exports){
angular.module('heremaps-events-module', [])
.factory('HereMapsEventsFactory', require('./events/events.js'))
.factory('HereMapsInfoBubbleFactory', require('./events/infobubble.js'));
angular.module('heremaps-ui-module', [])
.factory('HereMapsUiFactory', require('./ui/ui.js'))
module.exports = angular.module('heremaps-map-modules', [
'heremaps-events-module',
'heremaps-ui-module'
]);
},{"./events/events.js":5,"./events/infobubble.js":6,"./ui/ui.js":8}],8:[function(require,module,exports){
module.exports = HereMapsUiFactory;
HereMapsUiFactory.$inject = [
'HereMapsAPIService',
'HereMapsMarkerService',
'HereMapsUtilsService',
'HereMapsCONSTS'
];
function HereMapsUiFactory(HereMapsAPIService, HereMapsMarkerService, HereMapsUtilsService, HereMapsCONSTS) {
function UI(platform, alignment) {
this.map = platform.map;
this.layers = platform.layers;
this.alignment = alignment;
this.ui = platform.ui = H.ui.UI.createDefault(this.map, this.layers);
this.setupControls();
}
UI.isValidAlignment = isValidAlignment;
var proto = UI.prototype;
proto.setupControls = setupControls;
proto.createUserControl = createUserControl;
proto.setControlsAlignment = setControlsAlignment;
return {
start: function(args) {
if (!(args.platform.map instanceof H.Map) && !(args.platform.layers))
return console.error('Missed ui module dependencies');
var ui = new UI(args.platform, args.alignment);
}
}
function setupControls() {
var NAMES = HereMapsCONSTS.CONTROLS.NAMES,
userControl = this.createUserControl();
this.ui.getControl(NAMES.SETTINGS).setIncidentsLayer(false);
this.ui.addControl(NAMES.USER, userControl);
this.setControlsAlignment(NAMES);
}
function createUserControl() {
var self = this,
userControl = new H.ui.Control(),
markup = '<svg class="H_icon" fill="#fff" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path class="middle_location_stroke" d="M8 12c-2.206 0-4-1.795-4-4 0-2.206 1.794-4 4-4s4 1.794 4 4c0 2.205-1.794 4-4 4M8 1.25a6.75 6.75 0 1 0 0 13.5 6.75 6.75 0 0 0 0-13.5"></path><path class="inner_location_stroke" d="M8 5a3 3 0 1 1 .001 6A3 3 0 0 1 8 5m0-1C5.794 4 4 5.794 4 8c0 2.205 1.794 4 4 4s4-1.795 4-4c0-2.206-1.794-4-4-4"></path><path class="outer_location_stroke" d="M8 1.25a6.75 6.75 0 1 1 0 13.5 6.75 6.75 0 0 1 0-13.5M8 0C3.59 0 0 3.59 0 8c0 4.411 3.59 8 8 8s8-3.589 8-8c0-4.41-3.59-8-8-8"></path></svg>';
var userControlButton = new H.ui.base.Button({
label: markup,
onStateChange: function(evt) {
if (userControlButton.getState() === H.ui.base.Button.State.DOWN)
return;
HereMapsAPIService.getPosition().then(function(response) {
var position = {
lng: response.coords.longitude,
lat: response.coords.latitude
};
self.map.setCenter(position);
HereMapsUtilsService.zoom(self.map, 17, .08);
if (self.userMarker) {
self.userMarker.setPosition(position);
return;
}
self.userMarker = HereMapsMarkerService.addUserMarker(self.map, {
pos: position
});
});
}
});
userControl.addChild(userControlButton);
return userControl;
}
function setControlsAlignment(NAMES) {
if (!UI.isValidAlignment(this.alignment))
return;
for (var id in NAMES) {
var control = this.ui.getControl(NAMES[id]);
if (!NAMES.hasOwnProperty(id) || !control)
continue;
control.setAlignment(this.alignment);
}
}
function isValidAlignment(alignment) {
return !!(HereMapsCONSTS.CONTROLS.POSITIONS.indexOf(alignment) + 1);
}
};
},{}],9:[function(require,module,exports){
module.exports = function() {
var options = {};
var DEFAULT_API_VERSION = "3.0";
this.$get = function(){
return {
app_id: options.app_id,
app_code: options.app_code,
apiVersion: options.apiVersion || DEFAULT_API_VERSION,
useHTTPS: options.useHTTPS,
useCIT: !!options.useCIT,
mapTileConfig: options.mapTileConfig
}
};
this.setOptions = function(opts){
options = opts;
};
};
},{}],10:[function(require,module,exports){
module.exports = HereMapsUtilsService;
HereMapsUtilsService.$inject = [
'$rootScope',
'$timeout',
'HereMapsCONSTS'
];
function HereMapsUtilsService($rootScope, $timeout, HereMapsCONSTS) {
return {
throttle: throttle,
createScriptTag: createScriptTag,
createLinkTag: createLinkTag,
runScopeDigestIfNeed: runScopeDigestIfNeed,
isValidCoords: isValidCoords,
addEventListener: addEventListener,
zoom: zoom,
getBoundsRectFromPoints: getBoundsRectFromPoints,
generateId: generateId,
getMapFactory: getMapFactory
};
//#region PUBLIC
function throttle(fn, period) {
var timeout = null;
return function () {
if ($timeout)
$timeout.cancel(timeout);
timeout = $timeout(fn, period);
}
}
function addEventListener(obj, eventName, listener, useCapture) {
obj.addEventListener(eventName, listener, !!useCapture);
}
function runScopeDigestIfNeed(scope, cb) {
if (scope.$root && scope.$root.$$phase !== '$apply' && scope.$root.$$phase !== '$digest') {
scope.$digest(cb || angular.noop);
return true;
}
return false;
}
function createScriptTag(attrs) {
var script = document.getElementById(attrs.src);
if (script)
return false;
script = document.createElement('script');
script.type = 'text/javascript';
script.id = attrs.src;
_setAttrs(script, attrs);
return script;
}
function createLinkTag(attrs) {
var link = document.getElementById(attrs.href);
if (link)
return false;
link = document.createElement('link');
link.id = attrs.href;
_setAttrs(link, attrs);
return link;
}
function isValidCoords(coords) {
return coords &&
(typeof coords.latitude === 'string' || typeof coords.latitude === 'number') &&
(typeof coords.longitude === 'string' || typeof coords.longitude === 'number')
}
function zoom(map, value, step) {
var currentZoom = map.getZoom(),
_step = step || HereMapsCONSTS.ANIMATION_ZOOM_STEP,
factor = currentZoom >= value ? -1 : 1,
increment = step * factor;
return (function zoom() {
if (!step || Math.floor(currentZoom) === Math.floor(value)) {
map.setZoom(value);
return;
}
currentZoom += increment;
map.setZoom(currentZoom);
requestAnimationFrame(zoom);
})();
}
function getMapFactory(){
return H;
}
/**
* @method getBoundsRectFromPoints
*
* @param {Object} topLeft
* @property {Number|String} lat
* @property {Number|String} lng
* @param {Object} bottomRight
* @property {Number|String} lat
* @property {Number|String} lng
*
* @return {H.geo.Rect}
*/
function getBoundsRectFromPoints(topLeft, bottomRight) {
return H.geo.Rect.fromPoints(topLeft, bottomRight, true);
}
function generateId() {
var mask = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx',
regexp = /[xy]/g,
d = new Date().getTime(),
uuid = mask.replace(regexp, function (c) {
var r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
return uuid;
}
//#endregion PUBLIC
function _setAttrs(el, attrs) {
if (!el || !attrs)
throw new Error('Missed attributes');
for (var key in attrs) {
if (!attrs.hasOwnProperty(key))
continue;
el[key] = attrs[key];
}
}
};
},{}],11:[function(require,module,exports){
module.exports = HereMapsDefaultMarker;
HereMapsDefaultMarker.$inject = ['HereMapsMarkerInterface'];
function HereMapsDefaultMarker(HereMapsMarkerInterface){
function DefaultMarker(place){
this.place = place;
this.setCoords();
}
var proto = DefaultMarker.prototype = new HereMapsMarkerInterface();
proto.constructor = DefaultMarker;
proto.create = create;
return DefaultMarker;
function create(){
var marker = new H.map.Marker(this.coords);
this.addInfoBubble(marker);
return marker;
}
}
},{}],12:[function(require,module,exports){
module.exports = HereMapsDOMMarker;
HereMapsDOMMarker.$inject = ['HereMapsMarkerInterface'];
function HereMapsDOMMarker(HereMapsMarkerInterface){
function DOMMarker(place){
this.place = place;
this.setCoords();
}
var proto = DOMMarker.prototype = new HereMapsMarkerInterface();
proto.constructor = DOMMarker;
proto.create = create;
proto.getIcon = getIcon;
proto.setupEvents = setupEvents;
return DOMMarker;
function create(){
var marker = new H.map.DomMarker(this.coords, {
icon: this.getIcon()
});
this.addInfoBubble(marker);
return marker;
}
function getIcon(){
var icon = this.place.markup;
if(!icon)
throw new Error('markup missed');
return new H.map.DomIcon(icon);
}
function setupEvents(el, events, remove){
var method = remove ? 'removeEventListener' : 'addEventListener';
for(var key in events) {
if(!events.hasOwnProperty(key))
continue;
el[method].call(null, key, events[key]);
}
}
}
},{}],13:[function(require,module,exports){
module.exports = angular.module('heremaps-markers-module', [])
.factory('HereMapsMarkerInterface', require('./marker.js'))
.factory('HereMapsDefaultMarker', require('./default.marker.js'))
.factory('HereMapsDOMMarker', require('./dom.marker.js'))
.factory('HereMapsSVGMarker', require('./svg.marker.js'))
.service('HereMapsMarkerService', require('./markers.service.js'));
},{"./default.marker.js":11,"./dom.marker.js":12,"./marker.js":14,"./markers.service.js":15,"./svg.marker.js":16}],14:[function(require,module,exports){
module.exports = function(){
function MarkerInterface(){
throw new Error('Abstract class! The Instance should be created');
}
var proto = MarkerInterface.prototype;
proto.create = create;
proto.setCoords = setCoords;
proto.addInfoBubble = addInfoBubble;
function Marker(){}
Marker.prototype = proto;
return Marker;
function create(){
throw new Error('create:: not implemented');
}
function setCoords(){
this.coords = {
lat: this.place.pos.lat,
lng: this.place.pos.lng
}
}
function addInfoBubble(marker){
if(!this.place.popup)
return;
marker.setData(this.place.popup)
}
}
},{}],15:[function(require,module,exports){
module.exports = HereMapsMarkerService;
HereMapsMarkerService.$inject = [
'HereMapsDefaultMarker',
'HereMapsDOMMarker',
'HereMapsSVGMarker',
'HereMapsCONSTS'
];
function HereMapsMarkerService(HereMapsDefaultMarker, HereMapsDOMMarker, HereMapsSVGMarker, HereMapsCONSTS) {
var MARKER_TYPES = HereMapsCONSTS.MARKER_TYPES;
return {
addMarkersToMap: addMarkersToMap,
addUserMarker: addUserMarker,
updateMarkers: updateMarkers,
isMarkerInstance: isMarkerInstance,
setViewBounds: setViewBounds
}
function isMarkerInstance(target) {
return target instanceof H.map.Marker || target instanceof H.map.DomMarker;
}
function addUserMarker(map, place) {
if (map.userMarker)
return map.userMarker;
place.markup = '<svg width="35px" height="35px" viewBox="0 0 90 90" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">' +
'<defs><circle id="path-1" cx="302" cy="802" r="15"></circle>' +
'<mask id="mask-2" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="-30" y="-30" width="90" height="90">' +
'<rect x="257" y="757" width="90" height="90" fill="white"></rect><use xlink:href="#path-1" fill="black"></use>' +
'</mask></defs><g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">' +
'<g id="Service-Options---directions---map" transform="translate(-257.000000, -757.000000)"><g id="Oval-15">' +
'<use fill="#FFFFFF" fill-rule="evenodd" xlink:href="#path-1"></use>' +
'<use stroke-opacity="0.29613904" stroke="#3F34A0" mask="url(#mask-2)" stroke-width="60" xlink:href="#path-1"></use>' +
'<use stroke="#3F34A0" stroke-width="5" xlink:href="#path-1"></use></g></g></g></svg>';
map.userMarker = new HereMapsSVGMarker(place).create();
map.addObject(map.userMarker);
return map.userMarker;
}
function addMarkersToMap(map, places, refreshViewbounds) {
if (!places || !places.length)
return;
if (!(map instanceof H.Map))
throw new Error('Unsupported map instance');
if (!map.markersGroup)
map.markersGroup = new H.map.Group();
places.forEach(function (place, i) {
var creator = _getMarkerCreator(place),
marker = place.draggable ? _draggableMarkerMixin(creator.create()) : creator.create();
map.markersGroup.addObject(marker);
});
map.addObject(map.markersGroup);
if (refreshViewbounds) {
setViewBounds(map, map.markersGroup.getBounds());
}
}
function setViewBounds(map, bounds, opt_animate) {
map.setViewBounds(bounds, !!opt_animate);
}
function updateMarkers(map, places, refreshViewbounds) {
if (map.markersGroup) {
map.markersGroup.removeAll();
map.removeObject(map.markersGroup);
map.markersGroup = null;
}
addMarkersToMap.apply(null, arguments);
}
function _getMarkerCreator(place) {
var ConcreteMarker,
type = place.type ? place.type.toUpperCase() : null;
switch (type) {
case MARKER_TYPES.DOM:
ConcreteMarker = HereMapsDOMMarker;
break;
case MARKER_TYPES.SVG:
ConcreteMarker = HereMapsSVGMarker;
break;
default:
ConcreteMarker = HereMapsDefaultMarker;
}
return new ConcreteMarker(place);
}
function _draggableMarkerMixin(marker) {
marker.draggable = true;
return marker;
}
};
},{}],16:[function(require,module,exports){
module.exports = HereMapsSVGMarker;
HereMapsSVGMarker.$inject = ['HereMapsMarkerInterface'];
function HereMapsSVGMarker(HereMapsMarkerInterface){
function SVGMarker(place){
this.place = place;
this.setCoords();
}
var proto = SVGMarker.prototype = new HereMapsMarkerInterface();
proto.constructor = SVGMarker;
proto.create = create;
proto.getIcon = getIcon;
return SVGMarker;
function create(){
var marker = new H.map.Marker(this.coords, {
icon: this.getIcon(),
});
this.addInfoBubble(marker);
return marker;
}
function getIcon(){
var icon = this.place.markup;
if(!icon)
throw new Error('markup missed');
return new H.map.Icon(icon);
}
}
},{}],17:[function(require,module,exports){
module.exports = angular.module('heremaps-routes-module', [])
.service('HereMapsRoutesService', require('./routes.service.js'));
},{"./routes.service.js":18}],18:[function(require,module,exports){
module.exports = HereMapsRoutesService;
HereMapsRoutesService.$inject = ['$q', 'HereMapsMarkerService'];
function HereMapsRoutesService($q, HereMapsMarkerService) {
return {
calculateRoute: calculateRoute,
addRouteToMap: addRouteToMap,
cleanRoutes: cleanRoutes
}
function calculateRoute(heremaps, config) {
var platform = heremaps.platform,
map = heremaps.map,
router = platform.getRoutingService(),
dir = config.direction,
waypoints = dir.waypoints;
var mode = '{{MODE}};{{VECHILE}}'
.replace(/{{MODE}}/, dir.mode || 'fastest')
.replace(/{{VECHILE}}/, config.driveType);
var routeRequestParams = {
mode: mode,
representation: dir.representation || 'display',
language: dir.language || 'en-gb'
};
waypoints.forEach(function (waypoint, i) {
routeRequestParams["waypoint" + i] = [waypoint.lat, waypoint.lng].join(',');
});
_setAttributes(routeRequestParams, dir.attrs);
var deferred = $q.defer();
router.calculateRoute(routeRequestParams, function (result) {
deferred.resolve(result);
}, function (error) {
deferred.reject(error);
});
return deferred.promise;
}
function cleanRoutes(map) {
var group = map.routesGroup;
if (!group)
return;
group.removeAll();
map.removeObject(group);
map.routesGroup = null;
}
function addRouteToMap(map, routeData, clean) {
if (clean)
cleanRoutes(map);
var route = routeData.route;
if (!map || !route || !route.shape)
return;
var strip = new H.geo.Strip(), polyline = null;
route.shape.forEach(function (point) {
var parts = point.split(',');
strip.pushLatLngAlt(parts[0], parts[1]);
});
var style = routeData.style || {};
polyline = new H.map.Polyline(strip, {
style: {
lineWidth: style.lineWidth || 4,
strokeColor: style.color || 'rgba(0, 128, 255, 0.7)'
}
});
var group = map.routesGroup;
if (!group) {
group = map.routesGroup = new H.map.Group();
map.addObject(group);
}
group.addObject(polyline);
if(routeData.zoomToBounds) {
HereMapsMarkerService.setViewBounds(map, polyline.getBounds(), true);
}
}
//#region PRIVATE
function _setAttributes(params, attrs) {
var _key = 'attributes';
for (var key in attrs) {
if (!attrs.hasOwnProperty(key))
continue;
params[key + _key] = attrs[key];
}
}
/**
* Creates a series of H.map.Marker points from the route and adds them to the map.
* @param {Object} route A route as received from the H.service.RoutingService
*/
function addManueversToMap(map, route) {
var svgMarkup = '<svg width="18" height="18" ' +
'xmlns="http://www.w3.org/2000/svg">' +
'<circle cx="8" cy="8" r="8" ' +
'fill="#1b468d" stroke="white" stroke-width="1" />' +
'</svg>',
dotIcon = new H.map.Icon(svgMarkup, { anchor: { x: 8, y: 8 } }),
group = new H.map.Group(), i, j;
// Add a marker for each maneuver
for (i = 0; i < route.leg.length; i += 1) {
for (j = 0; j < route.leg[i].maneuver.length; j += 1) {
// Get the next maneuver.
maneuver = route.leg[i].maneuver[j];
// Add a marker to the maneuvers group
var marker = new H.map.Marker({
lat: maneuver.position.latitude,
lng: maneuver.position.longitude
},
{ icon: dotIcon }
);
marker.instruction = maneuver.instruction;
group.addObject(marker);
}
}
group.addEventListener('tap', function (evt) {
map.setCenter(evt.target.getPosition());
openBubble(evt.target.getPosition(), evt.target.instruction);
}, false);
// Add the maneuvers group to the map
map.addObject(group);
}
/**
* Creates a series of H.map.Marker points from the route and adds them to the map.
* @param {Object} route A route a