/* * jQuery UI addresspicker @VERSION * * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * * Depends: * jquery.ui.core.js * jquery.ui.widget.js * jquery.ui.autocomplete.js */ (function( $, undefined ) { $.widget( "ui.addresspicker", { options: { appendAddressString: "", draggableMarker: true, regionBias: null, bounds: '', componentsFilter:'', updateCallback: null, reverseGeocode: false, autocomplete: 'default', language: '', mapOptions: { zoom: 5, center: new google.maps.LatLng(46, 2), scrollwheel: false, mapTypeId: google.maps.MapTypeId.ROADMAP }, elements: { map: false, lat: false, lng: false, street_number: false, route: false, locality: false, sublocality: false, administrative_area_level_3: false, administrative_area_level_2: false, administrative_area_level_1: false, country: false, postal_code: false, type: false }, autocomplete: '' // could be autocomplete: "bootstrap" to use bootstrap typeahead autocomplete instead of jQueryUI }, marker: function() { return this.gmarker; }, map: function() { return this.gmap; }, updatePosition: function() { this._updatePosition(this.gmarker.getPosition()); }, reloadPosition: function() { this.gmarker.setVisible(true); this.gmarker.setPosition(new google.maps.LatLng(this.lat.val, this.lng.val)); this.gmap.setCenter(this.gmarker.getPosition()); }, resize: function() { google.maps.event.trigger(this.gmap, 'resize') }, selected: function() { return this.selectedResult; }, _mapped: {}, _create: function() { var self = this; this.geocoder = { geocode: function(options, callback) { jQuery.ajax({ url: "https://maps.googleapis.com/maps/api/geocode/json?" + jQuery.param(options) + '&sensor=false', type: "GET", success: function(data) { callback(data.results, data.status); } }); } //new google.maps.Geocoder(); }; if (this.options.autocomplete === 'bootstrap') { this.element.typeahead({ source: function(query, process) { self._mapped = {}; var response = function(results) { var labels = []; for (var i = 0; i < results.length; i++) { self._mapped[results[i].label] = results[i]; labels.push(results[i].label); } process(labels); }; var request = {term: query}; self._geocode(request, response); }, updater: function(item) { var ui = {item: self._mapped[item]} self._focusAddress(null, ui); self._selectAddress(null, ui); return item; } }); } else { this.element.autocomplete($.extend({ source: $.proxy(this._geocode, this), focus: $.proxy(this._focusAddress, this), select: $.proxy(this._selectAddress, this) }), this.options.autocomplete); } this.lat = $(this.options.elements.lat); this.lng = $(this.options.elements.lng); this.street_number = $(this.options.elements.street_number); this.route = $(this.options.elements.route); this.locality = $(this.options.elements.locality); this.sublocality = $(this.options.elements.sublocality); this.administrative_area_level_3 = $(this.options.elements.administrative_area_level_3); this.administrative_area_level_2 = $(this.options.elements.administrative_area_level_2); this.administrative_area_level_1 = $(this.options.elements.administrative_area_level_1); this.country = $(this.options.elements.country); this.postal_code = $(this.options.elements.postal_code); this.type = $(this.options.elements.type); if (this.options.elements.map) { this.mapElement = $(this.options.elements.map); this._initMap(); } }, _initMap: function() { if (this.lat && this.lat.val()) { this.options.mapOptions.center = new google.maps.LatLng(this.lat.val(), this.lng.val()); } this.gmap = new google.maps.Map(this.mapElement[0], this.options.mapOptions); this.gmarker = new google.maps.Marker({ position: this.options.mapOptions.center, map:this.gmap, draggable: this.options.draggableMarker}); google.maps.event.addListener(this.gmarker, 'dragend', $.proxy(this._markerMoved, this)); this.gmarker.setVisible(false); }, _updatePosition: function(location) { if (this.lat) { this.lat.val(location.lat()); } if (this.lng) { this.lng.val(location.lng()); } }, _addressParts: {street_number: null, route: null, locality: null, sublocality: null, administrative_area_level_3: null, administrative_area_level_2: null, administrative_area_level_1: null, country: null, postal_code:null, type: null}, _updateAddressParts: function(geocodeResult){ parsedResult = this._parseGeocodeResult(geocodeResult); for (addressPart in this._addressParts){ if (this[addressPart]){ if (parsedResult[addressPart] !== false){ this[addressPart].val(parsedResult[addressPart]); } else { this[addressPart].val(''); } } } }, _updateAddressPartsViaReverseGeocode: function(location){ this.geocoder.geocode({'latlng': location.lat() + "," + location.lng()}, $.proxy(function(results, status){ if (status == google.maps.GeocoderStatus.OK){ this._updateAddressParts(results[0]); this.element.val(results[0].formatted_address); this.selectedResult = results[0]; if (this.options.updateCallback) { this.options.updateCallback(this.selectedResult, this._parseGeocodeResult(this.selectedResult)); } } }, this)); }, _parseGeocodeResult: function(geocodeResult){ var parsed = this._parseLatAndLng(geocodeResult.geometry.location); for (var addressPart in this._addressParts){ parsed[addressPart] = this._findInfo(geocodeResult, addressPart); } parsed.type = geocodeResult.types[0]; return parsed; }, _parseLatAndLng: function(location){ var longitude, latitude; if(typeof(location.lat) === 'function'){ latitude = location.lat(); longitude = location.lng(); } else { latitude = location.lat; longitude = location.lng; } return { lat: latitude, lng: longitude }; }, _markerMoved: function() { this._updatePosition(this.gmarker.getPosition()); if (this.options.reverseGeocode){ this._updateAddressPartsViaReverseGeocode(this.gmarker.getPosition()); } }, // Autocomplete source method: fill its suggests with google geocoder results _geocode: function(request, response) { var address = request.term, self = this; this.geocoder.geocode({ 'language': this.options.language, 'address': address + this.options.appendAddressString, 'region': this.options.regionBias, 'bounds': this.options.bounds, 'components': this.options.componentsFilter }, function(results, status) { if (status == google.maps.GeocoderStatus.OK && results) { for (var i = 0; i < results.length; i++) { result = results[i] g = result.geometry g.location = new google.maps.LatLng(g.location.lat, g.location.lng); g.viewport = new google.maps.LatLngBounds( new google.maps.LatLng(g.viewport.southwest.lat, g.viewport.southwest.lng), new google.maps.LatLng(g.viewport.northeast.lat, g.viewport.northeast.lng) ) result.label = results[i].formatted_address; } } response(results); }) }, _findInfo: function(result, type) { for (var i = 0; i < result.address_components.length; i++) { var component = result.address_components[i]; if (component.types.indexOf(type) !=-1) { return component.long_name; } } return false; }, _focusAddress: function(event, ui) { var address = ui.item; if (!address) { return; } if (this.gmarker) { this.gmarker.setPosition(address.geometry.location); this.gmarker.setVisible(true); this.gmap.fitBounds(address.geometry.viewport); } this._updatePosition(address.geometry.location); this._updateAddressParts(address); }, _selectAddress: function(event, ui) { this.selectedResult = ui.item; if (this.options.updateCallback) { this.options.updateCallback(this.selectedResult, this._parseGeocodeResult(this.selectedResult)); } } }); $.extend( $.ui.addresspicker, { version: "@VERSION" }); // make IE think it doesn't suck if(!Array.indexOf){ Array.prototype.indexOf = function(obj){ for(var i=0; i