218 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			218 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|   | // A shim to implement the W3C Geolocation API Specification using Gears or the Ajax API
 | ||
|  | if (typeof navigator.geolocation == "undefined" || navigator.geolocation.shim ) { (function(){ | ||
|  | 
 | ||
|  | // -- BEGIN GEARS_INIT
 | ||
|  | (function() { | ||
|  |   // We are already defined. Hooray!
 | ||
|  |   if (window.google && google.gears) { | ||
|  |     return; | ||
|  |   } | ||
|  | 
 | ||
|  |   var factory = null; | ||
|  | 
 | ||
|  |   // Firefox
 | ||
|  |   if (typeof GearsFactory != 'undefined') { | ||
|  |     factory = new GearsFactory(); | ||
|  |   } else { | ||
|  |     // IE
 | ||
|  |     try { | ||
|  |       factory = new ActiveXObject('Gears.Factory'); | ||
|  |       // privateSetGlobalObject is only required and supported on WinCE.
 | ||
|  |       if (factory.getBuildInfo().indexOf('ie_mobile') != -1) { | ||
|  |         factory.privateSetGlobalObject(this); | ||
|  |       } | ||
|  |     } catch (e) { | ||
|  |       // Safari
 | ||
|  |       if ((typeof navigator.mimeTypes != 'undefined') && navigator.mimeTypes["application/x-googlegears"]) { | ||
|  |         factory = document.createElement("object"); | ||
|  |         factory.style.display = "none"; | ||
|  |         factory.width = 0; | ||
|  |         factory.height = 0; | ||
|  |         factory.type = "application/x-googlegears"; | ||
|  |         document.documentElement.appendChild(factory); | ||
|  |       } | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  |   // *Do not* define any objects if Gears is not installed. This mimics the
 | ||
|  |   // behavior of Gears defining the objects in the future.
 | ||
|  |   if (!factory) { | ||
|  |     return; | ||
|  |   } | ||
|  | 
 | ||
|  |   // Now set up the objects, being careful not to overwrite anything.
 | ||
|  |   //
 | ||
|  |   // Note: In Internet Explorer for Windows Mobile, you can't add properties to
 | ||
|  |   // the window object. However, global objects are automatically added as
 | ||
|  |   // properties of the window object in all browsers.
 | ||
|  |   if (!window.google) { | ||
|  |     google = {}; | ||
|  |   } | ||
|  | 
 | ||
|  |   if (!google.gears) { | ||
|  |     google.gears = {factory: factory}; | ||
|  |   } | ||
|  | })(); | ||
|  | // -- END GEARS_INIT
 | ||
|  | 
 | ||
|  | var GearsGeoLocation = (function() { | ||
|  |     // -- PRIVATE
 | ||
|  |     var geo = google.gears.factory.create('beta.geolocation'); | ||
|  |      | ||
|  |     var wrapSuccess = function(callback, self) { // wrap it for lastPosition love
 | ||
|  |         return function(position) { | ||
|  |             callback(position); | ||
|  |             self.lastPosition = position; | ||
|  |         }; | ||
|  |     }; | ||
|  |      | ||
|  |     // -- PUBLIC
 | ||
|  |     return { | ||
|  |         shim: true, | ||
|  |          | ||
|  |         type: "Gears", | ||
|  |          | ||
|  |         lastPosition: null, | ||
|  |          | ||
|  |         getCurrentPosition: function(successCallback, errorCallback, options) { | ||
|  |             var self = this; | ||
|  |             var sc = wrapSuccess(successCallback, self); | ||
|  |             geo.getCurrentPosition(sc, errorCallback, options); | ||
|  |         }, | ||
|  |          | ||
|  |         watchPosition: function(successCallback, errorCallback, options) { | ||
|  |             geo.watchPosition(successCallback, errorCallback, options); | ||
|  |         }, | ||
|  |          | ||
|  |         clearWatch: function(watchId) { | ||
|  |             geo.clearWatch(watchId); | ||
|  |         }, | ||
|  |          | ||
|  |         getPermission: function(siteName, imageUrl, extraMessage) { | ||
|  |             geo.getPermission(siteName, imageUrl, extraMessage); | ||
|  |         } | ||
|  | 
 | ||
|  |     }; | ||
|  | }); | ||
|  | 
 | ||
|  | var AjaxGeoLocation = (function() { | ||
|  |     // -- PRIVATE
 | ||
|  |     var loading = false; | ||
|  |     var loadGoogleLoader = function() { | ||
|  |         if (!hasGoogleLoader() && !loading) { | ||
|  |             loading = true; | ||
|  |             var s = document.createElement('script'); | ||
|  |             s.src = (document.location.protocol == "https:"?"https://":"http://") + 'www.google.com/jsapi?callback=_google_loader_apiLoaded'; | ||
|  |             s.type = "text/javascript"; | ||
|  |             document.getElementsByTagName('body')[0].appendChild(s); | ||
|  |         } | ||
|  |     }; | ||
|  |      | ||
|  |     var queue = []; | ||
|  |     var addLocationQueue = function(callback) { | ||
|  |         queue.push(callback); | ||
|  |     }; | ||
|  |      | ||
|  |     var runLocationQueue = function() { | ||
|  |         if (hasGoogleLoader()) { | ||
|  |             while (queue.length > 0) { | ||
|  |                 var call = queue.pop(); | ||
|  |                 call(); | ||
|  |             } | ||
|  |         } | ||
|  |     }; | ||
|  |      | ||
|  |     window['_google_loader_apiLoaded'] = function() { | ||
|  |         runLocationQueue(); | ||
|  |     }; | ||
|  |      | ||
|  |     var hasGoogleLoader = function() { | ||
|  |         return (window['google'] && google['loader']); | ||
|  |     }; | ||
|  |      | ||
|  |     var checkGoogleLoader = function(callback) { | ||
|  |         if (hasGoogleLoader()) { return true; } | ||
|  | 
 | ||
|  |         addLocationQueue(callback); | ||
|  |                  | ||
|  |         loadGoogleLoader(); | ||
|  |          | ||
|  |         return false; | ||
|  |     }; | ||
|  |      | ||
|  |     loadGoogleLoader(); // start to load as soon as possible just in case
 | ||
|  |      | ||
|  |     // -- PUBLIC
 | ||
|  |     return { | ||
|  |         shim: true, | ||
|  |          | ||
|  |         type: "ClientLocation", | ||
|  |          | ||
|  |         lastPosition: null, | ||
|  |          | ||
|  |         getCurrentPosition: function(successCallback, errorCallback, options) { | ||
|  |             var self = this; | ||
|  |             if (!checkGoogleLoader(function() { | ||
|  |                 self.getCurrentPosition(successCallback, errorCallback, options); | ||
|  |             })) { return; } | ||
|  |              | ||
|  |             if (google.loader.ClientLocation) { | ||
|  |                 var cl = google.loader.ClientLocation; | ||
|  |                  | ||
|  |                 var position = { | ||
|  |                     coords: { | ||
|  |                         latitude: cl.latitude, | ||
|  |                         longitude: cl.longitude, | ||
|  |                         altitude: null, | ||
|  |                         accuracy: 43000, // same as Gears accuracy over wifi?
 | ||
|  |                         altitudeAccuracy: null, | ||
|  |                         heading: null, | ||
|  |                         speed: null | ||
|  |                     }, | ||
|  |                     // extra info that is outside of the bounds of the core API
 | ||
|  |                     address: { | ||
|  |                         city: cl.address.city, | ||
|  |                         country: cl.address.country, | ||
|  |                         country_code: cl.address.country_code, | ||
|  |                         region: cl.address.region | ||
|  |                     }, | ||
|  |                     timestamp: new Date() | ||
|  |                 }; | ||
|  | 
 | ||
|  |                 successCallback(position); | ||
|  |                  | ||
|  |                 this.lastPosition = position; | ||
|  |             } else if (errorCallback === "function")  { | ||
|  |                 errorCallback({ code: 3, message: "Using the Google ClientLocation API and it is not able to calculate a location."}); | ||
|  |             } | ||
|  |         }, | ||
|  |          | ||
|  |         watchPosition: function(successCallback, errorCallback, options) { | ||
|  |             this.getCurrentPosition(successCallback, errorCallback, options); | ||
|  |              | ||
|  |             var self = this; | ||
|  |             var watchId = setInterval(function() { | ||
|  |                 self.getCurrentPosition(successCallback, errorCallback, options); | ||
|  |             }, 10000); | ||
|  |              | ||
|  |             return watchId; | ||
|  |         }, | ||
|  |          | ||
|  |         clearWatch: function(watchId) { | ||
|  |             clearInterval(watchId); | ||
|  |         }, | ||
|  |          | ||
|  |         getPermission: function(siteName, imageUrl, extraMessage) { | ||
|  |             // for now just say yes :)
 | ||
|  |             return true; | ||
|  |         } | ||
|  | 
 | ||
|  |     }; | ||
|  | }); | ||
|  | 
 | ||
|  | // If you have Gears installed use that, else use Ajax ClientLocation
 | ||
|  | navigator.geolocation = (window.google && google.gears) ? GearsGeoLocation() : AjaxGeoLocation(); | ||
|  | 
 | ||
|  | })(); | ||
|  | } |