├── .gitignore ├── .npmignore ├── CHANGELOG.md ├── Gruntfile.js ├── LICENSE ├── README.md ├── bower.json ├── dist └── angular-google-maps-geocoder.min.js ├── package.json └── src └── angular-google-maps-geocoder.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | 25 | # Dependency directory 26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 27 | node_modules 28 | 29 | bower_components 30 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .git 2 | .gitignore 3 | /node_modules 4 | bower.json 5 | CHANGELOG.md 6 | Gruntfile.js 7 | LICENSE.txt 8 | package.json 9 | README.md 10 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ### v0.0.4 2 | - Fix package.json 3 | 4 | ### v0.0.3 5 | - Add support for ui-bootstrap ~1.2.4 6 | 7 | ### v0.0.2 8 | - Fix wrong path in bower.json 9 | 10 | ### v0.0.1 11 | - First release. 12 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | 3 | var LIVERELOAD_PORT = 35729; 4 | 5 | grunt.initConfig({ 6 | pkg: grunt.file.readJSON('package.json'), 7 | 8 | connect: { 9 | server: { 10 | options: { 11 | livereload: LIVERELOAD_PORT 12 | } 13 | } 14 | }, 15 | 16 | jshint: { 17 | files: ['Gruntfile.js', 'src/*.js'], 18 | options: { 19 | globals: { 20 | angular: true 21 | } 22 | } 23 | }, 24 | 25 | uglify: { 26 | options: { 27 | banner: '/*! <%= pkg.name %> <%= pkg.version %> */\n' 28 | }, 29 | build: { 30 | src: 'src/<%= pkg.name %>.js', 31 | dest: 'dist/<%= pkg.name %>.min.js' 32 | } 33 | }, 34 | 35 | watch: { 36 | files: ['<%= jshint.files %>'], 37 | tasks: ['clear'], 38 | options: { 39 | debounceDelay: 1000, 40 | livereload: LIVERELOAD_PORT 41 | } 42 | } 43 | }); 44 | 45 | grunt.loadNpmTasks('grunt-contrib-jshint'); 46 | grunt.loadNpmTasks('grunt-contrib-uglify'); 47 | grunt.loadNpmTasks('grunt-contrib-watch'); 48 | grunt.loadNpmTasks('grunt-contrib-connect'); 49 | grunt.loadNpmTasks('grunt-clear'); 50 | 51 | grunt.registerTask('server', ['jshint', 'connect', 'watch']); 52 | grunt.registerTask('default', ['jshint', 'uglify']); 53 | 54 | }; 55 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Alexander Nestorov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # angular-google-maps-geocoder 2 | 3 | Angular typeahead Google Maps Geocoder 4 | 5 | ## How do I add this to my project? 6 | 7 | You can download `angular-google-maps-geocoder` by: 8 | 9 | * Using bower and running `bower install angular-google-maps-geocoder` 10 | * Using npm and running `npm install angular-google-maps-geocoder` 11 | * Downloading it manually from this repo 12 | 13 | ## How to use angular-google-maps-geocoder 14 | 15 | This module exposes a simple directive with the following attributes: 16 | 17 | * `placeid` - Will set the value of the input to the formatted address of the passed Google Maps place ID 18 | * `output` - The variable that will contain the selected value 19 | * `min-length` - Minimal number of characters before typeahead kicks-in 20 | * `wait-ms` - Minimal wait time after last character typed before typeahead kicks-in 21 | 22 | ## Demo 23 | 24 | [Plnkr demo](http://plnkr.co/edit/YkLpKrfIGW8drO5wyM3M?p=preview) 25 | 26 | ``` 27 |
34 | ``` 35 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-google-maps-geocoder", 3 | "version": "0.0.4", 4 | "homepage": "https://github.com/alexandernst/angular-google-maps-geocoder", 5 | "authors": [ 6 | "Alexander Nestorov " 7 | ], 8 | "description": "Angular bindings for the wonderful speakingurl library", 9 | "main": "dist/angular-google-maps-geocoder.min.js", 10 | "keywords": [ 11 | "angular", 12 | "google", 13 | "maps", 14 | "geocoder" 15 | ], 16 | "license": "MIT", 17 | "ignore": [ 18 | "**/.*", 19 | "node_modules" 20 | ], 21 | "dependencies": { 22 | "angular": ">=1.3" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /dist/angular-google-maps-geocoder.min.js: -------------------------------------------------------------------------------- 1 | /*! angular-google-maps-geocoder 0.0.2 */ 2 | var agmg=angular.module("angular-google-maps-geocoder",["ui.bootstrap"]);agmg.filter("trustAsHtml",["$sce",function(a){return function(b){return a.trustAsHtml(b)}}]),agmg.run(["$templateCache",function(a){"use strict";var b="";a.put("angular-google-maps-geocoder-item.html",b)}]),agmg.run(["$templateCache",function(a){"use strict";var b="";a.put("angular-google-maps-geocoder.html",b)}]),agmg.service("geocoder",["$q",function(a){var b=new google.maps.Geocoder;this.handle_reply=function(a,b,c){c==google.maps.GeocoderStatus.OK?a.resolve(b):c===google.maps.GeocoderStatus.ZERO_RESULTS?a.resolve([]):c===google.maps.GeocoderStatus.OVER_QUERY_LIMIT?a.reject("Over query limit"):c===google.maps.GeocoderStatus.REQUEST_DENIED?a.reject("Request denied"):a.reject("Unknown error")},this.geocode_by_id=function(c){var d=this,e=a.defer();return b.geocode({placeId:c},function(a,b){d.handle_reply(e,a,b)}),e.promise},this.geocode_by_query=function(c){var d=this,e=a.defer();return b.geocode({address:c},function(a,b){d.handle_reply(e,a,b)}),e.promise}}]),agmg.directive("angularGoogleMapsGeocoder",["geocoder",function(a){return{restrict:"AE",scope:{placeid:"@",output:"=",placeholder:"@",minLength:"@",waitMs:"@"},templateUrl:"angular-google-maps-geocoder.html",link:function(b,c,d){void 0!==d.placeid&&a.geocode_by_id(d.placeid).then(function(a){a.length>0&&(b.output=a[0])}),b.getLocation=function(b){return a.geocode_by_query(b)},b.format=function(a){if(angular.isObject(a)&&a.hasOwnProperty("formatted_address"))return a.formatted_address}}}}]); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-google-maps-geocoder", 3 | "version": "0.0.4", 4 | "description": "Angular typeahead google Maps Geocoder (also reverse geocoder)", 5 | "main": "angular-google-maps-geocoder.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git@github.com:alexandernst/angular-google-maps-geocoder.git" 9 | }, 10 | "dependencies": { 11 | "angular": "1.3.15" 12 | }, 13 | "devDependencies": { 14 | "grunt-contrib-uglify": ">=0.5.0", 15 | "grunt-contrib-jshint": "0.11.2", 16 | "grunt-contrib-watch": "0.6.1", 17 | "grunt-contrib-connect": "0.10.1", 18 | "grunt-clear": "0.2.1" 19 | }, 20 | "keywords": [ 21 | "angular", 22 | "google", 23 | "maps", 24 | "geocoder" 25 | ], 26 | "author": "Alexander Nestorov (https://github.com/alexandernst)", 27 | "license": "MIT", 28 | "bugs": { 29 | "url": "https://github.com/alexandernst/angular-google-maps-geocoder/issues" 30 | }, 31 | "homepage": "https://github.com/alexandernst/angular-google-maps-geocoder" 32 | } 33 | -------------------------------------------------------------------------------- /src/angular-google-maps-geocoder.js: -------------------------------------------------------------------------------- 1 | var agmg = angular.module('angular-google-maps-geocoder', ['ui.bootstrap']); 2 | 3 | agmg.filter('trustAsHtml', ['$sce', function($sce){ 4 | return function(text) { 5 | return $sce.trustAsHtml(text); 6 | }; 7 | }]); 8 | 9 | agmg.run(['$templateCache', function($templateCache) { 10 | 'use strict'; 11 | var template = "" + 12 | ""; 13 | $templateCache.put('angular-google-maps-geocoder-item.html', template); 14 | }]); 15 | 16 | agmg.run(['$templateCache', function($templateCache) { 17 | 'use strict'; 18 | var template = "" + 19 | ""; 27 | $templateCache.put('angular-google-maps-geocoder.html', template); 28 | }]); 29 | 30 | agmg.service("geocoder", ["$q", function($q) { 31 | var geocoder = new google.maps.Geocoder(); 32 | 33 | this.handle_reply = function(defer, results, status) { 34 | if(status == google.maps.GeocoderStatus.OK) { 35 | defer.resolve(results); 36 | } else if(status === google.maps.GeocoderStatus.ZERO_RESULTS) { 37 | defer.resolve([]); 38 | } else if(status === google.maps.GeocoderStatus.OVER_QUERY_LIMIT) { 39 | defer.reject("Over query limit"); 40 | } else if(status === google.maps.GeocoderStatus.REQUEST_DENIED) { 41 | defer.reject("Request denied"); 42 | } else { 43 | defer.reject("Unknown error"); 44 | } 45 | }; 46 | 47 | this.geocode_by_id = function(place_id) { 48 | var self = this; 49 | var defer = $q.defer(); 50 | 51 | geocoder.geocode({ placeId: place_id }, function(results, status) { 52 | self.handle_reply(defer, results, status); 53 | }); 54 | 55 | return defer.promise; 56 | }; 57 | 58 | this.geocode_by_query = function(query) { 59 | var self = this; 60 | var defer = $q.defer(); 61 | 62 | geocoder.geocode({ address: query }, function(results, status) { 63 | self.handle_reply(defer, results, status); 64 | }); 65 | 66 | return defer.promise; 67 | }; 68 | }]); 69 | 70 | agmg.directive("angularGoogleMapsGeocoder", ["geocoder", function(geocoder) { 71 | return { 72 | restrict: 'AE', 73 | 74 | scope: { 75 | "placeid": '@', 76 | "output": '=', 77 | "placeholder": '@', 78 | "minLength": '@', 79 | "waitMs": '@' 80 | }, 81 | 82 | templateUrl: 'angular-google-maps-geocoder.html', 83 | 84 | link: function($scope, element, attrs) { 85 | 86 | //Fetch the initial place_id data 87 | if(attrs.placeid !== undefined) { 88 | geocoder.geocode_by_id(attrs.placeid).then(function(results) { 89 | if(results.length > 0) $scope.output = results[0]; 90 | }); 91 | } 92 | 93 | //Get places when the user types in the input field 94 | $scope.getLocation = function(val) { 95 | return geocoder.geocode_by_query(val); 96 | }; 97 | 98 | //Format the received data 99 | $scope.format = function(val) { 100 | if(!angular.isObject(val) || !val.hasOwnProperty("formatted_address")) return; 101 | return val.formatted_address; 102 | }; 103 | 104 | } 105 | }; 106 | }]); 107 | --------------------------------------------------------------------------------