]> git.proxmox.com Git - extjs.git/blame - extjs/modern/modern/src/util/Geolocation.js
add extjs 6.0.1 sources
[extjs.git] / extjs / modern / modern / src / util / Geolocation.js
CommitLineData
6527f429
DM
1/**\r
2 * Provides a cross browser class for retrieving location information.\r
3 *\r
4 * Based on the [Geolocation API Specification](http://dev.w3.org/geo/api/spec-source.html)\r
5 *\r
6 * When instantiated, by default this class immediately begins tracking location information,\r
7 * firing a {@link #locationupdate} event when new location information is available. To disable this\r
8 * location tracking (which may be battery intensive on mobile devices), set {@link #autoUpdate} to `false`.\r
9 *\r
10 * When this is done, only calls to {@link #updateLocation} will trigger a location retrieval.\r
11 *\r
12 * A {@link #locationerror} event is raised when an error occurs retrieving the location, either due to a user\r
13 * denying the application access to it, or the browser not supporting it.\r
14 *\r
15 * The below code shows a GeoLocation making a single retrieval of location information.\r
16 *\r
17 * var geo = Ext.create('Ext.util.Geolocation', {\r
18 * autoUpdate: false,\r
19 * listeners: {\r
20 * locationupdate: function(geo) {\r
21 * alert('New latitude: ' + geo.getLatitude());\r
22 * },\r
23 * locationerror: function(geo, bTimeout, bPermissionDenied, bLocationUnavailable, message) {\r
24 * if(bTimeout){\r
25 * alert('Timeout occurred.');\r
26 * } else {\r
27 * alert('Error occurred.');\r
28 * }\r
29 * }\r
30 * }\r
31 * });\r
32 * geo.updateLocation();\r
33 */\r
34Ext.define('Ext.util.Geolocation', {\r
35 extend: 'Ext.Evented',\r
36 alternateClassName: ['Ext.util.GeoLocation'],\r
37\r
38 config: {\r
39 /**\r
40 * @event locationerror\r
41 * Raised when a location retrieval operation failed.\r
42 *\r
43 * In the case of calling updateLocation, this event will be raised only once.\r
44 *\r
45 * If {@link #autoUpdate} is set to `true`, this event could be raised repeatedly.\r
46 * The first error is relative to the moment {@link #autoUpdate} was set to `true`\r
47 * (or this {@link Ext.util.Geolocation} was initialized with the {@link #autoUpdate} config option set to `true`).\r
48 * Subsequent errors are relative to the moment when the device determines that it's position has changed.\r
49 * @param {Ext.util.Geolocation} this\r
50 * @param {Boolean} timeout\r
51 * Boolean indicating a timeout occurred\r
52 * @param {Boolean} permissionDenied\r
53 * Boolean indicating the user denied the location request\r
54 * @param {Boolean} locationUnavailable\r
55 * Boolean indicating that the location of the device could not be determined.\r
56 * For instance, one or more of the location providers used in the location acquisition\r
57 * process reported an internal error that caused the process to fail entirely.\r
58 * @param {String} message An error message describing the details of the error encountered.\r
59 *\r
60 * This attribute is primarily intended for debugging and should not be used\r
61 * directly in an application user interface.\r
62 */\r
63\r
64 /**\r
65 * @event locationupdate\r
66 * Raised when a location retrieval operation has been completed successfully.\r
67 * @param {Ext.util.Geolocation} this\r
68 * Retrieve the current location information from the GeoLocation object by using the read-only\r
69 * properties: {@link #latitude}, {@link #longitude}, {@link #accuracy}, {@link #altitude}, {@link #altitudeAccuracy}, {@link #heading}, and {@link #speed}.\r
70 */\r
71\r
72 /**\r
73 * @cfg {Boolean} autoUpdate\r
74 * When set to `true`, continually monitor the location of the device (beginning immediately)\r
75 * and fire {@link #locationupdate} and {@link #locationerror} events.\r
76 */\r
77 autoUpdate: true,\r
78\r
79 /**\r
80 * @cfg {Number} frequency\r
81 * The frequency of each update if {@link #autoUpdate} is set to `true`.\r
82 */\r
83 frequency: 10000,\r
84\r
85 /**\r
86 * @cfg {Number} latitude\r
87 * Read-only property representing the last retrieved\r
88 * geographical coordinate specified in degrees.\r
89 * @readonly\r
90 */\r
91 latitude: null,\r
92\r
93 /**\r
94 * @cfg {Number} longitude\r
95 * Read-only property representing the last retrieved\r
96 * geographical coordinate specified in degrees.\r
97 * @readonly\r
98 */\r
99 longitude: null,\r
100\r
101 /**\r
102 * @cfg {Number} accuracy\r
103 * Read-only property representing the last retrieved\r
104 * accuracy level of the latitude and longitude coordinates,\r
105 * specified in meters.\r
106 *\r
107 * This will always be a non-negative number.\r
108 *\r
109 * This corresponds to a 95% confidence level.\r
110 * @readonly\r
111 */\r
112 accuracy: null,\r
113\r
114 /**\r
115 * @cfg {Number} altitude\r
116 * Read-only property representing the last retrieved\r
117 * height of the position, specified in meters above the ellipsoid\r
118 * [WGS84](http://dev.w3.org/geo/api/spec-source.html#ref-wgs).\r
119 * @readonly\r
120 */\r
121 altitude: null,\r
122\r
123 /**\r
124 * @cfg {Number} altitudeAccuracy\r
125 * Read-only property representing the last retrieved\r
126 * accuracy level of the altitude coordinate, specified in meters.\r
127 *\r
128 * If altitude is not null then this will be a non-negative number.\r
129 * Otherwise this returns `null`.\r
130 *\r
131 * This corresponds to a 95% confidence level.\r
132 * @readonly\r
133 */\r
134 altitudeAccuracy: null,\r
135\r
136 /**\r
137 * @cfg {Number} heading\r
138 * Read-only property representing the last retrieved\r
139 * direction of travel of the hosting device,\r
140 * specified in non-negative degrees between 0 and 359,\r
141 * counting clockwise relative to the true north.\r
142 *\r
143 * If speed is 0 (device is stationary), then this returns `NaN`.\r
144 * @readonly\r
145 */\r
146 heading: null,\r
147\r
148 /**\r
149 * @cfg {Number} speed\r
150 * Read-only property representing the last retrieved\r
151 * current ground speed of the device, specified in meters per second.\r
152 *\r
153 * If this feature is unsupported by the device, this returns `null`.\r
154 *\r
155 * If the device is stationary, this returns 0,\r
156 * otherwise it returns a non-negative number.\r
157 * @readonly\r
158 */\r
159 speed: null,\r
160\r
161 /**\r
162 * @cfg {Date} timestamp\r
163 * Read-only property representing when the last retrieved\r
164 * positioning information was acquired by the device.\r
165 * @readonly\r
166 */\r
167 timestamp: null,\r
168\r
169 //PositionOptions interface\r
170 /**\r
171 * @cfg {Boolean} allowHighAccuracy\r
172 * When set to `true`, provide a hint that the application would like to receive\r
173 * the best possible results. This may result in slower response times or increased power consumption.\r
174 * The user might also deny this capability, or the device might not be able to provide more accurate\r
175 * results than if this option was set to `false`.\r
176 */\r
177 allowHighAccuracy: false,\r
178\r
179 /**\r
180 * @cfg {Number} timeout\r
181 * The maximum number of milliseconds allowed to elapse between a location update operation\r
182 * and the corresponding {@link #locationupdate} event being raised. If a location was not successfully\r
183 * acquired before the given timeout elapses (and no other internal errors have occurred in this interval),\r
184 * then a {@link #locationerror} event will be raised indicating a timeout as the cause.\r
185 *\r
186 * Note that the time that is spent obtaining the user permission is **not** included in the period\r
187 * covered by the timeout. The `timeout` attribute only applies to the location acquisition operation.\r
188 *\r
189 * In the case of calling `updateLocation`, the {@link #locationerror} event will be raised only once.\r
190 *\r
191 * If {@link #autoUpdate} is set to `true`, the {@link #locationerror} event could be raised repeatedly.\r
192 * The first timeout is relative to the moment {@link #autoUpdate} was set to `true`\r
193 * (or this {@link Ext.util.Geolocation} was initialized with the {@link #autoUpdate} config option set to `true`).\r
194 * Subsequent timeouts are relative to the moment when the device determines that it's position has changed.\r
195 */\r
196 timeout: Infinity,\r
197\r
198 /**\r
199 * @cfg {Number} maximumAge\r
200 * This option indicates that the application is willing to accept cached location information whose age\r
201 * is no greater than the specified time in milliseconds. If `maximumAge` is set to 0, an attempt to retrieve\r
202 * new location information is made immediately.\r
203 *\r
204 * Setting the `maximumAge` to Infinity returns a cached position regardless of its age.\r
205 *\r
206 * If the device does not have cached location information available whose age is no\r
207 * greater than the specified `maximumAge`, then it must acquire new location information.\r
208 *\r
209 * For example, if location information no older than 10 minutes is required, set this property to 600000.\r
210 */\r
211 maximumAge: 0,\r
212\r
213 /**\r
214 * @private\r
215 */\r
216 provider : undefined\r
217 },\r
218\r
219 updateMaximumAge: function() {\r
220 if (this.watchOperation) {\r
221 this.updateWatchOperation();\r
222 }\r
223 },\r
224\r
225 updateTimeout: function() {\r
226 if (this.watchOperation) {\r
227 this.updateWatchOperation();\r
228 }\r
229 },\r
230\r
231 updateAllowHighAccuracy: function() {\r
232 if (this.watchOperation) {\r
233 this.updateWatchOperation();\r
234 }\r
235 },\r
236\r
237 applyProvider: function(config) {\r
238 if (Ext.feature.has.Geolocation) {\r
239 if (!config) {\r
240 if (navigator && navigator.geolocation) {\r
241 config = navigator.geolocation;\r
242 }\r
243 else if (window.google) {\r
244 config = google.gears.factory.create('beta.geolocation');\r
245 }\r
246 }\r
247 }\r
248 else {\r
249 this.fireEvent('locationerror', this, false, false, true, 'This device does not support Geolocation.');\r
250 }\r
251 return config;\r
252 },\r
253\r
254 updateAutoUpdate: function(newAutoUpdate, oldAutoUpdate) {\r
255 var me = this,\r
256 provider = me.getProvider();\r
257\r
258 if (oldAutoUpdate && provider) {\r
259 clearInterval(me.watchOperationId);\r
260 me.watchOperationId = null;\r
261 }\r
262\r
263 if (newAutoUpdate) {\r
264 if (!provider) {\r
265 me.fireEvent('locationerror', me, false, false, true, null);\r
266 return;\r
267 }\r
268\r
269 try {\r
270 me.updateWatchOperation();\r
271 }\r
272 catch(e) {\r
273 me.fireEvent('locationerror', me, false, false, true, e.message);\r
274 }\r
275 }\r
276 },\r
277\r
278 /**\r
279 * @private\r
280 */\r
281 updateWatchOperation: function() {\r
282 var me = this,\r
283 provider = me.getProvider();\r
284\r
285 // The native watchPosition method is currently broken in iOS5...\r
286\r
287 if (me.watchOperationId) {\r
288 clearInterval(me.watchOperationId);\r
289 }\r
290\r
291 function pollPosition() {\r
292 provider.getCurrentPosition(\r
293 Ext.bind(me.fireUpdate, me),\r
294 Ext.bind(me.fireError, me),\r
295 me.parseOptions()\r
296 );\r
297 }\r
298\r
299 pollPosition();\r
300 me.watchOperationId = Ext.interval(pollPosition, this.getFrequency());\r
301 },\r
302\r
303 /**\r
304 * Executes a onetime location update operation,\r
305 * raising either a {@link #locationupdate} or {@link #locationerror} event.\r
306 *\r
307 * Does not interfere with or restart ongoing location monitoring.\r
308 * @param {Function} callback\r
309 * A callback method to be called when the location retrieval has been completed.\r
310 *\r
311 * Will be called on both success and failure.\r
312 *\r
313 * The method will be passed one parameter, {@link Ext.util.Geolocation}\r
314 * (**this** reference), set to `null` on failure.\r
315 *\r
316 * geo.updateLocation(function (geo) {\r
317 * alert('Latitude: ' + (geo !== null ? geo.latitude : 'failed'));\r
318 * });\r
319 *\r
320 * @param {Object} [scope]\r
321 * The scope (**this** reference) in which the handler function is executed.\r
322 *\r
323 * **If omitted, defaults to the object which fired the event.**\r
324 *\r
325 * <!--positonOptions undocumented param, see W3C spec-->\r
326 */\r
327 updateLocation: function(callback, scope, positionOptions) {\r
328 var me = this,\r
329 provider = me.getProvider();\r
330\r
331 var failFunction = function(message, error) {\r
332 if (error) {\r
333 me.fireError(error);\r
334 }\r
335 else {\r
336 me.fireEvent('locationerror', me, false, false, true, message);\r
337 }\r
338 if (callback) {\r
339 callback.call(scope || me, null, me); //last parameter for legacy purposes\r
340 }\r
341 };\r
342\r
343 if (!provider) {\r
344 failFunction(null);\r
345 return;\r
346 }\r
347\r
348 try {\r
349 provider.getCurrentPosition(\r
350 //success callback\r
351 function(position) {\r
352 me.fireUpdate(position);\r
353 if (callback) {\r
354 callback.call(scope || me, me, me); //last parameter for legacy purposes\r
355 }\r
356 },\r
357 //error callback\r
358 function(error) {\r
359 failFunction(null, error);\r
360 },\r
361 positionOptions || me.parseOptions()\r
362 );\r
363 }\r
364 catch(e) {\r
365 failFunction(e.message);\r
366 }\r
367 },\r
368\r
369 /**\r
370 * @private\r
371 */\r
372 fireUpdate: function(position) {\r
373 var me = this,\r
374 coords = position.coords;\r
375\r
376 this.position = position;\r
377\r
378 me.setConfig({\r
379 timestamp: position.timestamp,\r
380 latitude: coords.latitude,\r
381 longitude: coords.longitude,\r
382 accuracy: coords.accuracy,\r
383 altitude: coords.altitude,\r
384 altitudeAccuracy: coords.altitudeAccuracy,\r
385 heading: coords.heading,\r
386 speed: coords.speed\r
387 });\r
388\r
389 me.fireEvent('locationupdate', me);\r
390 },\r
391\r
392 /**\r
393 * @private\r
394 */\r
395 fireError: function(error) {\r
396 var errorCode = error.code;\r
397 this.fireEvent('locationerror', this,\r
398 errorCode == error.TIMEOUT,\r
399 errorCode == error.PERMISSION_DENIED,\r
400 errorCode == error.POSITION_UNAVAILABLE,\r
401 error.message == undefined ? null : error.message\r
402 );\r
403 },\r
404\r
405 /**\r
406 * @private\r
407 */\r
408 parseOptions: function() {\r
409 var timeout = this.getTimeout(),\r
410 ret = {\r
411 maximumAge: this.getMaximumAge(),\r
412 enableHighAccuracy: this.getAllowHighAccuracy()\r
413 };\r
414\r
415 //Google doesn't like Infinity\r
416 if (timeout !== Infinity) {\r
417 ret.timeout = timeout;\r
418 }\r
419 return ret;\r
420 },\r
421\r
422 destroy: function() {\r
423 this.setAutoUpdate(false);\r
424 this.callParent();\r
425 }\r
426});\r