vendor/assets/javascripts/gmaps-auto-complete.js in gmaps-autocomplete-rails-0.1.4 vs vendor/assets/javascripts/gmaps-auto-complete.js in gmaps-autocomplete-rails-0.2.0

- old
+ new

@@ -1,297 +1,157 @@ -var GmapsCompleter, GmapsCompleterDefaultAssist, - __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; +var geocoder; +var map; +var marker; -GmapsCompleter = (function() { - GmapsCompleter.prototype.geocoder = null; +// initialise the google maps objects, and add listeners +function gmaps_init(){ - GmapsCompleter.prototype.map = null; + // center of the universe + var latlng = new google.maps.LatLng(51.751724,-1.255284); - GmapsCompleter.prototype.marker = null; + var options = { + zoom: 2, + center: latlng, + mapTypeId: google.maps.MapTypeId.ROADMAP + }; - GmapsCompleter.prototype.inputField = null; + // create our map object + map = new google.maps.Map(document.getElementById("gmaps-canvas"), options); - GmapsCompleter.prototype.errorField = null; + // the geocoder object allows us to do latlng lookup based on address + geocoder = new google.maps.Geocoder(); - GmapsCompleter.prototype.positionOutputter = null; + // the marker shows us the position of the latest address + marker = new google.maps.Marker({ + map: map, + draggable: true + }); - GmapsCompleter.prototype.updateUI = null; + // event triggered when marker is dragged and dropped + google.maps.event.addListener(marker, 'dragend', function() { + geocode_lookup( 'latLng', marker.getPosition() ); + }); - GmapsCompleter.prototype.updateMap = null; + // event triggered when map is clicked + google.maps.event.addListener(map, 'click', function(event) { + marker.setPosition(event.latLng) + geocode_lookup( 'latLng', event.latLng ); + }); - GmapsCompleter.prototype.region = null; + $('#gmaps-error').hide(); +} - GmapsCompleter.prototype.country = null; +// move the marker to a new position, and center the map on it +function update_map( geometry ) { + map.fitBounds( geometry.viewport ) + marker.setPosition( geometry.location ) +} - GmapsCompleter.prototype.debugOn = false; +// fill in the UI elements with new position data +function update_ui( address, latLng ) { + $('#gmaps-input-address').autocomplete("close"); + $('#gmaps-input-address').val(address); + //$('#gmaps-output-latitude').html(latLng.lat()); + //$('#gmaps-output-longitude').html(latLng.lng()); +} - GmapsCompleter.prototype.mapElem = null; +// Query the Google geocode object +// +// type: 'address' for search by address +// 'latLng' for search by latLng (reverse lookup) +// +// value: search query +// +// update: should we update the map (center map and position marker)? +function geocode_lookup( type, value, update ) { + // default value: update = false + update = typeof update !== 'undefined' ? update : false; - GmapsCompleter.prototype.zoomLevel = 2; + request = {}; + request[type] = value; - GmapsCompleter.prototype.mapType = null; + geocoder.geocode(request, function(results, status) { + $('#gmaps-error').html(''); + $('#gmaps-error').hide(); + if (status == google.maps.GeocoderStatus.OK) { + // Google geocoding has succeeded! + if (results[0]) { + // Always update the UI elements with new location data + update_ui( results[0].formatted_address, + results[0].geometry.location ) - GmapsCompleter.prototype.pos = [0, 0]; - - GmapsCompleter.prototype.inputField = '#gmaps-input-address'; - - GmapsCompleter.prototype.errorField = '#gmaps-error'; - - function GmapsCompleter(opts) { - this.keyDownHandler = __bind(this.keyDownHandler, this); - this.performGeocode = __bind(this.performGeocode, this); - this.init(opts); - } - - GmapsCompleter.prototype.init = function(opts) { - var callOpts, completerAssistClass, error, lat, latlng, lng, mapElem, mapOptions, mapType, pos, self, zoomLevel; - opts = opts || {}; - callOpts = $.extend(true, {}, opts); - this.debugOn = opts['debugOn']; - this.debug('init(opts)', opts); - completerAssistClass = opts['assist']; - try { - this.assist = new completerAssistClass; - } catch (_error) { - error = _error; - this.debug('assist error', error, opts['assist']); - } - this.assist || (this.assist = new GmapsCompleterDefaultAssist); - this.defaultOptions = opts['defaultOptions'] || this.assist.options; - opts = $.extend(true, {}, this.defaultOptions, opts); - this.positionOutputter = opts['positionOutputter'] || this.assist.positionOutputter; - this.updateUI = opts['updateUI'] || this.assist.updateUI; - this.updateMap = opts['updateMap'] || this.assist.updateMap; - this.geocodeErrorMsg = opts['geocodeErrorMsg'] || this.assist.geocodeErrorMsg; - this.geocodeErrorMsg = opts['geocodeErrorMsg'] || this.assist.geocodeErrorMsg; - this.noAddressFoundMsg = opts['noAddressFoundMsg'] || this.assist.noAddressFoundMsg; - pos = opts['pos']; - lat = pos[0]; - lng = pos[1]; - mapType = opts['mapType']; - mapElem = null; - this.mapElem = $("gmaps-canvas"); - if (opts['mapElem']) { - this.mapElem = $(opts['mapElem']).get(0); - } - this.mapType = google.maps.MapTypeId.ROADMAP; - zoomLevel = opts['zoomLevel']; - this.inputField = opts['inputField']; - this.errorField = opts['#gmaps-error']; - this.debugOn = opts['debugOn']; - this.debug('called with opts', callOpts); - this.debug('final completerAssist', this.completerAssist); - this.debug('defaultOptions', this.defaultOptions); - this.debug('options after merge with defaults', opts); - latlng = new google.maps.LatLng(lat, lng); - this.debug('lat,lng', latlng); - mapOptions = { - zoom: zoomLevel, - center: latlng, - mapTypeId: mapType - }; - this.debug('map options', mapOptions); - this.geocoder = new google.maps.Geocoder(); - self = this; - if (typeof this.mapElem === 'undefined') { - this.showError("Map element " + opts['mapElem'] + " could not be resolved!"); - } - this.debug('mapElem', this.mapElem); - if (!this.mapElem) { - return; - } - this.map = new google.maps.Map(this.mapElem, mapOptions); - if (!this.map) { - return; - } - this.marker = new google.maps.Marker({ - map: this.map, - draggable: true - }); - return self.addMapListeners(this.marker, this.map); - }; - - GmapsCompleter.prototype.debug = function(label, obj) { - if (!this.debugOn) { - return; - } - return console.log(label, obj); - }; - - GmapsCompleter.prototype.addMapListeners = function(marker, map) { - var self; - self = this; - google.maps.event.addListener(marker, 'dragend', function() { - return self.geocodeLookup('latLng', marker.getPosition()); - }); - return google.maps.event.addListener(map, 'click', function(event) { - marker.setPosition(event.latLng); - return self.geocodeLookup('latLng', event.latLng); - }); - }; - - GmapsCompleter.prototype.geocodeLookup = function(type, value, update) { - var request; - this.update || (this.update = false); - request = {}; - request[type] = value; - return this.geocoder.geocode(request, this.performGeocode); - }; - - GmapsCompleter.prototype.performGeocode = function(results, status) { - this.debug('performGeocode', status); - $(this.errorField).html(''); - if (status === google.maps.GeocoderStatus.OK) { - return this.geocodeSuccess(results); - } else { - return this.geocodeFailure(type, value); - } - }; - - GmapsCompleter.prototype.geocodeSuccess = function(results) { - this.debug('geocodeSuccess', results); - if (results[0]) { - this.updateUI(results[0].formatted_address, results[0].geometry.location); - if (this.update) { - return this.updateMap(results[0].geometry); + // Only update the map (position marker and center map) if requested + if( update ) { update_map( results[0].geometry ) } + } else { + // Geocoder status ok but no results!? + $('#gmaps-error').html("Sorry, something went wrong. Try again!"); + $('#gmaps-error').show(); } } else { - return this.showError(this.geocodeErrorMsg()); - } - }; + // Google Geocoding has failed. Two common reasons: + // * Address not recognised (e.g. search for 'zxxzcxczxcx') + // * Location doesn't map to address (e.g. click in middle of Atlantic) - GmapsCompleter.prototype.geocodeFailure = function(type, value) { - this.debug('geocodeFailure', type); - if (type === 'address') { - return this.showError(this.invalidAddressMsg(value)); - } else { - this.showError(this.noAddressFoundMsg()); - return this.updateUI('', value); - } - }; - - GmapsCompleter.prototype.showError = function(msg) { - $(this.errorField).html(msg); - $(this.errorField).show(); - return setTimeout(function() { - return $(this.errorField).hide(); - }, 1000); - }; - - GmapsCompleter.prototype.autoCompleteInit = function(opts) { - var autocompleteOpts, defaultAutocompleteOpts, self; - opts = opts || {}; - this.region = opts['region'] || this.defaultOptions['region']; - this.country = opts['country'] || this.defaultOptions['country']; - this.debug('region', this.region); - self = this; - autocompleteOpts = opts['autocomplete'] || {}; - defaultAutocompleteOpts = { - select: function(event, ui) { - self.updateUI(ui.item.value, ui.item.geocode.geometry.location); - return self.updateMap(ui.item.geocode.geometry); - }, - source: function(request, response) { - var address, geocodeOpts, region, region_postfix; - region_postfix = ''; - region = self.region; - if (region) { - region_postfix = ', ' + region; - } - address = request.term + region_postfix; - self.debug('geocode address', address); - geocodeOpts = { - 'address': address - }; - return self.geocoder.geocode(geocodeOpts, function(results, status) { - return response($.map(results, function(item) { - var uiAddress; - uiAddress = item.formatted_address.replace(", " + self.country, ''); - return { - label: uiAddress, - value: uiAddress, - geocode: item - }; - })); - }); + if( type == 'address' ) { + // User has typed in an address which we can't geocode to a location + $('#gmaps-error').html("Sorry! We couldn't find " + value + ". Try a different search term, or click the map." ); + $('#gmaps-error').show(); + } else { + // User has clicked or dragged marker to somewhere that Google can't do a reverse lookup for + // In this case we display a warning, clear the address box, but fill in LatLng + $('#gmaps-error').html("Woah... that's pretty remote! You're going to have to manually enter a place name." ); + $('#gmaps-error').show(); + update_ui('', value) } }; - autocompleteOpts = $.extend(true, defaultAutocompleteOpts, autocompleteOpts); - $(this.inputField).autocomplete(autocompleteOpts); - return $(this.inputField).bind('keydown', this.keyDownHandler); - }; + }); +}; - GmapsCompleter.prototype.keyDownHandler = function(event) { - if (event.keyCode === 13) { - this.geocodeLookup('address', $(this.inputField).val(), true); - return $(this.inputField).autocomplete("disable"); - } else { - return $(this.inputField).autocomplete("enable"); - } - }; +// initialise the jqueryUI autocomplete element +function autocomplete_init() { + $("#gmaps-input-address").autocomplete({ - return GmapsCompleter; + // source is the list of input options shown in the autocomplete dropdown. + // see documentation: http://jqueryui.com/demos/autocomplete/ + source: function(request,response) { -})(); + // the geocode method takes an address or LatLng to search for + // and a callback function which should process the results into + // a format accepted by jqueryUI autocomplete + geocoder.geocode( {'address': request.term }, function(results, status) { + response($.map(results, function(item) { + return { + label: item.formatted_address, // appears in dropdown box + value: item.formatted_address, // inserted into input element when selected + geocode: item // all geocode data: used in select callback event + } + })); + }) + }, -GmapsCompleterDefaultAssist = (function() { - function GmapsCompleterDefaultAssist() {} + // event triggered when drop-down option selected + select: function(event,ui){ + update_ui( ui.item.value, ui.item.geocode.geometry.location ) + update_map( ui.item.geocode.geometry ) + } + }); - GmapsCompleterDefaultAssist.prototype.options = { - mapElem: '#gmaps-canvas', - zoomLevel: 2, - mapType: google.maps.MapTypeId.ROADMAP, - pos: [0, 0], - inputField: '#gmaps-input-address', - errorField: '#gmaps-error', - debugOn: true - }; + // triggered when user presses a key in the address box + $("#gmaps-input-address").bind('keydown', function(event) { + if(event.keyCode == 13) { + geocode_lookup( 'address', $('#gmaps-input-address').val(), true ); - GmapsCompleterDefaultAssist.prototype.updateMap = function(geometry) { - var map, marker; - map = this.map; - marker = this.marker; - if (map) { - map.fitBounds(geometry.viewport); + // ensures dropdown disappears when enter is pressed + $('#gmaps-input-address').autocomplete("disable") + } else { + // re-enable if previously disabled above + $('#gmaps-input-address').autocomplete("enable") } - if (marker) { - return marker.setPosition(geometry.location); - } - }; + }); +}; // autocomplete_init - GmapsCompleterDefaultAssist.prototype.updateUI = function(address, latLng) { - var country, inputField, updateAdr; - inputField = this.inputField; - country = this.country; - $(inputField).autocomplete('close'); - this.debug('country', country); - updateAdr = address.replace(', ' + country, ''); - updateAdr = address; - this.debug('updateAdr', updateAdr); - $(inputField).val(updateAdr); - return this.positionOutputter(latLng); +$(document).ready(function() { + if( $('#gmaps-canvas').length ) { + gmaps_init(); + autocomplete_init(); }; - - GmapsCompleterDefaultAssist.prototype.positionOutputter = function(latLng) { - $('#gmaps-output-latitude').html(latLng.lat()); - return $('#gmaps-output-longitude').html(latLng.lng()); - }; - - GmapsCompleterDefaultAssist.prototype.geocodeErrorMsg = function() { - return "Sorry, something went wrong. Try again!"; - }; - - GmapsCompleterDefaultAssist.prototype.invalidAddressMsg = function(value) { - return "Sorry! We couldn't find " + value + ". Try a different search term, or click the map."; - }; - - GmapsCompleterDefaultAssist.prototype.noAddressFoundMsg = function() { - return "Woah... that's pretty remote! You're going to have to manually enter a place name."; - }; - - return GmapsCompleterDefaultAssist; - -})(); - -window.GmapsCompleter = GmapsCompleter; - -window.GmapsCompleterDefaultAssist = GmapsCompleterDefaultAssist; +}); \ No newline at end of file