|
1 if (typeof(DeviceInfo) != 'object') |
|
2 DeviceInfo = {}; |
|
3 |
|
4 /** |
|
5 * This represents the PhoneGap API itself, and provides a global namespace for accessing |
|
6 * information about the state of PhoneGap. |
|
7 * @class |
|
8 */ |
|
9 PhoneGap = { |
|
10 queue: { |
|
11 ready: true, |
|
12 commands: [], |
|
13 timer: null |
|
14 }, |
|
15 _constructors: [] |
|
16 }; |
|
17 |
|
18 /** |
|
19 * Boolean flag indicating if the PhoneGap API is available and initialized. |
|
20 */ |
|
21 PhoneGap.available = DeviceInfo.uuid != undefined; |
|
22 |
|
23 /** |
|
24 * Execute a PhoneGap command in a queued fashion, to ensure commands do not |
|
25 * execute with any race conditions, and only run when PhoneGap is ready to |
|
26 * recieve them. |
|
27 * @param {String} command Command to be run in PhoneGap, e.g. "ClassName.method" |
|
28 * @param {String[]} [args] Zero or more arguments to pass to the method |
|
29 */ |
|
30 PhoneGap.exec = function() { |
|
31 PhoneGap.queue.commands.push(arguments); |
|
32 if (PhoneGap.queue.timer == null) |
|
33 PhoneGap.queue.timer = setInterval(PhoneGap.run_command, 10); |
|
34 }; |
|
35 /** |
|
36 * Internal function used to dispatch the request to PhoneGap. This needs to be implemented per-platform to |
|
37 * ensure that methods are called on the phone in a way appropriate for that device. |
|
38 * @private |
|
39 */ |
|
40 PhoneGap.run_command = function() { |
|
41 }; |
|
42 |
|
43 /** |
|
44 * This class contains acceleration information |
|
45 * @constructor |
|
46 * @param {Number} x The force applied by the device in the x-axis. |
|
47 * @param {Number} y The force applied by the device in the y-axis. |
|
48 * @param {Number} z The force applied by the device in the z-axis. |
|
49 */ |
|
50 function Acceleration(x, y, z) { |
|
51 /** |
|
52 * The force applied by the device in the x-axis. |
|
53 */ |
|
54 this.x = x; |
|
55 /** |
|
56 * The force applied by the device in the y-axis. |
|
57 */ |
|
58 this.y = y; |
|
59 /** |
|
60 * The force applied by the device in the z-axis. |
|
61 */ |
|
62 this.z = z; |
|
63 /** |
|
64 * The time that the acceleration was obtained. |
|
65 */ |
|
66 this.timestamp = new Date().getTime(); |
|
67 } |
|
68 |
|
69 /** |
|
70 * This class specifies the options for requesting acceleration data. |
|
71 * @constructor |
|
72 */ |
|
73 function AccelerationOptions() { |
|
74 /** |
|
75 * The timeout after which if acceleration data cannot be obtained the errorCallback |
|
76 * is called. |
|
77 */ |
|
78 this.timeout = 10000; |
|
79 } |
|
80 /** |
|
81 * This class provides access to device accelerometer data. |
|
82 * @constructor |
|
83 */ |
|
84 function Accelerometer() { |
|
85 /** |
|
86 * The last known acceleration. |
|
87 */ |
|
88 this.lastAcceleration = null; |
|
89 } |
|
90 |
|
91 /** |
|
92 * Asynchronously aquires the current acceleration. |
|
93 * @param {Function} successCallback The function to call when the acceleration |
|
94 * data is available |
|
95 * @param {Function} errorCallback The function to call when there is an error |
|
96 * getting the acceleration data. |
|
97 * @param {AccelerationOptions} options The options for getting the accelerometer data |
|
98 * such as timeout. |
|
99 */ |
|
100 |
|
101 Accelerometer.prototype.getCurrentAcceleration = function(successCallback, errorCallback, options) { |
|
102 // If the acceleration is available then call success |
|
103 // If the acceleration is not available then call error |
|
104 |
|
105 try { |
|
106 alert(1); |
|
107 if (!this.serviceObj) |
|
108 this.serviceObj = this.getServiceObj(); |
|
109 |
|
110 if (this.serviceObj == null) |
|
111 throw { |
|
112 name: "DeviceErr", |
|
113 message: "Could not initialize service object" |
|
114 }; |
|
115 |
|
116 //get the sensor channel |
|
117 var SensorParams = { |
|
118 SearchCriterion: "AccelerometerAxis" |
|
119 }; |
|
120 var returnvalue = this.serviceObj.ISensor.FindSensorChannel(SensorParams); |
|
121 alert(2); |
|
122 var error = returnvalue["ErrorCode"]; |
|
123 var errmsg = returnvalue["ErrorMessage"]; |
|
124 if (!(error == 0 || error == 1012)) { |
|
125 var ex = { |
|
126 name: "Unable to find Sensor Channel: " + error, |
|
127 message: errmsg |
|
128 }; |
|
129 throw ex; |
|
130 } |
|
131 var channelInfoMap = returnvalue["ReturnValue"][0]; |
|
132 var criteria = { |
|
133 ChannelInfoMap: channelInfoMap, |
|
134 ListeningType: "ChannelData" |
|
135 }; |
|
136 |
|
137 if (typeof(successCallback) != 'function') |
|
138 successCallback = function(){ |
|
139 }; |
|
140 if (typeof(errorCallback) != 'function') |
|
141 errorCallback = function(){ |
|
142 }; |
|
143 |
|
144 this.success_callback = successCallback; |
|
145 this.error_callback = errorCallback; |
|
146 //create a closure to persist this instance of Accelerometer into the RegisterForNofication callback |
|
147 var obj = this; |
|
148 |
|
149 // TODO: this call crashes WRT, but there is no other way to read the accel sensor |
|
150 // http://discussion.forum.nokia.com/forum/showthread.php?t=182151&highlight=memory+leak |
|
151 this.serviceObj.ISensor.RegisterForNotification(criteria, function(transId, eventCode, result){ |
|
152 try { |
|
153 alert(10); |
|
154 var criteria = { |
|
155 TransactionID: transId |
|
156 }; |
|
157 obj.serviceObj.ISensor.Cancel(criteria); |
|
158 |
|
159 var accel = new Acceleration(result.ReturnValue.XAxisData, result.ReturnValue.YAxisData, result.ReturnValue.ZAxisData); |
|
160 Accelerometer.lastAcceleration = accel; |
|
161 |
|
162 obj.success_callback(accel); |
|
163 |
|
164 } |
|
165 catch (ex) { |
|
166 obj.serviceObj.ISensor.Cancel(criteria); |
|
167 obj.error_callback(ex); |
|
168 } |
|
169 |
|
170 }); |
|
171 alert(4); |
|
172 } catch (ex) { |
|
173 alert(5); |
|
174 errorCallback(ex); |
|
175 } |
|
176 |
|
177 }; |
|
178 |
|
179 |
|
180 /** |
|
181 * Asynchronously aquires the acceleration repeatedly at a given interval. |
|
182 * @param {Function} successCallback The function to call each time the acceleration |
|
183 * data is available |
|
184 * @param {Function} errorCallback The function to call when there is an error |
|
185 * getting the acceleration data. |
|
186 * @param {AccelerationOptions} options The options for getting the accelerometer data |
|
187 * such as timeout. |
|
188 */ |
|
189 |
|
190 Accelerometer.prototype.watchAcceleration = function(successCallback, errorCallback, options) { |
|
191 this.getCurrentAcceleration(successCallback, errorCallback, options); |
|
192 // TODO: add the interval id to a list so we can clear all watches |
|
193 var frequency = (options != undefined)? options.frequency : 10000; |
|
194 return setInterval(function() { |
|
195 navigator.accelerometer.getCurrentAcceleration(successCallback, errorCallback, options); |
|
196 }, frequency); |
|
197 }; |
|
198 |
|
199 /** |
|
200 * Clears the specified accelerometer watch. |
|
201 * @param {String} watchId The ID of the watch returned from #watchAcceleration. |
|
202 */ |
|
203 Accelerometer.prototype.clearWatch = function(watchId) { |
|
204 clearInterval(watchId); |
|
205 }; |
|
206 |
|
207 //gets the Acceleration Service Object from WRT |
|
208 Accelerometer.prototype.getServiceObj = function() { |
|
209 var so; |
|
210 |
|
211 try { |
|
212 so = device.getServiceObject("Service.Sensor", "ISensor"); |
|
213 } catch (ex) { |
|
214 throw { |
|
215 name: "DeviceError", |
|
216 message: "Could not initialize accel service object (" + ex.name + ": " + ex.message + ")" |
|
217 }; |
|
218 } |
|
219 return so; |
|
220 }; |
|
221 |
|
222 if (typeof navigator.accelerometer == "undefined") navigator.accelerometer = new Accelerometer();/** |
|
223 * This class provides access to the device camera. |
|
224 * @constructor |
|
225 */ |
|
226 function Camera() { |
|
227 this.success_callback = null; |
|
228 this.error_callback = null; |
|
229 } |
|
230 |
|
231 /** |
|
232 * We use the Platform Services 2.0 API here. So we must include a portion of the |
|
233 * PS 2.0 source code (camera API). |
|
234 * @param {Function} successCallback |
|
235 * @param {Function} errorCallback |
|
236 * @param {Object} options |
|
237 */ |
|
238 Camera.prototype.getPicture = function(successCallback, errorCallback, options){ |
|
239 try { |
|
240 if (!this.serviceObj) { |
|
241 this.serviceObj = com.nokia.device.load("", "com.nokia.device.camera", ""); |
|
242 } |
|
243 if (!this.serviceObj) { |
|
244 throw { |
|
245 name: "CameraError", |
|
246 message: "could not load camera service" |
|
247 }; |
|
248 } |
|
249 var obj = this; |
|
250 |
|
251 obj.success_callback = successCallback; |
|
252 obj.error_callback = errorCallback; |
|
253 this.serviceObj.startCamera( function(transactionID, errorCode, outPut) { |
|
254 //outPut should be an array of image urls (local), or an error code |
|
255 if (errorCode == 0) { |
|
256 obj.success_callback(outPut); |
|
257 } |
|
258 else { |
|
259 obj.error_callback({ |
|
260 name: "CameraError", |
|
261 message: errorCode |
|
262 }); |
|
263 } |
|
264 }); |
|
265 |
|
266 } catch (ex) { |
|
267 errorCallback.call(ex); |
|
268 } |
|
269 |
|
270 }; |
|
271 |
|
272 if (typeof navigator.camera == "undefined") navigator.camera = new Camera();/* |
|
273 Copyright © 2009 Nokia. All rights reserved. |
|
274 Code licensed under the BSD License: |
|
275 Software License Agreement (BSD License) Copyright © 2009 Nokia. |
|
276 All rights reserved. |
|
277 Redistribution and use of this software in source and binary forms, with or without modification, are permitted provided that the following conditions are met: |
|
278 |
|
279 Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. |
|
280 Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. |
|
281 Neither the name of Nokia Corporation. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission of Nokia Corporation. |
|
282 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
283 |
|
284 version: 1.0 |
|
285 */ |
|
286 |
|
287 |
|
288 // utility.js |
|
289 // |
|
290 // This file contains some utility functions for S60 providers |
|
291 |
|
292 |
|
293 // Start an application and wait for it to exit |
|
294 |
|
295 //TBD: Get rid of this global, use closures instead |
|
296 |
|
297 DeviceError.prototype = new Error(); //inheritance occurs here |
|
298 DeviceError.prototype.constructor = DeviceError; //If this not present then, it uses default constructor of Error |
|
299 |
|
300 //constructor for DeviceError. |
|
301 function DeviceError(message,code) |
|
302 { |
|
303 this.toString = concatenate; |
|
304 this.code = code; |
|
305 this.name = "DeviceException";//we can even overwrite default name "Error" |
|
306 this.message=message; |
|
307 } |
|
308 |
|
309 function concatenate() |
|
310 { |
|
311 return (this.name+":"+" "+this.message+" "+this.code); |
|
312 } |
|
313 |
|
314 function splitErrorMessage(errmessage) |
|
315 { |
|
316 if(errmessage.search(/:/)!=-1) |
|
317 { |
|
318 if((errmessage.split(":").length)==2) |
|
319 { |
|
320 return errmessage.split(":")[1]; |
|
321 } |
|
322 if((errmessage.split(":").length)>2) |
|
323 { |
|
324 return errmessage.split(":")[2]; |
|
325 } |
|
326 } |
|
327 return errmessage; |
|
328 } |
|
329 |
|
330 |
|
331 var __s60_start_and_wait_cb; |
|
332 |
|
333 function __s60_on_app_exit(){ |
|
334 widget.onshow = null; |
|
335 if(__s60_start_and_wait_cb != null){ |
|
336 __s60_start_and_wait_cb(); |
|
337 } |
|
338 } |
|
339 |
|
340 function __s60_on_app_start(){ |
|
341 widget.onhide = null; |
|
342 widget.onshow = __s60_on_app_exit; |
|
343 } |
|
344 |
|
345 // This function cannot actually force JS to wait, |
|
346 // but it does supply a callback the apps can use |
|
347 // to continue processing on return from the app. |
|
348 // Apps should take care not to reinvoke this and |
|
349 // should be careful about any other processing |
|
350 // that might happen while the app is running. |
|
351 |
|
352 function __s60_start_and_wait(id, args, app_exit_cb){ |
|
353 __s60_start_and_wait_cb = app_exit_cb; |
|
354 widget.onhide = __s60_on_app_start; |
|
355 widget.openApplication(id, args); |
|
356 } |
|
357 |
|
358 function __s60_api_not_supported(){ |
|
359 throw(err_ServiceNotSupported); |
|
360 } |
|
361 |
|
362 function __s60_enumerate_object(object, namespace, func, param){ |
|
363 var key; |
|
364 for(key in object){ |
|
365 |
|
366 var propname; |
|
367 if(namespace){ |
|
368 propname = namespace + "." + key; |
|
369 } |
|
370 else{ |
|
371 propname = key; |
|
372 } |
|
373 var value = object[key]; |
|
374 if(typeof value == "object"){ |
|
375 __s60_enumerate_object(value, propname, func, param); |
|
376 } |
|
377 else { |
|
378 func(propname,value, param); |
|
379 } |
|
380 } |
|
381 } |
|
382 /* |
|
383 Copyright © 2009 Nokia. All rights reserved. |
|
384 Code licensed under the BSD License: |
|
385 Software License Agreement (BSD License) Copyright © 2009 Nokia. |
|
386 All rights reserved. |
|
387 Redistribution and use of this software in source and binary forms, with or without modification, are permitted provided that the following conditions are met: |
|
388 |
|
389 Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. |
|
390 Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. |
|
391 Neither the name of Nokia Corporation. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission of Nokia Corporation. |
|
392 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
393 |
|
394 version: 1.0 |
|
395 */ |
|
396 |
|
397 |
|
398 var __device_debug_on__ = true; |
|
399 var err_missing_argument = 1003; |
|
400 var event_cancelled = 3; |
|
401 var err_bad_argument = 1002; |
|
402 var err_InvalidService_Argument = 1000; |
|
403 var err_ServiceNotReady = 1006; |
|
404 var err_ServiceNotSupported = 1004; |
|
405 |
|
406 function __device_debug(text){ |
|
407 //if(__device_debug_on__) alert(text); |
|
408 } |
|
409 |
|
410 function __device_handle_exception(e, text){ |
|
411 __device_debug(text); |
|
412 throw(e); |
|
413 } |
|
414 |
|
415 function __device_typeof(value) |
|
416 { |
|
417 // First check to see if the value is undefined. |
|
418 if (value == undefined) { |
|
419 return "undefined"; |
|
420 } |
|
421 // Check for objects created with the "new" keyword. |
|
422 if (value instanceof Object) { |
|
423 // Check whether it's a string object. |
|
424 if (value instanceof String) { |
|
425 return "String"; |
|
426 } |
|
427 // Check whether it's an array object/array literal. |
|
428 else |
|
429 if (value instanceof Array) { |
|
430 return "Array"; |
|
431 } |
|
432 } |
|
433 // dealing with a literal. |
|
434 if (typeof value) { |
|
435 if (typeof value == "object") { |
|
436 if (typeof value == "object" && !value) { |
|
437 return "null"; |
|
438 } |
|
439 } |
|
440 // if not null check for other types |
|
441 |
|
442 // Check if it's a string literal. |
|
443 else if (typeof value == "string") { |
|
444 return "string"; |
|
445 } |
|
446 } |
|
447 } |
|
448 |
|
449 |
|
450 // The top-level service object. It would be nice to use a namespace here |
|
451 // (com.nokia.device.service), but emulating namespaces still allows name clashes. |
|
452 /* |
|
453 var sp_device = { |
|
454 //services: null; // TBD: Make the services list a member of this object? |
|
455 load: __device_service_load, |
|
456 listServices: __device_service_list, |
|
457 listInterfaces: __device_service_interfaces, |
|
458 version: "0.1", |
|
459 info: "device prototype" |
|
460 }; |
|
461 */ |
|
462 |
|
463 if(undefined == com) |
|
464 var com={}; |
|
465 |
|
466 if( typeof com != "object") |
|
467 throw("com defined as non object"); |
|
468 |
|
469 if(undefined == com.nokia) |
|
470 com.nokia = {}; |
|
471 |
|
472 if( typeof com.nokia != "object") |
|
473 throw("com.nokia defined as non object"); |
|
474 |
|
475 if(undefined == com.nokia.device) |
|
476 com.nokia.device = { |
|
477 load: __device_service_load, |
|
478 listServices: __device_service_list, |
|
479 listInterfaces: __device_service_interfaces, |
|
480 version: "0.1", |
|
481 info: "device prototype" |
|
482 }; |
|
483 else |
|
484 throw("com.nokia.device already defined"); |
|
485 |
|
486 com.nokia.device.SORT_ASCENDING = 0; |
|
487 com.nokia.device.SORT_DESCENDING = 1; |
|
488 |
|
489 com.nokia.device.SORT_BY_DATE = 0; |
|
490 com.nokia.device.SORT_BY_SENDER = 1; |
|
491 |
|
492 com.nokia.device.STATUS_READ = 0; |
|
493 com.nokia.device.STATUS_UNREAD = 1; |
|
494 |
|
495 |
|
496 // Configure the services offered. |
|
497 |
|
498 var __device_services_inited = false; |
|
499 |
|
500 var __device_services = [ |
|
501 |
|
502 // For now, the only service is the base "device"" service |
|
503 { |
|
504 "name":"com.nokia.device", |
|
505 "version": 0.1, |
|
506 "interfaces": [] |
|
507 } |
|
508 ]; |
|
509 |
|
510 // Initialize the configured services. |
|
511 |
|
512 function __device_services_init(){ |
|
513 if(__device_services_inited){ |
|
514 return; |
|
515 } |
|
516 __device_services_inited = true; |
|
517 |
|
518 // Get the service-specific service entries. Note that these |
|
519 // need to be individually wrapped by try/catch blocks so that the |
|
520 // interpreter gracefully handles missing services. |
|
521 |
|
522 try { |
|
523 __device_services[0].interfaces.push(__device_geolocation_service_entry); |
|
524 }catch (e){ |
|
525 __device_debug("Missing library implementation: " + e); |
|
526 } |
|
527 try { |
|
528 __device_services[0].interfaces.push(__device_camera_service_entry); |
|
529 }catch (e){ |
|
530 __device_debug("Missing library implementation: " + e); |
|
531 } |
|
532 try { |
|
533 __device_services[0].interfaces.push(__device_media_service_entry); |
|
534 }catch (e){ |
|
535 // __device_debug("Missing library implementation: " + e); |
|
536 } |
|
537 try { |
|
538 __device_services[0].interfaces.push(__device_contacts_service_entry); |
|
539 }catch (e){ |
|
540 // __device_debug("Missing library implementation: " + e); |
|
541 } |
|
542 try { |
|
543 __device_services[0].interfaces.push(__device_messaging_service_entry); |
|
544 }catch (e){ |
|
545 __device_debug("Missing library implementation: " + e); |
|
546 } |
|
547 try { |
|
548 __device_services[0].interfaces.push(__device_calendar_service_entry); |
|
549 }catch (e){ |
|
550 __device_debug("Missing library implementation: " + e); |
|
551 } |
|
552 try { |
|
553 __device_services[0].interfaces.push(__device_landmarks_service_entry); |
|
554 }catch (e){ |
|
555 __device_debug("Missing library implementation: " + e); |
|
556 } |
|
557 try { |
|
558 __device_services[0].interfaces.push(__device_event_service_entry); |
|
559 }catch (e){ |
|
560 __device_debug("Missing library implementation: " + e); |
|
561 } |
|
562 try { |
|
563 __device_services[0].interfaces.push(__device_sysinfo_service_entry); |
|
564 }catch (e){ |
|
565 __device_debug("Missing library implementation: " + e); |
|
566 } |
|
567 try { |
|
568 __device_services[0].interfaces.push(__device_sensors_service_entry); |
|
569 }catch (e){ |
|
570 __device_debug("Missing library implementation: " + e); |
|
571 } |
|
572 |
|
573 } |
|
574 |
|
575 function __device_get_implementation(i){ |
|
576 //__device_debug("get_implementation: " + i); |
|
577 return new i.proto(new(i.providers[0].instance)); |
|
578 } |
|
579 |
|
580 function __device_get_descriptor(i){ |
|
581 //__device_debug("get_descriptor: " + i); |
|
582 return new i.descriptor(new(i.providers[0].descriptor)); |
|
583 } |
|
584 |
|
585 function __device_get_interface(s, interfaceName, version){ |
|
586 //__device_debug("get_interface: " + s + " " + interfaceName); |
|
587 var i = s.interfaces; |
|
588 if((interfaceName == null) || (interfaceName == '')){ |
|
589 // Interface name not specified, get first interface, ignoring version |
|
590 return __device_get_implementation(i[0]); |
|
591 } |
|
592 |
|
593 // Find first match of name and version |
|
594 for (var d in i){ |
|
595 |
|
596 if(i[d].name == null){ |
|
597 __device_update_descriptor(i[d]); |
|
598 } |
|
599 if(i[d].name == undefined){ |
|
600 continue; |
|
601 } |
|
602 if (i[d].name == interfaceName){ |
|
603 // Match version if specified |
|
604 if ((version == null) || (version == '') || (i[d].version >= version)){ |
|
605 return __device_get_implementation(i[d]); |
|
606 } |
|
607 } |
|
608 } |
|
609 return null; |
|
610 } |
|
611 |
|
612 // Implemention of the load method |
|
613 |
|
614 function __device_service_load(serviceName, interfaceName, version){ |
|
615 |
|
616 __device_services_init(); |
|
617 |
|
618 // Service name is specified |
|
619 if ((serviceName != null) && (serviceName != '') &&(serviceName != "*")){ |
|
620 for(var s in __device_services){ |
|
621 if (serviceName == __device_services[s].name){ |
|
622 return __device_get_interface(__device_services[s], interfaceName, version); |
|
623 } |
|
624 } |
|
625 // Service name not specified, get first implementation |
|
626 } else { |
|
627 //__device_debug("Trying to get interface implementations: "); |
|
628 for(var s in __device_services){ |
|
629 //__device_debug("service_load: " + s + ":" + __device_services[s].name + ": " + interfaceName); |
|
630 var i = __device_get_interface(__device_services[s], interfaceName, version); |
|
631 if (i != null){ |
|
632 return i; |
|
633 } |
|
634 } |
|
635 } |
|
636 return null; |
|
637 } |
|
638 |
|
639 // Lazily fill in the descriptor table |
|
640 |
|
641 function __device_update_descriptor(i){ |
|
642 var d = __device_get_descriptor(i); |
|
643 i.name = d.interfaceName; |
|
644 i.version = d.version; |
|
645 } |
|
646 // Get an array of interface descriptors for a service |
|
647 |
|
648 function __device_interface_list(s){ |
|
649 var retval = new Array(); |
|
650 for(var i in s.interfaces){ |
|
651 if(s.interfaces[i].name == null){ |
|
652 __device_update_descriptor(s.interfaces[i]); |
|
653 } |
|
654 if(s.interfaces[i].name == undefined){ |
|
655 continue; |
|
656 } |
|
657 retval[i] = new Object(); |
|
658 retval[i].name = s.interfaces[i].name; |
|
659 retval[i].version = s.interfaces[i].version; |
|
660 } |
|
661 return retval; |
|
662 } |
|
663 |
|
664 // Get a service description |
|
665 |
|
666 function __device_service_descriptor(s){ |
|
667 this.name = s.name; |
|
668 this.version = s.version; |
|
669 this.interfaces = __device_interface_list(s); |
|
670 this.toString = __device_service_descriptor_to_string; |
|
671 } |
|
672 |
|
673 function __device_service_descriptor_to_string(){ |
|
674 var is = "\nInterfaces(s): "; |
|
675 |
|
676 for (i in this.interfaces){ |
|
677 is += "\n" + this.interfaces[i].name + " " + this.interfaces[0].version; |
|
678 } |
|
679 return ("Service: " + this.name + is); |
|
680 } |
|
681 |
|
682 // Implement the listServices method |
|
683 |
|
684 function __device_service_list(serviceName, interfaceName, version){ |
|
685 //__device_debug("__device_service_list: " + serviceName + " " + interfaceName); |
|
686 __device_services_init(); |
|
687 var retval = new Array(); |
|
688 var n = 0; |
|
689 |
|
690 //Treat empty service and interface names as wildcards |
|
691 if ((serviceName == null)|| (serviceName == '')/* || (serviceName == undefined)*/){ |
|
692 serviceName = ".*"; |
|
693 } |
|
694 if ((interfaceName == null) || (interfaceName == '') /*|| (serviceName == undefined)*/){ |
|
695 interfaceName = ".*"; |
|
696 } |
|
697 |
|
698 if ((typeof serviceName != "string") || (typeof interfaceName != "string")) { |
|
699 return retval; |
|
700 } |
|
701 |
|
702 // This method does regular expression matching of service and interface |
|
703 |
|
704 var sregx = new RegExp(serviceName); |
|
705 var iregx = new RegExp(interfaceName); |
|
706 |
|
707 for(var s in __device_services){ |
|
708 //__device_debug (serviceName + "==" + __device_services[s].name + "?:" + sregx.test(__device_services[s].name)); |
|
709 if (sregx.test(__device_services[s].name)){ |
|
710 // Find the first matching interface |
|
711 |
|
712 for(var i in __device_services[s].interfaces){ |
|
713 if(__device_services[s].interfaces[i].name == null){ |
|
714 __device_update_descriptor(__device_services[s].interfaces[i]); |
|
715 } |
|
716 if(__device_services[s].interfaces[i].name == undefined){ |
|
717 continue; |
|
718 } |
|
719 //__device_debug (interfaceName + "==" + __device_services[s].interfaces[i].name + "?:" + iregx.test(__device_services[s].interfaces[i].name)); |
|
720 if (iregx.test(__device_services[s].interfaces[i].name)){ |
|
721 if ((version == null) || (version == '') || (__device_services[s].interfaces[i].version >= version)){ |
|
722 // An interface matched, we're done. |
|
723 retval[n] = new __device_service_descriptor(__device_services[s]); |
|
724 break; |
|
725 } |
|
726 } |
|
727 } |
|
728 } |
|
729 ++n; |
|
730 } |
|
731 return retval; |
|
732 } |
|
733 |
|
734 // Implement the listInterfaces method |
|
735 |
|
736 function __device_service_interfaces(serviceName){ |
|
737 __device_services_init(); |
|
738 if(serviceName==null||serviceName==undefined||serviceName==''){ |
|
739 throw new DeviceError("Framework: listInterfaces: serviceName is missing", err_missing_argument); |
|
740 } |
|
741 for (var s in __device_services){ |
|
742 if(__device_services[s].name == serviceName){ |
|
743 return __device_interface_list(__device_services[s]); |
|
744 } |
|
745 } |
|
746 return null; |
|
747 } |
|
748 |
|
749 function modifyObjectBaseProp(obj){ |
|
750 for (pro in obj) { |
|
751 if(typeof obj[pro] == "function" ) |
|
752 obj[pro] = 0; |
|
753 } |
|
754 }; |
|
755 /* |
|
756 Copyright © 2009 Nokia. All rights reserved. |
|
757 Code licensed under the BSD License: |
|
758 Software License Agreement (BSD License) Copyright © 2009 Nokia. |
|
759 All rights reserved. |
|
760 Redistribution and use of this software in source and binary forms, with or without modification, are permitted provided that the following conditions are met: |
|
761 |
|
762 Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. |
|
763 Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. |
|
764 Neither the name of Nokia Corporation. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission of Nokia Corporation. |
|
765 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
766 |
|
767 version: 1.0 |
|
768 */ |
|
769 |
|
770 |
|
771 // S60 sp-based camera provider |
|
772 |
|
773 function __sp_camera_descriptor(){ |
|
774 //__device_debug("sp_camera_descriptor"); |
|
775 //Read-only properties |
|
776 this.interfaceName = "com.nokia.device.camera"; |
|
777 this.version = "0.1"; |
|
778 //Class-static properties |
|
779 } |
|
780 |
|
781 // TBD make local to closure funcs |
|
782 var __sp_camera_start_date; |
|
783 |
|
784 function __sp_camera_instance(){ |
|
785 //__device_debug("sp_camera_instance"); |
|
786 //Descriptor |
|
787 this.descriptor = new __sp_camera_descriptor(); |
|
788 //Core methods |
|
789 this.startCamera = __sp_startCamera; |
|
790 this.stopViewfinder = __s60_api_not_supported; |
|
791 //Extended methods |
|
792 this.takePicture = __s60_api_not_supported; |
|
793 //Private data |
|
794 } |
|
795 |
|
796 var CAMERA_APP_ID = 0x101f857a; |
|
797 |
|
798 //Apps should take care that this is not reinvoked |
|
799 //while the viewfinder is running. |
|
800 |
|
801 function __sp_startCamera(camera_cb){ |
|
802 |
|
803 //If callback is null , then return missing argument error |
|
804 if( camera_cb == null ) |
|
805 throw new DeviceError("Camera:startCamera:callback is missing", err_missing_argument); |
|
806 |
|
807 //If the callback is not a function, then return bad type error |
|
808 if( typeof(camera_cb) != "function" ) |
|
809 throw new DeviceError("Camera:startCamera:callback is a non-function", err_bad_argument); |
|
810 |
|
811 var finished = function (){ |
|
812 var invoker = function (arg1, arg2, arg3){ |
|
813 //__device_debug("invoker with: " + camera_cb); |
|
814 var it = arg3.ReturnValue; |
|
815 var item; |
|
816 var items = new Array(); |
|
817 while (( item = it.getNext()) != undefined){ |
|
818 var d = new Date(Date.parse(item.FileDate)); |
|
819 //__device_debug(item.FileName + " " + d ); |
|
820 // Items returned in reverse date order, so stop iterating before |
|
821 // reaching initial date. (Should be able to do this more efficiently |
|
822 // with sp filter, but that doesn't seem to work right now.) |
|
823 if (d > __sp_camera_start_date) { |
|
824 var pathname = item.FileNameAndPath.replace(/\\/g, "/"); |
|
825 var fileScheme = "file:///"; |
|
826 //Non-patched builds don't allow file scheme TBD: change this for patched builds |
|
827 items.unshift(fileScheme + pathname); |
|
828 } |
|
829 } |
|
830 var dummyTransID = 0; |
|
831 var dummyStatusCode = 0; |
|
832 camera_cb(dummyTransID, dummyStatusCode, items); |
|
833 }; |
|
834 |
|
835 |
|
836 //When camera returns, get the image(s) created |
|
837 try { |
|
838 var mso = device.getServiceObject("Service.MediaManagement", "IDataSource"); |
|
839 } |
|
840 catch(e) { |
|
841 __device_handle_exception (e, "media service not available : " + e); |
|
842 } |
|
843 |
|
844 var criteria = new Object(); |
|
845 modifyObjectBaseProp(criteria); |
|
846 criteria.Type = 'FileInfo'; |
|
847 criteria.Filter = new Object(); |
|
848 modifyObjectBaseProp(criteria.Filter); |
|
849 criteria.Filter.FileType = 'Image'; |
|
850 //criteria.Filter.Key = 'FileDate'; |
|
851 //criteria.Filter.StartRange = null; |
|
852 //criteria.Filter.EndRange = null; |
|
853 criteria.Sort = new Object(); |
|
854 modifyObjectBaseProp(criteria.Sort); |
|
855 criteria.Sort.Key = 'FileDate'; |
|
856 criteria.Sort.Order = 'Descending'; |
|
857 |
|
858 try { |
|
859 var rval = mso.IDataSource.GetList(criteria, invoker); |
|
860 } |
|
861 catch (e) { |
|
862 __device_handle_exception (e, "media service GetList failed: " + e); |
|
863 } |
|
864 }; |
|
865 |
|
866 __sp_camera_start_date = new Date(); |
|
867 __s60_start_and_wait(CAMERA_APP_ID, "", finished); |
|
868 var dummyTid = 0; |
|
869 return dummyTid; |
|
870 } |
|
871 |
|
872 |
|
873 /* |
|
874 Copyright © 2009 Nokia. All rights reserved. |
|
875 Code licensed under the BSD License: |
|
876 Software License Agreement (BSD License) Copyright © 2009 Nokia. |
|
877 All rights reserved. |
|
878 Redistribution and use of this software in source and binary forms, with or without modification, are permitted provided that the following conditions are met: |
|
879 |
|
880 Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. |
|
881 Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. |
|
882 Neither the name of Nokia Corporation. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission of Nokia Corporation. |
|
883 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
884 |
|
885 version: 1.0 |
|
886 */ |
|
887 |
|
888 |
|
889 // Camera service interface |
|
890 |
|
891 var __device_camera_service_entry = {"name": null, |
|
892 "version": null, |
|
893 "proto": __device_camera, |
|
894 "descriptor": __device_camera_descriptor, |
|
895 "providers": [{"descriptor": __sp_camera_descriptor, "instance": __sp_camera_instance}] |
|
896 }; |
|
897 |
|
898 function __device_camera_descriptor(provider){ |
|
899 this.interfaceName = provider.interfaceName; |
|
900 this.version = provider.version; |
|
901 } |
|
902 |
|
903 |
|
904 // Private camera prototype: called from service factory |
|
905 function __device_camera(provider){ |
|
906 //Private properties |
|
907 this.provider = provider; |
|
908 //Read-only properties |
|
909 this.interfaceName = provider.descriptor.interfaceName; |
|
910 this.version = provider.descriptor.version; |
|
911 // this.supportedMediaTypes = provider.supportedMediaTypes; |
|
912 // this.supportedSizes = provider.supportedSizes; |
|
913 //Core methods |
|
914 this.startCamera = __device_camera_startCamera; |
|
915 this.stopViewfinder = __device_camera_stopViewfinder; |
|
916 //Extended methods |
|
917 this.takePicture = __device_camera_takePicture; |
|
918 } |
|
919 |
|
920 |
|
921 //Why bother to define these methods? Because the camera |
|
922 //object defines the contract for providers! |
|
923 |
|
924 function __device_camera_startCamera(camera_cb){ |
|
925 return this.provider.startCamera(camera_cb); |
|
926 } |
|
927 |
|
928 function __device_camera_stopViewfinder(){ |
|
929 this.provider.stopViewfinder(); |
|
930 } |
|
931 |
|
932 function __device_camera_takePicture(format){ |
|
933 this.provider.takePicture(format); |
|
934 } |
|
935 /** |
|
936 * This class provides access to the device contacts. |
|
937 * @constructor |
|
938 */ |
|
939 |
|
940 function Contacts() { |
|
941 |
|
942 } |
|
943 |
|
944 function Contact() { |
|
945 this.id = null; |
|
946 this.name = { |
|
947 formatted: "", |
|
948 givenName: "", |
|
949 familyName: "" |
|
950 }; |
|
951 this.phones = []; |
|
952 this.emails = []; |
|
953 } |
|
954 |
|
955 Contact.prototype.displayName = function() |
|
956 { |
|
957 // TODO: can be tuned according to prefs |
|
958 return this.givenName + " " + this.familyName; |
|
959 }; |
|
960 |
|
961 /* |
|
962 * @param {ContactsFilter} filter Object with filter properties. filter.name only for now. |
|
963 * @param {function} successCallback Callback function on success |
|
964 * @param {function} errorCallback Callback function on failure |
|
965 * @param {object} options Object with properties .page and .limit for paging |
|
966 */ |
|
967 |
|
968 Contacts.prototype.find = function(filter, successCallback, errorCallback, options) { |
|
969 try { |
|
970 |
|
971 this.contactsService = device.getServiceObject("Service.Contact", "IDataSource"); |
|
972 this.options = options; |
|
973 |
|
974 var criteria = new Object(); |
|
975 criteria.Type = "Contact"; |
|
976 if (filter && filter.name) |
|
977 criteria.Filter = { SearchVal: filter.name }; |
|
978 |
|
979 if (typeof(successCallback) != 'function') |
|
980 successCallback = function(){}; |
|
981 if (typeof(errorCallback) != 'function') |
|
982 errorCallback = function(){}; |
|
983 if (typeof options == 'object'){ |
|
984 if (isNaN(this.options.limit)) |
|
985 this.options.limit = 200; |
|
986 if (isNaN(this.options.page)) |
|
987 this.options.page = 1; |
|
988 } |
|
989 |
|
990 //need a closure here to bind this method to this instance of the Contacts object |
|
991 this.global_success = successCallback; |
|
992 var obj = this; |
|
993 |
|
994 //WRT: result.ReturnValue is an iterator of contacts |
|
995 this.contactsService.IDataSource.GetList(criteria, function(transId, eventCode, result){ |
|
996 obj.success_callback(result.ReturnValue); |
|
997 }); |
|
998 } |
|
999 catch (ex) { |
|
1000 errorCallback(ex); |
|
1001 } |
|
1002 }; |
|
1003 |
|
1004 Contacts.prototype.success_callback = function(contacts_iterator) { |
|
1005 var gapContacts = new Array(); |
|
1006 contacts_iterator.reset(); |
|
1007 var contact; |
|
1008 var i = 0; |
|
1009 var end = this.options.page * this.options.limit; |
|
1010 var start = end - this.options.limit; |
|
1011 while ((contact = contacts_iterator.getNext()) != undefined && i < end) { |
|
1012 try { |
|
1013 if (i >= start) { |
|
1014 var gapContact = new Contact(); |
|
1015 gapContact.name.givenName = Contacts.GetValue(contact, "FirstName"); |
|
1016 gapContact.name.familyName = Contacts.GetValue(contact, "LastName"); |
|
1017 gapContact.name.formatted = gapContact.firstName + " " + gapContact.lastName; |
|
1018 gapContact.emails = Contacts.getEmailsList(contact); |
|
1019 gapContact.phones = Contacts.getPhonesList(contact); |
|
1020 gapContact.address = Contacts.getAddress(contact); |
|
1021 gapContact.id = Contacts.GetValue(contact, "id"); |
|
1022 gapContacts.push(gapContact); |
|
1023 } |
|
1024 i++; |
|
1025 } catch (e) { |
|
1026 alert("ContactsError (" + e.name + ": " + e.message + ")"); |
|
1027 } |
|
1028 } |
|
1029 this.contacts = gapContacts; |
|
1030 this.global_success(gapContacts); |
|
1031 }; |
|
1032 |
|
1033 Contacts.getEmailsList = function(contact) { |
|
1034 var emails = new Array(); |
|
1035 try { |
|
1036 emails[0] = { type:"General", address: Contacts.GetValue(contact, "EmailGen") }; |
|
1037 emails[1] = { type:"Work", address: Contacts.GetValue(contact, "EmailWork") }; |
|
1038 emails[2] = { type:"Home", address: Contacts.GetValue(contact, "EmailHome") }; |
|
1039 } catch (e) { |
|
1040 emails = []; |
|
1041 } |
|
1042 return emails; |
|
1043 }; |
|
1044 |
|
1045 Contacts.getPhonesList = function(contact) { |
|
1046 var phones = new Array(); |
|
1047 try { |
|
1048 phones[0] = { type:"Mobile", number: Contacts.GetValue(contact, "MobilePhoneGen") }; |
|
1049 phones[1] = { type:"Home", number: Contacts.GetValue(contact, "LandPhoneGen") }; |
|
1050 phones[2] = { type:"Fax", number: Contacts.GetValue(contact, "FaxNumberGen") }; |
|
1051 phones[3] = { type:"Work", number: Contacts.GetValue(contact, "LandPhoneWork") }; |
|
1052 phones[4] = { type:"WorkMobile", number: Contacts.GetValue(contact, "MobilePhoneWork") }; |
|
1053 } catch (e) { |
|
1054 phones = []; |
|
1055 } |
|
1056 return phones; |
|
1057 }; |
|
1058 |
|
1059 Contacts.getAddress = function(contact) { |
|
1060 var address = ""; |
|
1061 try { |
|
1062 address = Contacts.GetValue(contact, "AddrLabelHome") + ", " + Contacts.GetValue(contact, "AddrStreetHome") + ", " + |
|
1063 Contacts.GetValue(contact, "AddrLocalHome") + ", " + Contacts.GetValue(contact, "AddrRegionHome") + ", " + |
|
1064 Contacts.GetValue(contact, "AddrPostCodeHome") + ", " + Contacts.GetValue(contact, "AddrCountryHome"); |
|
1065 } catch (e) { |
|
1066 address = ""; |
|
1067 } |
|
1068 return address; |
|
1069 }; |
|
1070 |
|
1071 Contacts.GetValue = function(contactObj, key) { |
|
1072 try { |
|
1073 return contactObj[key]["Value"]; |
|
1074 } catch (e) { |
|
1075 return ""; |
|
1076 } |
|
1077 }; |
|
1078 |
|
1079 if (typeof navigator.contacts == "undefined") navigator.contacts = new Contacts(); |
|
1080 PhoneGap.ExtendWrtDeviceObj = function(){ |
|
1081 |
|
1082 if (!window.device) |
|
1083 window.device = {}; |
|
1084 navigator.device = window.device; |
|
1085 |
|
1086 try { |
|
1087 |
|
1088 if (window.menu) |
|
1089 window.menu.hideSoftkeys(); |
|
1090 |
|
1091 device.available = PhoneGap.available; |
|
1092 device.platform = null; |
|
1093 device.version = null; |
|
1094 device.name = null; |
|
1095 device.uuid = null; |
|
1096 |
|
1097 var so = device.getServiceObject("Service.SysInfo", "ISysInfo"); |
|
1098 var pf = PhoneGap.GetWrtPlatformVersion(so); |
|
1099 device.platform = pf.platform; |
|
1100 device.version = pf.version; |
|
1101 device.uuid = PhoneGap.GetWrtDeviceProperty(so, "IMEI"); |
|
1102 device.name = PhoneGap.GetWrtDeviceProperty(so, "PhoneModel"); |
|
1103 } |
|
1104 catch (e) { |
|
1105 device.available = false; |
|
1106 } |
|
1107 }; |
|
1108 |
|
1109 PhoneGap.GetWrtDeviceProperty = function(serviceObj, key) { |
|
1110 var criteria = { "Entity": "Device", "Key": key }; |
|
1111 var result = serviceObj.ISysInfo.GetInfo(criteria); |
|
1112 if (result.ErrorCode == 0) { |
|
1113 return result.ReturnValue.StringData; |
|
1114 } |
|
1115 else { |
|
1116 return null; |
|
1117 } |
|
1118 }; |
|
1119 |
|
1120 PhoneGap.GetWrtPlatformVersion = function(serviceObj) { |
|
1121 var criteria = { "Entity": "Device", "Key": "PlatformVersion" }; |
|
1122 var result = serviceObj.ISysInfo.GetInfo(criteria); |
|
1123 if (result.ErrorCode == 0) { |
|
1124 var version = {}; |
|
1125 version.platform = result.ReturnValue.MajorVersion; |
|
1126 version.version = result.ReturnValue.MinorVersion; |
|
1127 return version; |
|
1128 } |
|
1129 else { |
|
1130 return null; |
|
1131 } |
|
1132 }; |
|
1133 |
|
1134 PhoneGap.ExtendWrtDeviceObj();/** |
|
1135 * This class provides access to device GPS data. |
|
1136 * @constructor |
|
1137 */ |
|
1138 function Geolocation() { |
|
1139 /** |
|
1140 * The last known GPS position. |
|
1141 */ |
|
1142 this.lastPosition = null; |
|
1143 this.lastError = null; |
|
1144 this.callbacks = { |
|
1145 onLocationChanged: [], |
|
1146 onError: [] |
|
1147 }; |
|
1148 }; |
|
1149 |
|
1150 /** |
|
1151 * Asynchronously aquires the current position. |
|
1152 * @param {Function} successCallback The function to call when the position |
|
1153 * data is available |
|
1154 * @param {Function} errorCallback The function to call when there is an error |
|
1155 * getting the position data. |
|
1156 * @param {PositionOptions} options The options for getting the position data |
|
1157 * such as timeout. |
|
1158 */ |
|
1159 Geolocation.prototype.getCurrentPosition = function(successCallback, errorCallback, options) { |
|
1160 var referenceTime = 0; |
|
1161 if (this.lastPosition) |
|
1162 referenceTime = this.lastPosition.timestamp; |
|
1163 else |
|
1164 this.start(options); |
|
1165 |
|
1166 var timeout = 20000; |
|
1167 var interval = 500; |
|
1168 if (typeof(options) == 'object' && options.interval) |
|
1169 interval = options.interval; |
|
1170 |
|
1171 if (typeof(successCallback) != 'function') |
|
1172 successCallback = function() {}; |
|
1173 if (typeof(errorCallback) != 'function') |
|
1174 errorCallback = function() {}; |
|
1175 |
|
1176 var dis = this; |
|
1177 var delay = 0; |
|
1178 var timer = setInterval(function() { |
|
1179 delay += interval; |
|
1180 //if we have a new position, call success and cancel the timer |
|
1181 if (dis.lastPosition && dis.lastPosition.timestamp > referenceTime) { |
|
1182 successCallback(dis.lastPosition); |
|
1183 clearInterval(timer); |
|
1184 } else if (delay >= timeout) { //else if timeout has occured then call error and cancel the timer |
|
1185 errorCallback(); |
|
1186 clearInterval(timer); |
|
1187 } |
|
1188 //else the interval gets called again |
|
1189 }, interval); |
|
1190 }; |
|
1191 |
|
1192 /** |
|
1193 * Asynchronously aquires the position repeatedly at a given interval. |
|
1194 * @param {Function} successCallback The function to call each time the position |
|
1195 * data is available |
|
1196 * @param {Function} errorCallback The function to call when there is an error |
|
1197 * getting the position data. |
|
1198 * @param {PositionOptions} options The options for getting the position data |
|
1199 * such as timeout and the frequency of the watch. |
|
1200 */ |
|
1201 Geolocation.prototype.watchPosition = function(successCallback, errorCallback, options) { |
|
1202 // Invoke the appropriate callback with a new Position object every time the implementation |
|
1203 // determines that the position of the hosting device has changed. |
|
1204 this.getCurrentPosition(successCallback, errorCallback, options); |
|
1205 var frequency = 10000; |
|
1206 if (typeof options == 'object' && options.frequency) |
|
1207 frequency = options.frequency; |
|
1208 var that = this; |
|
1209 return setInterval(function() { |
|
1210 that.getCurrentPosition(successCallback, errorCallback, options); |
|
1211 }, frequency); |
|
1212 }; |
|
1213 |
|
1214 |
|
1215 /** |
|
1216 * Clears the specified position watch. |
|
1217 * @param {String} watchId The ID of the watch returned from #watchPosition. |
|
1218 */ |
|
1219 Geolocation.prototype.clearWatch = function(watchId) { |
|
1220 clearInterval(watchId); |
|
1221 }; |
|
1222 |
|
1223 Geolocation.prototype.start = function(options) { |
|
1224 var so = device.getServiceObject("Service.Location", "ILocation"); |
|
1225 |
|
1226 //construct the criteria for our location request |
|
1227 var updateOptions = new Object(); |
|
1228 // Specify that location information need not be guaranteed. This helps in |
|
1229 // that the widget doesn't need to wait for that information possibly indefinitely. |
|
1230 updateOptions.PartialUpdates = true; |
|
1231 |
|
1232 //default 15 seconds |
|
1233 if (typeof(options) == 'object' && options.timeout) |
|
1234 //options.timeout in in ms, updateOptions.UpdateTimeout in microsecs |
|
1235 updateOptions.UpdateTimeOut = options.timeout * 1000; |
|
1236 |
|
1237 //default 1 second |
|
1238 if (typeof(options) == 'object' && options.interval) |
|
1239 //options.timeout in in ms, updateOptions.UpdateTimeout in microsecs |
|
1240 updateOptions.UpdateInterval = options.interval * 1000; |
|
1241 |
|
1242 // Initialize the criteria for the GetLocation call |
|
1243 var trackCriteria = new Object(); |
|
1244 // could use "BasicLocationInformation" or "GenericLocationInfo" |
|
1245 trackCriteria.LocationInformationClass = "GenericLocationInfo"; |
|
1246 trackCriteria.Updateoptions = updateOptions; |
|
1247 |
|
1248 var dis = this; |
|
1249 so.ILocation.Trace(trackCriteria, function(transId, eventCode, result) { |
|
1250 var retVal = result.ReturnValue; |
|
1251 |
|
1252 if (result.ErrorCode != 0 || isNaN(retVal.Latitude)) |
|
1253 return; |
|
1254 |
|
1255 // heading options: retVal.TrueCourse, retVal.MagneticHeading, retVal.Heading, retVal.MagneticCourse |
|
1256 // but retVal.Heading was the only field being returned with data on the test device (Nokia 5800) |
|
1257 // WRT does not provide accuracy |
|
1258 var newCoords = new Coordinates(retVal.Latitude, retVal.Longitude, retVal.Altitude, null, retVal.Heading, retVal.HorizontalSpeed); |
|
1259 var positionObj = { coords: newCoords, timestamp: (new Date()).getTime() }; |
|
1260 |
|
1261 dis.lastPosition = positionObj; |
|
1262 }); |
|
1263 |
|
1264 }; |
|
1265 |
|
1266 |
|
1267 if (typeof navigator.geolocation == "undefined") navigator.geolocation = new Geolocation(); |
|
1268 |
|
1269 /** |
|
1270 * This class provides access to the device media, interfaces to both sound and video |
|
1271 * @constructor |
|
1272 */ |
|
1273 function Media(src, successCallback, errorCallback) { |
|
1274 this.src = src; |
|
1275 this.successCallback = successCallback; |
|
1276 this.errorCallback = errorCallback; |
|
1277 } |
|
1278 |
|
1279 Media.prototype.record = function() { |
|
1280 }; |
|
1281 |
|
1282 Media.prototype.play = function(src) { |
|
1283 |
|
1284 if (document.getElementById('gapsound')) |
|
1285 document.body.removeChild(document.getElementById('gapsound')); |
|
1286 var obj; |
|
1287 obj = document.createElement("embed"); |
|
1288 obj.setAttribute("id", "gapsound"); |
|
1289 obj.setAttribute("type", "audio/x-mpeg"); |
|
1290 obj.setAttribute("width", "0"); |
|
1291 obj.setAttribute("width", "0"); |
|
1292 obj.setAttribute("hidden", "true"); |
|
1293 obj.setAttribute("autostart", "true"); |
|
1294 obj.setAttribute("src", src); |
|
1295 document.body.appendChild(obj); |
|
1296 }; |
|
1297 |
|
1298 Media.prototype.pause = function() { |
|
1299 }; |
|
1300 |
|
1301 Media.prototype.stop = function() { |
|
1302 }; |
|
1303 |
|
1304 if (typeof navigator.media == "undefined") navigator.media = new Media(); |
|
1305 /** |
|
1306 * This class provides access to notifications on the device. |
|
1307 */ |
|
1308 function Notification() { |
|
1309 |
|
1310 } |
|
1311 |
|
1312 Notification.prototype.vibrate = function(mills) |
|
1313 { |
|
1314 |
|
1315 if (!Notification.getSysinfoObject()) |
|
1316 Notification.embedSysinfoObject(); |
|
1317 |
|
1318 this.sysinfo = Notification.getSysinfoObject(); |
|
1319 this.sysinfo.startvibra(mills, 100); |
|
1320 }; |
|
1321 |
|
1322 //TODO: this is not beeping |
|
1323 Notification.prototype.beep = function(count, volume) |
|
1324 { |
|
1325 if (!Notification.getSysinfoObject()) |
|
1326 Notification.embedSysinfoObject(); |
|
1327 |
|
1328 this.sysinfo = Notification.getSysinfoObject(); |
|
1329 this.sysinfo.beep(220,2000); |
|
1330 }; |
|
1331 |
|
1332 |
|
1333 /** |
|
1334 * Open a native alert dialog, with a customizable title and button text. |
|
1335 * @param {String} message Message to print in the body of the alert |
|
1336 * @param {String} [title="Alert"] Title of the alert dialog (default: Alert) |
|
1337 * @param {String} [buttonLabel="OK"] Label of the close button (default: OK) |
|
1338 */ |
|
1339 Notification.prototype.alert = function(message, title, buttonLabel) { |
|
1340 // Default is to use a browser alert; this will use "index.html" as the title though |
|
1341 alert(message); |
|
1342 }; |
|
1343 |
|
1344 /** |
|
1345 * Start spinning the activity indicator on the statusbar |
|
1346 */ |
|
1347 Notification.prototype.activityStart = function() { |
|
1348 }; |
|
1349 |
|
1350 /** |
|
1351 * Stop spinning the activity indicator on the statusbar, if it's currently spinning |
|
1352 */ |
|
1353 Notification.prototype.activityStop = function() { |
|
1354 }; |
|
1355 |
|
1356 /** |
|
1357 * Causes the device to blink a status LED. |
|
1358 * @param {Integer} count The number of blinks. |
|
1359 * @param {String} colour The colour of the light. |
|
1360 */ |
|
1361 Notification.prototype.blink = function(count, colour) { |
|
1362 |
|
1363 }; |
|
1364 |
|
1365 Notification.embedSysinfoObject = function() { |
|
1366 var el = document.createElement("embed"); |
|
1367 el.setAttribute("type", "application/x-systeminfo-widget"); |
|
1368 el.setAttribute("hidden", "yes"); |
|
1369 document.getElementsByTagName("body")[0].appendChild(el); |
|
1370 return; |
|
1371 }; |
|
1372 |
|
1373 Notification.getSysinfoObject = function() { |
|
1374 return document.embeds[0]; |
|
1375 }; |
|
1376 |
|
1377 if (typeof navigator.notification == "undefined") navigator.notification = new Notification(); |
|
1378 /** |
|
1379 * This class provides access to the device orientation. |
|
1380 * @constructor |
|
1381 */ |
|
1382 function Orientation() { |
|
1383 /** |
|
1384 * The current orientation, or null if the orientation hasn't changed yet. |
|
1385 */ |
|
1386 this.currentOrientation = null; |
|
1387 } |
|
1388 |
|
1389 /** |
|
1390 * Set the current orientation of the phone. This is called from the device automatically. |
|
1391 * |
|
1392 * When the orientation is changed, the DOMEvent \c orientationChanged is dispatched against |
|
1393 * the document element. The event has the property \c orientation which can be used to retrieve |
|
1394 * the device's current orientation, in addition to the \c Orientation.currentOrientation class property. |
|
1395 * |
|
1396 * @param {Number} orientation The orientation to be set |
|
1397 */ |
|
1398 Orientation.prototype.setOrientation = function(orientation) { |
|
1399 if (orientation == this.currentOrientation) |
|
1400 return; |
|
1401 var old = this.currentOrientation; |
|
1402 |
|
1403 this.currentOrientation = orientation; |
|
1404 var e = document.createEvent('Events'); |
|
1405 e.initEvent('orientationChanged', 'false', 'false'); |
|
1406 e.orientation = orientation; |
|
1407 e.oldOrientation = old; |
|
1408 document.dispatchEvent(e); |
|
1409 }; |
|
1410 |
|
1411 /** |
|
1412 * Asynchronously aquires the current orientation. |
|
1413 * @param {Function} successCallback The function to call when the orientation |
|
1414 * is known. |
|
1415 * @param {Function} errorCallback The function to call when there is an error |
|
1416 * getting the orientation. |
|
1417 */ |
|
1418 Orientation.prototype.getCurrentOrientation = function(successCallback, errorCallback) { |
|
1419 // If the orientation is available then call success |
|
1420 // If the orientation is not available then call error |
|
1421 try { |
|
1422 if (!this.serviceObj) |
|
1423 this.serviceObj = this.getServiceObj(); |
|
1424 |
|
1425 if (this.serviceObj == null) |
|
1426 errorCallback({ |
|
1427 name: "DeviceErr", |
|
1428 message: "Could not initialize service object" |
|
1429 }); |
|
1430 |
|
1431 //get the sensor channel |
|
1432 var SensorParams = { |
|
1433 SearchCriterion: "Orientation" |
|
1434 }; |
|
1435 var returnvalue = this.serviceObj.ISensor.FindSensorChannel(SensorParams); |
|
1436 |
|
1437 var error = returnvalue["ErrorCode"]; |
|
1438 var errmsg = returnvalue["ErrorMessage"]; |
|
1439 if (!(error == 0 || error == 1012)) { |
|
1440 var ex = { |
|
1441 name: "Unable to find Sensor Channel: " + error, |
|
1442 message: errmsg |
|
1443 }; |
|
1444 errorCallback(ex); |
|
1445 } |
|
1446 var channelInfoMap = returnvalue["ReturnValue"][0]; |
|
1447 var criteria = { |
|
1448 ChannelInfoMap: channelInfoMap, |
|
1449 ListeningType: "ChannelData" |
|
1450 }; |
|
1451 |
|
1452 if (typeof(successCallback) != 'function') |
|
1453 successCallback = function(){ |
|
1454 }; |
|
1455 if (typeof(errorCallback) != 'function') |
|
1456 errorCallback = function(){ |
|
1457 }; |
|
1458 |
|
1459 this.success_callback = successCallback; |
|
1460 this.error_callback = errorCallback; |
|
1461 |
|
1462 //create a closure to persist this instance of orientation object into the RegisterForNofication callback |
|
1463 var obj = this; |
|
1464 |
|
1465 this.serviceObj.ISensor.RegisterForNotification(criteria, function(transId, eventCode, result){ |
|
1466 alert(1); |
|
1467 var criteria = { |
|
1468 TransactionID: transId |
|
1469 }; |
|
1470 try { |
|
1471 var orientation = result.ReturnValue.DeviceOrientation; |
|
1472 obj.serviceObj.ISensor.Cancel(criteria); |
|
1473 |
|
1474 obj.setOrientation(orientation); |
|
1475 |
|
1476 obj.success_callback(orientation); |
|
1477 |
|
1478 } |
|
1479 catch (ex) { |
|
1480 obj.serviceObj.ISensor.Cancel(criteria); |
|
1481 obj.error_callback(ex); |
|
1482 } |
|
1483 |
|
1484 }); |
|
1485 } catch (ex) { |
|
1486 errorCallback({ name: "OrientationError", message: ex.name + ": " + ex.message }); |
|
1487 } |
|
1488 }; |
|
1489 |
|
1490 /** |
|
1491 * Asynchronously aquires the orientation repeatedly at a given interval. |
|
1492 * @param {Function} successCallback The function to call each time the orientation |
|
1493 * data is available. |
|
1494 * @param {Function} errorCallback The function to call when there is an error |
|
1495 * getting the orientation data. |
|
1496 */ |
|
1497 Orientation.prototype.watchOrientation = function(successCallback, errorCallback, options) { |
|
1498 // Invoke the appropriate callback with a new Position object every time the implementation |
|
1499 // determines that the position of the hosting device has changed. |
|
1500 this.getCurrentOrientation(successCallback, errorCallback); |
|
1501 var frequency = (options != undefined)? options.frequency : 1000; |
|
1502 return setInterval(function() { |
|
1503 navigator.orientation.getCurrentOrientation(successCallback, errorCallback); |
|
1504 }, frequency); |
|
1505 }; |
|
1506 |
|
1507 /** |
|
1508 * Clears the specified orientation watch. |
|
1509 * @param {String} watchId The ID of the watch returned from #watchOrientation. |
|
1510 */ |
|
1511 Orientation.prototype.clearWatch = function(watchId) { |
|
1512 clearInterval(watchId); |
|
1513 }; |
|
1514 |
|
1515 //gets the Acceleration Service Object from WRT |
|
1516 Orientation.prototype.getServiceObj = function() { |
|
1517 var so; |
|
1518 |
|
1519 try { |
|
1520 so = device.getServiceObject("Service.Sensor", "ISensor"); |
|
1521 } catch (ex) { |
|
1522 throw { |
|
1523 name: "DeviceError", |
|
1524 message: ex.name + ": " + ex.message |
|
1525 }; |
|
1526 } |
|
1527 return so; |
|
1528 }; |
|
1529 |
|
1530 if (typeof navigator.orientation == "undefined") navigator.orientation = new Orientation(); |
|
1531 /** |
|
1532 * This class contains position information. |
|
1533 * @param {Object} lat |
|
1534 * @param {Object} lng |
|
1535 * @param {Object} acc |
|
1536 * @param {Object} alt |
|
1537 * @param {Object} altacc |
|
1538 * @param {Object} head |
|
1539 * @param {Object} vel |
|
1540 * @constructor |
|
1541 */ |
|
1542 function Position(coords, timestamp) { |
|
1543 this.coords = coords; |
|
1544 this.timestamp = new Date().getTime(); |
|
1545 } |
|
1546 |
|
1547 function Coordinates(lat, lng, alt, acc, head, vel) { |
|
1548 /** |
|
1549 * The latitude of the position. |
|
1550 */ |
|
1551 this.latitude = lat; |
|
1552 /** |
|
1553 * The longitude of the position, |
|
1554 */ |
|
1555 this.longitude = lng; |
|
1556 /** |
|
1557 * The accuracy of the position. |
|
1558 */ |
|
1559 this.accuracy = acc; |
|
1560 /** |
|
1561 * The altitude of the position. |
|
1562 */ |
|
1563 this.altitude = alt; |
|
1564 /** |
|
1565 * The direction the device is moving at the position. |
|
1566 */ |
|
1567 this.heading = head; |
|
1568 /** |
|
1569 * The velocity with which the device is moving at the position. |
|
1570 */ |
|
1571 this.speed = vel; |
|
1572 } |
|
1573 |
|
1574 /** |
|
1575 * This class specifies the options for requesting position data. |
|
1576 * @constructor |
|
1577 */ |
|
1578 function PositionOptions() { |
|
1579 /** |
|
1580 * Specifies the desired position accuracy. |
|
1581 */ |
|
1582 this.enableHighAccuracy = true; |
|
1583 /** |
|
1584 * The timeout after which if position data cannot be obtained the errorCallback |
|
1585 * is called. |
|
1586 */ |
|
1587 this.timeout = 10000; |
|
1588 } |
|
1589 |
|
1590 /** |
|
1591 * This class contains information about any GSP errors. |
|
1592 * @constructor |
|
1593 */ |
|
1594 function PositionError() { |
|
1595 this.code = null; |
|
1596 this.message = ""; |
|
1597 } |
|
1598 |
|
1599 PositionError.UNKNOWN_ERROR = 0; |
|
1600 PositionError.PERMISSION_DENIED = 1; |
|
1601 PositionError.POSITION_UNAVAILABLE = 2; |
|
1602 PositionError.TIMEOUT = 3; |
|
1603 /** |
|
1604 * This class provides access to the device SMS functionality. |
|
1605 * @constructor |
|
1606 */ |
|
1607 function Sms() { |
|
1608 |
|
1609 } |
|
1610 |
|
1611 /** |
|
1612 * Sends an SMS message. |
|
1613 * @param {Integer} number The phone number to send the message to. |
|
1614 * @param {String} message The contents of the SMS message to send. |
|
1615 * @param {Function} successCallback The function to call when the SMS message is sent. |
|
1616 * @param {Function} errorCallback The function to call when there is an error sending the SMS message. |
|
1617 * @param {PositionOptions} options The options for accessing the GPS location such as timeout and accuracy. |
|
1618 */ |
|
1619 Sms.prototype.send = function(number, message, successCallback, errorCallback, options) { |
|
1620 try { |
|
1621 if (!this.serviceObj) |
|
1622 this.serviceObj = this.getServiceObj(); |
|
1623 |
|
1624 // Setup input params using dot syntax |
|
1625 var criteria = new Object(); |
|
1626 criteria.MessageType = 'SMS'; |
|
1627 criteria.To = number; |
|
1628 criteria.BodyText = message; |
|
1629 |
|
1630 var result = this.serviceObj.IMessaging.Send(criteria); |
|
1631 if (result.ErrorCode != 0 && result.ErrorCode != "0") |
|
1632 { |
|
1633 var exception = { name: "SMSError", message: result.ErrorMessage }; |
|
1634 throw exception; |
|
1635 } else { |
|
1636 successCallback.call(); |
|
1637 } |
|
1638 } |
|
1639 catch(ex) |
|
1640 { |
|
1641 errorCallback.call({ name: "SmsError", message: ex.name + ": " + ex.message }); |
|
1642 } |
|
1643 |
|
1644 }; |
|
1645 |
|
1646 |
|
1647 //gets the Sms Service Object from WRT |
|
1648 Sms.prototype.getServiceObj = function() { |
|
1649 var so; |
|
1650 |
|
1651 try { |
|
1652 so = device.getServiceObject("Service.Messaging", "IMessaging"); |
|
1653 } catch (ex) { |
|
1654 throw { |
|
1655 name: "SmsError", |
|
1656 message: "Failed to load sms service (" + ex.name + ": " + ex.message + ")" |
|
1657 }; |
|
1658 } |
|
1659 return so; |
|
1660 }; |
|
1661 |
|
1662 if (typeof navigator.sms == "undefined") navigator.sms = new Sms();/** |
|
1663 * @author ryan |
|
1664 */ |
|
1665 |
|
1666 function Storage() { |
|
1667 this.length = null; |
|
1668 this.available = true; |
|
1669 this.serialized = null; |
|
1670 this.items = null; |
|
1671 |
|
1672 if (!window.widget) { |
|
1673 this.available = false; |
|
1674 return; |
|
1675 } |
|
1676 var pref = window.widget.preferenceForKey(Storage.PREFERENCE_KEY); |
|
1677 |
|
1678 //storage not yet created |
|
1679 if (pref == "undefined" || pref == undefined) { |
|
1680 this.length = 0; |
|
1681 this.serialized = "({})"; |
|
1682 this.items = {}; |
|
1683 window.widget.setPreferenceForKey(this.serialized, Storage.PREFERENCE_KEY); |
|
1684 } else { |
|
1685 this.serialized = pref;'({"store_test": { "key": "store_test", "data": "asdfasdfs" },})'; |
|
1686 |
|
1687 this.items = eval(this.serialized); |
|
1688 |
|
1689 } |
|
1690 } |
|
1691 |
|
1692 Storage.PREFERENCE_KEY = "phonegap_storage_pref_key"; |
|
1693 |
|
1694 Storage.prototype.index = function (key) { |
|
1695 |
|
1696 }; |
|
1697 |
|
1698 Storage.prototype.getItem = function (key) { |
|
1699 try { |
|
1700 return this.items[key].data; |
|
1701 } catch (ex) { |
|
1702 return null; |
|
1703 } |
|
1704 }; |
|
1705 |
|
1706 Storage.prototype.setItem = function (key, data) { |
|
1707 |
|
1708 if (!this.items[key]) |
|
1709 this.length++; |
|
1710 this.items[key] = { |
|
1711 "key": key, |
|
1712 "data": data |
|
1713 }; |
|
1714 |
|
1715 this.serialize(); |
|
1716 }; |
|
1717 |
|
1718 Storage.prototype.removeItem = function (key) { |
|
1719 if (this.items[key]) { |
|
1720 this.items[key] = undefined; |
|
1721 this.length--; |
|
1722 } |
|
1723 this.serialize(); |
|
1724 }; |
|
1725 |
|
1726 Storage.prototype.clear = function () { |
|
1727 this.length = 0; |
|
1728 this.serialized = "({})"; |
|
1729 this.items = {}; |
|
1730 }; |
|
1731 |
|
1732 Storage.prototype.serialize = function() { |
|
1733 var json = ""; |
|
1734 |
|
1735 for (key in this.items) { |
|
1736 var item = this.items[key]; |
|
1737 json += "\"" + item.key + "\": { \"key\": \"" + item.key + "\", \"data\": \"" + item.data + "\" }, "; |
|
1738 } |
|
1739 |
|
1740 window.widget.setPreferenceForKey( "({" + json + "})", Storage.PREFERENCE_KEY); |
|
1741 }; |
|
1742 |
|
1743 if (typeof navigator.storage == "undefined" ) navigator.storage = new Storage(); |