if (typeof(DeviceInfo) != 'object') DeviceInfo = {}; /** * This represents the PhoneGap API itself, and provides a global namespace for accessing * information about the state of PhoneGap. * @class */ var PhoneGap = { queue: { ready: true, commands: [], timer: null } }; /** * Custom pub-sub channel that can have functions subscribed to it */ PhoneGap.Channel = function(type) { this.type = type; this.handlers = {}; this.guid = 0; this.fired = false; this.enabled = true; }; /** * Subscribes the given function to the channel. Any time that * Channel.fire is called so too will the function. * Optionally specify an execution context for the function * and a guid that can be used to stop subscribing to the channel. * Returns the guid. */ PhoneGap.Channel.prototype.subscribe = function(f, c, g) { // need a function to call if (f == null) { return; } var func = f; if (typeof c == "object" && f instanceof Function) { func = PhoneGap.close(c, f); } g = g || func.observer_guid || f.observer_guid || this.guid++; func.observer_guid = g; f.observer_guid = g; this.handlers[g] = func; return g; }; /** * Like subscribe but the function is only called once and then it * auto-unsubscribes itself. */ PhoneGap.Channel.prototype.subscribeOnce = function(f, c) { var g = null; var _this = this; var m = function() { f.apply(c || null, arguments); _this.unsubscribe(g); } if (this.fired) { if (typeof c == "object" && f instanceof Function) { f = PhoneGap.close(c, f); } f.apply(this, this.fireArgs); } else { g = this.subscribe(m); } return g; }; /** * Unsubscribes the function with the given guid from the channel. */ PhoneGap.Channel.prototype.unsubscribe = function(g) { if (g instanceof Function) { g = g.observer_guid; } this.handlers[g] = null; delete this.handlers[g]; }; /** * Calls all functions subscribed to this channel. */ PhoneGap.Channel.prototype.fire = function(e) { if (this.enabled) { var fail = false; for (var item in this.handlers) { var handler = this.handlers[item]; if (handler instanceof Function) { var rv = (handler.apply(this, arguments)==false); fail = fail || rv; } } this.fired = true; this.fireArgs = arguments; return !fail; } return true; }; /** * Calls the provided function only after all of the channels specified * have been fired. */ PhoneGap.Channel.join = function(h, c) { var i = c.length; var f = function() { if (!(--i)) h(); } for (var j=0; j 0) { s = s + ","; } var type = typeof args[i]; if ((type == "number") || (type == "boolean")) { s = s + args[i]; } else { s = s + '"' + args[i] + '"'; } } s = s + "]"; return s; } else { return JSON.stringify(args); } }; PhoneGap.callbackId = 0; PhoneGap.callbacks = {}; /** * Execute a PhoneGap command in a queued fashion, to ensure commands do not * execute with any race conditions, and only run when PhoneGap is ready to * recieve them. * @param {String} command Command to be run in PhoneGap, e.g. "ClassName.method" * @param {String[]} [args] Zero or more arguments to pass to the method */ PhoneGap.exec = function(clazz, action, args) { try { var callbackId = 0; var r = PluginManager.exec(clazz, action, callbackId, this.stringify(args), false); eval("var v="+r+";"); // If status is OK, then return value back to caller if (v.status == 0) { return v.message; } // If error, then display error else { console.log("Error: Status="+r.status+" Message="+v.message); return null; } } catch (e) { console.log("Error: "+e); } }; PhoneGap.execAsync = function(success, fail, clazz, action, args) { try { var callbackId = clazz + PhoneGap.callbackId++; if (success || fail) { PhoneGap.callbacks[callbackId] = {success:success, fail:fail}; } var r = PluginManager.exec(clazz, action, callbackId, this.stringify(args), true); // If a result was returned if ((typeof r == "string") && (r.length > 0)) { eval("var v="+r+";"); // If status is OK, then return value back to caller if (v.status == 0) { // If there is a success callback, then call it now with returned value if (success) { success(v.message); delete PhoneGap.callbacks[callbackId]; } return v.message; } // If error, then display error else { console.log("Error: Status="+r.status+" Message="+v.message); // If there is a fail callback, then call it now with returned value if (fail) { fail(v.message); delete PhoneGap.callbacks[callbackId]; } return null; } } } catch (e) { console.log("Error: "+e); } }; PhoneGap.callbackSuccess = function(callbackId, args) { if (PhoneGap.callbacks[callbackId]) { try { if (PhoneGap.callbacks[callbackId].success) { PhoneGap.callbacks[callbackId].success(args.message); } } catch (e) { console.log("Error in success callback: "+callbackId+" = "+e); } delete PhoneGap.callbacks[callbackId]; } }; PhoneGap.callbackError = function(callbackId, args) { if (PhoneGap.callbacks[callbackId]) { try { if (PhoneGap.callbacks[callbackId].fail) { PhoneGap.callbacks[callbackId].fail(args.message); } } catch (e) { console.log("Error in error callback: "+callbackId+" = "+e); } delete PhoneGap.callbacks[callbackId]; } }; /** * Internal function used to dispatch the request to PhoneGap. It processes the * command queue and executes the next command on the list. If one of the * arguments is a JavaScript object, it will be passed on the QueryString of the * url, which will be turned into a dictionary on the other end. * @private */ PhoneGap.run_command = function() { if (!PhoneGap.available || !PhoneGap.queue.ready) return; PhoneGap.queue.ready = false; var args = PhoneGap.queue.commands.shift(); if (PhoneGap.queue.commands.length == 0) { clearInterval(PhoneGap.queue.timer); PhoneGap.queue.timer = null; } var uri = []; var dict = null; for (var i = 1; i < args.length; i++) { var arg = args[i]; if (arg == undefined || arg == null) arg = ''; if (typeof(arg) == 'object') dict = arg; else uri.push(encodeURIComponent(arg)); } var url = "gap://" + args[0] + "/" + uri.join("/"); if (dict != null) { var query_args = []; for (var name in dict) { if (typeof(name) != 'string') continue; query_args.push(encodeURIComponent(name) + "=" + encodeURIComponent(dict[name])); } if (query_args.length > 0) url += "?" + query_args.join("&"); } document.location = url; }; /** * Internal function that uses XHR to call into PhoneGap Java code and retrieve * any JavaScript code that needs to be run. This is used for callbacks from * Java to JavaScript. */ PhoneGap.JSCallback = function() { var xmlhttp = new XMLHttpRequest(); // Callback function when XMLHttpRequest is ready xmlhttp.onreadystatechange=function(){ if(xmlhttp.readyState == 4){ // If callback has JavaScript statement to execute if (xmlhttp.status == 200) { var msg = xmlhttp.responseText; setTimeout(function() { try { var t = eval(msg); } catch (e) { console.log("JSCallback Error: "+e); } }, 1); setTimeout(PhoneGap.JSCallback, 1); } // If callback ping (used to keep XHR request from timing out) else if (xmlhttp.status == 404) { setTimeout(PhoneGap.JSCallback, 10); } // If error, restart callback server else { console.log("JSCallback Error: Request failed."); CallbackServer.restartServer(); setTimeout(PhoneGap.JSCallback, 100); } } } xmlhttp.open("GET", "http://127.0.0.1:"+CallbackServer.getPort()+"/" , true); xmlhttp.send(); }; /** * Create a UUID * * @return */ PhoneGap.createUUID = function() { return PhoneGap.UUIDcreatePart(4) + '-' + PhoneGap.UUIDcreatePart(2) + '-' + PhoneGap.UUIDcreatePart(2) + '-' + PhoneGap.UUIDcreatePart(2) + '-' + PhoneGap.UUIDcreatePart(6); }; PhoneGap.UUIDcreatePart = function(length) { var uuidpart = ""; for (var i=0; i