├── README ├── examples └── index.html └── jquery-location.js /README: -------------------------------------------------------------------------------- 1 | HTML5 GeoLocation jQuery Plugin 2 | http://github.com/teleject/HTML5-GeoLocation-jQuery-Plugin 3 | 4 | * See plugin's comments for more information. 5 | 6 | * Simple demo at http://2010.incontrolconference.com/eats/ 7 | 8 | * Austin, TX Coffeeshop demo at http://atxwebshow.com/coffeeshops/ 9 | 10 | * For UK readers, try this demo: http://2010.incontrolconference.com/eats/uk.html 11 | 12 | * Some tips to get up and running: 13 | 14 | - To get plugin to work on YOUR own site, you will need to get a Google Maps API registered to your domain: http://code.google.com/apis/maps/signup.html 15 | - Use Microformats' hCard for addresses 16 | - If possible, use longitude and latitude within hCard for quicker response times 17 | 18 | Thanks for your interest in this plugin! 19 | 20 | Best, 21 | Christopher Schmitt 22 | http://christopherschmitt.com/ 23 | http://twitter.com/@teleject -------------------------------------------------------------------------------- /examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | The Q Card 6 | 7 | 10 | 11 | 12 | 13 | 25 | 26 | 27 |
28 |
37 |
38 | 39 |

40 | 41 |

Restaurant Listings

42 | 43 |
44 |
    45 | 46 |
  1. 47 | 48 |
    49 | 50 | Jane 51 | 52 | Smith 53 | 54 |
    Old School BBQ and Grill
    55 | 56 |
    57 |
    2907 E MLK Jr Blvd.
    58 | Austin, 59 | TX, 60 | 78702 61 | 62 | USA 63 | 64 |
    65 |
    512-974-6830
    66 |
    67 | 68 |
    69 |
    70 | 71 |
  2. 72 |
  3. 73 | 74 |
    75 | 76 | Hans 77 | 78 | Haina 79 | 80 |
    Old School BBQ and Grill
    81 | 82 |
    83 |
    2326 E Cesar Chavez St
    84 | Austin, 85 | TX, 86 | 78702 87 | 88 | USA 89 | 90 |
    91 |
    512-974-6830
    92 |
    93 | 94 |
    95 |
    96 | 97 | 98 |
  4. 99 | 100 |
  5. 101 | 102 |
    103 | Dino 104 | 105 | Smith 106 | 107 |
    The Shed BBQ Rolling Joint
    108 | 109 |
    110 |
    1816 E 6th Street.
    111 | Austin, 112 | TX, 113 | 78702 114 | 115 | USA 116 | 117 |
    118 |
    504-432-4718
    119 |
    120 | 121 |
    122 |
    123 | 124 |
  6. 125 | 126 |
  7. 127 | 128 |
    129 | Bob 130 | 131 | Smith 132 | 133 |
    Franklin Barbecue
    134 | 135 |
    136 |
    3421 N. I-35
    137 | Austin, 138 | TX, 139 | 78722 140 | 141 | USA 142 | 143 |
    144 |
    512-653-1187
    145 |
    146 | 147 |
    148 |
    149 | 150 |
  8. 151 | 152 |
  9. 153 | 154 |
    155 | Tom 156 | 157 | Marku 158 | 159 |
    Muck-N-Dave's Texas BBQ
    160 | 161 |
    162 |
    1603 South Congress
    163 | 164 | Austin, 165 | TX 166 | 167 | 78704 168 | 169 | 170 | USA 171 | 172 |
    173 |
    512-590-3387
    174 | 175 |
    176 | 177 |
    178 |
    179 | 180 |
  10. 181 | 182 |
  11. 183 | 184 |
    185 | John 186 | 187 | Smith 188 | 189 |
    Snow's BBQ
    190 | 191 |
    192 |
    516 Main Street
    193 | Lexington, 194 | TX 195 | 78947 196 | 197 | USA 198 | 199 |
    200 | 201 |
    979-773-4640
    202 | 203 |
    204 | 205 |
    206 |
    207 | 208 |
  12. 209 | 210 | 211 |
