[CB-465] First pass at accel update. Watch acceleration doesnt seem to work yet though
Project: http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/commit/3255ae8b Tree: http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/tree/3255ae8b Diff: http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/diff/3255ae8b Branch: refs/heads/master Commit: 3255ae8b11d1c53c271e094ed39c9cf81145ca07 Parents: b47ab02 Author: Fil Maj <maj....@gmail.com> Authored: Wed May 16 10:30:39 2012 -0700 Committer: Fil Maj <maj....@gmail.com> Committed: Wed May 16 10:30:39 2012 -0700 ---------------------------------------------------------------------- .../cordova/accelerometer/Accelerometer.java | 240 ++++--- javascript/cordova.blackberry.js | 535 ++++++++++----- 2 files changed, 511 insertions(+), 264 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/blob/3255ae8b/framework/ext/src/org/apache/cordova/accelerometer/Accelerometer.java ---------------------------------------------------------------------- diff --git a/framework/ext/src/org/apache/cordova/accelerometer/Accelerometer.java b/framework/ext/src/org/apache/cordova/accelerometer/Accelerometer.java index a299ff7..18de371 100644 --- a/framework/ext/src/org/apache/cordova/accelerometer/Accelerometer.java +++ b/framework/ext/src/org/apache/cordova/accelerometer/Accelerometer.java @@ -30,14 +30,18 @@ import net.rim.device.api.system.AccelerometerListener; import net.rim.device.api.system.AccelerometerSensor; import net.rim.device.api.system.Application; +import java.util.Enumeration; +import java.util.Vector; +import java.util.Hashtable; + public class Accelerometer extends Plugin implements AccelerometerListener { private static final String ACTION_GET_ACCELERATION = "getAcceleration"; - private static final String ACTION_SET_TIMEOUT = "setTimeout"; - private static final String ACTION_GET_TIMEOUT = "getTimeout"; - private static final String ACTION_STOP = "stop"; + private static final String ACTION_ADD_WATCH = "addWatch"; + private static final String ACTION_CLEAR_WATCH = "clearWatch"; private static final int STOPPED = 0; + private static final int STARTING = 1; private static final int RUNNING = 2; private static final int ERROR_FAILED_TO_START = 3; @@ -50,56 +54,56 @@ public class Accelerometer extends Plugin implements AccelerometerListener { private static AccelerometerSensor.Channel _rawDataChannel = null; private int status = STOPPED; // status of this listener - private float timeout = 30000; // timeout in msec to close sensor channel - private long lastAccessTime; // last time accel data was retrieved - public PluginResult execute(String action, JSONArray args, String calbackId) { + private Hashtable watches = new Hashtable(); + private Vector callbacks = new Vector(); + + private short x, y, z; + private long timestamp; + + public PluginResult execute(String action, JSONArray args, String callbackId) { PluginResult result = null; - if (!AccelerometerSensor.isSupported()) { - result = new PluginResult( + try { + if (!AccelerometerSensor.isSupported()) { + result = new PluginResult( PluginResult.Status.ILLEGAL_ACCESS_EXCEPTION, "Accelerometer sensor not supported"); - } else if (ACTION_GET_ACCELERATION.equals(action)) { - AccelerometerData accelData = getCurrentAcceleration(); - if (accelData == null) { - return new PluginResult(PluginResult.Status.IO_EXCEPTION, - ERROR_FAILED_TO_START); - } - - JSONObject accel = new JSONObject(); - try { - accel.put("x", normalize(accelData.getLastXAcceleration())); - accel.put("y", normalize(accelData.getLastYAcceleration())); - accel.put("z", normalize(accelData.getLastZAcceleration())); - accel.put("timestamp", accelData.getLastTimestamp()); - } catch (JSONException e) { - return new PluginResult(PluginResult.Status.JSON_EXCEPTION, - "JSONException:" + e.getMessage()); + } else if (ACTION_GET_ACCELERATION.equals(action)) { + if (this.status != RUNNING) { + result = new PluginResult(PluginResult.Status.NO_RESULT); + result.setKeepCallback(true); + this.callbacks.addElement(callbackId); + this.start(); + } else { + result = new PluginResult( + PluginResult.Status.OK, + this.getAccelerationJSON()); + } + } else if (ACTION_ADD_WATCH.equals(action)) { + String watchId = args.getString(0); + this.watches.put(watchId, callbackId); + if (this.status != RUNNING) { + this.start(); + } + result = new PluginResult(PluginResult.Status.NO_RESULT); + result.setKeepCallback(true); + } else if (ACTION_CLEAR_WATCH.equals(action)) { + String watchId = args.getString(0); + if (this.watches.containsKey(watchId)) { + this.watches.remove(watchId); + if (this.size() == 0) { + this.stop(); + } + } + result = new PluginResult(PluginResult.Status.OK); + } else { + result = new PluginResult(PluginResult.Status.INVALID_ACTION, + "Accelerometer: Invalid action:" + action); } - result = new PluginResult(PluginResult.Status.OK, accel); - } else if (ACTION_GET_TIMEOUT.equals(action)) { - float f = getTimeout(); - return new PluginResult(PluginResult.Status.OK, Float.toString(f)); - } else if (ACTION_SET_TIMEOUT.equals(action)) { - try { - float t = Float.parseFloat(args.getString(0)); - setTimeout(t); - return new PluginResult(PluginResult.Status.OK, status); - } catch (NumberFormatException e) { - return new PluginResult(PluginResult.Status.ERROR, - e.getMessage()); - } catch (JSONException e) { - return new PluginResult(PluginResult.Status.JSON_EXCEPTION, - e.getMessage()); - } - } else if (ACTION_STOP.equals(action)) { - stop(); - return new PluginResult(PluginResult.Status.OK, STOPPED); - } else { - result = new PluginResult(PluginResult.Status.INVALID_ACTION, - "Accelerometer: Invalid action:" + action); + } catch(JSONException e) { + result = new PluginResult(PluginResult.Status.JSON_EXCEPTION); } return result; @@ -114,26 +118,14 @@ public class Accelerometer extends Plugin implements AccelerometerListener { * @return T=returns value */ public boolean isSynch(String action) { - return true; - } - - /** - * Set the timeout to turn off accelerometer sensor. - * - * @param timeout - * Timeout in msec. - */ - private void setTimeout(float timeout) { - this.timeout = timeout; - } - - /** - * Get the timeout to turn off accelerometer sensor. - * - * @return timeout in msec - */ - private float getTimeout() { - return timeout; + if (action.equals("getAcceleration") && this.status == RUNNING) { + return true; + } else if (action.equals("addWatch") && this.status == RUNNING) { + return true; + } else if (action.equals("clearWatch")) { + return true; + } + return false; } /** @@ -153,48 +145,34 @@ public class Accelerometer extends Plugin implements AccelerometerListener { } /** - * Returns last acceleration data from the accelerometer sensor. + * Implements the AccelerometerListener method. * - * @return AccelerometerData with last acceleration data */ - private AccelerometerData getCurrentAcceleration() { - AccelerometerData accelData; - - if (status != RUNNING) { - accelData = start(); - } - else { - // get the last acceleration - accelData = getChannel().getAccelerometerData(); - } - // remember the access time (for timeout purposes) - lastAccessTime = System.currentTimeMillis(); + public void onData(AccelerometerData accelData) { + if (this.status == STOPPED) return; - return accelData; - } + this.timestamp = accelData.getLastTimestamp(); + this.x = accelData.getLastXAcceleration(); + this.y = accelData.getLastYAcceleration(); + this.z = accelData.getLastZAcceleration(); - /** - * Implements the AccelerometerListener method. We listen for the purpose of - * closing the application's accelerometer sensor channel after timeout has - * been exceeded. - */ - public void onData(AccelerometerData accelData) { - // time that accel event was received - long timestamp = accelData.getLastTimestamp(); + this.win(); - // If values haven't been read for length of timeout, - // turn off accelerometer sensor to save power - if ((timestamp - lastAccessTime) > timeout) { - Logger.log("stopping due to timeout, status = " + status); - stop(); + if (this.size() == 0) { + this.stop(); } } /** * Adds this listener to sensor channel. */ - private AccelerometerData start() { + private void start() { + // If already started or starting, return. + if (this.status == RUNNING || this.status == STARTING) return; + + this.status = STARTING; + // open the sensor channel and register listener getChannel().setAccelerometerListener(this); Logger.log(this.getClass().getName() + ": sensor listener added"); @@ -224,12 +202,12 @@ public class Accelerometer extends Plugin implements AccelerometerListener { // Sensor failed to start. if (waittime == 0) { stop(); - return null; + this.status = ERROR_FAILED_TO_START; + this.fail(this.status, "Accelerometer could not be started."); + return; } - status = RUNNING; - - return accelData; + this.status = RUNNING; } /** @@ -242,7 +220,51 @@ public class Accelerometer extends Plugin implements AccelerometerListener { Logger.log(this.getClass().getName() + ": sensor channel closed"); } - status = STOPPED; + this.status = STOPPED; + } + + private void fail(int code, String message) { + // Error object + JSONObject errorObj = new JSONObject(); + try { + errorObj.put("code", code); + errorObj.put("message", message); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + PluginResult err = new PluginResult(PluginResult.Status.ERROR, errorObj); + + for (Enumeration e = this.callbacks.elements(); e.hasMoreElements();) + { + this.error(err, (String)e.nextElement()); + } + this.callbacks.removeAllElements(); + + err.setKeepCallback(true); + + for (Enumeration e = this.watches.keys(); e.hasMoreElements();) + { + this.error(err, (String)this.watches.get((String)e.nextElement())); + } + } + + private void win() { + // Success return object + PluginResult result = new PluginResult(PluginResult.Status.OK, this.getAccelerationJSON()); + + for (Enumeration e = this.callbacks.elements(); e.hasMoreElements();) + { + this.success(result, (String)e.nextElement()); + } + this.callbacks.removeAllElements(); + + result.setKeepCallback(true); + + for (Enumeration e = this.watches.keys(); e.hasMoreElements();) + { + this.success(result, (String)this.watches.get((String)e.nextElement())); + } } /** @@ -252,6 +274,10 @@ public class Accelerometer extends Plugin implements AccelerometerListener { stop(); } + private int size() { + return this.watches.size() + this.callbacks.size(); + } + /** * Normalize the range of values returned by BlackBerry to the agreed upon * cross platform range. @@ -276,4 +302,16 @@ public class Accelerometer extends Plugin implements AccelerometerListener { return Double.parseDouble(buf.toString()); } + + private JSONObject getAccelerationJSON() { + JSONObject accel = new JSONObject(); + try { + accel.put("x", normalize(this.x)); + accel.put("y", normalize(this.y)); + accel.put("z", normalize(this.z)); + accel.put("timestamp", this.timestamp); + } catch (JSONException e) { + } + return accel; + } } http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/blob/3255ae8b/javascript/cordova.blackberry.js ---------------------------------------------------------------------- diff --git a/javascript/cordova.blackberry.js b/javascript/cordova.blackberry.js index 8b543e0..fa272c8 100644 --- a/javascript/cordova.blackberry.js +++ b/javascript/cordova.blackberry.js @@ -1,6 +1,6 @@ -// commit 9cfdc134f83b5d51f655e52ec7d4ddab167437c7 +// commit 7b6ae77e5030060e8e99fe0b79ddcf9d698bf375 -// File generated at :: Tue May 01 2012 14:06:43 GMT-0700 (PDT) +// File generated at :: Wed May 16 2012 10:03:30 GMT-0700 (PDT) /* Licensed to the Apache Software Foundation (ASF) under one @@ -98,17 +98,7 @@ var documentEventHandlers = {}, document.addEventListener = function(evt, handler, capture) { var e = evt.toLowerCase(); - if (e == 'deviceready') { - channel.onDeviceReady.subscribeOnce(handler); - } else if (e == 'resume') { - channel.onResume.subscribe(handler); - // if subscribing listener after event has already fired, invoke the handler - if (channel.onResume.fired && typeof handler == 'function') { - handler(); - } - } else if (e == 'pause') { - channel.onPause.subscribe(handler); - } else if (typeof documentEventHandlers[e] != 'undefined') { + if (typeof documentEventHandlers[e] != 'undefined') { documentEventHandlers[e].subscribe(handler); } else { m_document_addEventListener.call(document, evt, handler, capture); @@ -126,13 +116,8 @@ window.addEventListener = function(evt, handler, capture) { document.removeEventListener = function(evt, handler, capture) { var e = evt.toLowerCase(); - // Check for pause/resume events first. - if (e == 'resume') { - channel.onResume.unsubscribe(handler); - } else if (e == 'pause') { - channel.onPause.unsubscribe(handler); // If unsubcribing from an event that is handled by a plugin - } else if (typeof documentEventHandlers[e] != "undefined") { + if (typeof documentEventHandlers[e] != "undefined") { documentEventHandlers[e].unsubscribe(handler); } else { m_document_removeEventListener.call(document, evt, handler, capture); @@ -318,6 +303,11 @@ var cordova = { } }; +// Register pause, resume and deviceready channels as events on document. +channel.onPause = cordova.addDocumentEventHandler('pause'); +channel.onResume = cordova.addDocumentEventHandler('resume'); +channel.onDeviceReady = cordova.addDocumentEventHandler('deviceready'); + // Adds deprecation warnings to functions of an object (but only logs a message once) function deprecateFunctions(obj, objLabel) { var newObj = {}; @@ -645,10 +635,13 @@ Channel.prototype.unsubscribe = function(g) { if (g === null || g === undefined) { throw "You must pass _something_ into Channel.unsubscribe"; } if (typeof g == 'function') { g = g.observer_guid; } - this.handlers[g] = null; - delete this.handlers[g]; - this.numHandlers--; - if (this.events.onUnsubscribe) this.events.onUnsubscribe.call(this); + var handler = this.handlers[g]; + if (handler) { + this.handlers[g] = null; + delete this.handlers[g]; + this.numHandlers--; + if (this.events.onUnsubscribe) this.events.onUnsubscribe.call(this); + } }; /** @@ -771,6 +764,9 @@ module.exports = { path: 'cordova/plugin/network' } } + }, + splashscreen: { + path: 'cordova/plugin/splashscreen' } } }, @@ -1155,13 +1151,14 @@ module.exports = { // file: lib/common/plugin/Acceleration.js define("cordova/plugin/Acceleration", function(require, exports, module) { var Acceleration = function(x, y, z, timestamp) { - this.x = x; - this.y = y; - this.z = z; - this.timestamp = timestamp || (new Date()).getTime(); + this.x = x; + this.y = y; + this.z = z; + this.timestamp = timestamp || (new Date()).getTime(); }; module.exports = Acceleration; + }); // file: lib/common/plugin/Camera.js @@ -1786,15 +1783,20 @@ var Coordinates = function(lat, lng, alt, acc, head, vel, altacc) { /** * The altitude of the position. */ - this.altitude = alt; + this.altitude = (alt !== undefined ? alt : null); /** * The direction the device is moving at the position. */ - this.heading = head; + this.heading = (head !== undefined ? head : null); /** * The velocity with which the device is moving at the position. */ - this.speed = vel; + this.speed = (vel !== undefined ? vel : null); + + if (this.speed === 0 || this.speed === null) { + this.heading = NaN; + } + /** * The altitude accuracy of the position. */ @@ -1802,6 +1804,7 @@ var Coordinates = function(lat, lng, alt, acc, head, vel, altacc) { }; module.exports = Coordinates; + }); // file: lib/common/plugin/DirectoryEntry.js @@ -1986,6 +1989,21 @@ Entry.prototype.getMetadata = function(successCallback, errorCallback) { }; /** + * Set the metadata of the entry. + * + * @param successCallback + * {Function} is called with a Metadata object + * @param errorCallback + * {Function} is called with a FileError + * @param metadataObject + * {Object} keys and values to set + */ +Entry.prototype.setMetadata = function(successCallback, errorCallback, metadataObject) { + + exec(successCallback, errorCallback, "File", "setMetadata", [this.fullPath, metadataObject]); +}; + +/** * Move a file or directory to a new location. * * @param parent @@ -3269,11 +3287,16 @@ define("cordova/plugin/Position", function(require, exports, module) { var Coordinates = require('cordova/plugin/Coordinates'); var Position = function(coords, timestamp) { - this.coords = new Coordinates(coords.latitude, coords.longitude, coords.altitude, coords.accuracy, coords.heading, coords.velocity, coords.altitudeAccuracy); + if (coords) { + this.coords = new Coordinates(coords.latitude, coords.longitude, coords.altitude, coords.accuracy, coords.heading, coords.velocity, coords.altitudeAccuracy); + } else { + this.coords = new Coordinates(); + } this.timestamp = (timestamp !== undefined) ? timestamp : new Date().getTime(); }; module.exports = Position; + }); // file: lib/common/plugin/PositionError.js @@ -3354,11 +3377,16 @@ define("cordova/plugin/accelerometer", function(require, exports, module) { * @constructor */ var utils = require("cordova/utils"), - exec = require("cordova/exec"); + exec = require("cordova/exec"), + Acceleration = require('cordova/plugin/Acceleration'); + -// Local singleton variables. +// Keeps reference to watchAcceleration calls. var timers = {}; +// Last returned acceleration object from native +var accel = null; + var accelerometer = { /** * Asynchronously aquires the current acceleration. @@ -3368,21 +3396,18 @@ var accelerometer = { * @param {AccelerationOptions} options The options for getting the accelerometer data such as timeout. (OPTIONAL) */ getCurrentAcceleration: function(successCallback, errorCallback, options) { - // successCallback required if (typeof successCallback !== "function") { - console.log("Accelerometer Error: successCallback is not a function"); - return; + throw "getCurrentAcceleration must be called with at least a success callback function as first parameter."; } - // errorCallback optional - if (errorCallback && (typeof errorCallback !== "function")) { - console.log("Accelerometer Error: errorCallback is not a function"); - return; - } + var win = function(a) { + accel = new Acceleration(a.x, a.y, a.z, a.timestamp); + successCallback(accel); + }; // Get acceleration - exec(successCallback, errorCallback, "Accelerometer", "getAcceleration", []); + exec(win, errorCallback, "Accelerometer", "getAcceleration", []); }, /** @@ -3394,36 +3419,34 @@ var accelerometer = { * @return String The watch id that must be passed to #clearWatch to stop watching. */ watchAcceleration: function(successCallback, errorCallback, options) { - // Default interval (10 sec) - var frequency = (options !== undefined && options.frequency !== undefined)? options.frequency : 10000; + var frequency = (options && options.frequency && typeof options.frequency == 'number') ? options.frequency : 10000; // successCallback required if (typeof successCallback !== "function") { - console.log("Accelerometer Error: successCallback is not a function"); - return; - } - - // errorCallback optional - if (errorCallback && (typeof errorCallback !== "function")) { - console.log("Accelerometer Error: errorCallback is not a function"); - return; + throw "watchAcceleration must be called with at least a success callback function as first parameter."; } - // Make sure accelerometer timeout > frequency + 10 sec - exec( - function(timeout) { - if (timeout < (frequency + 10000)) { - exec(null, null, "Accelerometer", "setTimeout", [frequency + 10000]); - } - }, - function(e) { }, "Accelerometer", "getTimeout", []); - - // Start watch timer + // Keep reference to watch id, and report accel readings as often as defined in frequency var id = utils.createUUID(); timers[id] = window.setInterval(function() { - exec(successCallback, errorCallback, "Accelerometer", "getAcceleration", []); - }, (frequency ? frequency : 1)); + if (accel) { + successCallback(accel); + } + }, frequency); + + // Success callback from native just updates the accel object. + var win = function(a) { + accel = new Acceleration(a.x, a.y, a.z, a.timestamp); + }; + + // Fail callback clears the watch and sends an error back. + var fail = function(err) { + accelerometer.clearWatch(id); + errorCallback(err); + }; + + exec(win, fail, "Accelerometer", "addWatch", [id, frequency]); return id; }, @@ -3434,16 +3457,17 @@ var accelerometer = { * @param {String} id The id of the watch returned from #watchAcceleration. */ clearWatch: function(id) { - // Stop javascript timer & remove from timer list - if (id && timers[id] !== undefined) { + if (id && timers[id]) { window.clearInterval(timers[id]); delete timers[id]; + exec(null, null, "Accelerometer", "clearWatch", [id]); } } }; module.exports = accelerometer; + }); // file: lib/common/plugin/battery.js @@ -5179,27 +5203,45 @@ var timers = {}; // list of timers in use // Returns default params, overrides if provided with values function parseParameters(options) { var opt = { - maximumAge: 10000, + maximumAge: 0, enableHighAccuracy: false, - timeout: 10000 + timeout: Infinity }; if (options) { - if (options.maximumAge !== undefined) { + if (options.maximumAge !== undefined && !isNaN(options.maximumAge) && options.maximumAge > 0) { opt.maximumAge = options.maximumAge; } if (options.enableHighAccuracy !== undefined) { opt.enableHighAccuracy = options.enableHighAccuracy; } - if (options.timeout !== undefined) { - opt.timeout = options.timeout; + if (options.timeout !== undefined && !isNaN(options.timeout)) { + if (options.timeout < 0) { + opt.timeout = 0; + } else { + opt.timeout = options.timeout; + } } } return opt; } +// Returns a timeout failure, closed over a specified timeout value and error callback. +function createTimeout(errorCallback, timeout) { + var t = setTimeout(function() { + clearTimeout(t); + t = null; + errorCallback({ + code:PositionError.TIMEOUT, + message:"Position retrieval timed out." + }); + }, timeout); + return t; +} + var geolocation = { + lastPosition:null, // reference to last known (cached) position returned /** * Asynchronously aquires the current position. * @@ -5208,10 +5250,24 @@ var geolocation = { * @param {PositionOptions} options The options for getting the position data. (OPTIONAL) */ getCurrentPosition:function(successCallback, errorCallback, options) { + if (arguments.length === 0) { + throw new Error("getCurrentPosition must be called with at least one argument."); + } options = parseParameters(options); + // Timer var that will fire an error callback if no position is retrieved from native + // before the "timeout" param provided expires + var timeoutTimer = null; + var win = function(p) { - successCallback(new Position( + clearTimeout(timeoutTimer); + if (!timeoutTimer) { + // Timeout already happened, or native fired error callback for + // this geo request. + // Don't continue with success callback. + return; + } + var pos = new Position( { latitude:p.latitude, longitude:p.longitude, @@ -5222,13 +5278,45 @@ var geolocation = { altitudeAccuracy:p.altitudeAccuracy }, p.timestamp || new Date() - )); + ); + geolocation.lastPosition = pos; + successCallback(pos); }; var fail = function(e) { - errorCallback(new PositionError(e.code, e.message)); + clearTimeout(timeoutTimer); + timeoutTimer = null; + var err = new PositionError(e.code, e.message); + if (errorCallback) { + errorCallback(err); + } }; - exec(win, fail, "Geolocation", "getLocation", [options.enableHighAccuracy, options.timeout, options.maximumAge]); + // Check our cached position, if its timestamp difference with current time is less than the maximumAge, then just + // fire the success callback with the cached position. + if (geolocation.lastPosition && options.maximumAge && (((new Date()).getTime() - geolocation.lastPosition.timestamp.getTime()) <= options.maximumAge)) { + successCallback(geolocation.lastPosition); + // If the cached position check failed and the timeout was set to 0, error out with a TIMEOUT error object. + } else if (options.timeout === 0) { + fail({ + code:PositionError.TIMEOUT, + message:"timeout value in PositionOptions set to 0 and no cached Position object available, or cached Position object's age exceed's provided PositionOptions' maximumAge parameter." + }); + // Otherwise we have to call into native to retrieve a position. + } else { + if (options.timeout !== Infinity) { + // If the timeout value was not set to Infinity (default), then + // set up a timeout function that will fire the error callback + // if no successful position was retrieved before timeout expired. + timeoutTimer = createTimeout(fail, options.timeout); + } else { + // This is here so the check in the win function doesn't mess stuff up + // may seem weird but this guarantees timeoutTimer is + // always truthy before we call into native + timeoutTimer = true; + } + exec(win, fail, "Geolocation", "getLocation", [options.enableHighAccuracy, options.maximumAge]); + } + return timeoutTimer; }, /** * Asynchronously watches the geolocation for changes to geolocation. When a change occurs, @@ -5240,12 +5328,46 @@ var geolocation = { * @return String The watch id that must be passed to #clearWatch to stop watching. */ watchPosition:function(successCallback, errorCallback, options) { + if (arguments.length === 0) { + throw new Error("watchPosition must be called with at least one argument."); + } options = parseParameters(options); var id = utils.createUUID(); - timers[id] = window.setInterval(function() { - geolocation.getCurrentPosition(successCallback, errorCallback, options); - }, options.timeout); + + // Tell device to get a position ASAP, and also retrieve a reference to the timeout timer generated in getCurrentPosition + timers[id] = geolocation.getCurrentPosition(successCallback, errorCallback, options); + + var fail = function(e) { + clearTimeout(timers[id]); + var err = new PositionError(e.code, e.message); + if (errorCallback) { + errorCallback(err); + } + }; + + var win = function(p) { + clearTimeout(timers[id]); + if (options.timeout !== Infinity) { + timers[id] = createTimeout(fail, options.timeout); + } + var pos = new Position( + { + latitude:p.latitude, + longitude:p.longitude, + altitude:p.altitude, + accuracy:p.accuracy, + heading:p.heading, + velocity:p.velocity, + altitudeAccuracy:p.altitudeAccuracy + }, + p.timestamp || new Date() + ); + geolocation.lastPosition = pos; + successCallback(pos); + }; + + exec(win, fail, "Geolocation", "addWatch", [id, options.enableHighAccuracy]); return id; }, @@ -5256,13 +5378,15 @@ var geolocation = { */ clearWatch:function(id) { if (id && timers[id] !== undefined) { - window.clearInterval(timers[id]); + clearTimeout(timers[id]); delete timers[id]; + exec(null, null, "Geolocation", "clearWatch", [id]); } } }; module.exports = geolocation; + }); // file: lib/common/plugin/network.js @@ -5480,6 +5604,19 @@ module.exports = function(uri, successCallback, errorCallback) { }); +// file: lib/common/plugin/splashscreen.js +define("cordova/plugin/splashscreen", function(require, exports, module) { +var exec = require('cordova/exec'); + +var splashscreen = { + hide:function() { + exec(null, null, "SplashScreen", "hide", []); + } +}; + +module.exports = splashscreen; +}); + // file: lib/webworks/plugin/webworks/manager.js define("cordova/plugin/webworks/manager", function(require, exports, module) { // Define JavaScript plugin implementations that are common across @@ -5500,104 +5637,175 @@ module.exports = { // file: lib/common/utils.js define("cordova/utils", function(require, exports, module) { -function UUIDcreatePart(length) { - var uuidpart = ""; - for (var i=0; i<length; i++) { - var uuidchar = parseInt((Math.random() * 256), 10).toString(16); - if (uuidchar.length == 1) { - uuidchar = "0" + uuidchar; - } - uuidpart += uuidchar; - } - return uuidpart; -} +var utils = exports; -var _self = { - isArray:function(a) { - return Object.prototype.toString.call(a) == '[object Array]'; - }, - isDate:function(d) { - return Object.prototype.toString.call(d) == '[object Date]'; - }, - /** - * Does a deep clone of the object. - */ - clone: function(obj) { - if(!obj || typeof obj == 'function' || _self.isDate(obj) || typeof obj != 'object') { - return obj; - } +/** + * Returns an indication of whether the argument is an array or not + */ +utils.isArray = function(a) { + return Object.prototype.toString.call(a) == '[object Array]'; +}; - var retVal, i; +/** + * Returns an indication of whether the argument is a Date or not + */ +utils.isDate = function(d) { + return Object.prototype.toString.call(d) == '[object Date]'; +}; - if(_self.isArray(obj)){ - retVal = []; - for(i = 0; i < obj.length; ++i){ - retVal.push(_self.clone(obj[i])); - } - return retVal; - } +/** + * Does a deep clone of the object. + */ +utils.clone = function(obj) { + if(!obj || typeof obj == 'function' || utils.isDate(obj) || typeof obj != 'object') { + return obj; + } - retVal = {}; - for(i in obj){ - if(!(i in retVal) || retVal[i] != obj[i]) { - retVal[i] = _self.clone(obj[i]); - } + var retVal, i; + + if(utils.isArray(obj)){ + retVal = []; + for(i = 0; i < obj.length; ++i){ + retVal.push(utils.clone(obj[i])); } return retVal; - }, + } - close: function(context, func, params) { - if (typeof params == 'undefined') { - return function() { - return func.apply(context, arguments); - }; - } else { - return function() { - return func.apply(context, params); - }; + retVal = {}; + for(i in obj){ + if(!(i in retVal) || retVal[i] != obj[i]) { + retVal[i] = utils.clone(obj[i]); } - }, - - /** - * Create a UUID - */ - createUUID: function() { - return UUIDcreatePart(4) + '-' + - UUIDcreatePart(2) + '-' + - UUIDcreatePart(2) + '-' + - UUIDcreatePart(2) + '-' + - UUIDcreatePart(6); - }, + } + return retVal; +}; - /** - * Extends a child object from a parent object using classical inheritance - * pattern. - */ - extend: (function() { - // proxy used to establish prototype chain - var F = function() {}; - // extend Child from Parent - return function(Child, Parent) { - F.prototype = Parent.prototype; - Child.prototype = new F(); - Child.__super__ = Parent.prototype; - Child.prototype.constructor = Child; +/** + * Returns a wrappered version of the function + */ +utils.close = function(context, func, params) { + if (typeof params == 'undefined') { + return function() { + return func.apply(context, arguments); }; - }()), + } else { + return function() { + return func.apply(context, params); + }; + } +}; - /** - * Alerts a message in any available way: alert or console.log. - */ - alert:function(msg) { - if (alert) { - alert(msg); - } else if (console && console.log) { - console.log(msg); +/** + * Create a UUID + */ +utils.createUUID = function() { + return UUIDcreatePart(4) + '-' + + UUIDcreatePart(2) + '-' + + UUIDcreatePart(2) + '-' + + UUIDcreatePart(2) + '-' + + UUIDcreatePart(6); +}; + +/** + * Extends a child object from a parent object using classical inheritance + * pattern. + */ +utils.extend = (function() { + // proxy used to establish prototype chain + var F = function() {}; + // extend Child from Parent + return function(Child, Parent) { + F.prototype = Parent.prototype; + Child.prototype = new F(); + Child.__super__ = Parent.prototype; + Child.prototype.constructor = Child; + }; +}()); + +/** + * Alerts a message in any available way: alert or console.log. + */ +utils.alert = function(msg) { + if (alert) { + alert(msg); + } else if (console && console.log) { + console.log(msg); + } +}; + +/** + * Formats a string and arguments following it ala sprintf() + * + * format chars: + * %j - format arg as JSON + * %o - format arg as JSON + * %c - format arg as '' + * %% - replace with '%' + * any other char following % will format it's + * arg via toString(). + * + * for rationale, see FireBug's Console API: + * http://getfirebug.com/wiki/index.php/Console_API + */ +utils.format = function(formatString /* ,... */) { + if (formatString === null || formatString === undefined) return ""; + if (arguments.length == 1) return formatString.toString(); + + var pattern = /(.*?)%(.)(.*)/; + var rest = formatString.toString(); + var result = []; + var args = [].slice.call(arguments,1); + + while (args.length) { + var arg = args.shift(); + var match = pattern.exec(rest); + + if (!match) break; + + rest = match[3]; + + result.push(match[1]); + + if (match[2] == '%') { + result.push('%'); + args.unshift(arg); + continue; } + + result.push(formatted(arg, match[2])); } + + result.push(rest); + + return result.join(''); }; -module.exports = _self; +//------------------------------------------------------------------------------ +function UUIDcreatePart(length) { + var uuidpart = ""; + for (var i=0; i<length; i++) { + var uuidchar = parseInt((Math.random() * 256), 10).toString(16); + if (uuidchar.length == 1) { + uuidchar = "0" + uuidchar; + } + uuidpart += uuidchar; + } + return uuidpart; +} + +//------------------------------------------------------------------------------ +function formatted(object, formatChar) { + + switch(formatChar) { + case 'j': + case 'o': return JSON.stringify(object); + case 'c': return ''; + } + + if (null === object) return Object.prototype.toString.call(object); + + return object.toString(); +} }); @@ -5639,7 +5847,7 @@ window.cordova = require('cordova'); // Fire onDeviceReady event once all constructors have run and // cordova info has been received from native side. channel.join(function() { - channel.onDeviceReady.fire(); + require('cordova').fireDocumentEvent('deviceready'); }, channel.deviceReadyChannelsArray); }, [ channel.onDOMContentLoaded, channel.onNativeReady ]); @@ -5658,4 +5866,5 @@ window.cordova = require('cordova'); }(window)); + })(); \ No newline at end of file