var ngMap = angular.module('ngMap', []); /** * @ngdoc service * @name Attr2Options * @description * Converts tag attributes to options used by google api v3 objects, map, marker, polygon, circle, etc. */ /*jshint -W030*/ ngMap.service('Attr2Options', ['$parse', 'NavigatorGeolocation', 'GeoCoder', function($parse, NavigatorGeolocation, GeoCoder) { var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g; var MOZ_HACK_REGEXP = /^moz([A-Z])/; var orgAttributes = function(el) { (el.length > 0) && (el = el[0]); var orgAttributes = {}; for (var i=0; i * * */ /*jshint -W089*/ ngMap.directive('bicyclingLayer', ['Attr2Options', function(Attr2Options) { var parser = Attr2Options; var getLayer = function(options, events) { var layer = new google.maps.BicyclingLayer(options); for (var eventName in events) { google.maps.event.addListener(layer, eventName, events[eventName]); } return layer; }; return { restrict: 'E', require: '^map', link: function(scope, element, attrs, mapController) { var orgAttrs = parser.orgAttributes(element); var filtered = parser.filter(attrs); var options = parser.getOptions(filtered); var events = parser.getEvents(scope, filtered); void 0; var layer = getLayer(options, events); mapController.addObject('bicyclingLayers', layer); parser.observeAttrSetObj(orgAttrs, attrs, layer); //observers } }; // return }]); /** * @ngdoc directive * @name cloud-layer * @requires Attr2Options * @description * Requires: map directive * Restrict To: Element * * @example * Example: * * * * */ /*jshint -W089*/ ngMap.directive('cloudLayer', ['Attr2Options', function(Attr2Options) { var parser = Attr2Options; var getLayer = function(options, events) { var layer = new google.maps.weather.CloudLayer(options); for (var eventName in events) { google.maps.event.addListener(layer, eventName, events[eventName]); } return layer; }; return { restrict: 'E', require: '^map', link: function(scope, element, attrs, mapController) { var orgAttrs = parser.orgAttributes(element); var filtered = parser.filter(attrs); var options = parser.getOptions(filtered); var events = parser.getEvents(scope, filtered); void 0; var layer = getLayer(options, events); mapController.addObject('cloudLayers', layer); parser.observeAttrSetObj(orgAttrs, attrs, layer); //observers } }; // return }]); /*jshint -W030*/ /** * @ngdoc directive * @name custom-control * @requires Attr2Options * @requires $compile * @description * Build custom control and set to the map with position * * Requires: map directive * * Restrict To: Element * * @param {String} position position of this control * i.e. TOP_RIGHT * @param {Number} index index of the control * @example * * Example: * * *
* Home *
*
*
* */ /*jshint -W089*/ ngMap.directive('customControl', ['Attr2Options', '$compile', function(Attr2Options, $compile) { var parser = Attr2Options; return { restrict: 'E', require: '^map', link: function(scope, element, attrs, mapController) { element.css('display','none'); var orgAttrs = parser.orgAttributes(element); var filtered = parser.filter(attrs); var options = parser.getOptions(filtered, scope); var events = parser.getEvents(scope, filtered); void 0; /** * build a custom control element */ var compiled = $compile(element.html().trim())(scope); var customControlEl = compiled[0]; /** * set events */ for (var eventName in events) { google.maps.event.addDomListener(customControlEl, eventName, events[eventName]); } mapController.addObject('customControls', customControlEl); scope.$on('mapInitialized', function(evt, map) { var position = options.position; map.controls[google.maps.ControlPosition[position]].push(customControlEl); }); } //link }; // return }]);// function /** * @ngdoc directive * @name drawing-manager * @requires Attr2Options * @description * Requires: map directive * Restrict To: Element * * @example * Example: * * * * * * TODO: Add remove button. * currently, for out solution, we have the shapes/markers in our own controller, and we use some css classes to change the shape button * to a remove button (
X
) and have the remove operation in our own controller. */ /*jshint -W089*/ ngMap.directive('drawingManager', ['Attr2Options', function(Attr2Options) { var parser = Attr2Options; return { restrict: 'E', require: '^map', link: function(scope, element, attrs, mapController) { var orgAttrs = parser.orgAttributes(element); var filtered = parser.filter(attrs); var options = parser.getOptions(filtered); var controlOptions = parser.getControlOptions(filtered); var events = parser.getEvents(scope, filtered); void 0; /** * set options */ var drawingManager = new google.maps.drawing.DrawingManager({ drawingMode: options.drawingmode, drawingControl: options.drawingcontrol, drawingControlOptions: controlOptions.drawingControlOptions, circleOptions:options.circleoptions, markerOptions:options.markeroptions, polygonOptions:options.polygonoptions, polylineOptions:options.polylineoptions, rectangleOptions:options.rectangleoptions }); /** * set events */ var events = parser.getEvents(scope, filtered); for (var eventName in events) { google.maps.event.addListener(drawingManager, eventName, events[eventName]); } mapController.addObject('mapDrawingManager', drawingManager); } }; // return }]); /** * @ngdoc directive * @name dynamic-maps-engine-layer * @description * Requires: map directive * Restrict To: Element * * @example * Example: * * * */ /*jshint -W089*/ ngMap.directive('dynamicMapsEngineLayer', ['Attr2Options', function(Attr2Options) { var parser = Attr2Options; var getDynamicMapsEngineLayer = function(options, events) { var layer = new google.maps.visualization.DynamicMapsEngineLayer(options); for (var eventName in events) { google.maps.event.addListener(layer, eventName, events[eventName]); } return layer; }; return { restrict: 'E', require: '^map', link: function(scope, element, attrs, mapController) { var filtered = parser.filter(attrs); var options = parser.getOptions(filtered); var events = parser.getEvents(scope, filtered, events); void 0; var layer = getDynamicMapsEngineLayer(options, events); mapController.addObject('mapsEngineLayers', layer); } }; // return }]); /** * @ngdoc directive * @name fusion-tables-layer * @description * Requires: map directive * Restrict To: Element * * @example * Example: * * * * */ /*jshint -W089*/ ngMap.directive('fusionTablesLayer', ['Attr2Options', function(Attr2Options) { var parser = Attr2Options; var getLayer = function(options, events) { var layer = new google.maps.FusionTablesLayer(options); for (var eventName in events) { google.maps.event.addListener(layer, eventName, events[eventName]); } return layer; }; return { restrict: 'E', require: '^map', link: function(scope, element, attrs, mapController) { var filtered = parser.filter(attrs); var options = parser.getOptions(filtered); var events = parser.getEvents(scope, filtered, events); void 0; var layer = getLayer(options, events); mapController.addObject('fusionTablesLayers', layer); } }; // return }]); /** * @ngdoc directive * @name heatmap-layer * @requires Attr2Options * @description * Requires: map directive * Restrict To: Element * * @example * Example: * * * * */ /*jshint -W089*/ ngMap.directive('heatmapLayer', ['Attr2Options', '$window', function(Attr2Options, $window) { var parser = Attr2Options; return { restrict: 'E', require: '^map', link: function(scope, element, attrs, mapController) { var filtered = parser.filter(attrs); /** * set options */ var options = parser.getOptions(filtered); options.data = $window[attrs.data] || scope[attrs.data]; if (options.data instanceof Array) { options.data = new google.maps.MVCArray(options.data); } else { throw "invalid heatmap data"; } var layer = new google.maps.visualization.HeatmapLayer(options); /** * set events */ var events = parser.getEvents(scope, filtered); void 0; mapController.addObject('heatmapLayers', layer); } }; // return }]); /*jshint -W030*/ /** * @ngdoc directive * @name info-window * @requires Attr2Options * @requires $compile * @description * Defines infoWindow and provides compile method * * Requires: map directive * * Restrict To: Element * * @param {Boolean} visible Indicates to show it when map is initialized * @param {Boolean} visible-on-marker Indicates to show it on a marker when map is initialized * @param {String} <InfoWindowOption> Any InfoWindow options, * https://developers.google.com/maps/documentation/javascript/reference?csw=1#InfoWindowOptions * @param {String} <InfoWindowEvent> Any InfoWindow events, https://developers.google.com/maps/documentation/javascript/reference * @example * Usage: * * * * * Example: * * *
* Chicago, IL
* LatLng: {{chicago.lat()}}, {{chicago.lng()}},
* World Coordinate: {{worldCoordinate.x}}, {{worldCoordinate.y}},
* Pixel Coordinate: {{pixelCoordinate.x}}, {{pixelCoordinate.y}},
* Tile Coordinate: {{tileCoordinate.x}}, {{tileCoordinate.y}} at Zoom Level {{map.getZoom()}} *
*
*
*/ ngMap.directive('infoWindow', ['Attr2Options', '$compile', '$timeout', function(Attr2Options, $compile, $timeout) { var parser = Attr2Options; var getInfoWindow = function(options, events, element) { var infoWindow; /** * set options */ if (options.position && !(options.position instanceof google.maps.LatLng)) { var address = options.position; delete options.position; infoWindow = new google.maps.InfoWindow(options); var callback = function() { infoWindow.open(infoWindow.map); } parser.setDelayedGeoLocation(infoWindow, 'setPosition', address, {callback: callback}); } else { infoWindow = new google.maps.InfoWindow(options); } /** * set events */ if (Object.keys(events).length > 0) { void 0; } for (var eventName in events) { if (eventName) { google.maps.event.addListener(infoWindow, eventName, events[eventName]); } } /** * set template ane template-relate functions * it must have a container element with ng-non-bindable */ var template = element.html().trim(); if (angular.element(template).length != 1) { throw "info-window working as a template must have a container"; } infoWindow.__template = template.replace(/\s?ng-non-bindable[='"]+/,""); infoWindow.__compile = function(scope) { var el = $compile(infoWindow.__template)(scope); scope.$apply(); infoWindow.setContent(el[0]); }; infoWindow.__eval = function(event) { var template = infoWindow.__template; var _this = this; template = template.replace(/{{(event|this)[^;\}]+}}/g, function(match) { var expression = match.replace(/[{}]/g, "").replace("this.", "_this."); return eval(expression); }); return template; }; return infoWindow; }; return { restrict: 'E', require: '^map', link: function(scope, element, attrs, mapController) { element.css('display','none'); var orgAttrs = parser.orgAttributes(element); var filtered = parser.filter(attrs); var options = parser.getOptions(filtered, scope); var events = parser.getEvents(scope, filtered); void 0; var infoWindow = getInfoWindow(options, events, element); mapController.addObject('infoWindows', infoWindow); parser.observeAttrSetObj(orgAttrs, attrs, infoWindow); /* observers */ // show InfoWindow when initialized if (infoWindow.visible) { //if (!infoWindow.position) { throw "Invalid position"; } scope.$on('mapInitialized', function(evt, map) { $timeout(function() { infoWindow.__template = infoWindow.__eval.apply(this, [evt]); infoWindow.__compile(scope); infoWindow.map = map; infoWindow.position && infoWindow.open(map); }); }); } // show InfoWindow on a marker when initialized if (infoWindow.visibleOnMarker) { scope.$on('mapInitialized', function(evt, map) { $timeout(function() { var markerId = infoWindow.visibleOnMarker; var marker = map.markers[markerId]; if (!marker) throw "Invalid marker id"; infoWindow.__template = infoWindow.__eval.apply(this, [evt]); infoWindow.__compile(scope); infoWindow.open(map, marker); }); }); } /** * provide showInfoWindow method to scope */ scope.showInfoWindow = scope.showInfoWindow || function(event, id, anchor) { var infoWindow = mapController.map.infoWindows[id], tempTemplate = infoWindow.__template; // set template in a temporary variable infoWindow.__template = infoWindow.__eval.apply(this, [event]); infoWindow.__compile(scope); if (anchor) { infoWindow.open(mapController.map, anchor); } else if (this.getPosition) { infoWindow.open(mapController.map, this); } else { infoWindow.open(mapController.map); } infoWindow.__template = tempTemplate; // reset template to the object }; /** * provide hideInfoWindow method to scope */ scope.hideInfoWindow = scope.hideInfoWindow || function(event, id, anchor) { var infoWindow = mapController.map.infoWindows[id]; infoWindow.__template = infoWindow.__eval.apply(this, [event]); infoWindow.__compile(scope); infoWindow.close(); }; } //link }; // return }]);// function /** * @ngdoc directive * @name kml-layer * @requires Attr2Options * @description * renders Kml layer on a map * Requires: map directive * Restrict To: Element * * @param {Url} url url of the kml layer * @param {KmlLayerOptions} KmlLayerOptions * (https://developers.google.com/maps/documentation/javascript/reference#KmlLayerOptions) * @param {String} <KmlLayerEvent> Any KmlLayer events, https://developers.google.com/maps/documentation/javascript/reference * @example * Usage: * * * * * Example: * * * * */ /*jshint -W089*/ ngMap.directive('kmlLayer', ['Attr2Options', function(Attr2Options) { var parser = Attr2Options; var getKmlLayer = function(options, events) { var kmlLayer = new google.maps.KmlLayer(options); for (var eventName in events) { google.maps.event.addListener(kmlLayer, eventName, events[eventName]); } return kmlLayer; }; return { restrict: 'E', require: '^map', link: function(scope, element, attrs, mapController) { var orgAttrs = parser.orgAttributes(element); var filtered = parser.filter(attrs); var options = parser.getOptions(filtered); var events = parser.getEvents(scope, filtered); void 0; var kmlLayer = getKmlLayer(options, events); mapController.addObject('kmlLayers', kmlLayer); parser.observeAttrSetObj(orgAttrs, attrs, kmlLayer); //observers } }; // return }]); /** * @ngdoc directive * @name map-data * @description * set map data * Requires: map directive * Restrict To: Element * * @param {String} method-name, run map.data[method-name] with attribute value * @example * Example: * * * * */ ngMap.directive('mapData', ['Attr2Options', function(Attr2Options) { var parser = Attr2Options; return { restrict: 'E', require: '^map', link: function(scope, element, attrs, mapController) { var filtered = parser.filter(attrs); var options = parser.getOptions(filtered); var events = parser.getEvents(scope, filtered, events); void 0; scope.$on('mapInitialized', function(event, map) { /** * options */ for (var key in options) { if (key) { var val = options[key]; if (typeof scope[val] === "function") { map.data[key](scope[val]); } else { map.data[key](val); } } // if (key) } /** * events */ for (var eventName in events) { if (events[eventName]) { map.data.addListener(eventName, events[eventName]); } } }); } }; // return }]); /** * @ngdoc directive * @name lazy-load * @requires Attr2Options * @description * Requires: Delay the initialization of directive until required .js loads * Restrict To: Attribute * * @param {String} lazy-load script source file location * example: * 'http://maps.googlecom/maps/api/js' * @example * Example: * *
* * * *
*/ /*jshint -W089*/ ngMap.directive('mapLazyLoad', ['$compile', '$timeout', function($compile, $timeout) { 'use strict'; var directiveDefinitionObject = { compile: function(tElement, tAttrs) { (!tAttrs.mapLazyLoad) && void 0; var savedHtml = tElement.html(), src = tAttrs.mapLazyLoad; /** * if already loaded, stop processing it */ if (document.querySelector('script[src="'+src+'"]')) { return false; } tElement.html(''); // will compile again after script is loaded return { pre: function(scope, element, attrs) { window.lazyLoadCallback = function() { void 0; $timeout(function() { /* give some time to load */ element.html(savedHtml); $compile(element.contents())(scope); }, 100); }; var scriptEl = document.createElement('script'); scriptEl.src = src + '?callback=lazyLoadCallback'; document.body.appendChild(scriptEl); } }; } }; return directiveDefinitionObject; }]); /** * @ngdoc directive * @name map-type * @requires Attr2Options * @description * Requires: map directive * Restrict To: Element * * @example * Example: * * * * */ /*jshint -W089*/ ngMap.directive('mapType', ['Attr2Options', '$window', function(Attr2Options, $window) { var parser = Attr2Options; return { restrict: 'E', require: '^map', link: function(scope, element, attrs, mapController) { var mapTypeName = attrs.name, mapTypeObject; if (!mapTypeName) { throw "invalid map-type name"; } if (attrs.object) { var __scope = scope[attrs.object] ? scope : $window; mapTypeObject = __scope[attrs.object]; if (typeof mapTypeObject == "function") { mapTypeObject = new mapTypeObject(); } } if (!mapTypeObject) { throw "invalid map-type object"; } scope.$on('mapInitialized', function(evt, map) { map.mapTypes.set(mapTypeName, mapTypeObject); }); mapController.addObject('mapTypes', mapTypeObject); } }; // return }]); /** * @ngdoc directive * @name map * @requires Attr2Options * @description * Implementation of {@link MapController} * Initialize a Google map within a `
` tag with given options and register events * It accepts children directives; marker, shape, or marker-clusterer * * It initialize map, children tags, then emits message as soon as the action is done * The message emitted from this directive is; * . mapInitialized * * Restrict To: * Element * * @param {Array} geo-fallback-center * The center of map incase geolocation failed. i.e. [0,0] * @param {String} init-event The name of event to initialize this map. * If this option is given, the map won't be initialized until the event is received. * To invoke the event, use $scope.$emit or $scope.$broacast. * i.e. * @param {String} <MapOption> Any Google map options, * https://developers.google.com/maps/documentation/javascript/reference?csw=1#MapOptions * @param {String} <MapEvent> Any Google map events, * https://rawgit.com/allenhwkim/angularjs-google-maps/master/build/map_events.html * @example * Usage: * * ... Any children directives * * * Example: * * * * * */ /*jshint -W030*/ ngMap.directive('map', ['Attr2Options', '$timeout', function(Attr2Options, $timeout) { var parser = Attr2Options; function getStyle(el,styleProp) { if (el.currentStyle) { var y = el.currentStyle[styleProp]; } else if (window.getComputedStyle) { var y = document.defaultView.getComputedStyle(el,null).getPropertyValue(styleProp); } return y; } return { restrict: 'AE', controller: ngMap.MapController, /** * Initialize map and events * @memberof map * @param {$scope} scope * @param {angular.element} element * @param {Hash} attrs * @ctrl {MapController} ctrl */ link: function (scope, element, attrs, ctrl) { var orgAttrs = parser.orgAttributes(element); scope.google = google; //used by $scope.eval in Attr2Options to avoid eval() /** * create a new `div` inside map tag, so that it does not touch map element * http://stackoverflow.com/questions/20955356 */ var el = document.createElement("div"); el.style.width = "100%"; el.style.height = "100%"; element.prepend(el); /** * if style is not given to the map element, set display and height */ if (getStyle(element[0], 'display') != "block") { element.css('display','block'); } if (getStyle(element[0], 'height').match(/^(0|auto)/)) { element.css('height','300px'); } /** * initialize function */ var initializeMap = function(mapOptions, mapEvents) { var map = new google.maps.Map(el, {}); map.markers = {}; map.shapes = {}; /** * resize the map to prevent showing partially, in case intialized too early */ $timeout(function() { google.maps.event.trigger(map, "resize"); }); /** * set options */ mapOptions.zoom = mapOptions.zoom || 15; var center = mapOptions.center; if (!center) { mapOptions.center = new google.maps.LatLng(0,0); } else if (!(center instanceof google.maps.LatLng)) { delete mapOptions.center; Attr2Options.setDelayedGeoLocation(map, 'setCenter', center, {fallbackLocation: options.geoFallbackCenter}); } map.setOptions(mapOptions); /** * set events */ for (var eventName in mapEvents) { if (eventName) { google.maps.event.addListener(map, eventName, mapEvents[eventName]); } } /** * set observers */ parser.observeAttrSetObj(orgAttrs, attrs, map); /** * set controller and set objects * so that map can be used by other directives; marker or shape * ctrl._objects are gathered when marker and shape are initialized before map is set */ ctrl.map = map; /* so that map can be used by other directives; marker or shape */ ctrl.addObjects(ctrl._objects); // /* providing method to add a marker used by user scope */ // map.addMarker = ctrl.addMarker; /** * set map for scope and controller and broadcast map event * scope.map will be overwritten if user have multiple maps in a scope, * thus the last map will be set as scope.map. * however an `mapInitialized` event will be emitted every time. */ scope.map = map; scope.map.scope = scope; //google.maps.event.addListenerOnce(map, "idle", function() { scope.$emit('mapInitialized', map); //}); // the following lines will be deprecated on behalf of mapInitialized // to collect maps, we should use scope.maps in your own controller, i.e. MyCtrl scope.maps = scope.maps || {}; scope.maps[options.id||Object.keys(scope.maps).length] = map; scope.$emit('mapsInitialized', scope.maps); }; // function initializeMap() /** * get map options and events */ var filtered = parser.filter(attrs); var options = parser.getOptions(filtered, scope); var controlOptions = parser.getControlOptions(filtered); var mapOptions = angular.extend(options, controlOptions); var mapEvents = parser.getEvents(scope, filtered); void 0; if (attrs.initEvent) { // allows controlled initialization scope.$on(attrs.initEvent, function() { !ctrl.map && initializeMap(mapOptions, mapEvents); // init if not done }); } else { initializeMap(mapOptions, mapEvents); } // if } }; }]); /** * @ngdoc directive * @name MapController * @requires $scope * @property {Hash} controls collection of Controls initiated within `map` directive * @property {Hash} markersi collection of Markers initiated within `map` directive * @property {Hash} shapes collection of shapes initiated within `map` directive * @property {MarkerClusterer} markerClusterer MarkerClusterer initiated within `map` directive */ /*jshint -W089*/ ngMap.MapController = function() { this.map = null; this._objects = []; /** * Add a marker to map and $scope.markers * @memberof MapController * @name addMarker * @param {Marker} marker google map marker */ this.addMarker = function(marker) { /** * marker and shape are initialized before map is initialized * so, collect _objects then will init. those when map is initialized * However the case as in ng-repeat, we can directly add to map */ if (this.map) { this.map.markers = this.map.markers || {}; marker.setMap(this.map); if (marker.centered) { this.map.setCenter(marker.position); } var len = Object.keys(this.map.markers).length; this.map.markers[marker.id || len] = marker; } else { this._objects.push(marker); } }; /** * Add a shape to map and $scope.shapes * @memberof MapController * @name addShape * @param {Shape} shape google map shape */ this.addShape = function(shape) { if (this.map) { this.map.shapes = this.map.shapes || {}; shape.setMap(this.map); var len = Object.keys(this.map.shapes).length; this.map.shapes[shape.id || len] = shape; } else { this._objects.push(shape); } }; this.addObject = function(groupName, obj) { if (this.map) { this.map[groupName] = this.map[groupName] || {}; var len = Object.keys(this.map[groupName]).length; this.map[groupName][obj.id || len] = obj; if (groupName != "infoWindows" && obj.setMap) { //infoWindow.setMap works like infoWindow.open obj.setMap(this.map); } } else { obj.groupName = groupName; this._objects.push(obj); } } /** * Add a shape to map and $scope.shapes * @memberof MapController * @name addShape * @param {Shape} shape google map shape */ this.addObjects = function(objects) { for (var i=0; i * * */ /*jshint -W089*/ ngMap.directive('mapsEngineLayer', ['Attr2Options', function(Attr2Options) { var parser = Attr2Options; var getMapsEngineLayer = function(options, events) { var layer = new google.maps.visualization.MapsEngineLayer(options); for (var eventName in events) { google.maps.event.addListener(layer, eventName, events[eventName]); } return layer; }; return { restrict: 'E', require: '^map', link: function(scope, element, attrs, mapController) { var filtered = parser.filter(attrs); var options = parser.getOptions(filtered); var events = parser.getEvents(scope, filtered, events); void 0; var layer = getMapsEngineLayer(options, events); mapController.addObject('mapsEngineLayers', layer); } }; // return }]); /** * @ngdoc directive * @name marker * @requires Attr2Options * @requires NavigatorGeolocation * @description * Draw a Google map marker on a map with given options and register events * * Requires: map directive * * Restrict To: Element * * @param {String} position address, 'current', or [latitude, longitude] * example: * '1600 Pennsylvania Ave, 20500 Washingtion DC', * 'current position', * '[40.74, -74.18]' * @param {Boolean} centered if set, map will be centered with this marker * @param {String} <MarkerOption> Any Marker options, https://developers.google.com/maps/documentation/javascript/reference?csw=1#MarkerOptions * @param {String} <MapEvent> Any Marker events, https://developers.google.com/maps/documentation/javascript/reference * @example * Usage: * * * * * Example: * *
* * * * * */ ngMap.directive('marker', ['Attr2Options', function(Attr2Options) { var parser = Attr2Options; var getMarker = function(options, events) { var marker; /** * set options */ if (options.icon instanceof Object) { if ((""+options.icon.path).match(/^[A-Z_]+$/)) { options.icon.path = google.maps.SymbolPath[options.icon.path]; } for (var key in options.icon) { var arr = options.icon[key]; if (key == "anchor" || key == "origin") { options.icon[key] = new google.maps.Point(arr[0], arr[1]); } else if (key == "size" || key == "scaledSize") { options.icon[key] = new google.maps.Size(arr[0], arr[1]); } } } if (!(options.position instanceof google.maps.LatLng)) { var orgPosition = options.position; options.position = new google.maps.LatLng(0,0); marker = new google.maps.Marker(options); parser.setDelayedGeoLocation(marker, 'setPosition', orgPosition); } else { marker = new google.maps.Marker(options); } /** * set events */ if (Object.keys(events).length > 0) { void 0; } for (var eventName in events) { if (eventName) { google.maps.event.addListener(marker, eventName, events[eventName]); } } return marker; }; return { restrict: 'E', require: '^map', link: function(scope, element, attrs, mapController) { var orgAttrs = parser.orgAttributes(element); var filtered = parser.filter(attrs); var markerOptions = parser.getOptions(filtered, scope); var markerEvents = parser.getEvents(scope, filtered); void 0; /** * set event to clean up removed marker * useful with ng-repeat */ element.bind('$destroy', function() { var markers = marker.map.markers; for (var name in markers) { if (markers[name] == marker) { delete markers[name]; } } marker.setMap(null); }); var marker = getMarker(markerOptions, markerEvents); mapController.addMarker(marker); /** * set observers */ parser.observeAttrSetObj(orgAttrs, attrs, marker); /* observers */ } //link }; // return }]);// /** * @ngdoc directive * @name overlay-map-type * @requires Attr2Options * @description * Requires: map directive * Restrict To: Element * * @example * Example: * * * * */ /*jshint -W089*/ ngMap.directive('overlayMapType', ['Attr2Options', '$window', function(Attr2Options, $window) { var parser = Attr2Options; return { restrict: 'E', require: '^map', link: function(scope, element, attrs, mapController) { var overlayMapTypeObject; var initMethod = attrs.initMethod || "insertAt"; if (attrs.object) { var __scope = scope[attrs.object] ? scope : $window; overlayMapTypeObject = __scope[attrs.object]; if (typeof overlayMapTypeObject == "function") { overlayMapTypeObject = new overlayMapTypeObject(); } } if (!overlayMapTypeObject) { throw "invalid map-type object"; } scope.$on('mapInitialized', function(evt, map) { if (initMethod == "insertAt") { var index = parseInt(attrs.index, 10); map.overlayMapTypes.insertAt(index, overlayMapTypeObject); } else if (initMethod == "push") { map.overlayMapTypes.push(overlayMapTypeObject); } }); mapController.addObject('overlayMapTypes', overlayMapTypeObject); } }; // return }]); /** * @ngdoc directive * @name shape * @requires Attr2Options * @description * Initialize a Google map shape in map with given options and register events * The shapes are: * . circle * . polygon * . polyline * . rectangle * . groundOverlay(or image) * * Requires: map directive * * Restrict To: Element * * @param {Boolean} centered if set, map will be centered with this marker * @param {String} <OPTIONS> * For circle, [any circle options](https://developers.google.com/maps/documentation/javascript/reference#CircleOptions) * For polygon, [any polygon options](https://developers.google.com/maps/documentation/javascript/reference#PolygonOptions) * For polyline, [any polyline options](https://developers.google.com/maps/documentation/javascript/reference#PolylineOptions) * For rectangle, [any rectangle options](https://developers.google.com/maps/documentation/javascript/reference#RectangleOptions) * For image, [any groundOverlay options](https://developers.google.com/maps/documentation/javascript/reference#GroundOverlayOptions) * @param {String} <MapEvent> Any Shape events, https://developers.google.com/maps/documentation/javascript/reference * @example * Usage: * * * * * Example: * * * * * * * * * * * * * * * * * * * * * * For full-working example, please visit * [shape example](https://rawgit.com/allenhwkim/angularjs-google-maps/master/build/shape.html) */ ngMap.directive('shape', ['Attr2Options', function(Attr2Options) { var parser = Attr2Options; var getBounds = function(points) { return new google.maps.LatLngBounds(points[0], points[1]); }; var getShape = function(options, events) { var shape; var shapeName = options.name; delete options.name; //remove name bcoz it's not for options void 0; /** * set options */ if (options.icons) { for (var i=0; i * * */ /*jshint -W089*/ ngMap.directive('trafficLayer', ['Attr2Options', function(Attr2Options) { var parser = Attr2Options; var getLayer = function(options, events) { var layer = new google.maps.TrafficLayer(options); for (var eventName in events) { google.maps.event.addListener(layer, eventName, events[eventName]); } return layer; }; return { restrict: 'E', require: '^map', link: function(scope, element, attrs, mapController) { var orgAttrs = parser.orgAttributes(element); var filtered = parser.filter(attrs); var options = parser.getOptions(filtered); var events = parser.getEvents(scope, filtered); void 0; var layer = getLayer(options, events); mapController.addObject('trafficLayers', layer); parser.observeAttrSetObj(orgAttrs, attrs, layer); //observers } }; // return }]); /** * @ngdoc directive * @name transit-layer * @requires Attr2Options * @description * Requires: map directive * Restrict To: Element * * @example * Example: * * * * */ /*jshint -W089*/ ngMap.directive('transitLayer', ['Attr2Options', function(Attr2Options) { var parser = Attr2Options; var getLayer = function(options, events) { var layer = new google.maps.TransitLayer(options); for (var eventName in events) { google.maps.event.addListener(layer, eventName, events[eventName]); } return layer; }; return { restrict: 'E', require: '^map', link: function(scope, element, attrs, mapController) { var orgAttrs = parser.orgAttributes(element); var filtered = parser.filter(attrs); var options = parser.getOptions(filtered); var events = parser.getEvents(scope, filtered); void 0; var layer = getLayer(options, events); mapController.addObject('transitLayers', layer); parser.observeAttrSetObj(orgAttrs, attrs, layer); //observers } }; // return }]); /** * @ngdoc directive * @name weather-layer * @requires Attr2Options * @description * Requires: map directive * Restrict To: Element * * @example * Example: * * * * */ /*jshint -W089*/ ngMap.directive('weatherLayer', ['Attr2Options', function(Attr2Options) { var parser = Attr2Options; var getLayer = function(options, events) { var layer = new google.maps.weather.WeatherLayer(options); for (var eventName in events) { google.maps.event.addListener(layer, eventName, events[eventName]); } return layer; }; return { restrict: 'E', require: '^map', link: function(scope, element, attrs, mapController) { var orgAttrs = parser.orgAttributes(element); var filtered = parser.filter(attrs); var options = parser.getOptions(filtered); var events = parser.getEvents(scope, filtered); void 0; var layer = getLayer(options, events); mapController.addObject('weatherLayers', layer); parser.observeAttrSetObj(orgAttrs, attrs, layer); //observers } }; // return }]);