(function($) { 'use strict'; $.fn.geocodify = function(options) { var settings = { 'regionBias': null, 'viewportBias': null, 'onSelect': function(ele) { alert('Jump to: ' + ele.formatted_address); }, 'minimumCharacters': 5, 'prepSearchString': null, 'filterResults': null, 'errorHandler': null, 'noResultsText': "No results found. Please refine your search.", 'acceptableAddressTypes': ['street_address', 'route', 'intersection', 'political', 'country', 'administrative_area_level_1', 'administrative_area_level_2', 'administrative_area_level_3 ', 'colloquial_area', 'locality', 'sublocality', 'neighborhood', 'premise', 'subpremise', 'postal_code', 'natural_feature', 'airport', 'park', 'point_of_interest', 'post_box', 'street_number', 'floor', 'room'], 'keyCodes': { UP: 38, DOWN: 40, DEL: 46, TAB: 9, RETURN: 13, ESC: 27, COMMA: 188, PAGEUP: 33, PAGEDOWN: 34, BACKSPACE: 8 } }; return this.each(function() { var $this = $(this), $input = $this, dropdownId = $this.attr("id") + "-dropdown", dropdown; if (options) { $.extend(settings, options); } // Ensure that autocomplete is turned off on input field $input.attr("autocomplete", "off").addClass("geocodify"); // Add the dropdown box $("
") .attr({ id: dropdownId }) .addClass("geocodify-dropdown") .hide() .insertAfter($input); dropdown = $("#" + dropdownId); // Define what will happen when the form is reset $this.reset = function() { dropdown.empty(); dropdown.hide(); }; // Create the bizness for how the geocoder work $this.previousSearch = null; $this.searchCache = {}; $this.google = new google.maps.Geocoder(); $this.fetch = function(query, force) { if (query === $this.previousSearch && force !== true) { return false; } $this.previousSearch = query; var qLength = query.length, params = { 'address': query }; if (qLength < settings.minimumCharacters && force !== true) { dropdown.html(""); dropdown.hide(); return false; } if (settings.prepSearchString) { query = settings.prepSearchString(query); } if (settings.regionBias) { params.region = settings.regionBias; } if (settings.viewportBias) { params.bounds = settings.viewportBias; } this.google.geocode(params, $this.onGeocode(force)); }; // The callback that runs after the geocoder returns $this.onGeocode = function(force) { return function(results, status) { var keep = [], count = 0, ul, li; $this.reset(); // Handle errors if (status !== google.maps.GeocoderStatus.OK) { if (settings.errorHandler) { settings.errorHandler(results, status); return false; } } // Loop through the results and filter out precision // levels we will not accept. $.each(results, function(i, val) { $.each(val.types, function(ii, type) { if (new RegExp(type).test(settings.acceptableAddressTypes.join("|"))) { keep.push(val); return false; } }); }); // Further filter the results if a function has been provided if (settings.filterResults) { keep = settings.filterResults(keep); } count = keep.length; if (count === 0) { ul = $("