├── 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 |
37 |
38 |
39 |
40 |
41 | Restaurant Listings
42 |
43 |
44 |
45 |
46 | -
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 |
72 | -
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 |
99 |
100 | -
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 |
125 |
126 | -
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 |
151 |
152 | -
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 |
181 |
182 | -
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 |
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 |
--------------------------------------------------------------------------------