{"id":26878846,"url":"https://github.com/logicify/angular-gmap","last_synced_at":"2026-03-10T12:33:00.076Z","repository":{"id":35130485,"uuid":"39335182","full_name":"Logicify/angular-gmap","owner":"Logicify","description":"google maps wrapper based on angular js","archived":false,"fork":false,"pushed_at":"2016-07-20T22:35:14.000Z","size":461,"stargazers_count":3,"open_issues_count":2,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-28T03:02:54.393Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Logicify.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-07-19T13:47:05.000Z","updated_at":"2017-08-01T08:49:30.000Z","dependencies_parsed_at":"2022-08-17T21:31:21.259Z","dependency_job_id":null,"html_url":"https://github.com/Logicify/angular-gmap","commit_stats":null,"previous_names":["artemijan/logicify-gmap"],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Logicify%2Fangular-gmap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Logicify%2Fangular-gmap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Logicify%2Fangular-gmap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Logicify%2Fangular-gmap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Logicify","download_url":"https://codeload.github.com/Logicify/angular-gmap/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252930403,"owners_count":21827049,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-31T12:29:49.733Z","updated_at":"2025-12-12T03:03:59.172Z","avatar_url":"https://github.com/Logicify.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"### What is this repository for? ###\n\n* This product is a wrapper for [google maps api](https://developers.google.com/maps/documentation/javascript/tutorial) based on angular.\n* Stable Version 0.1.14\n\n[![NPM](https://nodei.co/npm/logicify-gmap.png?downloads=true\u0026downloadRank=true)](https://www.npmjs.com/package/logicify-gmap)\n\n### For developers ###\n\n* node.js and npm\n```shell\n npm install grunt-cli -g\n npm install bower -g\n npm install\n grunt logicifyGmap\n```\n### Usage ###\n\n#### JSFiddle example ####\n[![example](http://i.imgur.com/BRZKfPm.png)](https://jsfiddle.net/s6s4mbc5/73/)\n```shell\nbower install logicify-gmap\n```\n\nor\n\n```shell\nnpm install logicify-gmap\n```\n\n#### At first you need include google api reference into your html file. ####\n\nSomething like that:\n```html\n\u003cscript src=\"https://maps.googleapis.com/maps/api/js?v=3.20\"\u003e\u003c/script\u003e\n```\n###### You need to be sure that this api is loaded before angular.js ######\n\n##### Inject module into your angular app #####\n\n```js\nvar app = angular.module('myApp', [ \"LogicifyGMap\" ]);\n```\n\n##### Inject map (directive) #####\nplace it in your html file\n```html\n\u003clogicify-gmap center=\"gmOpts.center\"\n               gm-options=\"gmOpts\"\n               gm-ready=\"ready\"\n               css-options=\"cssOpts\"\u003e\n\u003c/logicify-gmap\u003e\n```\n\n* center - center map (is LatLng object from [google api](https://developers.google.com/maps/documentation/javascript/tutorial));\n* gm-options  - (javascript object) is google maps options [google api](https://developers.google.com/maps/documentation/javascript/tutorial)\n* gm-ready - (function) callback function fires when directive is rendered and passes on gmap Object.\n\nFrom controller\n```js\nvar app = angular.module('myApp', [ \"LogicifyGMap\" ]);\napp.controller('myCtrl',['$scope',function($scope){\n    $scope.cssOpts = {width: '50%', height: '50%', 'min-width': '400px', 'min-height': '200px'};\n    $scope.gmOpts = {zoom: 10, center: new google.maps.LatLng(-1, 1)};\n    $scope.ready = function(gmap){\n        $scope.gmap = gmap; //it's google maps object (not wrapped)\n    };\n}]);\n```\n* css-options - is javascript object is needed for injecting css into map element\n\n##### Custom X (close) button for info window. #####\n\n```css\n     .gm-style-iw+div{\n         display:none\n         }\n```\n\nwhere .gm-style-iw is a class of container element, and next div is close button!\n\n##### Inject map controls (directive) #####\n\nhtml\n\n```html\n\u003clogicify-gmap center=\"gmOpts.center\"\n               gm-options=\"gmOpts\"\n               gm-ready=\"ready\"\n               css-options=\"cssOpts\"\u003e\n    \u003clogicify-gmap-control\n    control-position=\"position\"\n    control-index=\"1\"\n    events=\"controlEvents\"\u003e\n        \u003cbutton\u003ePush me\u003c/button\u003e\n        \u003cinput type=\"file\"\u003e\n    \u003c/logicify-gmap-control\u003e\n\u003c/logicify-gmap\u003e\n```\n\nscript\n\n```js\n$scope.index = 1;\n$scope.position = google.maps.ControlPosition.BOTTOM_LEFT;\n$scope.controlEvents = {\n                click: function (event) {\n                    //it's google.maps.event\n                },\n                fileSelect: function(file){\n                    //this method binds on file input inside logicify-gmap-control directive\n                    //it's DOM event\n                }\n            };\n```\n\ncontrolEvents - it's just a javascript object. Each key should be an event name ('click','mouseover'...) and value is a callback function.\n\n## Info window ##\n\nIt's angular supported. So you can use angular inside info window template (directives, scope, controller...).\n\n#### Inject 'InfoWindow' service from 'logicify-gmap' api. ####\n```js\nmodule.controller('myCtrl', ['$scope', '$timeout', 'InfoWindow', function ($scope, $timeout, InfoWindow) {\n            $scope.markers = [];\n            $scope.cssOpts = {width: '50%', height: '50%', 'min-width': '400px', 'min-height': '200px'};\n            $scope.gmOpts = {zoom: 10, center: new google.maps.LatLng(-1, 1)};\n            $scope.closeInfoWindow = function (infowindow) {\n                infowindow.close(true); //destroy scope and info window element\n                //or\n                //infowindow.close();  //just close info window\n            };\n            $scope.ready = function (map) {\n                var infowindow = new InfoWindow({templateUrl: 'template.html'}); //it's not infowindow now. (object like \"javascript promise\", but not a promise)\n                function attach(marker) {\n                    google.maps.event.addListener(marker, 'click', function (markerObj) { //on marker click\n                        infowindow.$ready(function (wnd) { // pass infowindow object\n                            wnd.open(map, marker); //open infowindow\n                        });\n                    });\n                }\n\n                //loop all markers\n                for (var i = 10; i \u003c 15; i++) {\n                    var pos = new google.maps.LatLng(-1 + 1 / i, 1 + 1 / i);//random position\n                    var marker = new google.maps.Marker({    //create new marker\n                        id: 'marker_' + i,\n                        name: 'is_' + i,\n                        position: pos,\n                        map: map\n                    });\n                    $scope.markers.push(marker);\n                    attach(marker);//attach listener\n                }\n            };\n\n        }]);\n```\n\n#### template.html ####\n\n```html\n\u003cdiv\u003e\n    \u003clabel\u003e{{$infoWND.anchor.id}}\u003c/label\u003e\n    \u003cbutton ng-click=\"closeInfoWindow($infoWND)\"\u003eClose me\u003c/button\u003e\n\u003c/div\u003e\n```\n\n* when you try to create info window object\n\n```js\nvar infowindow = new InfoWindow({templateUrl: 'template.html'});\n```\n\nIt's not an infowindow yet. Because rendering template and apply scope digest takes some time.\n\n```js\n infowindow.$ready(function (wnd) {\n                            //do something with 'wnd'\n                        });\n```\n\nAnd now 'wnd' is info window object.\n\n##### you can use $infoWND object in the template.html. $infoWND.anchor is a marker! #####\n\n### Many info windows in one time: ###\n\n```js\n$scope.ready = function (map) {\n\n                function attach(marker) {\n                    var infowindow = new InfoWindow({templateUrl: 'template.html'}); //create new infowindow for each marker\n                    google.maps.event.addListener(marker, 'click', function (markerObj) { //on marker click\n                        infowindow.$ready(function (wnd) { // pass infowindow object\n                            wnd.open(map, marker); //open infowindow\n                        });\n                    });\n                }\n\n                //loop all markers\n                for (var i = 10; i \u003c 15; i++) {\n                    var pos = new google.maps.LatLng(-1 + 1 / i, 1 + 1 / i);//random position\n                    var marker = new google.maps.Marker({    //create new marker\n                        id: 'marker_' + i,\n                        name: 'is_' + i,\n                        position: pos,\n                        map: map\n                    });\n                    $scope.markers.push(marker);\n                    attach(marker);//attach listener\n                }\n            };\n```\n\nIf you want more than one info window on google map, you just need create it for each marker!\n\n```js\nvar infowindow = new InfoWindow({templateUrl: 'template.html'}); //in the loop\n```\n\n### Closing info window can be done in two ways: ###\n\n1) Destroy scope and element. Please careful with this param, because to render it again - takes more time then just apply scope digest.\n```js\ninfowindow.close(true)\n```\n2) Just hide window (proper way).\n```js\ninfowindow.close();\n```\n###### Note that after opening info window (wnd.open(map)) you can access to wnd.$scope (property \"$scope\" only, not \"scope\")!\nwhy only after opening? Because \"open\" method rewrites infowindow scope and applies digest. So you can access the scope only after calling method \"open\".\n\n## XML overlays support\n\n[![jsfiddle example](http://i.imgur.com/ulcqPif.png)](https://jsfiddle.net/rfgzw63r/9/)\n\nThere is a way to display xml overlays on google map using \"xml-overlays\" directive.\nNote that we are using [geoxml3](https://github.com/artemijan/geoxml3) library to parse xml files.\nXML files can be: .zip, .kmz, .kml, or just a string.\nKml\\kmz object can contain:\n```js\n var list = [\n        {url:'some url of kml or kmz file here'},\n        {file: instance of Blob here},\n        {content: just string value}\n ]\n```\n#### Basic usage:\ninclude this file to your html:\n- geoxml3.js\n\n###### HTML\n```html\n\u003cdiv ng-controller=\"TestController\"\u003e\n    \u003clogicify-gmap\n            center=\"gmOpts.center\"\n            gm-options=\"gmOpts\"\n            gm-ready=\"ready\"\n            css-options=\"cssOpts\"\u003e\n        \u003clogicify-gmap-control\n                control-position=\"position\"\n                control-index=\"1\"\n                events=\"controlEvents\"\u003e\n            \u003cbutton\u003ePush me\u003c/button\u003e\n        \u003c/logicify-gmap-control\u003e\n        \u003cxml-overlays\n                kml-collection=\"kmlCollection\"\n                gmap-events=\"kmlEvents\"\u003e\n        \u003c/xml-overlays\u003e\n    \u003c/logicify-gmap\u003e\n\u003c/div\u003e\n```\n###### JS\n```js\napp.controller('TestController', ['$scope', '$timeout', 'InfoWindow', function ($scope, $timeout, InfoWindow) {\n        $scope.markers = [];\n        $scope.controlEvents = {\n            click: function (event) {\n                $scope.kmlCollection = [\n                    {url: 'tristate_area.kml'}\n                ];\n            }\n        };\n        $scope.cssOpts = {\n            width: '80%',\n            height: '60%',\n            'min-width': '400px',\n            'min-height': '200px'\n        };\n        $scope.gmOpts = {\n            zoom: 16,\n            center: new google.maps.LatLng(-1, 1)\n        };\n        $scope.kmlCollection = [\n            {url: 'cta.kml'}\n        ];\n        $timeout(function () {\n            $scope.kmlCollection.push({url: 'tristate_area.kml'});\n        }, 3000);\n        $timeout(function () {\n            $scope.kmlCollection.pop();\n        }, 6000);\n        $timeout(function () {\n            $scope.kmlCollection = [{url: 'tristate_area.kml'},{url: 'cta.kml'}];\n        }, 9000);\n        $scope.kmlEvents = {};\n        $scope.position = google.maps.ControlPosition.BOTTOM_LEFT;\n        $scope.index = 1;\n    }]);\n```\n###### Events\n```html\n \u003cxml-overlays\n                kml-collection=\"kmlCollection\"\n                gmap-events=\"kmlEvents\"\u003e\n \u003c/xml-overlays\u003e\n```\n```js\nvar kmlEvents = {\n    onAfterParse:function(doc){\n        //doc - array with documents\n    },\n    onAfterParseFailed:function(err){\n\n    },\n    onAfterCreateGroundOverlay:function(groundOverlayGMapMVCObject){\n    },\n    onAfterCreatePolygon:function(polygonMVCObject,placemark){\n        //all mvc objects has methods \"get\" \u0026 \"set\"\n    },\n    onAfterCreatePolyLine:function(polyLineMVCObject,placemark){\n\n    }\n};\n```\nAlso you can include all [events from geoxml3 lib](https://github.com/artemijan/geoxml3/blob/wiki/ParserReference.md)\n###### Options:\nall options described on [geoxml3 repository](https://github.com/artemijan/geoxml3/blob/wiki/ParserReference.md)\nThere is one more option fit-bounds-afterAll\n\n```html\n\u003cxml-overlays\n                kml-collection=\"kmlCollection\"\n                gmap-events=\"kmlEvents\"\n                fit-bounds-afterAll=\"false\"\u003e\n\u003c/xml-overlays\u003e\n```\nThis option is true by default. When you are disabling this option the last layer will be displayed on the map.\nTo view all layers you need modify zoom and center of the map by mouse.\nIf this options is enabled, then all layers will be displayed on the map, and you don't need to scroll and dragging the map to view all layers\n###### Progress callback\nHtml example\n```html\n\u003cxml-overlays\n                kml-collection=\"kmlCollection\"\n                gmap-events=\"kmlEvents\"\n                on-progress=\"callback\"\u003e\n\u003c/xml-overlays\u003e\n```\nProgress object structure\n```js\ncallback = function(progress){\n    progress = {\n            done: Integer,\n            errors: Integer,\n            total: Integer\n        };\n}\n```\nProgress callback calls each time when xml file downloaded and parsed (or parsing is failed).\n###### Infowindow\nYou can create and inject infowindow to your overlays.\nBut if you want to be able to access overlay MVC object from infowindow scope then you need just add property to infowindow object.\n```js\n $scope.overlaysInfowindow = new InfoWindow({templateUrl: 'infowindow.html'});\n $scope.overlaysInfowindow.$ready(overlayInfowindowReady); //w8 for downloading template\n function overlayInfowindowReady(wnd) {\n     wnd.$onOpen = function (gObj) {   //method \"open\" of infowindow calls by geoxml3 parser, so you don't need call \"infowindow.open(map,marker)\" like for markers\n        wnd.$scope.mvcObject = gObj;   //when infowindow opened then calls \"$onOpen\" callback with google mvc object\n        gObj.setDraggable(true);\n   };\n }\n```\nHTML\n```html\n\u003cdiv class=\"infowindow\"\u003e\n    {{mvcObject.title}}\n    {{mvcObject.get('fillColor')}}\n    ...etc\n\u003c/div\u003e\n```\nsee more information about [google mvc object](https://developers.google.com/maps/documentation/javascript/reference#MVCObject)\n###### Load kml\\kmz file via HTML file input:\n\n[![jsfiddle example](http://i.imgur.com/VDYVUJw.png)](https://jsfiddle.net/7gu8cksn/5/)\n\n###### How it works\nThe kml\\kmz collection is instance of \"SmartCollection\" (you can inject it just by adding \"SmartCollection\"-service to your dependency).\nSmartCollection - is angular service. SmartCollection instanceOf Array === true.\n```js\nvar file1 = {url:'http://some url'}, file2 = {url:'http://some url'}, file3 = {url:'http://some url'};\nscope.kmlCollection = [file1,file2,file3]; //create new collection\nscope.kmlCollection = [file1, file2, file3] //delete old collection and crete new one (all those files will be downloaded again)\nscope.kmlCollection.push({url:'http://different url'}); //only this file will be downloaded and parsed.\n//next example\nscope.kmlCollection.splice(1,scope.kmlCollection.length) // delete last 2 items (file1 wouldn't be reloaded)\nscope.kmlCollection = [file1]; //reload file1 and delete rest\n```\n#### Drawing support\n\n####### First of all you need to see\n\n[![google maps spec](http://atendesigngroup.com/sites/default/files/styles/very_large/public/GoogleMapsAPI.png?itok=acFlX03s)](https://developers.google.com/maps/documentation/javascript/drawinglayer).\n\n###### Usage:\n- Add dependency injection for google maps drawing api (taken from google maps drawing spec):\n```html\n\u003cscript type=\"text/javascript\"\n  src=\"https://maps.googleapis.com/maps/api/js?\u0026libraries=drawing\"\u003e\n\u003c/script\u003e\n```\nAs can you see dependency injection it's just url param.\n- Include this html into gmap directive:\n```html\n\u003clogicify-gmap\n            center=\"gmOpts.center\"\n            gm-options=\"gmOpts\"\n            gm-ready=\"ready\"\n            css-options=\"cssOpts\"\u003e\n        \u003clogicify-gmap-draw\n                gmap-events=\"draw.events\"\n                draw-options=\"draw.options\"\u003e\n        \u003c/logicify-gmap-draw\u003e\n\u003c/logicify-gmap\u003e\n```\n- Implement JS logic to be able manipulate the map (controller code):\n\n```js\nscope.draw = {\n            //put all drawing things in one place\n            events: {\n                drawing: {},\n                overlays: {\n                    click: function (e, map) {\n                        var self = this;\n                        //note that \"this\" can be overlay or marker, you need to be careful, because marker doesn't have \"center\" property and overlay has.\n                        if (scope.overlaysInfowindow) {\n                            scope.overlaysInfowindow.$ready(function (wnd) {\n                                wnd.setPosition(e.latLng);//info window position\n                                wnd.open(map);\n                                wnd.$scope.mvcObject = self;\n                                wnd.$scope.applyConfig = applyConfig;\n                            });\n                        }\n                    }\n                }\n            },\n            //see google maps spec about drawing options\n            options: {\n                drawingMode: google.maps.drawing.OverlayType.MARKER,\n                drawingControl: true,\n                drawingControlOptions: {\n                    position: google.maps.ControlPosition.TOP_CENTER,\n                    drawingModes: [\n                        google.maps.drawing.OverlayType.MARKER,\n                        google.maps.drawing.OverlayType.CIRCLE,\n                        google.maps.drawing.OverlayType.POLYGON,\n                        google.maps.drawing.OverlayType.POLYLINE,\n                        google.maps.drawing.OverlayType.RECTANGLE\n                    ]\n                },\n                markerOptions: {icon: 'beachflag.png'},\n                circleOptions: {\n                    fillColor: '#ffff00',\n                    fillOpacity: 1,\n                    strokeWeight: 5,\n                    editable: true,\n                    zIndex: 1\n                }\n            }\n        };\n        scope.cssOpts = {\n            width: '80%',\n            height: '60%',\n            'min-width': '400px',\n            'min-height': '200px'\n        };\n        scope.gmOpts = {\n            zoom: 16,\n            center: new google.maps.LatLng(-1, 1)\n        };\n        function applyConfig(mvcObject) {\n            /**\n             * Redraw overlay\n             */\n            mvcObject.setMap(null);\n            mvcObject.setMap(scope.gmap);\n        }\n\n        scope.ready = function (map) {\n            scope.gmap = map;\n            scope.overlaysInfowindow = new infoWindow({templateUrl: 'infowindow.html'});\n        };\n```\n\n##### Custom lines (requires drawing manager)\n\nIf you want custom lines, overlay borders then you need to do the next:\n\n- include css file to your html (gmap-minimum-ui.css) to allow dropdown to work correctly (gmap-dropdown based on css transitions)\n- include html code to your gmap directive (into logicify-gmap-draw directive):\n```html\n\u003cscript type=\"text/ng-template\" id=\"dropdown.html\"\u003e\n        \u003cdiv class=\"custom-holder\"\u003e\n            \u003cspan class=\"custom-title\" title=\"it's google baby \u003c(^_^)\u003e\"\u003eG(.)(.)gle\u003c/span\u003e\n            \u003cdiv gmap-dropdown gmap-dropdown-items=\"polyLineTypes\" on-dropdown-select-item=\"onSelectPolyLineType\"\u003e\u003c/div\u003e\n        \u003c/div\u003e\n\u003c/script\u003e\n\u003clogicify-gmap\n            center=\"gmOpts.center\"\n            gm-options=\"gmOpts\"\n            gm-ready=\"ready\"\n            css-options=\"cssOpts\"\u003e\n        \u003clogicify-gmap-draw\n                gmap-events=\"draw.events\"\n                draw-options=\"draw.options\"\u003e\n            \u003cgmap-extended-draw\n                    line-types-control-position=\"lineTypesControlPosition\"\n                    gmap-dropdown-template-url=\"dropDownTemplate\"\u003e\n                    gmap-dropdown-template=\"dropDownContent\"\u003e\n            \u003c/gmap-extended-draw\u003e\n        \u003c/logicify-gmap-draw\u003e\n    \u003c/logicify-gmap\u003e\n```\nif you wouldn't define line-types-control-position attribute, then directive will append this\ndropdown to current element, so you will be able to draw it out of map\n- write some javascript in your controller:\n```js\nscope.lineTypesControlPosition = google.maps.ControlPosition.TOP_CENTER; //let's say that it will be at top-center\n//scope.dropDownTemplate = 'dropdown.html';\n//you can define your own dropdown template(bootstrap for example)\n//scope.dropDownContent = \u003cdiv\u003eDropdown here\u003c/div\u003e\n//define dropdown template as string\n//if you wouldn't define any template, then 'gmap-extended-draw' directive will use internal directive 'gmap-dropdown',\n//so you don't need define your own dropdown\nscope.draw = {//draw options here, see example above};\nscope.cssOpts = {\n    width: '90%',\n    height: '90%',\n    'min-width': '400px',\n    'min-height': '200px'\n};\n\nscope.gmOpts = {\n    zoom: 16,\n    center: new google.maps.LatLng(-1, 1)\n};\nscope.ready = function (map) {\n    scope.gmap = map;\n};\n```\n\n######Note that if you would use your own dropdown, then please keep following rules:\n\n- \"onSelectPolyLineType(item)\" use this callback name in your html to select;\n- Use \"current\" object name to access selected item;\n- \"polyLineTypes\" use this object name to display poly line types in the dropdown;\nExample for custom bootstrap dropdown:\n```html\n\u003cdiv class=\"dropdown\"\u003e\n  \u003cbutton class=\"btn btn-default dropdown-toggle\" type=\"button\" id=\"dropdownMenu1\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"true\"\u003e\n    \u003cspan class=\"gmap-dropdown-header\" ng-bind=\"current.name||current\"\u003e\u003c/span\u003e\n    \u003cspan class=\"caret\"\u003e\u003c/span\u003e\n  \u003c/button\u003e\n  \u003cul class=\"dropdown-menu\" aria-labelledby=\"dropdownMenu1\"\u003e\n    \u003cli ng-repeat=\"item in dropDownItems\" ng-click=\"onSelectItemLocally(item)\"\u003e\u003ca ng-bind=\"item.name || item\"\u003e\u003c/a\u003e\u003c/li\u003e\n  \u003c/ul\u003e\n\u003c/div\u003e\n```\n[![jsfiddle example](http://i.imgur.com/1ly0fvZ.png)](https://jsfiddle.net/m2dpme1d/7/)\n\n###### Extending line types\nYou can extend list of supported line types (dotted, dashed, arrow-dotted etc.)\n```html\n\u003clogicify-gmap\n            center=\"gmOpts.center\"\n            gm-options=\"gmOpts\"\n            gm-ready=\"ready\"\n            css-options=\"cssOpts\"\u003e\n        \u003clogicify-gmap-draw\n                gmap-events=\"draw.events\"\n                draw-options=\"draw.options\"\u003e\n            \u003cgmap-extended-draw\n                    line-types-control-position=\"lineTypesControlPosition\"\n                    gmap-dropdown-template-url=\"dropDownTemplate\"\n                    override-line-types=\"overrideLineTypes\"\n                    on-after-drawing-overlay=\"onAfterDraw\"\u003e\n            \u003c/gmap-extended-draw\u003e\n        \u003c/logicify-gmap-draw\u003e\n    \u003c/logicify-gmap\u003e\n```\nAs can you see there are few attributes added. override-line-types=\"overrideLineTypes\" and on-after-drawing-overlay=\"onAfterDraw\"\nController code below:\n```js\nscope.lineTypesControlPosition = google.maps.ControlPosition.TOP_CENTER;\nscope.overrideLineTypes = function (lineTypesArray) {\n    var icon = {\n        path: 'M0 0, L5 10, 10 -5', //svg path definition\n        strokeWeight: 2,\n        scale: 0.4\n    };\n    var layer = {\n        name: 'Nice line',\n        icons: [{icon: icon, offset: '100%', repeat: '20px'}],\n        parentOptions: {\n            strokeOpacity: 0\n        }\n    };\n    lineTypesArray.push(layer);\n    return lineTypesArray;//return array back to directive (Required!!!!!)\n};\n//will not fires if marker or circle was added\nscope.onAfterDraw = function (lineType) {\n    this.set('fillColor','#0af10a');\n    //this - overlay\n    //lineType - is an item from array of line types\n    //this.border - is poly line around rectangle or polygon, because only those figures can't be styled with strokeStyle (strokeOpacity of overlay is 0)\n    //border can be null if overlay is polyLine!!!! Otherwise it will be google MVC object always\n    if(this.border!=null){\n        //do something here\n    }\n};\n```\nWhat is \"icons\" in lineTypesArray exactly? For example:\n\n```js\nvar dottedIcon =  {\n    path: 'M 0,-1 0,1', //it's svg path definition, please see w3 spec\n    //options below\n    strokeOpacity: 1,\n    strokeWeight: 4,\n    scale: 0.2\n}\nvar arrow = {//arrow definition here}\nvar lineType = {\n    name: 'My name is dotted line', //name displayed in dropdown list\n    icons: [dottedIcon, arrow], //set dotted line here\n    //those options will be applied to overlay\n    parentOptions: {\n        strokeOpacity: 0 //should be a 0, because you are drawing dotted line, we don't need any border\n    }\n}\n```\nYou should check w3 org spec at first\n\n[![svg path definition](http://www.designfridge.co.uk/web-design/wp-content/uploads/2009/11/w3.gif)](http://www.w3schools.com/svg/svg_path.asp)\n\n###### Please see on-after-drawing-overlay callback.\nThis callback fires when custom lines applied to overlay (rectangle, polyline, polygon only).\nBorder of shapes can't be styled as dotted or dashed for example, so we decided remove border of the shape overlay, and draw polyline instead.\nSo each \"overlay\" object passed via this callback should have \"overlay.border\" property (it's poly line).\n\n###### Editable mode.\n\nYou need to put all overlays to some collection. And then by clicking on some control, just set \"editable\" to true for all overlays.\n\n```js\nscope.drawOptions = {\n    events: {\n        drawing: {\n            overlaycomplete: function (e) {\n                var self = this;\n                overlaysCollection.push(e.overlay);\n            }\n        }\n    }\n};\nscope.onAfterDraw = function (lineType) {\n    overlaysCollection.push(this);\n};\nscope.toggleEditMode = function(){\n    scope.isEditModeEnabled = !scope.isEditModeEnabled;\n    overlaysCollection.forEach(function(overlay){\n        overlay.set(\"editable\",scope.isEditableModeEnabled);\n        if(overlay.border){\n            //do something with custom border (if it's polyline)\n            border.set(\"editable\", scope.isEditableModeEnabled)\n        }\n    });\n};\n```\n\n###### If you want remove overlay you can do the next:\n\n```js\n$scope.draw = {\n    \tevents: {\n            drawing: {\n                overlaycomplete: function (e) {\n                    //add listener\n                    google.maps.event.addListener(e.overlay, 'click', function (e) {\n                        if (window.event.ctrlKey) {\n                            this.setMap(null);\n                            if (this.border \u0026\u0026 typeof this.border.setMap === 'function') {\n                                this.border.setMap(null);\n                            }\n                            //when overlay removed, we don't need any listeners on it\n                            google.maps.event.clearInstanceListeners(this);\n                        }\n                    });\n                }\n            }\n        }\n\t};\n```\n###### Please don't forget cleanup after you self. Remove all listeners from google instance if it's not needed any more.\n\n[![jsfiddle example](http://i.imgur.com/g9kMqzk.png)](https://jsfiddle.net/nzm72vLh/11/)\n\n###### Color picker\nYou can pick a color for lines and shapes. You need to do the next:\n```html\n\u003clogicify-gmap\n            center=\"gmOpts.center\"\n            gm-options=\"gmOpts\"\n            gm-ready=\"ready\"\n            css-options=\"cssOpts\"\u003e\n        \u003clogicify-gmap-draw\n                gmap-events=\"draw.events\"\n                draw-options=\"draw.options\"\u003e\n            \u003cgmap-extended-draw\n                    line-types-control-position=\"lineTypesControlPosition\"\n                    gmap-dropdown-template-url=\"dropDownTemplate\"\n                    override-line-types=\"overrideLineTypes\"\n                    on-after-drawing-overlay=\"onAfterDraw\"\n                    gmap-color-picker=\"\"\n                    color-picker-control-position=\"colorPickerControlPosition\"\n                    enable-opacity-range=\"true\"\u003e\n            \u003c/gmap-extended-draw\u003e\n        \u003c/logicify-gmap-draw\u003e\n    \u003c/logicify-gmap\u003e\n```\nOr\n```html\n\u003clogicify-gmap\n            center=\"gmOpts.center\"\n            gm-options=\"gmOpts\"\n            gm-ready=\"ready\"\n            css-options=\"cssOpts\"\u003e\n        \u003clogicify-gmap-draw\n                gmap-events=\"draw.events\"\n                draw-options=\"draw.options\"\u003e\n            \u003cgmap-extended-draw\n                    line-types-control-position=\"lineTypesControlPosition\"\n                    gmap-dropdown-template-url=\"dropDownTemplate\"\n                    override-line-types=\"overrideLineTypes\"\n                    on-after-drawing-overlay=\"onAfterDraw\"\u003e\n                        \u003cgmap-color-picker\n                                color-picker-control-position=\"colorPickerControlPosition\"\n                                enable-opacity-range=\"true\"\n                                gmap-color-picker-template-url=\"dropDownTemplate\"\n                                gmap-color-picker-template=\"dropDownContent\"\n                                override-destinations=\"overrideCallback\"\u003e\n                        \u003c/gmap-color-picker\u003e\n            \u003c/gmap-extended-draw\u003e\n        \u003c/logicify-gmap-draw\u003e\n    \u003c/logicify-gmap\u003e\n```\n```js\nscope.colorPickerControlPosition = google.maps.ControlPosition.TOP_CENTER;\n//scope.colorPickerTemplate = 'colorPicker.html';\n//you can define your own color picker template(bootstrap for example)\n//scope.colorPickerContent = \u003cdiv\u003eColor picker here\u003c/div\u003e\n//define colorPicker template as string\n//if you wouldn't define any template, then 'gmap-color-picker' directive will use internal html,\n//so you don't need define your own color picker\n```\nyou can override destinations (border, fill). Attribute \"override-destinations\" contains overrideCallback.\nThis callback calls when directive initialize.\n```js\nscope.overrideCallback = function(destinations){\n    destinations.forEach(function(destination){\n        destination.name += ' color or opacity';//you can see on the button \"Fill color or opacity\"\n    });\n    return destinations; //required!!! You need return array back to directive.\n}\n```\nFor custom color pickers you need to keep next rules:\n- if there's opacity input, then \"onSelectOpacity\" callback should be called in your html\n- ng-model is \"destinations[destination].opacity.value\" or \"destinations[destination].color.value\"\n- Destination name could be \"Border\" or \"Fill\" (or you can override it, but only two cases), for example in your html: \"destinations[destination].name\"\nExample html:\n```html\n\u003cinput min=\"1\" max=\"100\" type=\"range\" ng-change=\"onSelectOpacity()\" ng-model=\"destinations[destination].opacity.value\"/\u003e\n```\n- Button \"toggle destination\" should call \"toggleDestination\" callback (you can use any DOM event for this, \"ng-click\" for example)\n- For color picker you should use \"onSelectColor\" callback in your html\n- Note that all examples are with ng-model. So all callbacks (\"onSelectOpacity\" or \"onSelectColor\") calls to update drawing manager only, because it's in a parent directive\n\nExample for color picker and change destination button:\n```html\n\u003cbutton ng-click=\"toggleDestination()\" ng-bind=\"destinations[destination].name\"\u003e\u003c/button\u003e\n\u003cinput type=\"color\" ng-model=\"destinations[destination].color.value\" ng-change=\"onSelectColor()\"/\u003e\n```\n###### Internal color picker - it's html5 input (type=\"color\"). Please see browser capability\n\n##Auto complete address search support\nNote that \"places\" library is required.\n\nYour html\n```html\n\u003clogicify-gmap\n            center=\"gmOpts.center\"\n            gm-options=\"gmOpts\"\n            gm-ready=\"ready\"\n            css-options=\"cssOpts\"\u003e\n        \u003cgmap-auto-complete\n                auto-complete-place-holder=\"placeHolder\"\n                default-zoom-on-placeChange=\"16\"\n                gmap-on-place-changed=\"onPlaceChanged\"\n                auto-complete-control-position=\"autoCompleteControlPosition\"\n                enable-auto-complete-type-selectors=\"true\"\n                enable-default-marker=\"enableDefaultMarker\"\n                on-reverse-address-complete=\"onReverseAddressComplete\"\u003e\n        \u003c/gmap-auto-complete\u003e\n\u003c/logicify-gmap\u003e\n\u003cscript src=\"https://maps.googleapis.com/maps/api/js?libraries=places\"\u003e\u003c/script\u003e\n```\nController code:\n```js\nscope.autoCompleteControlPosition = google.maps.ControlPosition.TOP_CENTER;\nscope.placeHolder = 'Enter location';\nscope.enableDefaultMarker = false;\nscope.onPlaceChanged = function (map, place, inputValue) {\n//if no infowindow then create\n    if (!scope.placesInfoWindow) {\n        scope.placesInfoWindow = new infoWindow({templateUrl: 'place.html'});\n    }\n    //if no marker then create\n    if (!scope.placeMarker) {\n        scope.placeMarker = new google.maps.Marker({\n            id: 'places_marker',\n            map: map\n        });\n    }\n    var position = null;\n    if (!place.geometry) {\n        //if no geometry then check for latitude and longitude in address box\n        var searchFor = inputValue;\n        if (typeof searchFor === 'string' \u0026\u0026 searchFor.length \u003e 0) {\n            var splitLatLon = searchFor.split(','),\n                latitude = splitLatLon[0] * 1,\n                longitude = splitLatLon[1] * 1;\n            if (splitLatLon.length == 2 \u0026\u0026 angular.isNumber(latitude) \u0026\u0026 angular.isNumber(longitude) \u0026\u0026 !isNaN(latitude) \u0026\u0026 !isNaN(longitude)) {\n                position = {lat: latitude, lng: longitude};\n                map.setCenter(position);\n            }\n        }\n        //if no position then do nothing\n        if (!position) {\n            scope.placeMarker.setVisible(false);\n            scope.placesInfoWindow.$ready(function (wnd) {\n                wnd.close();\n            });\n            return;\n        }\n     } else {\n        //if there's geometry\n        position = place.geometry.location;\n     }\n     scope.placeMarker.setPosition(position);\n     scope.placeMarker.setVisible(true);\n     scope.placesInfoWindow.$ready(function (wnd) {\n        wnd.place = place;\n        wnd.open(map, scope.placeMarker);\n     });\n};\n```\n\n[![jsfiddle example](http://i.imgur.com/TaPLAaP.png)](https://jsfiddle.net/gwdcf9c0/8/)\n\n###### Reverse auto complete search\nFor example we handle 'dragend' event of marker.\n```js\nscope.onReverseAddressComplete = function (searchResults) {\n    return searchResults[0].formatted_address.split(',').splice(0, 1).join(',');\n};\nscope.placeMarker.setDraggable(true);\ngoogle.maps.event.addListener(scope.placeMarker, 'dragend', function () {\n    //broadcast event to directive scope, and pass marker position\n    scope.$broadcast('gmap-auto-complete:reverse', this.position);\n});\n```\nTake a look please on \"onReverseAddressComplete\" callback.\nThis callback fires each time if there are some results while searching by position (only for reverse).\nYou just need define attribute in the directive element (on-reverse-address-complete=\"callback\")\nand you can modify address string that will be displayed in the input.\n\n[jsfiddle example](https://jsfiddle.net/1yxrzr82/2/)\n\n#### Marker cluster\nWe don't provide any support for markers and clustering.\nIf you want to use markers, please use standard google maps api (such as google.maps.Marker).\nSee examples on top of this page (for markers creation).\n\nWhy we don't support this feature?\n\nBecause markers collection can be huge. And watching this collection by angular \"$watch\" can cause performance issues.\nSo all markers staff rely on user.\n\n###### Example\nHow to use clustering:\nAt first you need include script [\"markerclusterer.js\"](https://rawgit.com/googlemaps/js-marker-clusterer/gh-pages/src/markerclusterer.js) (direct raw link)\n\nHere is [git reference](https://github.com/googlemaps/js-marker-clusterer)\n\nYou can use bower install to get this library:\n```shell\nbower install js-marker-cluster\n```\nAnd then you can find this script in \"src\" folder!\n\nhere is [examples page](https://googlemaps.github.io/js-marker-clusterer/docs/examples.html)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flogicify%2Fangular-gmap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flogicify%2Fangular-gmap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flogicify%2Fangular-gmap/lists"}