212 | 213 |
214 | 215 | 216 |
217 | 218 | 219 | -------------------------------------------------------------------------------- /jquery-location.js: -------------------------------------------------------------------------------- 1 | /** 2 | * jQuery HTML5 GeoLocation LookUp Plugin. This Plugin will perform geocoder lookups on 3 | * elements in the page, and will calulate distance based on visitor geo location. 4 | * 5 | * @option apiKey Google API key to use, for loading google maps 6 | * @option geodata Selector / Element for geodata 7 | * @option notification Selector / Element for notification elements 8 | * @option recheck Selector / Element for recheck element 9 | * @option distance Selector / Element for distance element 10 | * @option geoAdr Selector / Element for .adr element containing location data 11 | * @option listElement Selector / Element for the element(s) containing location data 12 | * 13 | * 14 | * 15 | * @method location Run plugin with optional parameters 16 | * @method version Output plugin version 17 | * 18 | * 19 | * @note 20 | * this plugin requires jquery library, along with google api + google maps api. 21 | * 22 | * if google api is not already loaded; 23 | * Provide your google api key, and this plugin will attempt to load the google apis dynamically 24 | * The jquery library should be loaded within your html, if using this plugin to load google apis. 25 | * 26 | * @usage 27 | * 28 | * $('#location_container').location(); 29 | * 30 | * or 31 | * 32 | * $('#locations').location( { apiKey: 'YOUR_API_KEY_HERE', geodata: '#geodata', notification: '.notification' } ); 33 | * 34 | * 35 | * @example HTML Markup 36 | * 37 | * 38 | * data-latitude & data-longitude are optional, plugin will attempt to look up 39 | * postal address values 40 | * 41 | *
42 | * Street Address Value 43 | * City Name Value, 44 | * State Value 45 | * Postal Code Value 46 | * Country Value 47 | *
48 | * 49 | * 50 | * 51 | * Copyright (c) 2010 Christopher Schmitt 52 | * 53 | * Permission is hereby granted, free of charge, to any person obtaining a copy 54 | * of this software and associated documentation files (the "Software"), to deal 55 | * in the Software without restriction, including without limitation the rights 56 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 57 | * copies of the Software, and to permit persons to whom the Software is 58 | * furnished to do so, subject to the following conditions: 59 | * 60 | * The above copyright notice and this permission notice shall be included in 61 | * all copies or substantial portions of the Software. 62 | * 63 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 64 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 65 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 66 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 67 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 68 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 69 | * THE SOFTWARE. 70 | * 71 | * 72 | * @author Christopher Schmitt 73 | * @author Ryon Labaw 74 | * @author Kyle Simpson 75 | * @author Marc Grabanski 76 | * 77 | * @version 1.0.0 78 | * 79 | * @changelog 80 | * + 1.0.0 First release 81 | * 82 | * 83 | */ 84 | 85 | 86 | 87 | if (typeof(jQuery) == 'undefined') 88 | { 89 | alert('jquery library was not found.'); 90 | } 91 | 92 | (function( $ ){ 93 | 94 | $.fn.extend($.fn, { 95 | 96 | loadGoogle: function ( ) { 97 | 98 | if (typeof(google) != 'undefined' && typeof(google.load) != 'undefined') { 99 | google.load("maps", "3",{"other_params":"sensor=true", callback: 100 | function(){ 101 | $(this).location(options); 102 | }}); 103 | return; 104 | } 105 | 106 | $.getScript('http://www.google.com/jsapi?key='+options.apiKey, 107 | function() { 108 | $(this).location(options); 109 | }); 110 | }, 111 | 112 | runApp : function( ) { 113 | 114 | i = 0; 115 | $(options.selector+" "+options.notification).show(); 116 | num_locations = $(options.selector+" "+options.listElement).length; 117 | xlocations = $(options.selector+" "+options.listElement).detach(); 118 | 119 | if (!tc) 120 | { 121 | $(this).getGeo(); 122 | } 123 | 124 | }, 125 | 126 | getGeo : function ( ) { 127 | 128 | if (!tc) 129 | { 130 | // timeout geolocation request, fallback on loader.ClientLocation 131 | setTimeout(function(){tc++; $(this).getGeo();},500); 132 | } 133 | 134 | if (!tc && navigator.geolocation) 135 | { 136 | navigator.geolocation.getCurrentPosition( 137 | function (position) { 138 | tc++; 139 | if (position && typeof(position.coords) != 'undefined') 140 | { 141 | $(this).updateMyLocation( position.coords.latitude,position.coords.longitude ); 142 | 143 | $(this).sortLocations( position.coords.latitude, position.coords.longitude ); 144 | } 145 | },$(this).getGeo); //,{enableHighAccuracy:true}); 146 | 147 | } else if (tc < 2) { 148 | if ((typeof google == 'object') && google.loader && google.loader.ClientLocation) { 149 | $(this).updateMyLocation( google.loader.ClientLocation.latitude,google.loader.ClientLocation.longitude ); 150 | $(this).sortLocations( google.loader.ClientLocation.latitude, google.loader.ClientLocation.longitude ); 151 | } 152 | } 153 | }, 154 | sortLocations : function ( lat, lng ) { 155 | 156 | i = 0; 157 | point = new google.maps.LatLng(lat, lng); 158 | 159 | addresses = $(xlocations).map(function(){ 160 | var $adr = $(this).find(options.geoAdr), latLng = null, lat, lng; 161 | latLng = ((lat = $adr.attr("data-latitude")) && (lng = $adr.attr("data-longitude")))?new google.maps.LatLng(lat,lng):null; 162 | return { "text": $adr.find('.street-address').text() +' , '+ $adr.find('.locality').text() +' , '+ $adr.find('.region').text() +' '+$adr.find('.postal-code').text(), "latLng":latLng, "div": $(this) }; 163 | }); 164 | 165 | $(addresses).each( function( i, el ) { 166 | var dest = el.latLng || el.text; 167 | directions.route({ "origin": point, "destination": dest, "travelMode": google.maps.DirectionsTravelMode.DRIVING }, 168 | function ( result, status ) { 169 | if (typeof(addresses[i]) != 'undefined') 170 | { 171 | addresses[i].distance = (status == "OK")?result.routes[0].legs[0].distance.value:'unknown'; 172 | $(this).count(); 173 | } 174 | }); 175 | }); 176 | }, 177 | 178 | count : function ( ) { 179 | i++; 180 | if (i === num_locations) { 181 | $(this).sortItems(); 182 | } 183 | }, 184 | 185 | sortItems : function ( ) { 186 | addresses.sort(function(a,b){ return a.distance - b.distance; }); 187 | $(addresses).each(function(i, address){ 188 | $(address.div).find(options.distance).text($(this).formatDistance(address.distance)); 189 | $(options.selector+" ol").append( address.div ); 190 | }); 191 | $(options.selector+" "+options.notification).hide(); 192 | $(this).showRecheckControl(); 193 | }, 194 | 195 | formatDistance : function ( distance ) { 196 | var dist = distance, meters_to_mile = 1609.344; 197 | if (dist > (meters_to_mile/10)) { 198 | dist = (Math.round((dist/meters_to_mile)*10) / 10) +" miles"; 199 | } else { 200 | dist = (parseFloat(dist) == dist)? dist+" meters" : dist = "unknown"; 201 | } 202 | return dist; 203 | }, 204 | 205 | updateMyLocation : function ( lat, lng ) { 206 | var myloc = new google.maps.LatLng(lat,lng); 207 | var req = {latLng:myloc} ; 208 | 209 | geocoder.geocode(req,function(responses,status){ 210 | if (status == "OK") { 211 | var geoloc = responses[0].formatted_address; 212 | $(options.geodata).text(geoloc); 213 | } else { 214 | //error 215 | } 216 | }); 217 | 218 | }, 219 | 220 | showRecheckControl : function ( ) { 221 | $(options.recheck).show().click(function(evt){ 222 | $(this).unbind("click").hide(); 223 | $(this).runApp(); 224 | evt.preventDefault(); 225 | return false; 226 | }); 227 | }, 228 | version: function ( ) { 229 | return (typeof(options)!='undefined')?options.version:'1.0.0'; 230 | }, 231 | location : function ( opts ) { 232 | 233 | var defaults = { 234 | apiKey : '', 235 | selector : '#locations', 236 | geodata : '#geodata', 237 | notification : '.notification', 238 | recheck : '#recheck', 239 | distance : '.distance', 240 | geoAdr : '.adr', 241 | listElement : 'li', 242 | version : '' 243 | }; 244 | 245 | options = $.extend(defaults, opts); 246 | options.version = '1.0.0'; 247 | addresses = {}; 248 | xlocations = {}; 249 | num_locations = 0; 250 | tc = 0; 251 | i = 0; 252 | 253 | if ((typeof(google) == 'undefined') || (typeof(google.load) == 'undefined') || (typeof(google.maps) == 'undefined')) { 254 | $(this).loadGoogle(); 255 | return; 256 | } 257 | 258 | directions = new google.maps.DirectionsService(); 259 | geocoder = new google.maps.Geocoder(); 260 | 261 | 262 | return this.each(function() { 263 | $(this).runApp(); 264 | }); 265 | 266 | } 267 | 268 | }); 269 | 270 | })( jQuery ); 271 | 272 | --------------------------------------------------------------------------------