├── .gitignore ├── dist ├── angularLocationpicker.jquery.min.js ├── angularLocationpicker.jquery.min.js.map ├── angularLocationpicker.jquery.js ├── ngLocationpicker │ └── locationpicker.ts ├── locationpicker.jquery.min.js ├── locationpicker.jquery.min.js.map └── locationpicker.jquery.js ├── LICENSE ├── bower.json ├── package.json ├── locationpicker.jquery.json ├── README.md ├── src ├── ngLocationpicker │ └── locationpicker.ts ├── angularLocationpicker.jquery.js └── locationpicker.jquery.js ├── Gruntfile.js └── examples ├── simple.html ├── angularExample.html ├── mapInModalDialog.html └── examples.html /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea 3 | .idea -------------------------------------------------------------------------------- /dist/angularLocationpicker.jquery.min.js: -------------------------------------------------------------------------------- 1 | /*! jquery-locationpicker - v0.1.16 - 2017-10-02 */ 2 | 3 | "use strict";angular.module("angular-jquery-locationpicker",[]).constant("angularJQueryLocationpickerDefaultValue",{css:{width:"550px",height:"400px","float":"left"}}).service("angularJQueryLocationpickerService",["angularJQueryLocationpickerDefaultValue",function(a){var b={};return b.callAutosizeOnInit=function(a,b){var c=b;b=c?function(){$(a).locationpicker("autosize"),c()}:function(){$(a).locationpicker("autosize")}},b.checkDefaultStyles=function(b){var c=b[0].style;b.css({width:c.width||a.css.width,height:c.height||a.css.height,"float":c["float"]||a.css["float"],overflow:"hidden"})},b}]).directive("locationpicker",["angularJQueryLocationpickerService",function(a){return{restrict:"EA",replace:!0,scope:{options:"="},link:function(b,c){a.checkDefaultStyles(c),a.callAutosizeOnInit(c,b.options.oninitialized),$(c).locationpicker(b.options)}}}]); 4 | //# sourceMappingURL=angularLocationpicker.jquery.min.js.map -------------------------------------------------------------------------------- /dist/angularLocationpicker.jquery.min.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"angularLocationpicker.jquery.min.js","sources":["../src/angularLocationpicker.jquery.js"],"names":["angular","module","constant","css","width","height","float","service","defaultValue","callAutosizeOnInit","element","initCb","cb","$","locationpicker","checkDefaultStyles","elementStyle","style","overflow","directive","restrict","replace","scope","options","link","oninitialized"],"mappings":";;AAGA,YACAA,SAAQC,OAAO,oCACVC,SAAS,2CACNC,KACIC,MAAO,QACPC,OAAQ,QACRC,QAAO,UAGdC,QAAQ,sCACL,0CACA,SAAUC,GACN,GAAID,KAoCJ,OA7BAA,GAAQE,mBAAqB,SAAUC,EAASC,GAC5C,GAAIC,GAAKD,CAELA,GADEC,EACO,WACLC,EAAEH,GAASI,eAAe,YAC1BF,KAGK,WACLC,EAAEH,GAASI,eAAe,cAUtCP,EAAQQ,mBAAqB,SAAUL,GACnC,GAAIM,GAAeN,EAAQ,GAAGO,KAC9BP,GAAQP,KACJC,MAAOY,EAAaZ,OAASI,EAAaL,IAAIC,MAC9CC,OAAQW,EAAaX,QAAUG,EAAaL,IAAIE,OAChDC,QAAOU,EAAAA,UAAsBR,EAAaL,IAAbK,SAC7BU,SAAU,YAIXX,KAGdY,UAAU,kBACP,qCACA,SAAUZ,GACN,OACIa,SAAU,KACVC,SAAS,EACTC,OACIC,QAAS,KAEbC,KAAM,SAAUF,EAAOZ,GACnBH,EAAQQ,mBAAmBL,GAC3BH,EAAQE,mBAAmBC,EAASY,EAAMC,QAAQE,eAClDZ,EAAEH,GAASI,eAAeQ,EAAMC"} -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Logicify 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | 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, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-locationpicker-plugin", 3 | "version": "0.1.15", 4 | "homepage": "https://github.com/Logicify/jquery-locationpicker-plugin", 5 | "authors": [ 6 | "Dmitry Berezovsky " 7 | ], 8 | "description": "This plug-in allows finding and selecting a location on the Google map. Along with single point selection, it allows area selection by choosing a point and specifying a radius. The selection can be saved to any HTML input element or processed by Javascript with callback support. An optional automatic address resolver can reverse geocode the selection to an address. The plug-in also supports searching by address typed into the bound input element which uses auto-complete feature from Google API to make the search process easier. In this case the marker will be automatically positioned on the map after successful address resolution.", 9 | "main": "dist/locationpicker.jquery.js", 10 | "keywords": [ 11 | "jquery-plugin", 12 | "googlemap", 13 | "gmapapi", 14 | "location", 15 | "input", 16 | "radius", 17 | "map" 18 | ], 19 | "license": "MIT", 20 | "ignore": [ 21 | "**/.*", 22 | "node_modules", 23 | "bower_components", 24 | "test", 25 | "tests", 26 | "examples" 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-locationpicker", 3 | "version": "0.1.16", 4 | "keywords": [ 5 | "jquery-plugin", 6 | "googlemap", 7 | "gmapapi", 8 | "location", 9 | "input", 10 | "map", 11 | "radius" 12 | ], 13 | "license": "MIT", 14 | "author": "corvis", 15 | "bugs": { 16 | "url": "https://github.com/Logicify/jquery-locationpicker-plugin/issues" 17 | }, 18 | "homepage": "http://logicify.github.io/jquery-locationpicker-plugin/", 19 | "repository": { 20 | "type": "git", 21 | "url": "https://github.com/Logicify/jquery-locationpicker-plugin.git" 22 | }, 23 | "main": "dist/locationpicker.jquery.min.js", 24 | "description": "This plug-in allows finding and selecting a location on the Google map. Along with single point selection, it allows area selection by choosing a point and specifying a radius. The selection can be saved to any HTML input element or processed by Javascript with callback support. An optional automatic address resolver can reverse geocode the selection to an address. The plug-in also supports searching by address typed into the bound input element which uses auto-complete feature from Google API to make the search process easier. In this case the marker will be automatically positioned on the map after successful address resolution.", 25 | "dependencies": {}, 26 | "devDependencies": { 27 | "grunt": "~0.4.5", 28 | "grunt-contrib-clean": "^0.6.0", 29 | "grunt-contrib-concat": "^0.5.0", 30 | "grunt-contrib-copy": "^1.0.0", 31 | "grunt-contrib-uglify": "^0.8.0", 32 | "load-grunt-tasks": "^3.1.0" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /locationpicker.jquery.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "locationpicker", 3 | "title": "jQuery Location Picker", 4 | "description": "This plug-in allows to easily find and select a location on the Google map. Along with a single point selection, it allows to choose an area by providing its center and the radius. All the data can be saved to any HTML input element automatically as well as be processed by Javascript (callback support). The other feature of the plug-in is automatic address resolver which allows to get address line from the selected latitude and longitude. The plug-in also supports searching by address typed into the bound input element which uses auto-complete feature from Google API to make the search process easier. In this case the marker will be automatically positioned on the map after successful address resolution.", 5 | "keywords": [ 6 | "googlemap", 7 | "gmapapi", "location", 8 | "input", 9 | "map", 10 | "radius" 11 | ], 12 | "version": "0.1.15", 13 | "author": { 14 | "name": "Dmitry Berezovsky", 15 | "url": "http://logicify.com/" 16 | }, 17 | "licenses": [ 18 | { 19 | "type": "MIT", 20 | "url": "https://github.com/Logicify/jquery-locationpicker-plugin/blob/master/LICENSE" 21 | } 22 | ], 23 | "bugs": "https://github.com/Logicify/jquery-locationpicker-plugin/issues", 24 | "homepage": "http://logicify.github.io/jquery-locationpicker-plugin/", 25 | "docs": "http://logicify.github.io/jquery-locationpicker-plugin/", 26 | "download": "https://github.com/Logicify/jquery-locationpicker-plugin/archive/master.zip", 27 | "dependencies": { 28 | "jquery": ">=1.5" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /dist/angularLocationpicker.jquery.js: -------------------------------------------------------------------------------- 1 | /*! jquery-locationpicker - v0.1.16 - 2017-10-02 */ 2 | "use strict"; 3 | 4 | angular.module("angular-jquery-locationpicker", []).constant("angularJQueryLocationpickerDefaultValue", { 5 | css: { 6 | width: "550px", 7 | height: "400px", 8 | "float": "left" 9 | } 10 | }).service("angularJQueryLocationpickerService", [ "angularJQueryLocationpickerDefaultValue", function(defaultValue) { 11 | var service = {}; 12 | service.callAutosizeOnInit = function(element, initCb) { 13 | var cb = initCb; 14 | if (!!cb) { 15 | initCb = function() { 16 | $(element).locationpicker("autosize"); 17 | cb(); 18 | }; 19 | } else { 20 | initCb = function() { 21 | $(element).locationpicker("autosize"); 22 | }; 23 | } 24 | }; 25 | service.checkDefaultStyles = function(element) { 26 | var elementStyle = element[0].style; 27 | element.css({ 28 | width: elementStyle.width || defaultValue.css.width, 29 | height: elementStyle.height || defaultValue.css.height, 30 | "float": elementStyle.float || defaultValue.css.float, 31 | overflow: "hidden" 32 | }); 33 | }; 34 | return service; 35 | } ]).directive("locationpicker", [ "angularJQueryLocationpickerService", function(service) { 36 | return { 37 | restrict: "EA", 38 | replace: true, 39 | scope: { 40 | options: "=" 41 | }, 42 | link: function(scope, element, attrs) { 43 | service.checkDefaultStyles(element); 44 | service.callAutosizeOnInit(element, scope.options.oninitialized); 45 | $(element).locationpicker(scope.options); 46 | } 47 | }; 48 | } ]); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | JQuery Location Picker plugin 2 | ============================= 3 | 4 | ![Location Picker](http://logicify.github.io/jquery-locationpicker-plugin/images/basic_ui.png) 5 | 6 | This plug-in allows finding and selecting a location on the Google map. Along with single point selection, it allows area selection by choosing a point and specifying a radius. The selection can be saved to any HTML input element or processed by Javascript with callback support. 7 | 8 | An optional automatic address resolver can reverse geocode the selection to an address. The plug-in also supports searching by address typed into the bound input element which uses auto-complete feature from Google API to make the search process easier. In this case the marker will be automatically positioned on the map after successful address resolution. 9 | 10 | Usage 11 | ----- 12 | 13 | The plug-in requires [jQuery](http://jquery.com/) and the [Google Maps API](https://developers.google.com/maps/). Integration is pretty simple: 14 | 15 | * Add jQuery and Google Maps API to the `` of your HTML file: 16 | ``` 17 | 18 | // be careful to include the parameter "libraries=places" 19 | 20 | 21 | ``` 22 | 23 | * Put container somewhere in your page's ``: 24 | ``` 25 |
26 | ``` 27 | 28 | * Attach the plug-in to container: 29 | ``` 30 | 33 | ``` 34 | 35 | Documentation and Examples 36 | -------------------------- 37 | 38 | Documentation along with examples available [here](http://logicify.github.io/jquery-locationpicker-plugin/). 39 | 40 | 41 | Credits 42 | ------- 43 | * Dmitry Berezovsky, Logicify () 44 | * Gennadiy Varava, Logicify () 45 | * Emanuele Coppola, Libre sc () 46 | 47 | -------------------------------------------------------------------------------- /dist/ngLocationpicker/locationpicker.ts: -------------------------------------------------------------------------------- 1 | import {Component, ElementRef, Input, NgModule, OnInit, Renderer2, ViewChild} from '@angular/core'; 2 | import {CommonModule} from '@angular/common'; 3 | 4 | declare var $: any; 5 | declare var require: any; 6 | 7 | @Component({ 8 | selector: 'l-locationpicker', 9 | styles: [` 10 | .l-locationpicker-class { 11 | position: relative; 12 | display: inline-block; 13 | overflow: hidden; 14 | width: 700px; 15 | height: 500px; 16 | } 17 | `], 18 | template: ` 19 |
20 |
Loading
21 |
22 | ` 23 | }) 24 | export class LocationpickerComponent implements OnInit { 25 | 26 | @Input() lSettings: object = {}; 27 | 28 | @Input() lClass: string = 'l-locationpicker-class'; 29 | 30 | @ViewChild('locationpickerEl') locationpickerEl: ElementRef; 31 | 32 | $picker: any; 33 | 34 | constructor(private rd: Renderer2) { 35 | } 36 | 37 | ngOnInit() { 38 | require.ensure(['./../locationpicker.jquery.js'], require => { 39 | require('./../locationpicker.jquery.js'); 40 | this.$picker = $(this.locationpickerEl.nativeElement).locationpicker(this.lSettings); 41 | this.rd.addClass(this.locationpickerEl.nativeElement, this.lClass) 42 | }); 43 | } 44 | 45 | getLocation() { 46 | return this.$picker.locationpicker('location'); 47 | } 48 | 49 | setPosition(position: { radius?: number, latitude: number, longitude: number }) { 50 | this.$picker.locationpicker('location', position); 51 | } 52 | 53 | subscribeEvent(event: string, callback: () => void) { 54 | this.$picker.locationpicker('subscribe', {event, callback}) 55 | } 56 | 57 | getMap() { 58 | return this.$picker.locationpicker('map'); 59 | } 60 | 61 | autosize() { 62 | this.$picker.locationpicker('autosize'); 63 | } 64 | } 65 | 66 | @NgModule({ 67 | imports: [CommonModule], 68 | declarations: [LocationpickerComponent], 69 | exports: [LocationpickerComponent] 70 | }) 71 | export class LocationpickerModule { 72 | } 73 | -------------------------------------------------------------------------------- /src/ngLocationpicker/locationpicker.ts: -------------------------------------------------------------------------------- 1 | import {Component, ElementRef, Input, NgModule, OnInit, Renderer2, ViewChild} from '@angular/core'; 2 | import {CommonModule} from '@angular/common'; 3 | 4 | declare var $: any; 5 | declare var require: any; 6 | 7 | @Component({ 8 | selector: 'l-locationpicker', 9 | styles: [` 10 | .l-locationpicker-class { 11 | position: relative; 12 | display: inline-block; 13 | overflow: hidden; 14 | width: 700px; 15 | height: 500px; 16 | } 17 | `], 18 | template: ` 19 |
20 |
Loading
21 |
22 | ` 23 | }) 24 | export class LocationpickerComponent implements OnInit { 25 | 26 | @Input() lSettings: object = {}; 27 | 28 | @Input() lClass: string = 'l-locationpicker-class'; 29 | 30 | @ViewChild('locationpickerEl') locationpickerEl: ElementRef; 31 | 32 | $picker: any; 33 | 34 | constructor(private rd: Renderer2) { 35 | } 36 | 37 | ngOnInit() { 38 | require.ensure(['./../locationpicker.jquery.js'], require => { 39 | require('./../locationpicker.jquery.js'); 40 | this.$picker = $(this.locationpickerEl.nativeElement).locationpicker(this.lSettings); 41 | this.rd.addClass(this.locationpickerEl.nativeElement, this.lClass) 42 | }); 43 | } 44 | 45 | getLocation() { 46 | return this.$picker.locationpicker('location'); 47 | } 48 | 49 | setPosition(position: { radius?: number, latitude: number, longitude: number }) { 50 | this.$picker.locationpicker('location', position); 51 | } 52 | 53 | subscribeEvent(event: string, callback: () => void) { 54 | this.$picker.locationpicker('subscribe', {event, callback}) 55 | } 56 | 57 | getMap() { 58 | return this.$picker.locationpicker('map'); 59 | } 60 | 61 | autosize() { 62 | this.$picker.locationpicker('autosize'); 63 | } 64 | } 65 | 66 | @NgModule({ 67 | imports: [CommonModule], 68 | declarations: [LocationpickerComponent], 69 | exports: [LocationpickerComponent] 70 | }) 71 | export class LocationpickerModule { 72 | } 73 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function (grunt) { 4 | 5 | // Load grunt tasks automatically 6 | require('load-grunt-tasks')(grunt); 7 | 8 | // Configurable paths for the application 9 | var appConfig = { 10 | app: 'src', 11 | dist: 'dist' 12 | }; 13 | 14 | grunt.initConfig({ 15 | // Project settings 16 | pkg: grunt.file.readJSON('package.json'), 17 | appConfig: appConfig, 18 | // Empties folders to start fresh 19 | clean: { 20 | dist: { 21 | files: [{ 22 | dot: true, 23 | src: [ 24 | '<%= appConfig.dist %>/{,*/}*' 25 | ] 26 | }] 27 | } 28 | }, 29 | uglify: { 30 | options: { 31 | banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' + 32 | '<%= grunt.template.today("yyyy-mm-dd") %> */\n' 33 | }, 34 | minimize: { 35 | options: { 36 | beautify: false, 37 | compress: true, 38 | sourceMap: true 39 | }, 40 | files: { 41 | '<%= appConfig.dist %>/locationpicker.jquery.min.js': ['<%= appConfig.app %>/locationpicker.jquery.js'], 42 | '<%= appConfig.dist %>/angularLocationpicker.jquery.min.js': ['<%= appConfig.app %>/angularLocationpicker.jquery.js'] 43 | } 44 | }, 45 | beautify: { 46 | options: { 47 | beautify: { 48 | width: 80, 49 | beautify: true 50 | }, 51 | compress: false, 52 | sourceMap: false, 53 | mangle: false 54 | }, 55 | files: { 56 | '<%= appConfig.dist %>/locationpicker.jquery.js': ['<%= appConfig.app %>/locationpicker.jquery.js'], 57 | '<%= appConfig.dist %>/angularLocationpicker.jquery.js': ['<%= appConfig.app %>/angularLocationpicker.jquery.js'] 58 | } 59 | } 60 | }, 61 | copy: { 62 | main: { 63 | expand: true, 64 | cwd: 'src/ngLocationpicker/', 65 | src: '**', 66 | dest: 'dist/ngLocationpicker', 67 | } 68 | } 69 | }); 70 | 71 | grunt.registerTask('build', [ 72 | 'clean:dist', 73 | 'uglify:minimize', 74 | 'uglify:beautify', 75 | 'copy' 76 | ]); 77 | 78 | }; -------------------------------------------------------------------------------- /src/angularLocationpicker.jquery.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by sumragen on 21.09.16. 3 | */ 4 | 'use strict'; 5 | angular.module('angular-jquery-locationpicker', []) 6 | .constant('angularJQueryLocationpickerDefaultValue', { 7 | css: { 8 | width: '550px', 9 | height: '400px', 10 | float: 'left' 11 | } 12 | }) 13 | .service('angularJQueryLocationpickerService', [ 14 | 'angularJQueryLocationpickerDefaultValue', 15 | function (defaultValue) { 16 | var service = {}; 17 | 18 | /** 19 | * Without 'autosize' method map will be consist of grey box 20 | * @param element 21 | * @param initCb - defined method 'oninitialized' by user 22 | */ 23 | service.callAutosizeOnInit = function (element, initCb) { 24 | var cb = initCb; 25 | if (!!cb) { 26 | initCb = function () { 27 | $(element).locationpicker('autosize'); 28 | cb(); 29 | } 30 | } else { 31 | initCb = function () { 32 | $(element).locationpicker('autosize'); 33 | } 34 | } 35 | }; 36 | 37 | /** 38 | * If user forgot add some style parameters then assign default value 39 | * When user assign styles by css classes that method override values. Need use !important 40 | * @param element 41 | */ 42 | service.checkDefaultStyles = function (element) { 43 | var elementStyle = element[0].style; 44 | element.css({ 45 | width: elementStyle.width || defaultValue.css.width, 46 | height: elementStyle.height || defaultValue.css.height, 47 | float: elementStyle.float || defaultValue.css.float, 48 | overflow: 'hidden' 49 | }); 50 | }; 51 | 52 | return service; 53 | } 54 | ]) 55 | .directive('locationpicker', [ 56 | 'angularJQueryLocationpickerService', 57 | function (service) { 58 | return { 59 | restrict: 'EA', 60 | replace: true, 61 | scope: { 62 | options: '=' 63 | }, 64 | link: function (scope, element, attrs) { 65 | service.checkDefaultStyles(element); 66 | service.callAutosizeOnInit(element, scope.options.oninitialized); 67 | $(element).locationpicker(scope.options); 68 | } 69 | }; 70 | }]); -------------------------------------------------------------------------------- /examples/simple.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Simple example 14 | 15 | 16 | 17 | 18 |
19 |
20 | 21 | 22 |
23 | 24 |
25 |
26 |
27 | 28 | 29 |
30 | 31 |
32 |
33 |
34 |
 
35 |
36 | 37 | 38 |
39 | 40 |
41 | 42 | 43 |
44 | 45 |
46 |
47 |
48 | 68 |
69 | 70 | 71 | -------------------------------------------------------------------------------- /examples/angularExample.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | Angular example 19 | 20 | 21 | 22 | 23 |
24 |
25 | 26 | 27 |
28 | 29 |
30 |
31 |
32 | 33 | 34 |
35 | 36 |
37 |
38 | 39 | 40 | 41 | 42 |
 
43 |
44 | 45 | 46 |
47 | 48 |
49 | 50 | 51 |
52 | 53 |
54 |
55 |
56 |
57 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /examples/mapInModalDialog.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Simple example 14 | 15 | 20 | 21 | 22 | 23 | 24 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /dist/locationpicker.jquery.min.js: -------------------------------------------------------------------------------- 1 | /*! jquery-locationpicker - v0.1.16 - 2017-10-02 */ 2 | 3 | !function(a){function b(a,b){var c=new google.maps.Map(a,b),d=new google.maps.Marker({position:new google.maps.LatLng(54.19335,-3.92695),map:c,title:"Drag Me",visible:b.markerVisible,draggable:b.markerDraggable,icon:void 0!==b.markerIcon?b.markerIcon:void 0});return{map:c,marker:d,circle:null,location:d.position,radius:b.radius,locationName:b.locationName,addressComponents:{formatted_address:null,addressLine1:null,addressLine2:null,streetName:null,streetNumber:null,city:null,district:null,state:null,stateOrProvince:null},settings:b.settings,domContainer:a,geodecoder:new google.maps.Geocoder}}function c(a){return void 0!=d(a)}function d(b){return a(b).data("locationpicker")}function e(a,b){if(a){var c=i.locationFromLatLng(b.marker.position);a.latitudeInput&&a.latitudeInput.val(c.latitude).change(),a.longitudeInput&&a.longitudeInput.val(c.longitude).change(),a.radiusInput&&a.radiusInput.val(b.radius).change(),a.locationNameInput&&a.locationNameInput.val(b.locationName).change()}}function f(b,c){if(b){if(b.radiusInput&&b.radiusInput.on("change",function(b){var d=a(this).val();b.originalEvent&&!isNaN(d)&&(c.radius=d,i.setPosition(c,c.location,function(a){a.settings.onchanged.apply(c.domContainer,[i.locationFromLatLng(a.location),a.radius,!1])}))}),b.locationNameInput&&c.settings.enableAutocomplete){var d=!1;c.autocomplete=new google.maps.places.Autocomplete(b.locationNameInput.get(0),c.settings.autocompleteOptions),google.maps.event.addListener(c.autocomplete,"place_changed",function(){d=!1;var a=c.autocomplete.getPlace();return a.geometry?void i.setPosition(c,a.geometry.location,function(a){e(b,a),a.settings.onchanged.apply(c.domContainer,[i.locationFromLatLng(a.location),a.radius,!1])}):void c.settings.onlocationnotfound(a.name)}),c.settings.enableAutocompleteBlur&&(b.locationNameInput.on("change",function(a){a.originalEvent&&(d=!0)}),b.locationNameInput.on("blur",function(f){f.originalEvent&&setTimeout(function(){var f=a(b.locationNameInput).val();f.length>5&&d&&(d=!1,c.geodecoder.geocode({address:f},function(a,d){d==google.maps.GeocoderStatus.OK&&a&&a.length&&i.setPosition(c,a[0].geometry.location,function(a){e(b,a),a.settings.onchanged.apply(c.domContainer,[i.locationFromLatLng(a.location),a.radius,!1])})}))},1e3)}))}b.latitudeInput&&b.latitudeInput.on("change",function(b){var d=a(this).val();b.originalEvent&&!isNaN(d)&&i.setPosition(c,new google.maps.LatLng(d,c.location.lng()),function(a){a.settings.onchanged.apply(c.domContainer,[i.locationFromLatLng(a.location),a.radius,!1]),e(c.settings.inputBinding,c)})}),b.longitudeInput&&b.longitudeInput.on("change",function(b){var d=a(this).val();b.originalEvent&&!isNaN(d)&&i.setPosition(c,new google.maps.LatLng(c.location.lat(),d),function(a){a.settings.onchanged.apply(c.domContainer,[i.locationFromLatLng(a.location),a.radius,!1]),e(c.settings.inputBinding,c)})})}}function g(a){google.maps.event.trigger(a.map,"resize"),setTimeout(function(){a.map.setCenter(a.marker.position)},300)}function h(b,c,d){var e=a.extend({},a.fn.locationpicker.defaults,d),g=e.location.latitude,h=e.location.longitude,j=e.radius,k=b.settings.location.latitude,l=b.settings.location.longitude,m=b.settings.radius;(g!=k||h!=l||j!=m)&&(b.settings.location.latitude=g,b.settings.location.longitude=h,b.radius=j,i.setPosition(b,new google.maps.LatLng(b.settings.location.latitude,b.settings.location.longitude),function(a){f(b.settings.inputBinding,b),a.settings.oninitialized(c)}))}var i={drawCircle:function(b,c,d,e){return null!=b.circle&&b.circle.setMap(null),d>0?(d*=1,e=a.extend({strokeColor:"#0000FF",strokeOpacity:.35,strokeWeight:2,fillColor:"#0000FF",fillOpacity:.2},e),e.map=b.map,e.radius=d,e.center=c,b.circle=new google.maps.Circle(e),b.circle):null},setPosition:function(a,b,c){a.location=b,a.marker.setPosition(b),a.map.panTo(b),this.drawCircle(a,b,a.radius,{}),a.settings.enableReverseGeocode?this.updateLocationName(a,c):c&&c.call(this,a)},locationFromLatLng:function(a){return{latitude:a.lat(),longitude:a.lng()}},addressByFormat:function(a,b){for(var c=null,d=a.length-1;d>=0;d--)a[d].types.indexOf(b)>=0&&(c=a[d]);return c||a[0]},updateLocationName:function(a,b){a.geodecoder.geocode({latLng:a.marker.position},function(c,d){if(d==google.maps.GeocoderStatus.OK&&c.length>0){var e=i.addressByFormat(c,a.settings.addressFormat);a.locationName=e.formatted_address,a.addressComponents=i.address_component_from_google_geocode(e.address_components)}else if(d==google.maps.GeocoderStatus.OVER_QUERY_LIMIT)return setTimeout(function(){i.updateLocationName(a,b)},1e3);b&&b.call(this,a)})},address_component_from_google_geocode:function(a){for(var b={},c=a.length-1;c>=0;c--){var d=a[c];d.types.indexOf("postal_code")>=0?b.postalCode=d.short_name:d.types.indexOf("street_number")>=0?b.streetNumber=d.short_name:d.types.indexOf("route")>=0?b.streetName=d.short_name:d.types.indexOf("locality")>=0?b.city=d.short_name:d.types.indexOf("sublocality")>=0?b.district=d.short_name:d.types.indexOf("administrative_area_level_1")>=0?b.stateOrProvince=d.short_name:d.types.indexOf("country")>=0&&(b.country=d.short_name)}return b.addressLine1=[b.streetNumber,b.streetName].join(" ").trim(),b.addressLine2="",b}};a.fn.locationpicker=function(j,k){if("string"==typeof j){var l=this.get(0);if(!c(l))return;var m=d(l);switch(j){case"location":if(void 0==k){var n=i.locationFromLatLng(m.location);return n.radius=m.radius,n.name=m.locationName,n}k.radius&&(m.radius=k.radius),i.setPosition(m,new google.maps.LatLng(k.latitude,k.longitude),function(a){e(a.settings.inputBinding,a)});break;case"subscribe":if(void 0==k)return null;var o=k.event,p=k.callback;if(!o||!p)return console.error('LocationPicker: Invalid arguments for method "subscribe"'),null;google.maps.event.addListener(m.map,o,p);break;case"map":if(void 0==k){var q=i.locationFromLatLng(m.location);return q.formattedAddress=m.locationName,q.addressComponents=m.addressComponents,{map:m.map,marker:m.marker,location:q}}return null;case"autosize":return g(m),this}return null}return this.each(function(){function g(){i.setPosition(m,m.marker.position,function(a){var b=i.locationFromLatLng(m.location);e(m.settings.inputBinding,m),a.settings.onchanged.apply(m.domContainer,[b,a.radius,!0])})}var k=a(this);if(c(this))return void h(d(this),a(this),j);var l=a.extend({},a.fn.locationpicker.defaults,j),m=new b(this,a.extend({},{zoom:l.zoom,center:new google.maps.LatLng(l.location.latitude,l.location.longitude),mapTypeId:l.mapTypeId,mapTypeControl:!1,styles:l.styles,disableDoubleClickZoom:!1,scrollwheel:l.scrollwheel,streetViewControl:!1,radius:l.radius,locationName:l.locationName,settings:l,autocompleteOptions:l.autocompleteOptions,addressFormat:l.addressFormat,draggable:l.draggable,markerIcon:l.markerIcon,markerDraggable:l.markerDraggable,markerVisible:l.markerVisible},l.mapOptions));k.data("locationpicker",m),l.markerInCenter&&(m.map.addListener("bounds_changed",function(){m.marker.dragging||(m.marker.setPosition(m.map.center),e(m.settings.inputBinding,m))}),m.map.addListener("idle",function(){m.marker.dragging||g()})),google.maps.event.addListener(m.marker,"drag",function(){e(m.settings.inputBinding,m)}),google.maps.event.addListener(m.marker,"dragend",function(){g()}),i.setPosition(m,new google.maps.LatLng(l.location.latitude,l.location.longitude),function(a){e(l.inputBinding,m),f(l.inputBinding,m),a.settings.oninitialized(k)})})},a.fn.locationpicker.defaults={location:{latitude:40.7324319,longitude:-73.82480777777776},locationName:"",radius:500,zoom:15,mapTypeId:google.maps.MapTypeId.ROADMAP,styles:[],mapOptions:{},scrollwheel:!0,inputBinding:{latitudeInput:null,longitudeInput:null,radiusInput:null,locationNameInput:null},enableAutocomplete:!1,enableAutocompleteBlur:!1,autocompleteOptions:null,addressFormat:"postal_code",enableReverseGeocode:!0,draggable:!0,onchanged:function(){},onlocationnotfound:function(){},oninitialized:function(){},markerIcon:void 0,markerDraggable:!0,markerVisible:!0}}(jQuery); 4 | //# sourceMappingURL=locationpicker.jquery.min.js.map -------------------------------------------------------------------------------- /dist/locationpicker.jquery.min.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"locationpicker.jquery.min.js","sources":["../src/locationpicker.jquery.js"],"names":["$","GMapContext","domElement","options","_map","google","maps","Map","_marker","Marker","position","LatLng","map","title","visible","markerVisible","draggable","markerDraggable","icon","undefined","markerIcon","marker","circle","location","radius","locationName","addressComponents","formatted_address","addressLine1","addressLine2","streetName","streetNumber","city","district","state","stateOrProvince","settings","domContainer","geodecoder","Geocoder","isPluginApplied","domObj","getContextForElement","data","updateInputValues","inputBinding","gmapContext","currentLocation","GmUtility","locationFromLatLng","latitudeInput","val","latitude","change","longitudeInput","longitude","radiusInput","locationNameInput","setupInputListenersInput","on","e","radiusInputValue","this","originalEvent","isNaN","setPosition","context","onchanged","apply","enableAutocomplete","blur","autocomplete","places","Autocomplete","get","autocompleteOptions","event","addListener","place","getPlace","geometry","onlocationnotfound","name","enableAutocompleteBlur","setTimeout","address","length","geocode","results","status","GeocoderStatus","OK","latitudeInputValue","lng","longitudeInputValue","lat","autosize","trigger","setCenter","updateMap","$target","extend","fn","locationpicker","defaults","latNew","lngNew","radiusNew","latOld","lngOld","radiusOld","oninitialized","drawCircle","center","setMap","strokeColor","strokeOpacity","strokeWeight","fillColor","fillOpacity","Circle","gMapContext","callback","panTo","enableReverseGeocode","updateLocationName","call","lnlg","addressByFormat","addresses","format","result","i","types","indexOf","latLng","addressFormat","address_component_from_google_geocode","address_components","OVER_QUERY_LIMIT","component","postalCode","short_name","country","join","trim","params","_targetDomElement","console","error","locationObj","formattedAddress","each","displayMarkerWithSelectedArea","zoom","mapTypeId","mapTypeControl","styles","disableDoubleClickZoom","scrollwheel","streetViewControl","mapOptions","markerInCenter","dragging","MapTypeId","ROADMAP","jQuery"],"mappings":"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"} -------------------------------------------------------------------------------- /examples/examples.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | jquery-location-picker demo 18 | 19 | 20 | 21 | 22 |
23 |
24 |

25 | 26 |

Providing options

27 |
 28 | <div id="somecomponent" style="width: 500px; height: 400px;"></div>
 29 | <script>
 30 | $('#somecomponent').locationpicker({
 31 | 	location: {latitude: 46.15242437752303, longitude: 2.7470703125},
 32 | 	radius: 300,
 33 |         markerIcon: 'http://www.iconsdb.com/icons/preview/tropical-blue/map-marker-2-xl.png'
 34 | });
 35 | </script>
 36 | 				
37 |

Result

38 | 39 |
40 | 51 | 52 |

Binding UI with the widget

53 |
 54 | Location: <input type="text" id="us2-address" style="width: 200px"/>
 55 | Radius: <input type="text" id="us2-radius"/>
 56 | <div id="us2" style="width: 500px; height: 400px;"></div>
 57 | Lat.: <input type="text" id="us2-lat"/>
 58 | Long.: <input type="text" id="us2-lon"/>
 59 | <script>$('#us2').locationpicker({
 60 | 	location: {latitude: 46.15242437752303, longitude: 2.7470703125},
 61 | 	radius: 300,
 62 | 	inputBinding: {
 63 |         latitudeInput: $('#us2-lat'),
 64 |         longitudeInput: $('#us2-lon'),
 65 |         radiusInput: $('#us2-radius'),
 66 |         locationNameInput: $('#us2-address')
 67 |     }
 68 | 	});
 69 | </script>
 70 | 				
71 |

Result:

72 | 73 |
74 |
75 | 76 | 77 |
78 | 79 |
80 |
81 |
82 | 83 | 84 |
85 | 86 |
87 |
88 |
89 |
 
90 |
91 | 92 | 93 |
94 | 95 |
96 | 97 | 98 |
99 | 100 |
101 |
102 |
103 |
104 | 120 | 121 |

Subscribing for events

122 | 123 |

The following example illustrates how to subscribe "Change" event. See the list of the available events along with functions signature above.

124 |
125 | $('#us3').locationpicker({
126 | location: {latitude: 46.15242437752303, longitude: 2.7470703125},
127 | radius: 300,
128 | inputBinding: {
129 | 	latitudeInput: $('#us3-lat'),
130 | 	longitudeInput: $('#us3-lon'),
131 | 	radiusInput: $('#us3-radius'),
132 | 	locationNameInput: $('#us3-address')
133 | },
134 | enableAutocomplete: true,
135 | onchanged: function(currentLocation, radius, isMarkerDropped) {
136 | 	alert("Location changed. New location (" + currentLocation.latitude + ", " + currentLocation.longitude + ")");
137 | }
138 | 				
139 |
140 |
141 | 142 | 143 |
144 | 145 |
146 |
147 |
148 | 149 | 150 |
151 | 152 |
153 |
154 |
155 |
 
156 |
157 | 158 | 159 |
160 | 161 |
162 | 163 | 164 |
165 | 166 |
167 |
168 |
169 | 188 |
189 |

Manipulating map widget from callback

190 | 191 |

If you need direct access to the actual Google Maps widget you can use map method as follows. This example illustrates how to set zoom pragmatically each time when location has been changed.

192 |
193 | $('#us4').locationpicker({
194 | location: {latitude: 46.15242437752303, longitude: 2.7470703125},
195 | radius: 300,
196 | onchanged: function(currentLocation, radius, isMarkerDropped) {
197 |     var mapContext = $(this).locationpicker('map');
198 |     mapContext.map.setZoom(20);
199 | }
200 | 				
201 |
202 |
203 | 216 |
217 | 218 |

Advanced usage of geo decoder features

219 | 220 |

221 | Along with decoded readable location name plugin returns address split on components (state, postal code, etc.) which in some cases can be pretty useful. 222 |

223 |
224 | function updateControls(addressComponents) {
225 |     $('#us5-street1').val(addressComponents.addressLine1);
226 |     $('#us5-city').val(addressComponents.city);
227 |     $('#us5-state').val(addressComponents.stateOrProvince);
228 |     $('#us5-zip').val(addressComponents.postalCode);
229 |     $('#us5-country').val(addressComponents.country);
230 | }
231 | $('#us5').locationpicker({
232 |     location: {latitude: 42.00, longitude: -73.82480799999996},
233 |     radius: 300,
234 |     onchanged: function (currentLocation, radius, isMarkerDropped) {
235 |         var addressComponents = $(this).locationpicker('map').location.addressComponents;
236 |         updateControls(addressComponents);
237 |     },
238 |     oninitialized: function(component) {
239 |         var addressComponents = $(component).locationpicker('map').location.addressComponents;
240 |         updateControls(addressComponents);
241 |     }
242 | });
243 |     
244 |
245 |
246 |
247 |
248 |

249 |
250 |
251 |
252 |
253 | 254 | 255 |
256 | 257 |
258 |
259 |
260 | 261 | 262 |
263 | 264 |
265 |
266 |
267 | 268 | 269 |
270 | 271 |
272 |
273 |
274 | 275 | 276 |
277 | 278 |
279 |
280 |
281 | 282 | 283 |
284 | 285 |
286 |
287 |
288 |
289 |
290 |
291 | 315 |
316 | 317 |
318 | Dmitry Berezovsky, Logicify (http://logicify.com/) 319 |
320 | 321 |
322 | 327 |
328 | 329 | 330 | 331 | -------------------------------------------------------------------------------- /dist/locationpicker.jquery.js: -------------------------------------------------------------------------------- 1 | /*! jquery-locationpicker - v0.1.16 - 2017-10-02 */ 2 | (function($) { 3 | function GMapContext(domElement, options) { 4 | var _map = new google.maps.Map(domElement, options); 5 | var _marker = new google.maps.Marker({ 6 | position: new google.maps.LatLng(54.19335, -3.92695), 7 | map: _map, 8 | title: "Drag Me", 9 | visible: options.markerVisible, 10 | draggable: options.markerDraggable, 11 | icon: options.markerIcon !== undefined ? options.markerIcon : undefined 12 | }); 13 | return { 14 | map: _map, 15 | marker: _marker, 16 | circle: null, 17 | location: _marker.position, 18 | radius: options.radius, 19 | locationName: options.locationName, 20 | addressComponents: { 21 | formatted_address: null, 22 | addressLine1: null, 23 | addressLine2: null, 24 | streetName: null, 25 | streetNumber: null, 26 | city: null, 27 | district: null, 28 | state: null, 29 | stateOrProvince: null 30 | }, 31 | settings: options.settings, 32 | domContainer: domElement, 33 | geodecoder: new google.maps.Geocoder() 34 | }; 35 | } 36 | var GmUtility = { 37 | drawCircle: function(gmapContext, center, radius, options) { 38 | if (gmapContext.circle != null) { 39 | gmapContext.circle.setMap(null); 40 | } 41 | if (radius > 0) { 42 | radius *= 1; 43 | options = $.extend({ 44 | strokeColor: "#0000FF", 45 | strokeOpacity: .35, 46 | strokeWeight: 2, 47 | fillColor: "#0000FF", 48 | fillOpacity: .2 49 | }, options); 50 | options.map = gmapContext.map; 51 | options.radius = radius; 52 | options.center = center; 53 | gmapContext.circle = new google.maps.Circle(options); 54 | return gmapContext.circle; 55 | } 56 | return null; 57 | }, 58 | setPosition: function(gMapContext, location, callback) { 59 | gMapContext.location = location; 60 | gMapContext.marker.setPosition(location); 61 | gMapContext.map.panTo(location); 62 | this.drawCircle(gMapContext, location, gMapContext.radius, {}); 63 | if (gMapContext.settings.enableReverseGeocode) { 64 | this.updateLocationName(gMapContext, callback); 65 | } else { 66 | if (callback) { 67 | callback.call(this, gMapContext); 68 | } 69 | } 70 | }, 71 | locationFromLatLng: function(lnlg) { 72 | return { 73 | latitude: lnlg.lat(), 74 | longitude: lnlg.lng() 75 | }; 76 | }, 77 | addressByFormat: function(addresses, format) { 78 | var result = null; 79 | for (var i = addresses.length - 1; i >= 0; i--) { 80 | if (addresses[i].types.indexOf(format) >= 0) { 81 | result = addresses[i]; 82 | } 83 | } 84 | return result || addresses[0]; 85 | }, 86 | updateLocationName: function(gmapContext, callback) { 87 | gmapContext.geodecoder.geocode({ 88 | latLng: gmapContext.marker.position 89 | }, function(results, status) { 90 | if (status == google.maps.GeocoderStatus.OK && results.length > 0) { 91 | var address = GmUtility.addressByFormat(results, gmapContext.settings.addressFormat); 92 | gmapContext.locationName = address.formatted_address; 93 | gmapContext.addressComponents = GmUtility.address_component_from_google_geocode(address.address_components); 94 | } else if (status == google.maps.GeocoderStatus.OVER_QUERY_LIMIT) { 95 | return setTimeout(function() { 96 | GmUtility.updateLocationName(gmapContext, callback); 97 | }, 1e3); 98 | } 99 | if (callback) { 100 | callback.call(this, gmapContext); 101 | } 102 | }); 103 | }, 104 | address_component_from_google_geocode: function(address_components) { 105 | var result = {}; 106 | for (var i = address_components.length - 1; i >= 0; i--) { 107 | var component = address_components[i]; 108 | if (component.types.indexOf("postal_code") >= 0) { 109 | result.postalCode = component.short_name; 110 | } else if (component.types.indexOf("street_number") >= 0) { 111 | result.streetNumber = component.short_name; 112 | } else if (component.types.indexOf("route") >= 0) { 113 | result.streetName = component.short_name; 114 | } else if (component.types.indexOf("locality") >= 0) { 115 | result.city = component.short_name; 116 | } else if (component.types.indexOf("sublocality") >= 0) { 117 | result.district = component.short_name; 118 | } else if (component.types.indexOf("administrative_area_level_1") >= 0) { 119 | result.stateOrProvince = component.short_name; 120 | } else if (component.types.indexOf("country") >= 0) { 121 | result.country = component.short_name; 122 | } 123 | } 124 | result.addressLine1 = [ result.streetNumber, result.streetName ].join(" ").trim(); 125 | result.addressLine2 = ""; 126 | return result; 127 | } 128 | }; 129 | function isPluginApplied(domObj) { 130 | return getContextForElement(domObj) != undefined; 131 | } 132 | function getContextForElement(domObj) { 133 | return $(domObj).data("locationpicker"); 134 | } 135 | function updateInputValues(inputBinding, gmapContext) { 136 | if (!inputBinding) return; 137 | var currentLocation = GmUtility.locationFromLatLng(gmapContext.marker.position); 138 | if (inputBinding.latitudeInput) { 139 | inputBinding.latitudeInput.val(currentLocation.latitude).change(); 140 | } 141 | if (inputBinding.longitudeInput) { 142 | inputBinding.longitudeInput.val(currentLocation.longitude).change(); 143 | } 144 | if (inputBinding.radiusInput) { 145 | inputBinding.radiusInput.val(gmapContext.radius).change(); 146 | } 147 | if (inputBinding.locationNameInput) { 148 | inputBinding.locationNameInput.val(gmapContext.locationName).change(); 149 | } 150 | } 151 | function setupInputListenersInput(inputBinding, gmapContext) { 152 | if (inputBinding) { 153 | if (inputBinding.radiusInput) { 154 | inputBinding.radiusInput.on("change", function(e) { 155 | var radiusInputValue = $(this).val(); 156 | if (!e.originalEvent || isNaN(radiusInputValue)) { 157 | return; 158 | } 159 | gmapContext.radius = radiusInputValue; 160 | GmUtility.setPosition(gmapContext, gmapContext.location, function(context) { 161 | context.settings.onchanged.apply(gmapContext.domContainer, [ GmUtility.locationFromLatLng(context.location), context.radius, false ]); 162 | }); 163 | }); 164 | } 165 | if (inputBinding.locationNameInput && gmapContext.settings.enableAutocomplete) { 166 | var blur = false; 167 | gmapContext.autocomplete = new google.maps.places.Autocomplete(inputBinding.locationNameInput.get(0), gmapContext.settings.autocompleteOptions); 168 | google.maps.event.addListener(gmapContext.autocomplete, "place_changed", function() { 169 | blur = false; 170 | var place = gmapContext.autocomplete.getPlace(); 171 | if (!place.geometry) { 172 | gmapContext.settings.onlocationnotfound(place.name); 173 | return; 174 | } 175 | GmUtility.setPosition(gmapContext, place.geometry.location, function(context) { 176 | updateInputValues(inputBinding, context); 177 | context.settings.onchanged.apply(gmapContext.domContainer, [ GmUtility.locationFromLatLng(context.location), context.radius, false ]); 178 | }); 179 | }); 180 | if (gmapContext.settings.enableAutocompleteBlur) { 181 | inputBinding.locationNameInput.on("change", function(e) { 182 | if (!e.originalEvent) { 183 | return; 184 | } 185 | blur = true; 186 | }); 187 | inputBinding.locationNameInput.on("blur", function(e) { 188 | if (!e.originalEvent) { 189 | return; 190 | } 191 | setTimeout(function() { 192 | var address = $(inputBinding.locationNameInput).val(); 193 | if (address.length > 5 && blur) { 194 | blur = false; 195 | gmapContext.geodecoder.geocode({ 196 | address: address 197 | }, function(results, status) { 198 | if (status == google.maps.GeocoderStatus.OK && results && results.length) { 199 | GmUtility.setPosition(gmapContext, results[0].geometry.location, function(context) { 200 | updateInputValues(inputBinding, context); 201 | context.settings.onchanged.apply(gmapContext.domContainer, [ GmUtility.locationFromLatLng(context.location), context.radius, false ]); 202 | }); 203 | } 204 | }); 205 | } 206 | }, 1e3); 207 | }); 208 | } 209 | } 210 | if (inputBinding.latitudeInput) { 211 | inputBinding.latitudeInput.on("change", function(e) { 212 | var latitudeInputValue = $(this).val(); 213 | if (!e.originalEvent || isNaN(latitudeInputValue)) { 214 | return; 215 | } 216 | GmUtility.setPosition(gmapContext, new google.maps.LatLng(latitudeInputValue, gmapContext.location.lng()), function(context) { 217 | context.settings.onchanged.apply(gmapContext.domContainer, [ GmUtility.locationFromLatLng(context.location), context.radius, false ]); 218 | updateInputValues(gmapContext.settings.inputBinding, gmapContext); 219 | }); 220 | }); 221 | } 222 | if (inputBinding.longitudeInput) { 223 | inputBinding.longitudeInput.on("change", function(e) { 224 | var longitudeInputValue = $(this).val(); 225 | if (!e.originalEvent || isNaN(longitudeInputValue)) { 226 | return; 227 | } 228 | GmUtility.setPosition(gmapContext, new google.maps.LatLng(gmapContext.location.lat(), longitudeInputValue), function(context) { 229 | context.settings.onchanged.apply(gmapContext.domContainer, [ GmUtility.locationFromLatLng(context.location), context.radius, false ]); 230 | updateInputValues(gmapContext.settings.inputBinding, gmapContext); 231 | }); 232 | }); 233 | } 234 | } 235 | } 236 | function autosize(gmapContext) { 237 | google.maps.event.trigger(gmapContext.map, "resize"); 238 | setTimeout(function() { 239 | gmapContext.map.setCenter(gmapContext.marker.position); 240 | }, 300); 241 | } 242 | function updateMap(gmapContext, $target, options) { 243 | var settings = $.extend({}, $.fn.locationpicker.defaults, options), latNew = settings.location.latitude, lngNew = settings.location.longitude, radiusNew = settings.radius, latOld = gmapContext.settings.location.latitude, lngOld = gmapContext.settings.location.longitude, radiusOld = gmapContext.settings.radius; 244 | if (latNew == latOld && lngNew == lngOld && radiusNew == radiusOld) return; 245 | gmapContext.settings.location.latitude = latNew; 246 | gmapContext.settings.location.longitude = lngNew; 247 | gmapContext.radius = radiusNew; 248 | GmUtility.setPosition(gmapContext, new google.maps.LatLng(gmapContext.settings.location.latitude, gmapContext.settings.location.longitude), function(context) { 249 | setupInputListenersInput(gmapContext.settings.inputBinding, gmapContext); 250 | context.settings.oninitialized($target); 251 | }); 252 | } 253 | $.fn.locationpicker = function(options, params) { 254 | if (typeof options == "string") { 255 | var _targetDomElement = this.get(0); 256 | if (!isPluginApplied(_targetDomElement)) return; 257 | var gmapContext = getContextForElement(_targetDomElement); 258 | switch (options) { 259 | case "location": 260 | if (params == undefined) { 261 | var location = GmUtility.locationFromLatLng(gmapContext.location); 262 | location.radius = gmapContext.radius; 263 | location.name = gmapContext.locationName; 264 | return location; 265 | } else { 266 | if (params.radius) { 267 | gmapContext.radius = params.radius; 268 | } 269 | GmUtility.setPosition(gmapContext, new google.maps.LatLng(params.latitude, params.longitude), function(gmapContext) { 270 | updateInputValues(gmapContext.settings.inputBinding, gmapContext); 271 | }); 272 | } 273 | break; 274 | 275 | case "subscribe": 276 | if (params == undefined) { 277 | return null; 278 | } else { 279 | var event = params.event; 280 | var callback = params.callback; 281 | if (!event || !callback) { 282 | console.error('LocationPicker: Invalid arguments for method "subscribe"'); 283 | return null; 284 | } 285 | google.maps.event.addListener(gmapContext.map, event, callback); 286 | } 287 | break; 288 | 289 | case "map": 290 | if (params == undefined) { 291 | var locationObj = GmUtility.locationFromLatLng(gmapContext.location); 292 | locationObj.formattedAddress = gmapContext.locationName; 293 | locationObj.addressComponents = gmapContext.addressComponents; 294 | return { 295 | map: gmapContext.map, 296 | marker: gmapContext.marker, 297 | location: locationObj 298 | }; 299 | } else { 300 | return null; 301 | } 302 | 303 | case "autosize": 304 | autosize(gmapContext); 305 | return this; 306 | } 307 | return null; 308 | } 309 | return this.each(function() { 310 | var $target = $(this); 311 | if (isPluginApplied(this)) { 312 | updateMap(getContextForElement(this), $(this), options); 313 | return; 314 | } 315 | var settings = $.extend({}, $.fn.locationpicker.defaults, options); 316 | var gmapContext = new GMapContext(this, $.extend({}, { 317 | zoom: settings.zoom, 318 | center: new google.maps.LatLng(settings.location.latitude, settings.location.longitude), 319 | mapTypeId: settings.mapTypeId, 320 | mapTypeControl: false, 321 | styles: settings.styles, 322 | disableDoubleClickZoom: false, 323 | scrollwheel: settings.scrollwheel, 324 | streetViewControl: false, 325 | radius: settings.radius, 326 | locationName: settings.locationName, 327 | settings: settings, 328 | autocompleteOptions: settings.autocompleteOptions, 329 | addressFormat: settings.addressFormat, 330 | draggable: settings.draggable, 331 | markerIcon: settings.markerIcon, 332 | markerDraggable: settings.markerDraggable, 333 | markerVisible: settings.markerVisible 334 | }, settings.mapOptions)); 335 | $target.data("locationpicker", gmapContext); 336 | function displayMarkerWithSelectedArea() { 337 | GmUtility.setPosition(gmapContext, gmapContext.marker.position, function(context) { 338 | var currentLocation = GmUtility.locationFromLatLng(gmapContext.location); 339 | updateInputValues(gmapContext.settings.inputBinding, gmapContext); 340 | context.settings.onchanged.apply(gmapContext.domContainer, [ currentLocation, context.radius, true ]); 341 | }); 342 | } 343 | if (settings.markerInCenter) { 344 | gmapContext.map.addListener("bounds_changed", function() { 345 | if (!gmapContext.marker.dragging) { 346 | gmapContext.marker.setPosition(gmapContext.map.center); 347 | updateInputValues(gmapContext.settings.inputBinding, gmapContext); 348 | } 349 | }); 350 | gmapContext.map.addListener("idle", function() { 351 | if (!gmapContext.marker.dragging) { 352 | displayMarkerWithSelectedArea(); 353 | } 354 | }); 355 | } 356 | google.maps.event.addListener(gmapContext.marker, "drag", function(event) { 357 | updateInputValues(gmapContext.settings.inputBinding, gmapContext); 358 | }); 359 | google.maps.event.addListener(gmapContext.marker, "dragend", function(event) { 360 | displayMarkerWithSelectedArea(); 361 | }); 362 | GmUtility.setPosition(gmapContext, new google.maps.LatLng(settings.location.latitude, settings.location.longitude), function(context) { 363 | updateInputValues(settings.inputBinding, gmapContext); 364 | setupInputListenersInput(settings.inputBinding, gmapContext); 365 | context.settings.oninitialized($target); 366 | }); 367 | }); 368 | }; 369 | $.fn.locationpicker.defaults = { 370 | location: { 371 | latitude: 40.7324319, 372 | longitude: -73.82480777777776 373 | }, 374 | locationName: "", 375 | radius: 500, 376 | zoom: 15, 377 | mapTypeId: google.maps.MapTypeId.ROADMAP, 378 | styles: [], 379 | mapOptions: {}, 380 | scrollwheel: true, 381 | inputBinding: { 382 | latitudeInput: null, 383 | longitudeInput: null, 384 | radiusInput: null, 385 | locationNameInput: null 386 | }, 387 | enableAutocomplete: false, 388 | enableAutocompleteBlur: false, 389 | autocompleteOptions: null, 390 | addressFormat: "postal_code", 391 | enableReverseGeocode: true, 392 | draggable: true, 393 | onchanged: function(currentLocation, radius, isMarkerDropped) {}, 394 | onlocationnotfound: function(locationName) {}, 395 | oninitialized: function(component) {}, 396 | markerIcon: undefined, 397 | markerDraggable: true, 398 | markerVisible: true 399 | }; 400 | })(jQuery); -------------------------------------------------------------------------------- /src/locationpicker.jquery.js: -------------------------------------------------------------------------------- 1 | (function ( $ ) { 2 | 3 | /** 4 | * Holds google map object and related utility entities. 5 | * @constructor 6 | */ 7 | function GMapContext(domElement, options) { 8 | var _map = new google.maps.Map(domElement, options); 9 | var _marker = new google.maps.Marker({ 10 | position: new google.maps.LatLng(54.19335, -3.92695), 11 | map: _map, 12 | title: "Drag Me", 13 | visible: options.markerVisible, 14 | draggable: options.markerDraggable, 15 | icon: (options.markerIcon !== undefined) ? options.markerIcon : undefined 16 | }); 17 | return { 18 | map: _map, 19 | marker: _marker, 20 | circle: null, 21 | location: _marker.position, 22 | radius: options.radius, 23 | locationName: options.locationName, 24 | addressComponents: { 25 | formatted_address: null, 26 | addressLine1: null, 27 | addressLine2: null, 28 | streetName: null, 29 | streetNumber: null, 30 | city: null, 31 | district: null, 32 | state: null, 33 | stateOrProvince: null 34 | }, 35 | settings: options.settings, 36 | domContainer: domElement, 37 | geodecoder: new google.maps.Geocoder() 38 | } 39 | } 40 | 41 | // Utility functions for Google Map Manipulations 42 | var GmUtility = { 43 | /** 44 | * Draw a circle over the the map. Returns circle object. 45 | * Also writes new circle object in gmapContext. 46 | * 47 | * @param center - LatLng of the center of the circle 48 | * @param radius - radius in meters 49 | * @param gmapContext - context 50 | * @param options 51 | */ 52 | drawCircle: function(gmapContext, center, radius, options) { 53 | if (gmapContext.circle != null) { 54 | gmapContext.circle.setMap(null); 55 | } 56 | if (radius > 0) { 57 | radius *= 1; 58 | options = $.extend({ 59 | strokeColor: "#0000FF", 60 | strokeOpacity: 0.35, 61 | strokeWeight: 2, 62 | fillColor: "#0000FF", 63 | fillOpacity: 0.20 64 | }, options); 65 | options.map = gmapContext.map; 66 | options.radius = radius; 67 | options.center = center; 68 | gmapContext.circle = new google.maps.Circle(options); 69 | return gmapContext.circle; 70 | } 71 | return null; 72 | }, 73 | /** 74 | * 75 | * @param gMapContext 76 | * @param location 77 | * @param callback 78 | */ 79 | setPosition: function(gMapContext, location, callback) { 80 | gMapContext.location = location; 81 | gMapContext.marker.setPosition(location); 82 | gMapContext.map.panTo(location); 83 | this.drawCircle(gMapContext, location, gMapContext.radius, {}); 84 | if (gMapContext.settings.enableReverseGeocode) { 85 | this.updateLocationName(gMapContext, callback); 86 | } else { 87 | if (callback) { 88 | callback.call(this, gMapContext); 89 | } 90 | } 91 | 92 | }, 93 | locationFromLatLng: function(lnlg) { 94 | return {latitude: lnlg.lat(), longitude: lnlg.lng()} 95 | }, 96 | addressByFormat: function (addresses, format) { 97 | var result = null; 98 | for(var i = addresses.length - 1; i >= 0; i--){ 99 | if(addresses[i].types.indexOf(format) >= 0){ 100 | result = addresses[i]; 101 | } 102 | } 103 | return result || addresses[0]; 104 | }, 105 | updateLocationName: function(gmapContext, callback) { 106 | gmapContext.geodecoder.geocode({ 107 | latLng: gmapContext.marker.position 108 | }, function(results, status) { 109 | if (status == google.maps.GeocoderStatus.OK && results.length > 0) { 110 | var address = GmUtility.addressByFormat(results, gmapContext.settings.addressFormat); 111 | gmapContext.locationName = address.formatted_address; 112 | gmapContext.addressComponents = GmUtility.address_component_from_google_geocode(address.address_components); 113 | }else if (status == google.maps.GeocoderStatus.OVER_QUERY_LIMIT) { 114 | return setTimeout(function () { 115 | GmUtility.updateLocationName(gmapContext, callback); 116 | }, 1000); 117 | } 118 | if (callback) { 119 | callback.call(this, gmapContext); 120 | } 121 | }); 122 | }, 123 | address_component_from_google_geocode: function(address_components) { 124 | var result = {}; 125 | for (var i = address_components.length-1; i>=0; i--) { 126 | var component = address_components[i]; 127 | // Postal code 128 | if (component.types.indexOf('postal_code') >= 0) { 129 | result.postalCode = component.short_name; 130 | } 131 | // Street number 132 | else if (component.types.indexOf('street_number') >= 0) { 133 | result.streetNumber = component.short_name; 134 | } 135 | // Street name 136 | else if (component.types.indexOf('route') >= 0) { 137 | result.streetName = component.short_name; 138 | } 139 | // City 140 | else if (component.types.indexOf('locality') >= 0) { 141 | result.city = component.short_name; 142 | } 143 | // District 144 | else if (component.types.indexOf('sublocality') >= 0) { 145 | result.district = component.short_name; 146 | } 147 | // State \ Province 148 | else if (component.types.indexOf('administrative_area_level_1') >= 0) { 149 | result.stateOrProvince = component.short_name; 150 | } 151 | // State \ Province 152 | else if (component.types.indexOf('country') >= 0) { 153 | result.country = component.short_name; 154 | } 155 | } 156 | result.addressLine1 = [result.streetNumber, result.streetName].join(' ').trim(); 157 | result.addressLine2 = ''; 158 | return result; 159 | } 160 | }; 161 | 162 | function isPluginApplied(domObj) { 163 | return getContextForElement(domObj) != undefined; 164 | } 165 | 166 | function getContextForElement(domObj) { 167 | return $(domObj).data("locationpicker"); 168 | } 169 | 170 | function updateInputValues(inputBinding, gmapContext){ 171 | if (!inputBinding) return; 172 | var currentLocation = GmUtility.locationFromLatLng(gmapContext.marker.position); 173 | if (inputBinding.latitudeInput) { 174 | inputBinding.latitudeInput.val(currentLocation.latitude).change(); 175 | } 176 | if (inputBinding.longitudeInput) { 177 | inputBinding.longitudeInput.val(currentLocation.longitude).change(); 178 | } 179 | if (inputBinding.radiusInput) { 180 | inputBinding.radiusInput.val(gmapContext.radius).change(); 181 | } 182 | if (inputBinding.locationNameInput) { 183 | inputBinding.locationNameInput.val(gmapContext.locationName).change(); 184 | } 185 | } 186 | 187 | function setupInputListenersInput(inputBinding, gmapContext) { 188 | if (inputBinding) { 189 | if (inputBinding.radiusInput){ 190 | inputBinding.radiusInput.on("change", function(e) { 191 | var radiusInputValue = $(this).val(); 192 | if (!e.originalEvent || isNaN(radiusInputValue)) { return } 193 | gmapContext.radius = radiusInputValue; 194 | GmUtility.setPosition(gmapContext, gmapContext.location, function(context){ 195 | context.settings.onchanged.apply(gmapContext.domContainer, 196 | [GmUtility.locationFromLatLng(context.location), context.radius, false]); 197 | }); 198 | }); 199 | } 200 | if (inputBinding.locationNameInput && gmapContext.settings.enableAutocomplete) { 201 | var blur = false; 202 | gmapContext.autocomplete = new google.maps.places.Autocomplete(inputBinding.locationNameInput.get(0), gmapContext.settings.autocompleteOptions); 203 | google.maps.event.addListener(gmapContext.autocomplete, 'place_changed', function() { 204 | blur = false; 205 | var place = gmapContext.autocomplete.getPlace(); 206 | if (!place.geometry) { 207 | gmapContext.settings.onlocationnotfound(place.name); 208 | return; 209 | } 210 | GmUtility.setPosition(gmapContext, place.geometry.location, function(context) { 211 | updateInputValues(inputBinding, context); 212 | context.settings.onchanged.apply(gmapContext.domContainer, 213 | [GmUtility.locationFromLatLng(context.location), context.radius, false]); 214 | }); 215 | }); 216 | if(gmapContext.settings.enableAutocompleteBlur) { 217 | inputBinding.locationNameInput.on("change", function(e) { 218 | if (!e.originalEvent) { return } 219 | blur = true; 220 | }); 221 | inputBinding.locationNameInput.on("blur", function(e) { 222 | if (!e.originalEvent) { return } 223 | setTimeout(function() { 224 | var address = $(inputBinding.locationNameInput).val(); 225 | if (address.length > 5 && blur) { 226 | blur = false; 227 | gmapContext.geodecoder.geocode({'address': address}, function(results, status) { 228 | if(status == google.maps.GeocoderStatus.OK && results && results.length) { 229 | GmUtility.setPosition(gmapContext, results[0].geometry.location, function(context) { 230 | updateInputValues(inputBinding, context); 231 | context.settings.onchanged.apply(gmapContext.domContainer, 232 | [GmUtility.locationFromLatLng(context.location), context.radius, false]); 233 | }); 234 | } 235 | }); 236 | } 237 | }, 1000); 238 | }); 239 | } 240 | } 241 | if (inputBinding.latitudeInput) { 242 | inputBinding.latitudeInput.on("change", function(e) { 243 | var latitudeInputValue = $(this).val(); 244 | if (!e.originalEvent || isNaN(latitudeInputValue) ) { return } 245 | GmUtility.setPosition(gmapContext, new google.maps.LatLng(latitudeInputValue, gmapContext.location.lng()), function(context){ context.settings.onchanged.apply(gmapContext.domContainer, 246 | [GmUtility.locationFromLatLng(context.location), context.radius, false]); 247 | updateInputValues(gmapContext.settings.inputBinding, gmapContext); 248 | }); 249 | }); 250 | } 251 | if (inputBinding.longitudeInput) { 252 | inputBinding.longitudeInput.on("change", function(e) { 253 | var longitudeInputValue = $(this).val(); 254 | if (!e.originalEvent || isNaN(longitudeInputValue) ) { return } 255 | GmUtility.setPosition(gmapContext, new google.maps.LatLng(gmapContext.location.lat(), longitudeInputValue), function(context){ 256 | context.settings.onchanged.apply(gmapContext.domContainer, 257 | [GmUtility.locationFromLatLng(context.location), context.radius, false]); 258 | updateInputValues(gmapContext.settings.inputBinding, gmapContext); 259 | }); 260 | }); 261 | } 262 | } 263 | } 264 | 265 | function autosize(gmapContext) { 266 | google.maps.event.trigger(gmapContext.map, 'resize'); 267 | setTimeout(function() { 268 | gmapContext.map.setCenter(gmapContext.marker.position); 269 | }, 300); 270 | } 271 | 272 | function updateMap(gmapContext, $target, options) { 273 | var settings = $.extend({}, $.fn.locationpicker.defaults, options ), 274 | latNew = settings.location.latitude, 275 | lngNew = settings.location.longitude, 276 | radiusNew = settings.radius, 277 | latOld = gmapContext.settings.location.latitude, 278 | lngOld = gmapContext.settings.location.longitude, 279 | radiusOld = gmapContext.settings.radius; 280 | 281 | if (latNew == latOld && lngNew == lngOld && radiusNew == radiusOld) 282 | return; 283 | 284 | gmapContext.settings.location.latitude = latNew; 285 | gmapContext.settings.location.longitude = lngNew; 286 | gmapContext.radius = radiusNew; 287 | 288 | GmUtility.setPosition(gmapContext, new google.maps.LatLng(gmapContext.settings.location.latitude, gmapContext.settings.location.longitude), function(context){ 289 | setupInputListenersInput(gmapContext.settings.inputBinding, gmapContext); 290 | context.settings.oninitialized($target); 291 | }); 292 | } 293 | /** 294 | * Initializeialization: 295 | * $("#myMap").locationpicker(options); 296 | * @param options 297 | * @param params 298 | * @returns {*} 299 | */ 300 | $.fn.locationpicker = function( options, params ) { 301 | if (typeof options == 'string') { // Command provided 302 | var _targetDomElement = this.get(0); 303 | // Plug-in is not applied - nothing to do. 304 | if (!isPluginApplied(_targetDomElement)) return; 305 | var gmapContext = getContextForElement(_targetDomElement); 306 | switch (options) { 307 | case "location": 308 | if (params == undefined) { // Getter 309 | var location = GmUtility.locationFromLatLng(gmapContext.location); 310 | location.radius = gmapContext.radius; 311 | location.name = gmapContext.locationName; 312 | return location; 313 | } else { // Setter 314 | if (params.radius) { 315 | gmapContext.radius = params.radius; 316 | } 317 | GmUtility.setPosition(gmapContext, new google.maps.LatLng(params.latitude, params.longitude), function(gmapContext) { 318 | updateInputValues(gmapContext.settings.inputBinding, gmapContext); 319 | }); 320 | } 321 | break; 322 | case "subscribe": 323 | /** 324 | * Provides interface for subscribing for GoogleMap events. 325 | * See Google API documentation for details. 326 | * Parameters: 327 | * - event: string, name of the event 328 | * - callback: function, callback function to be invoked 329 | */ 330 | if (params == undefined) { // Getter is not available 331 | return null; 332 | } else { 333 | var event = params.event; 334 | var callback = params.callback; 335 | if (!event || ! callback) { 336 | console.error("LocationPicker: Invalid arguments for method \"subscribe\"") 337 | return null; 338 | } 339 | google.maps.event.addListener(gmapContext.map, event, callback); 340 | } 341 | break; 342 | case "map": 343 | /** 344 | * Returns object which allows access actual google widget and marker paced on it. 345 | * Structure: { 346 | * map: Instance of the google map widget 347 | * marker: marker placed on map 348 | * } 349 | */ 350 | if (params == undefined) { // Getter 351 | var locationObj = GmUtility.locationFromLatLng(gmapContext.location); 352 | locationObj.formattedAddress = gmapContext.locationName; 353 | locationObj.addressComponents = gmapContext.addressComponents; 354 | return { 355 | map: gmapContext.map, 356 | marker: gmapContext.marker, 357 | location: locationObj 358 | } 359 | } else { // Setter is not available 360 | return null; 361 | } 362 | case "autosize": 363 | autosize(gmapContext); 364 | return this; 365 | } 366 | return null; 367 | } 368 | return this.each(function() { 369 | var $target = $(this); 370 | // If plug-in hasn't been applied before - initialize, otherwise - skip 371 | if (isPluginApplied(this)){ 372 | updateMap(getContextForElement(this), $(this), options); 373 | return; 374 | } 375 | // Plug-in initialization is required 376 | // Defaults 377 | var settings = $.extend({}, $.fn.locationpicker.defaults, options ); 378 | // Initialize 379 | var gmapContext = new GMapContext(this, $.extend({}, { 380 | zoom: settings.zoom, 381 | center: new google.maps.LatLng(settings.location.latitude, settings.location.longitude), 382 | mapTypeId: settings.mapTypeId, 383 | mapTypeControl: false, 384 | styles: settings.styles, 385 | disableDoubleClickZoom: false, 386 | scrollwheel: settings.scrollwheel, 387 | streetViewControl: false, 388 | radius: settings.radius, 389 | locationName: settings.locationName, 390 | settings: settings, 391 | autocompleteOptions : settings.autocompleteOptions, 392 | addressFormat: settings.addressFormat, 393 | draggable: settings.draggable, 394 | markerIcon: settings.markerIcon, 395 | markerDraggable: settings.markerDraggable, 396 | markerVisible: settings.markerVisible 397 | }, settings.mapOptions)); 398 | $target.data("locationpicker", gmapContext); 399 | // Subscribe GMap events 400 | function displayMarkerWithSelectedArea() { 401 | GmUtility.setPosition(gmapContext, gmapContext.marker.position, function (context) { 402 | var currentLocation = GmUtility.locationFromLatLng(gmapContext.location); 403 | updateInputValues(gmapContext.settings.inputBinding, gmapContext); 404 | context.settings.onchanged.apply(gmapContext.domContainer, [currentLocation, context.radius, true]); 405 | }); 406 | } 407 | if (settings.markerInCenter) { 408 | gmapContext.map.addListener("bounds_changed", function () { 409 | if (!gmapContext.marker.dragging) { 410 | gmapContext.marker.setPosition(gmapContext.map.center); 411 | updateInputValues(gmapContext.settings.inputBinding, gmapContext); 412 | } 413 | }); 414 | gmapContext.map.addListener("idle", function () { 415 | if (!gmapContext.marker.dragging) { 416 | displayMarkerWithSelectedArea(); 417 | } 418 | }); 419 | } 420 | google.maps.event.addListener(gmapContext.marker, "drag", function(event) { 421 | updateInputValues(gmapContext.settings.inputBinding, gmapContext); 422 | }); 423 | google.maps.event.addListener(gmapContext.marker, "dragend", function(event) { 424 | displayMarkerWithSelectedArea(); 425 | }); 426 | GmUtility.setPosition(gmapContext, new google.maps.LatLng(settings.location.latitude, settings.location.longitude), function(context){ 427 | updateInputValues(settings.inputBinding, gmapContext); 428 | // Set input bindings if needed 429 | setupInputListenersInput(settings.inputBinding, gmapContext); 430 | context.settings.oninitialized($target); 431 | }); 432 | }); 433 | }; 434 | $.fn.locationpicker.defaults = { 435 | location: {latitude: 40.7324319, longitude: -73.82480777777776}, 436 | locationName: "", 437 | radius: 500, 438 | zoom: 15, 439 | mapTypeId: google.maps.MapTypeId.ROADMAP, 440 | styles: [], 441 | mapOptions: {}, 442 | scrollwheel: true, 443 | inputBinding: { 444 | latitudeInput: null, 445 | longitudeInput: null, 446 | radiusInput: null, 447 | locationNameInput: null 448 | }, 449 | enableAutocomplete: false, 450 | enableAutocompleteBlur: false, 451 | autocompleteOptions: null, 452 | addressFormat: 'postal_code', 453 | enableReverseGeocode: true, 454 | draggable: true, 455 | onchanged: function(currentLocation, radius, isMarkerDropped) {}, 456 | onlocationnotfound: function(locationName) {}, 457 | oninitialized: function (component) {}, 458 | // must be undefined to use the default gMaps marker 459 | markerIcon: undefined, 460 | markerDraggable: true, 461 | markerVisible : true 462 | } 463 | }( jQuery )); 464 | --------------------------------------------------------------------------------