Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

updated all platforms to 0.9.3, waiting for docs update before release

  • Loading branch information...
commit 34d72e1ebec7d05ab93ab5de9f35101f3a0140f9 1 parent 634a1a9
@stevengill stevengill authored
Showing with 3,625 additions and 1,018 deletions.
  1. +11 −1 .gitignore
  2. +2 −2 Android/Sample/.classpath
  3. +8 −118 Android/Sample/assets/www/index.html
  4. +127 −0 Android/Sample/assets/www/main.js
  5. +526 −139 Android/Sample/assets/www/phonegap-0.9.3.js
  6. BIN  Android/Sample/libs/phonegap-0.9.3.jar
  7. BIN  Android/Sample/res/drawable-hdpi/icon.png
  8. BIN  Android/Sample/res/drawable-ldpi/icon.png
  9. BIN  Android/Sample/res/drawable-mdpi/icon.png
  10. BIN  Android/phonegap-0.9.3.jar
  11. +526 −139 Android/phonegap-0.9.3.js
  12. +25 −12 BlackBerry/Widget/framework/ext/src/com/phonegap/PhoneGapExtension.java
  13. +20 −6 BlackBerry/Widget/framework/ext/src/com/phonegap/accelerometer/Accelerometer.java
  14. +5 −5 BlackBerry/Widget/framework/ext/src/com/phonegap/api/Plugin.java
  15. +106 −0 BlackBerry/Widget/framework/ext/src/com/phonegap/api/PluginManager.java
  16. +0 −48 BlackBerry/Widget/framework/ext/src/com/phonegap/api/PluginManagerFeature.java
  17. +43 −23 BlackBerry/Widget/framework/ext/src/com/phonegap/api/PluginManagerFunction.java
  18. +17 −2 BlackBerry/Widget/framework/ext/src/com/phonegap/api/PluginResult.java
  19. +3 −3 BlackBerry/Widget/framework/ext/src/com/phonegap/device/{DeviceFeature.java → Device.java}
  20. +335 −0 BlackBerry/Widget/framework/ext/src/com/phonegap/file/FileManager.java
  21. +141 −115 BlackBerry/Widget/framework/ext/src/com/phonegap/geolocation/Geolocation.java
  22. +52 −43 BlackBerry/Widget/framework/ext/src/com/phonegap/geolocation/GeolocationListener.java
  23. +72 −0 BlackBerry/Widget/framework/ext/src/com/phonegap/util/Log.java
  24. +0 −51 BlackBerry/Widget/framework/ext/src/com/phonegap/util/LogFeature.java
  25. +35 −2 BlackBerry/Widget/js/_phonegap.js
  26. +0 −23 BlackBerry/Widget/js/camera.js
  27. +93 −16 BlackBerry/Widget/js/contact_bbw.js
  28. +670 −0 BlackBerry/Widget/js/file.js
  29. +63 −24 BlackBerry/Widget/js/geolocation.js
  30. +34 −1 BlackBerry/Widget/template/build.xml
  31. +30 −0 BlackBerry/Widget/template/lib/yuicompressor/LICENSE
  32. +140 −0 BlackBerry/Widget/template/lib/yuicompressor/README
  33. BIN  BlackBerry/Widget/template/lib/yuicompressor/yuicompressor-2.4.2.jar
  34. +5 −0 BlackBerry/Widget/template/www/config.xml
  35. +527 −244 BlackBerry/Widget/template/www/index.html
  36. +7 −0 BlackBerry/Widget/template/www/javascript/header.txt
  37. +2 −1  README.md
  38. 0  Symbian/Makefile
  39. 0  Symbian/README.md
  40. 0  Symbian/framework/www/Icon.png
  41. 0  Symbian/framework/www/Info.plist
  42. 0  Symbian/framework/www/index.html
  43. 0  Symbian/framework/www/phonegap.js
  44. 0  Symbian/js/acceleration.js
  45. 0  Symbian/js/accelerometer.js
  46. 0  Symbian/js/audio.js
  47. 0  Symbian/js/camera.js
  48. 0  Symbian/js/camera/com.nokia.device.camera.js
  49. 0  Symbian/js/camera/com.nokia.device.framework.js
  50. 0  Symbian/js/camera/com.nokia.device.utility.js
  51. 0  Symbian/js/camera/s60_camera.js
  52. 0  Symbian/js/contacts.js
  53. 0  Symbian/js/debugconsole.js
  54. 0  Symbian/js/device.js
  55. 0  Symbian/js/geolocation.js
  56. 0  Symbian/js/map.js
  57. 0  Symbian/js/network.js
  58. 0  Symbian/js/notification.js
  59. 0  Symbian/js/orientation.js
  60. 0  Symbian/js/phonegap.js.base
  61. 0  Symbian/js/position.js
  62. 0  Symbian/js/sms.js
  63. 0  Symbian/js/storage.js
  64. 0  Symbian/js/telephony.js
  65. BIN  iOS/PhoneGapLibInstaller.pkg
  66. 0  webOS/Makefile
  67. 0  webOS/README.md
  68. 0  webOS/framework/www/app/assistants/First-assistant.js
  69. 0  webOS/framework/www/app/assistants/stage-assistant.js
  70. 0  webOS/framework/www/app/views/First/First-scene.html
  71. 0  webOS/framework/www/appinfo.json
  72. 0  webOS/framework/www/icon.png
  73. 0  webOS/framework/www/index.html
  74. 0  webOS/framework/www/phonegap.js
  75. 0  webOS/framework/www/sources.json
  76. 0  webOS/js/acceleration.js
  77. 0  webOS/js/accelerometer.js
  78. 0  webOS/js/audio.js
  79. 0  webOS/js/camera.js
  80. 0  webOS/js/contacts.js
  81. 0  webOS/js/debugconsole.js
  82. 0  webOS/js/device.js
  83. 0  webOS/js/file.js
  84. 0  webOS/js/geolocation.js
  85. 0  webOS/js/map.js
  86. 0  webOS/js/network.js
  87. 0  webOS/js/notification.js
  88. 0  webOS/js/orientation.js
  89. 0  webOS/js/phonegap.js.base
  90. 0  webOS/js/position.js
  91. 0  webOS/js/sms.js
  92. 0  webOS/js/storage.js
  93. 0  webOS/js/telephony.js
View
12 .gitignore
@@ -1,3 +1,4 @@
+<<<<<<< HEAD
.DS_Store
.*.sw?
*.cso
@@ -6,4 +7,13 @@ tmp/
lib/iphone/phonegap-min.js
lib/iphone/phonegap.js
android/bin
-android/gen
+android/gen
+=======
+default.properties
+gen
+assets/www/phonegap.js
+local.properties
+framework/phonegap.jar
+framework/bin
+framework/assets/www/.DS_Store
+>>>>>>> fbe96f891bc56cfff38037bf6087d60ceb17e286
View
4 Android/Sample/.classpath
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
- <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
- <classpathentry kind="lib" path="libs/phonegap.jar"/>
+ <classpathentry kind="lib" path="libs/phonegap-0.9.3.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
View
126 Android/Sample/assets/www/index.html
@@ -5,135 +5,25 @@
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>PhoneGap</title>
<link rel="stylesheet" href="master.css" type="text/css" media="screen" title="no title" charset="utf-8">
- <script type="text/javascript" charset="utf-8" src="phonegap-0.9.3.js"></script>
- <script type="text/javascript" charset="utf-8">
-
- var deviceInfo = function(){
- document.getElementById("platform").innerHTML = device.platform;
- document.getElementById("version").innerHTML = device.version;
- document.getElementById("uuid").innerHTML = device.uuid;
- }
-
- var getLocation = function() {
- var suc = function(p){
- alert(p.coords.latitude + " " + p.coords.longitude);
- };
- var fail = function(){};
- navigator.geolocation.getCurrentPosition(suc,fail);
- }
-
- var beep = function(){
- navigator.notification.beep(2);
- }
-
- var vibrate = function(){
- navigator.notification.vibrate(0);
- }
-
- var getContact = function(){
- var suc = function(c){ alert("Contact 4: " + c.contacts[3].name); };
- var fail = function(){};
- navigator.ContactManager.get(suc, fail);
- }
-
- var watchAccel = function() {
- var suc = function(a){
- document.getElementById('x').innerHTML = roundNumber(a.x);
- document.getElementById('y').innerHTML = roundNumber(a.y);
- document.getElementById('z').innerHTML = roundNumber(a.z);
- };
- var fail = function(){};
- var opt = {};
- opt.frequency = 100;
- timer = navigator.accelerometer.watchAcceleration(suc,fail,opt);
- }
-
- function roundNumber(num) {
- var dec = 3;
- var result = Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
- return result;
- }
-
- var preventBehavior = function(e) {
- e.preventDefault();
- };
+ <script type="text/javascript" charset="utf-8" src="phonegap-0.9.3.js"></script>
+ <script type="text/javascript" charset="utf-8" src="main.js"></script>
- function show_pic()
- {
- var viewport = document.getElementById('viewport');
- viewport.style.display = "";
- navigator.camera.getPicture(dump_pic, fail, { quality: 50 });
- }
-
- function dump_pic(data)
- {
- var viewport = document.getElementById('viewport');
- console.log(data);
- viewport.style.display = "";
- viewport.style.position = "absolute";
- viewport.style.top = "10px";
- viewport.style.left = "10px";
- document.getElementById("test_img").src = "data:image/jpeg;base64," + data;
- }
-
- function close()
- {
- var viewport = document.getElementById('viewport');
- viewport.style.position = "relative";
- viewport.style.display = "none";
- }
-
- function fail(fail)
- {
- alert(fail);
- }
-
- // This is just to do this.
- function readFile()
- {
- navigator.file.read('/sdcard/phonegap.txt', fail , fail);
- }
-
- function writeFile()
- {
- navigator.file.write('foo.txt', "This is a test of writing to a file", fail, fail);
- }
-
- function get_contacts()
- {
- var obj = new ContactFindOptions();
- obj.filter="";
- obj.multiple=true;
- obj.limit=5;
- navigator.service.contacts.find(["displayName", "phoneNumbers", "emails"], count_contacts, fail, obj);
- }
-
- function count_contacts(contacts)
- {
- alert(contacts.length);
- }
-
- function init(){
- document.addEventListener("touchmove", preventBehavior, false);
- document.addEventListener("deviceready", deviceInfo, true);
- }
-
- </script>
</head>
<body onload="init();" id="stage" class="theme">
<h1>Welcome to PhoneGap!</h1>
<h2>this file is located at assets/index.html</h2>
<div id="info">
- <h4>Platform: <span id="platform">&nbsp;</span></h4>
- <h4>Version: <span id="version">&nbsp;</span></h4>
- <h4>UUID: <span id="uuid">&nbsp;</span></h4>
- </div>
+ <h4>Platform: <span id="platform"> &nbsp;</span>, Version: <span id="version">&nbsp;</span></h4>
+ <h4>UUID: <span id="uuid"> &nbsp;</span>, Name: <span id="name">&nbsp;</span></h4>
+ <h4>Width: <span id="width"> &nbsp;</span>, Height: <span id="height">&nbsp;
+ </span>, Color Depth: <span id="colorDepth"></span></h4>
+ </div>
<dl id="accel-data">
<dt>X:</dt><dd id="x">&nbsp;</dd>
<dt>Y:</dt><dd id="y">&nbsp;</dd>
<dt>Z:</dt><dd id="z">&nbsp;</dd>
</dl>
- <a href="#" class="btn large" onclick="watchAccel();">Watch Accelerometer</a>
+ <a href="#" class="btn large" onclick="toggleAccel();">Toggle Accelerometer</a>
<a href="#" class="btn large" onclick="getLocation();">Get Location</a>
<a href="tel://411" class="btn large">Call 411</a>
<a href="#" class="btn large" onclick="beep();">Beep</a>
View
127 Android/Sample/assets/www/main.js
@@ -0,0 +1,127 @@
+ var deviceInfo = function(){
+ document.getElementById("platform").innerHTML = device.platform;
+ document.getElementById("version").innerHTML = device.version;
+ document.getElementById("uuid").innerHTML = device.uuid;
+ document.getElementById("name").innerHTML = device.name;
+ document.getElementById("width").innerHTML = screen.width;
+ document.getElementById("height").innerHTML = screen.height;
+ document.getElementById("colorDepth").innerHTML = screen.colorDepth;
+ };
+
+ var getLocation = function() {
+ var suc = function(p){
+ alert(p.coords.latitude + " " + p.coords.longitude);
+ };
+ var fail = function(){};
+ navigator.geolocation.getCurrentPosition(suc,fail);
+ };
+
+ var beep = function(){
+ navigator.notification.beep(2);
+ };
+
+ var vibrate = function(){
+ navigator.notification.vibrate(0);
+ };
+
+ function roundNumber(num) {
+ var dec = 3;
+ var result = Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
+ return result;
+ }
+
+ var accelerationWatch = false;
+
+ var toggleAccel = function() {
+ if (accelerationWatch) {
+ navigator.accelerometer.clearWatch(accelerationWatch);
+ updateAcceleration( {
+ x : "",
+ y : "",
+ z : ""
+ });
+ accelerationWatch = false;
+ } else {
+ accelerationWatch = true;
+ var options = new Object();
+ options.frequency = 1000;
+ accelerationWatch = navigator.accelerometer.watchAcceleration(
+ updateAcceleration, function(ex) {
+ navigator.accelerometer.clearWatch(accel_watch_id);
+ alert("accel fail (" + ex.name + ": " + ex.message + ")");
+ }, options);
+ }
+ };
+
+ function updateAcceleration(a) {
+ document.getElementById('x').innerHTML = roundNumber(a.x);
+ document.getElementById('y').innerHTML = roundNumber(a.y);
+ document.getElementById('z').innerHTML = roundNumber(a.z);
+ }
+
+ var preventBehavior = function(e) {
+ e.preventDefault();
+ };
+
+ function show_pic()
+ {
+ var viewport = document.getElementById('viewport');
+ viewport.style.display = "";
+ navigator.camera.getPicture(dump_pic, fail, { quality: 50 });
+ }
+
+ function dump_pic(data)
+ {
+ var viewport = document.getElementById('viewport');
+ console.log(data);
+ viewport.style.display = "";
+ viewport.style.position = "absolute";
+ viewport.style.top = "10px";
+ viewport.style.left = "10px";
+ document.getElementById("test_img").src = "data:image/jpeg;base64," + data;
+ }
+
+ function close()
+ {
+ var viewport = document.getElementById('viewport');
+ viewport.style.position = "relative";
+ viewport.style.display = "none";
+ }
+
+ function fail(fail)
+ {
+ alert(fail);
+ }
+
+ // This is just to do this.
+ function readFile()
+ {
+ navigator.file.read('/sdcard/phonegap.txt', fail , fail);
+ }
+
+ function writeFile()
+ {
+ navigator.file.write('foo.txt', "This is a test of writing to a file", fail, fail);
+ }
+
+ function get_contacts()
+ {
+ var obj = new ContactFindOptions();
+ obj.filter="";
+ obj.multiple=true;
+ obj.limit=5;
+ navigator.service.contacts.find(["displayName", "phoneNumbers", "emails"], contacts_success, fail, obj);
+ }
+
+ function contacts_success(contacts)
+ {
+ alert(contacts.length + ' contacts returned.' +
+ (contacts[2] ? (' Third contact is ' + contacts[2].displayName) : ''));
+ }
+
+
+ function init(){
+ //the next line makes it impossible to see Contacts on the HTC Evo since it doesn't have a scroll button
+// document.addEventListener("touchmove", preventBehavior, false);
+ document.addEventListener("deviceready", deviceInfo, true);
+ }
View
665 Android/Sample/assets/www/phonegap-0.9.3.js
@@ -157,26 +157,32 @@ PhoneGap.addConstructor = function(func) {
try {
func();
} catch(e) {
- if (typeof(debug['log']) == 'function') {
- debug.log("Failed to run constructor: " + debug.processMessage(e));
- } else {
- alert("Failed to run constructor: " + e.message);
- }
+ console.log("Failed to run constructor: " + e);
}
});
};
/**
- * Adds a plugin object to window.plugins
+ * Plugins object
*/
-PhoneGap.addPlugin = function(name, obj) {
- if ( !window.plugins ) {
- window.plugins = {};
- }
+if (!window.plugins) {
+ window.plugins = {};
+}
- if ( !window.plugins[name] ) {
- window.plugins[name] = obj;
- }
+/**
+ * Adds a plugin object to window.plugins.
+ * The plugin is accessed using window.plugins.<name>
+ *
+ * @param name The plugin name
+ * @param obj The plugin object
+ */
+PhoneGap.addPlugin = function(name, obj) {
+ if (!window.plugins[name]) {
+ window.plugins[name] = obj;
+ }
+ else {
+ console.log("Error: Plugin "+name+" already exists.");
+ }
}
/**
@@ -286,7 +292,7 @@ document.addEventListener = function(evt, handler, capture) {
} else if (e == 'pause') {
PhoneGap.onPause.subscribe(handler);
} else {
- PhoneGap.m_document_addEventListener.call(document, evt, handler);
+ PhoneGap.m_document_addEventListener.call(document, evt, handler, capture);
}
};
@@ -315,18 +321,27 @@ PhoneGap.stringify = function(args) {
var start = true;
s = s + '{';
for (var name in args[i]) {
- if (!start) {
- s = s + ',';
- }
- s = s + '"' + name + '":';
- var nameType = typeof args[i][name];
- if ((nameType == "number") || (nameType == "boolean")) {
- s = s + args[i][name];
- }
- else {
- s = s + '"' + args[i][name] + '"';
- }
- start=false;
+ if (args[i][name] != null) {
+ if (!start) {
+ s = s + ',';
+ }
+ s = s + '"' + name + '":';
+ var nameType = typeof args[i][name];
+ if ((nameType == "number") || (nameType == "boolean")) {
+ s = s + args[i][name];
+ }
+ else if ((typeof args[i][name]) == 'function') {
+ // don't copy the functions
+ s = s + '""';
+ }
+ else if (args[i][name] instanceof Object) {
+ s = s + this.stringify(args[i][name]);
+ }
+ else {
+ s = s + '"' + args[i][name] + '"';
+ }
+ start=false;
+ }
}
s = s + '}';
}
@@ -430,7 +445,7 @@ PhoneGap.exec = function(success, fail, service, action, args) {
// If there is a success callback, then call it now with returned value
if (success) {
try {
- success(v.message);
+ success(v.message);
}
catch (e) {
console.log("Error in success callback: "+callbackId+" = "+e);
@@ -492,7 +507,7 @@ PhoneGap.callbackSuccess = function(callbackId, args) {
if (args.status == PhoneGap.callbackStatus.OK) {
try {
if (PhoneGap.callbacks[callbackId].success) {
- PhoneGap.callbacks[callbackId].success(args.message);
+ PhoneGap.callbacks[callbackId].success(args.message);
}
}
catch (e) {
@@ -722,6 +737,22 @@ PhoneGap.close = function(context, func, params) {
}
};
+/**
+ * Load a JavaScript file after page has loaded.
+ *
+ * @param {String} jsfile The url of the JavaScript file to load.
+ * @param {Function} successCallback The callback to call when the file has been loaded.
+ */
+PhoneGap.includeJavascript = function(jsfile, successCallback) {
+ var id = document.getElementsByTagName("head")[0];
+ var el = document.createElement('script');
+ el.type = 'text/javascript';
+ if (typeof successCallback == 'function') {
+ el.onload = successCallback;
+ }
+ el.src = jsfile;
+ id.appendChild(el);
+};
/*
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
@@ -852,6 +883,74 @@ PhoneGap.addConstructor(function() {
*/
/**
+ * Constructor
+ */
+function App() {
+}
+
+/**
+ * Clear the resource cache.
+ */
+App.prototype.clearCache = function() {
+ PhoneGap.exec(null, null, "App", "clearCache", []);
+};
+
+/**
+ * Load the url into the webview.
+ *
+ * @param url The URL to load
+ * @param props Properties that can be passed in to the activity:
+ * wait: int => wait msec before loading URL
+ * loadingDialog: "Title,Message" => display a native loading dialog
+ * hideLoadingDialogOnPage: boolean => hide loadingDialog when page loaded instead of when deviceready event occurs.
+ * loadInWebView: boolean => cause all links on web page to be loaded into existing web view, instead of being loaded into new browser.
+ * loadUrlTimeoutValue: int => time in msec to wait before triggering a timeout error
+ * errorUrl: URL => URL to load if there's an error loading specified URL with loadUrl(). Should be a local URL such as file:///android_asset/www/error.html");
+ * keepRunning: boolean => enable app to keep running in background
+ *
+ * Example:
+ * App app = new App();
+ * app.loadUrl("http://server/myapp/index.html", {wait:2000, loadingDialog:"Wait,Loading App", loadUrlTimeoutValue: 60000});
+ */
+App.prototype.loadUrl = function(url, props) {
+ PhoneGap.exec(null, null, "App", "loadUrl", [url, props]);
+};
+
+/**
+ * Cancel loadUrl that is waiting to be loaded.
+ */
+App.prototype.cancelLoadUrl = function() {
+ PhoneGap.exec(null, null, "App", "cancelLoadUrl", []);
+};
+
+/**
+ * Clear web history in this web view.
+ * Instead of BACK button loading the previous web page, it will exit the app.
+ */
+App.prototype.clearHistory = function() {
+ PhoneGap.exec(null, null, "App", "clearHistory", []);
+};
+
+/**
+ * Add a class that implements a service.
+ *
+ * @param serviceType
+ * @param className
+ */
+App.prototype.addService = function(serviceType, className) {
+ PhoneGap.exec(null, null, "App", "addService", [serviceType, className]);
+};
+
+
+/*
+ * PhoneGap is available under *either* the terms of the modified BSD license *or* the
+ * MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
+ *
+ * Copyright (c) 2005-2010, Nitobi Software Inc.
+ * Copyright (c) 2010, IBM Corporation
+ */
+
+/**
* This class provides access to the device camera.
*
* @constructor
@@ -1089,6 +1188,7 @@ var Contact = function(id, displayName, name, nickname, phoneNumbers, emails, ad
ims, organizations, published, updated, birthday, anniversary, gender, note,
preferredUsername, photos, tags, relationships, urls, accounts, utcOffset, connected) {
this.id = id || null;
+ this.rawId = null;
this.displayName = displayName || null;
this.name = name || null; // ContactName
this.nickname = nickname || null;
@@ -1124,8 +1224,9 @@ Contact.prototype.remove = function(successCB, errorCB) {
errorObj.code = ContactError.NOT_FOUND_ERROR;
errorCB(errorObj);
}
-
- PhoneGap.exec(successCB, errorCB, "Contacts", "remove", [this.id]);
+ else {
+ PhoneGap.exec(successCB, errorCB, "Contacts", "remove", [this.id]);
+ }
};
/**
@@ -1136,6 +1237,48 @@ Contact.prototype.remove = function(successCB, errorCB) {
Contact.prototype.clone = function() {
var clonedContact = PhoneGap.clone(this);
clonedContact.id = null;
+ clonedContact.rawId = null;
+ // Loop through and clear out any id's in phones, emails, etc.
+ if (clonedContact.phoneNumbers) {
+ for (i=0; i<clonedContact.phoneNumbers.length; i++) {
+ clonedContact.phoneNumbers[i].id = null;
+ }
+ }
+ if (clonedContact.emails) {
+ for (i=0; i<clonedContact.emails.length; i++) {
+ clonedContact.emails[i].id = null;
+ }
+ }
+ if (clonedContact.addresses) {
+ for (i=0; i<clonedContact.addresses.length; i++) {
+ clonedContact.addresses[i].id = null;
+ }
+ }
+ if (clonedContact.ims) {
+ for (i=0; i<clonedContact.ims.length; i++) {
+ clonedContact.ims[i].id = null;
+ }
+ }
+ if (clonedContact.organizations) {
+ for (i=0; i<clonedContact.organizations.length; i++) {
+ clonedContact.organizations[i].id = null;
+ }
+ }
+ if (clonedContact.tags) {
+ for (i=0; i<clonedContact.tags.length; i++) {
+ clonedContact.tags[i].id = null;
+ }
+ }
+ if (clonedContact.relationships) {
+ for (i=0; i<clonedContact.relationships.length; i++) {
+ clonedContact.relationships[i].id = null;
+ }
+ }
+ if (clonedContact.urls) {
+ for (i=0; i<clonedContact.urls.length; i++) {
+ clonedContact.urls[i].id = null;
+ }
+ }
return clonedContact;
};
@@ -1145,6 +1288,7 @@ Contact.prototype.clone = function() {
* @param errorCB error callback
*/
Contact.prototype.save = function(successCB, errorCB) {
+ PhoneGap.exec(successCB, errorCB, "Contacts", "save", [this]);
};
/**
@@ -1167,11 +1311,13 @@ var ContactName = function(formatted, familyName, givenName, middle, prefix, suf
/**
* Generic contact field.
+* @param {DOMString} id unique identifier, should only be set by native code
* @param type
* @param value
* @param primary
*/
var ContactField = function(type, value, primary) {
+ this.id = null;
this.type = type || null;
this.value = value || null;
this.primary = primary || null;
@@ -1179,6 +1325,7 @@ var ContactField = function(type, value, primary) {
/**
* Contact address.
+* @param {DOMString} id unique identifier, should only be set by native code
* @param formatted
* @param streetAddress
* @param locality
@@ -1187,6 +1334,7 @@ var ContactField = function(type, value, primary) {
* @param country
*/
var ContactAddress = function(formatted, streetAddress, locality, region, postalCode, country) {
+ this.id = null;
this.formatted = formatted || null;
this.streetAddress = streetAddress || null;
this.locality = locality || null;
@@ -1197,6 +1345,7 @@ var ContactAddress = function(formatted, streetAddress, locality, region, postal
/**
* Contact organization.
+* @param {DOMString} id unique identifier, should only be set by native code
* @param name
* @param dept
* @param title
@@ -1206,6 +1355,7 @@ var ContactAddress = function(formatted, streetAddress, locality, region, postal
* @param desc
*/
var ContactOrganization = function(name, dept, title, startDate, endDate, location, desc) {
+ this.id = null;
this.name = name || null;
this.department = dept || null;
this.title = title || null;
@@ -1217,11 +1367,13 @@ var ContactOrganization = function(name, dept, title, startDate, endDate, locati
/**
* Contact account.
+* @param {DOMString} id unique identifier, should only be set by native code
* @param domain
* @param username
* @param userid
*/
var ContactAccount = function(domain, username, userid) {
+ this.id = null;
this.domain = domain || null;
this.username = username || null;
this.userid = userid || null;
@@ -1254,7 +1406,7 @@ Contacts.prototype.find = function(fields, successCB, errorCB, options) {
* @returns new Contact object
*/
Contacts.prototype.create = function(properties) {
- var contact = new Contact();
+ var contact = new Contact();
for (i in properties) {
if (contact[i]!='undefined') {
contact[i]=properties[i];
@@ -1264,6 +1416,23 @@ Contacts.prototype.create = function(properties) {
};
/**
+* This function returns and array of contacts. It is required as we need to convert raw
+* JSON objects into concrete Contact objects. Currently this method is called after
+* navigator.service.contacts.find but before the find methods success call back.
+*
+* @param jsonArray an array of JSON Objects that need to be converted to Contact objects.
+* @returns an array of Contact objects
+*/
+Contacts.prototype.cast = function(pluginResult) {
+ var contacts = new Array();
+ for (var i=0; i<pluginResult.message.length; i++) {
+ contacts.push(navigator.service.contacts.create(pluginResult.message[i]));
+ }
+ pluginResult.message = contacts;
+ return pluginResult;
+}
+
+/**
* ContactFindOptions.
* @param filter used to match contacts against
* @param multiple boolean used to determine if more than one contact should be returned
@@ -1452,19 +1621,14 @@ PhoneGap.addConstructor(function() {
*/
/**
- * List of files
- */
-function FileList() {
- this.files = {};
-};
-
-/**
- * Describes a single file in a FileList
+ * This class provides some useful information about a file.
+ * This is the fields returned when navigator.fileMgr.getFileProperties()
+ * is called.
*/
-function File() {
- this.name = null;
- this.type = null;
- this.urn = null;
+function FileProperties(filePath) {
+ this.filePath = filePath;
+ this.size = 0;
+ this.lastModifiedDate = null;
};
/**
@@ -1484,22 +1648,22 @@ File._createEvent = function(type, target) {
};
function FileError() {
- // File error codes
- // Found in DOMException
- this.NOT_FOUND_ERR = 1;
- this.SECURITY_ERR = 2;
- this.ABORT_ERR = 3;
-
- // Added by this specification
- this.NOT_READABLE_ERR = 4;
- this.ENCODING_ERR = 5;
- this.NO_MODIFICATION_ALLOWED_ERR = 6;
- this.INVALID_STATE_ERR = 7;
- this.SYNTAX_ERR = 8;
-
this.code = null;
};
+// File error codes
+// Found in DOMException
+FileError.NOT_FOUND_ERR = 1;
+FileError.SECURITY_ERR = 2;
+FileError.ABORT_ERR = 3;
+
+// Added by this specification
+FileError.NOT_READABLE_ERR = 4;
+FileError.ENCODING_ERR = 5;
+FileError.NO_MODIFICATION_ALLOWED_ERR = 6;
+FileError.INVALID_STATE_ERR = 7;
+FileError.SYNTAX_ERR = 8;
+
//-----------------------------------------------------------------------------
// File manager
//-----------------------------------------------------------------------------
@@ -1507,41 +1671,53 @@ function FileError() {
function FileMgr() {
};
+FileMgr.prototype.getFileProperties = function(filePath) {
+ return PhoneGap.exec(null, null, "File", "getFile", [filePath]);
+};
+
FileMgr.prototype.getFileBasePaths = function() {
};
+FileMgr.prototype.getRootPaths = function() {
+ return PhoneGap.exec(null, null, "File", "getRootPaths", []);
+};
+
FileMgr.prototype.testSaveLocationExists = function(successCallback, errorCallback) {
- PhoneGap.exec(successCallback, errorCallback, "File", "testSaveLocationExists", []);
+ return PhoneGap.exec(successCallback, errorCallback, "File", "testSaveLocationExists", []);
};
FileMgr.prototype.testFileExists = function(fileName, successCallback, errorCallback) {
- PhoneGap.exec(successCallback, errorCallback, "File", "testFileExists", [fileName]);
+ return PhoneGap.exec(successCallback, errorCallback, "File", "testFileExists", [fileName]);
};
FileMgr.prototype.testDirectoryExists = function(dirName, successCallback, errorCallback) {
- PhoneGap.exec(successCallback, errorCallback, "File", "testDirectoryExists", [dirName]);
+ return PhoneGap.exec(successCallback, errorCallback, "File", "testDirectoryExists", [dirName]);
};
FileMgr.prototype.createDirectory = function(dirName, successCallback, errorCallback) {
- PhoneGap.exec(successCallback, errorCallback, "File", "createDirectory", [dirName]);
+ return PhoneGap.exec(successCallback, errorCallback, "File", "createDirectory", [dirName]);
};
FileMgr.prototype.deleteDirectory = function(dirName, successCallback, errorCallback) {
- PhoneGap.exec(successCallback, errorCallback, "File", "deleteDirectory", [dirName]);
+ return PhoneGap.exec(successCallback, errorCallback, "File", "deleteDirectory", [dirName]);
};
FileMgr.prototype.deleteFile = function(fileName, successCallback, errorCallback) {
- PhoneGap.exec(successCallback, errorCallback, "File", "deleteFile", [fileName]);
+ return PhoneGap.exec(successCallback, errorCallback, "File", "deleteFile", [fileName]);
};
FileMgr.prototype.getFreeDiskSpace = function(successCallback, errorCallback) {
- PhoneGap.exec(successCallback, errorCallback, "File", "getFreeDiskSpace", []);
+ return PhoneGap.exec(successCallback, errorCallback, "File", "getFreeDiskSpace", []);
};
FileMgr.prototype.writeAsText = function(fileName, data, append, successCallback, errorCallback) {
PhoneGap.exec(successCallback, errorCallback, "File", "writeAsText", [fileName, data, append]);
};
+FileMgr.prototype.write = function(fileName, data, position, successCallback, errorCallback) {
+ PhoneGap.exec(successCallback, errorCallback, "File", "write", [fileName, data, position]);
+};
+
FileMgr.prototype.truncate = function(fileName, size, successCallback, errorCallback) {
PhoneGap.exec(successCallback, errorCallback, "File", "truncate", [fileName, size]);
};
@@ -1601,14 +1777,28 @@ FileReader.DONE = 2;
*/
FileReader.prototype.abort = function() {
this.readyState = FileReader.DONE;
+ this.result = null;
+ // set error
+ var error = new FileError();
+ error.code = error.ABORT_ERR;
+ this.error = error;
+
+ // If error callback
+ if (typeof this.onerror == "function") {
+ var evt = File._createEvent("error", this);
+ this.onerror(evt);
+ }
// If abort callback
if (typeof this.onabort == "function") {
var evt = File._createEvent("abort", this);
this.onabort(evt);
}
-
- // TODO: Anything else to do? Maybe sent to native?
+ // If load end callback
+ if (typeof this.onloadend == "function") {
+ var evt = File._createEvent("loadend", this);
+ this.onloadend(evt);
+ }
};
/**
@@ -1648,15 +1838,15 @@ FileReader.prototype.readAsText = function(file, encoding) {
// Save result
me.result = r;
- // DONE state
- me.readyState = FileReader.DONE;
-
// If onload callback
if (typeof me.onload == "function") {
var evt = File._createEvent("load", me);
me.onload(evt);
}
+ // DONE state
+ me.readyState = FileReader.DONE;
+
// If onloadend callback
if (typeof me.onloadend == "function") {
var evt = File._createEvent("loadend", me);
@@ -1675,15 +1865,15 @@ FileReader.prototype.readAsText = function(file, encoding) {
// Save error
me.error = e;
- // DONE state
- me.readyState = FileReader.DONE;
-
// If onerror callback
if (typeof me.onerror == "function") {
var evt = File._createEvent("error", me);
me.onerror(evt);
}
+ // DONE state
+ me.readyState = FileReader.DONE;
+
// If onloadend callback
if (typeof me.onloadend == "function") {
var evt = File._createEvent("loadend", me);
@@ -1729,15 +1919,15 @@ FileReader.prototype.readAsDataURL = function(file) {
// Save result
me.result = r;
- // DONE state
- me.readyState = FileReader.DONE;
-
// If onload callback
if (typeof me.onload == "function") {
var evt = File._createEvent("load", me);
me.onload(evt);
}
+ // DONE state
+ me.readyState = FileReader.DONE;
+
// If onloadend callback
if (typeof me.onloadend == "function") {
var evt = File._createEvent("loadend", me);
@@ -1756,15 +1946,15 @@ FileReader.prototype.readAsDataURL = function(file) {
// Save error
me.error = e;
- // DONE state
- me.readyState = FileReader.DONE;
-
// If onerror callback
if (typeof me.onerror == "function") {
var evt = File._createEvent("error", me);
me.onerror(evt);
}
+ // DONE state
+ me.readyState = FileReader.DONE;
+
// If onloadend callback
if (typeof me.onloadend == "function") {
var evt = File._createEvent("loadend", me);
@@ -1804,9 +1994,20 @@ FileReader.prototype.readAsArrayBuffer = function(file) {
* For Android:
* The root directory is the root of the file system.
* To write to the SD card, the file name is "sdcard/my_file.txt"
+ *
+ * @param filePath the file to write to
+ * @param append if true write to the end of the file, otherwise overwrite the file
*/
-function FileWriter() {
+function FileWriter(filePath, append) {
this.fileName = "";
+ this.length = 0;
+ if (filePath) {
+ var f = navigator.fileMgr.getFileProperties(filePath);
+ this.fileName = f.name;
+ this.length = f.size;
+ }
+ // default is to write at the beginning of the file
+ this.position = (append !== true) ? 0 : this.length;
this.readyState = 0; // EMPTY
@@ -1833,17 +2034,38 @@ FileWriter.DONE = 2;
* Abort writing file.
*/
FileWriter.prototype.abort = function() {
- this.readyState = FileWriter.DONE;
-
+ // set error
+ var error = new FileError();
+ error.code = error.ABORT_ERR;
+ this.error = error;
+
+ // If error callback
+ if (typeof this.onerror == "function") {
+ var evt = File._createEvent("error", this);
+ this.onerror(evt);
+ }
// If abort callback
if (typeof this.onabort == "function") {
var evt = File._createEvent("abort", this);
this.onabort(evt);
}
+
+ this.readyState = FileWriter.DONE;
- // TODO: Anything else to do? Maybe sent to native?
+ // If load end callback
+ if (typeof this.onloadend == "function") {
+ var evt = File._createEvent("writeend", this);
+ this.onloadend(evt);
+ }
};
+/**
+ * @Deprecated: use write instead
+ *
+ * @param file to write the data to
+ * @param text to be written
+ * @param bAppend if true write to end of file, otherwise overwrite the file
+ */
FileWriter.prototype.writeAsText = function(file, text, bAppend) {
// Throw an exception if we are already writing a file
if (this.readyState == FileWriter.WRITING) {
@@ -1927,13 +2149,135 @@ FileWriter.prototype.writeAsText = function(file, text, bAppend) {
};
-FileWriter.prototype.truncate = function(file, size) {
+/**
+ * Writes data to the file
+ *
+ * @param text to be written
+ */
+FileWriter.prototype.write = function(text) {
// Throw an exception if we are already writing a file
if (this.readyState == FileWriter.WRITING) {
throw FileError.INVALID_STATE_ERR;
}
- this.fileName = file;
+ // WRITING state
+ this.readyState = FileWriter.WRITING;
+
+ var me = this;
+
+ // If onwritestart callback
+ if (typeof me.onwritestart == "function") {
+ var evt = File._createEvent("writestart", me);
+ me.onwritestart(evt);
+ }
+
+ // Write file
+ navigator.fileMgr.write(this.fileName, text, this.position,
+
+ // Success callback
+ function(r) {
+
+ // If DONE (cancelled), then don't do anything
+ if (me.readyState == FileWriter.DONE) {
+ return;
+ }
+
+ // So if the user wants to keep appending to the file
+ me.length = Math.max(me.length, me.position + r);
+ // position always increases by bytes written because file would be extended
+ me.position += r;
+
+ // If onwrite callback
+ if (typeof me.onwrite == "function") {
+ var evt = File._createEvent("write", me);
+ me.onwrite(evt);
+ }
+
+ // DONE state
+ me.readyState = FileWriter.DONE;
+
+ // If onwriteend callback
+ if (typeof me.onwriteend == "function") {
+ var evt = File._createEvent("writeend", me);
+ me.onwriteend(evt);
+ }
+ },
+
+ // Error callback
+ function(e) {
+
+ // If DONE (cancelled), then don't do anything
+ if (me.readyState == FileWriter.DONE) {
+ return;
+ }
+
+ // Save error
+ me.error = e;
+
+ // If onerror callback
+ if (typeof me.onerror == "function") {
+ var evt = File._createEvent("error", me);
+ me.onerror(evt);
+ }
+
+ // DONE state
+ me.readyState = FileWriter.DONE;
+
+ // If onwriteend callback
+ if (typeof me.onwriteend == "function") {
+ var evt = File._createEvent("writeend", me);
+ me.onwriteend(evt);
+ }
+ }
+ );
+
+};
+
+/**
+ * Moves the file pointer to the location specified.
+ *
+ * If the offset is a negative number the position of the file
+ * pointer is rewound. If the offset is greater than the file
+ * size the position is set to the end of the file.
+ *
+ * @param offset is the location to move the file pointer to.
+ */
+FileWriter.prototype.seek = function(offset) {
+ // Throw an exception if we are already writing a file
+ if (this.readyState === FileWriter.WRITING) {
+ throw FileError.INVALID_STATE_ERR;
+ }
+
+ if (!offset) {
+ return;
+ }
+
+ // See back from end of file.
+ if (offset < 0) {
+ this.position = Math.max(offset + this.length, 0);
+ }
+ // Offset is bigger then file size so set position
+ // to the end of the file.
+ else if (offset > this.length) {
+ this.position = this.length;
+ }
+ // Offset is between 0 and file size so set the position
+ // to start writing.
+ else {
+ this.position = offset;
+ }
+};
+
+/**
+ * Truncates the file to the size specified.
+ *
+ * @param size to chop the file at.
+ */
+FileWriter.prototype.truncate = function(size) {
+ // Throw an exception if we are already writing a file
+ if (this.readyState == FileWriter.WRITING) {
+ throw FileError.INVALID_STATE_ERR;
+ }
// WRITING state
this.readyState = FileWriter.WRITING;
@@ -1947,7 +2291,7 @@ FileWriter.prototype.truncate = function(file, size) {
}
// Write file
- navigator.fileMgr.truncate(file, size,
+ navigator.fileMgr.truncate(this.fileName, size,
// Success callback
function(r) {
@@ -1957,8 +2301,9 @@ FileWriter.prototype.truncate = function(file, size) {
return;
}
- // Save result
- me.result = r;
+ // Update the length of the file
+ me.length = r;
+ me.position = Math.min(me.position, r);;
// If onwrite callback
if (typeof me.onwrite == "function") {
@@ -2211,27 +2556,38 @@ PhoneGap.addConstructor(function() {
* Copyright (c) 2010, IBM Corporation
*/
-function KeyEvent()
-{
-}
-KeyEvent.prototype.backTrigger = function()
-{
- var e = document.createEvent('Events');
- e.initEvent('backKeyDown');
- document.dispatchEvent(e);
-}
+/*
+ * PhoneGap is available under *either* the terms of the modified BSD license *or* the
+ * MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
+ *
+ * Copyright (c) 2005-2010, Nitobi Software Inc.
+ * Copyright (c) 2010, IBM Corporation
+ */
-KeyEvent.prototype.menuTrigger = function()
-{
- var e = document.createEvent('Events');
- e.initEvent('menuKeyDown');
- document.dispatchEvent(e);
+function KeyEvent() {
}
-if (document.keyEvent == null || typeof document.keyEvent == 'undefined')
-{
- window.keyEvent = document.keyEvent = new KeyEvent();
+KeyEvent.prototype.backTrigger = function() {
+ var e = document.createEvent('Events');
+ e.initEvent('backKeyDown');
+ document.dispatchEvent(e);
+};
+
+KeyEvent.prototype.menuTrigger = function() {
+ var e = document.createEvent('Events');
+ e.initEvent('menuKeyDown');
+ document.dispatchEvent(e);
+};
+
+KeyEvent.prototype.searchTrigger = function() {
+ var e = document.createEvent('Events');
+ e.initEvent('searchKeyDown');
+ document.dispatchEvent(e);
+};
+
+if (document.keyEvent == null || typeof document.keyEvent == 'undefined') {
+ window.keyEvent = document.keyEvent = new KeyEvent();
}
@@ -2707,20 +3063,6 @@ PositionError.TIMEOUT = 3;
* Copyright (c) 2010, IBM Corporation
*/
-PhoneGap.addConstructor(function() {
- if (typeof navigator.splashScreen == "undefined") {
- navigator.splashScreen = SplashScreen; // SplashScreen object come from native side through addJavaScriptInterface
- }
-});
-
-/*
- * PhoneGap is available under *either* the terms of the modified BSD license *or* the
- * MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
- *
- * Copyright (c) 2005-2010, Nitobi Software Inc.
- * Copyright (c) 2010, IBM Corporation
- */
-
/*
* This is purely for the Android 1.5/1.6 HTML 5 Storage
* I was hoping that Android 2.0 would deprecate this, but given the fact that
@@ -2736,29 +3078,12 @@ var DroidDB = function() {
};
/**
- * Callback from native code when result from a query is available.
- * PRIVATE METHOD
- *
- * @param rawdata JSON string of the row data
- * @param id Query id
- */
-DroidDB.prototype.addResult = function(rawdata, id) {
- try {
- eval("var data = " + rawdata + ";");
- var query = this.queryQueue[id];
- query.resultSet.push(data);
- } catch (e) {
- console.log("DroidDB.addResult(): Error="+e);
- }
-};
-
-/**
* Callback from native code when query is complete.
* PRIVATE METHOD
*
* @param id Query id
*/
-DroidDB.prototype.completeQuery = function(id) {
+DroidDB.prototype.completeQuery = function(id, data) {
var query = this.queryQueue[id];
if (query) {
try {
@@ -2774,8 +3099,8 @@ DroidDB.prototype.completeQuery = function(id) {
// Save query results
var r = new DroidDB_Result();
- r.rows.resultSet = query.resultSet;
- r.rows.length = query.resultSet.length;
+ r.rows.resultSet = data;
+ r.rows.length = data.length;
try {
if (typeof query.successCallback == 'function') {
query.successCallback(query.tx, r);
@@ -2842,7 +3167,7 @@ var DatabaseShell = function() {
* @param successCallback {Function}
* @param errorCallback {Function}
*/
-DatabaseShell.prototype.transaction = function(process, successCallback, errorCallback) {
+DatabaseShell.prototype.transaction = function(process, errorCallback, successCallback) {
var tx = new DroidDB_Tx();
tx.successCallback = successCallback;
tx.errorCallback = errorCallback;
@@ -3023,11 +3348,73 @@ DroidDB_openDatabase = function(name, version, display_name, size) {
return db;
};
+
+/**
+ * For browsers with no localStorage we emulate it with SQLite. Follows the w3c api.
+ * TODO: Do similar for sessionStorage.
+ */
+
+var CupcakeLocalStorage = function() {
+ try {
+
+ this.db = openDatabase('localStorage', '1.0', 'localStorage', 2621440);
+ var storage = {};
+ this.db.transaction(
+ function (transaction) {
+ transaction.executeSql('CREATE TABLE IF NOT EXISTS storage (id NVARCHAR(40) PRIMARY KEY, body NVARCHAR(255))');
+ transaction.executeSql('SELECT * FROM storage', [], function(tx, result) {
+ for(var i = 0; i < result.rows.length; i++) {
+ storage[result.rows.item(i)['id']] = result.rows.item(i)['body'];
+ }
+ });
+
+ },
+ function (err) {
+ alert(err.message);
+ }
+ );
+ this.setItem = function(key, val) {
+ console.log('set');
+ storage[key] = val;
+
+ this.db.transaction(
+ function (transaction) {
+ transaction.executeSql('CREATE TABLE IF NOT EXISTS storage (id NVARCHAR(40) PRIMARY KEY, body NVARCHAR(255))');
+
+ transaction.executeSql('REPLACE INTO storage (id, body) values(?,?)', [key,val]);
+ }
+ );
+ }
+ this.getItem = function(key) {
+ return storage[key];
+ }
+ this.removeItem = function(key) {
+ delete storage[key];
+ this.db.transaction(
+ function (transaction) {
+ transaction.executeSql('CREATE TABLE IF NOT EXISTS storage (id NVARCHAR(40) PRIMARY KEY, body NVARCHAR(255))');
+
+ transaction.executeSql('DELETE FROM storage where id=?', [key]);
+ }
+ );
+
+ }
+
+ } catch(e) {
+ alert("Database error "+e+".");
+ return;
+ }
+};
PhoneGap.addConstructor(function() {
- if (typeof window.openDatabase == "undefined") {
+ if (typeof window.openDatabase == "undefined") {
navigator.openDatabase = window.openDatabase = DroidDB_openDatabase;
window.droiddb = new DroidDB();
}
+
+ if (typeof window.localStorage == "undefined") {
+ navigator.localStorage = window.localStorage = new CupcakeLocalStorage();
+ }
});
+
View
BIN  Android/Sample/libs/phonegap-0.9.3.jar
Binary file not shown
View
BIN  Android/Sample/res/drawable-hdpi/icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  Android/Sample/res/drawable-ldpi/icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  Android/Sample/res/drawable-mdpi/icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  Android/phonegap-0.9.3.jar
Binary file not shown
View
665 Android/phonegap-0.9.3.js
@@ -157,26 +157,32 @@ PhoneGap.addConstructor = function(func) {
try {
func();
} catch(e) {
- if (typeof(debug['log']) == 'function') {
- debug.log("Failed to run constructor: " + debug.processMessage(e));
- } else {
- alert("Failed to run constructor: " + e.message);
- }
+ console.log("Failed to run constructor: " + e);
}
});
};
/**
- * Adds a plugin object to window.plugins
+ * Plugins object
*/
-PhoneGap.addPlugin = function(name, obj) {
- if ( !window.plugins ) {
- window.plugins = {};
- }
+if (!window.plugins) {
+ window.plugins = {};
+}
- if ( !window.plugins[name] ) {
- window.plugins[name] = obj;
- }
+/**
+ * Adds a plugin object to window.plugins.
+ * The plugin is accessed using window.plugins.<name>
+ *
+ * @param name The plugin name
+ * @param obj The plugin object
+ */
+PhoneGap.addPlugin = function(name, obj) {
+ if (!window.plugins[name]) {
+ window.plugins[name] = obj;
+ }
+ else {
+ console.log("Error: Plugin "+name+" already exists.");
+ }
}
/**
@@ -286,7 +292,7 @@ document.addEventListener = function(evt, handler, capture) {
} else if (e == 'pause') {
PhoneGap.onPause.subscribe(handler);
} else {
- PhoneGap.m_document_addEventListener.call(document, evt, handler);
+ PhoneGap.m_document_addEventListener.call(document, evt, handler, capture);
}
};
@@ -315,18 +321,27 @@ PhoneGap.stringify = function(args) {
var start = true;
s = s + '{';
for (var name in args[i]) {
- if (!start) {
- s = s + ',';
- }
- s = s + '"' + name + '":';
- var nameType = typeof args[i][name];
- if ((nameType == "number") || (nameType == "boolean")) {
- s = s + args[i][name];
- }
- else {
- s = s + '"' + args[i][name] + '"';
- }
- start=false;
+ if (args[i][name] != null) {
+ if (!start) {
+ s = s + ',';
+ }
+ s = s + '"' + name + '":';
+ var nameType = typeof args[i][name];
+ if ((nameType == "number") || (nameType == "boolean")) {
+ s = s + args[i][name];
+ }
+ else if ((typeof args[i][name]) == 'function') {
+ // don't copy the functions
+ s = s + '""';
+ }
+ else if (args[i][name] instanceof Object) {
+ s = s + this.stringify(args[i][name]);
+ }
+ else {
+ s = s + '"' + args[i][name] + '"';
+ }
+ start=false;
+ }
}
s = s + '}';
}
@@ -430,7 +445,7 @@ PhoneGap.exec = function(success, fail, service, action, args) {
// If there is a success callback, then call it now with returned value
if (success) {
try {
- success(v.message);
+ success(v.message);
}
catch (e) {
console.log("Error in success callback: "+callbackId+" = "+e);
@@ -492,7 +507,7 @@ PhoneGap.callbackSuccess = function(callbackId, args) {
if (args.status == PhoneGap.callbackStatus.OK) {
try {
if (PhoneGap.callbacks[callbackId].success) {
- PhoneGap.callbacks[callbackId].success(args.message);
+ PhoneGap.callbacks[callbackId].success(args.message);
}
}
catch (e) {
@@ -722,6 +737,22 @@ PhoneGap.close = function(context, func, params) {
}
};
+/**
+ * Load a JavaScript file after page has loaded.
+ *
+ * @param {String} jsfile The url of the JavaScript file to load.
+ * @param {Function} successCallback The callback to call when the file has been loaded.
+ */
+PhoneGap.includeJavascript = function(jsfile, successCallback) {
+ var id = document.getElementsByTagName("head")[0];
+ var el = document.createElement('script');
+ el.type = 'text/javascript';
+ if (typeof successCallback == 'function') {
+ el.onload = successCallback;
+ }
+ el.src = jsfile;
+ id.appendChild(el);
+};
/*
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
@@ -852,6 +883,74 @@ PhoneGap.addConstructor(function() {
*/
/**
+ * Constructor
+ */
+function App() {
+}
+
+/**
+ * Clear the resource cache.
+ */
+App.prototype.clearCache = function() {
+ PhoneGap.exec(null, null, "App", "clearCache", []);
+};
+
+/**
+ * Load the url into the webview.
+ *
+ * @param url The URL to load
+ * @param props Properties that can be passed in to the activity:
+ * wait: int => wait msec before loading URL
+ * loadingDialog: "Title,Message" => display a native loading dialog
+ * hideLoadingDialogOnPage: boolean => hide loadingDialog when page loaded instead of when deviceready event occurs.
+ * loadInWebView: boolean => cause all links on web page to be loaded into existing web view, instead of being loaded into new browser.
+ * loadUrlTimeoutValue: int => time in msec to wait before triggering a timeout error
+ * errorUrl: URL => URL to load if there's an error loading specified URL with loadUrl(). Should be a local URL such as file:///android_asset/www/error.html");
+ * keepRunning: boolean => enable app to keep running in background
+ *
+ * Example:
+ * App app = new App();
+ * app.loadUrl("http://server/myapp/index.html", {wait:2000, loadingDialog:"Wait,Loading App", loadUrlTimeoutValue: 60000});
+ */
+App.prototype.loadUrl = function(url, props) {
+ PhoneGap.exec(null, null, "App", "loadUrl", [url, props]);
+};
+
+/**
+ * Cancel loadUrl that is waiting to be loaded.
+ */
+App.prototype.cancelLoadUrl = function() {
+ PhoneGap.exec(null, null, "App", "cancelLoadUrl", []);
+};
+
+/**
+ * Clear web history in this web view.
+ * Instead of BACK button loading the previous web page, it will exit the app.
+ */
+App.prototype.clearHistory = function() {
+ PhoneGap.exec(null, null, "App", "clearHistory", []);
+};
+
+/**
+ * Add a class that implements a service.
+ *
+ * @param serviceType
+ * @param className
+ */
+App.prototype.addService = function(serviceType, className) {
+ PhoneGap.exec(null, null, "App", "addService", [serviceType, className]);
+};
+
+
+/*
+ * PhoneGap is available under *either* the terms of the modified BSD license *or* the
+ * MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
+ *
+ * Copyright (c) 2005-2010, Nitobi Software Inc.
+ * Copyright (c) 2010, IBM Corporation
+ */
+
+/**
* This class provides access to the device camera.
*
* @constructor
@@ -1089,6 +1188,7 @@ var Contact = function(id, displayName, name, nickname, phoneNumbers, emails, ad
ims, organizations, published, updated, birthday, anniversary, gender, note,
preferredUsername, photos, tags, relationships, urls, accounts, utcOffset, connected) {
this.id = id || null;
+ this.rawId = null;
this.displayName = displayName || null;
this.name = name || null; // ContactName
this.nickname = nickname || null;
@@ -1124,8 +1224,9 @@ Contact.prototype.remove = function(successCB, errorCB) {
errorObj.code = ContactError.NOT_FOUND_ERROR;
errorCB(errorObj);
}
-
- PhoneGap.exec(successCB, errorCB, "Contacts", "remove", [this.id]);
+ else {
+ PhoneGap.exec(successCB, errorCB, "Contacts", "remove", [this.id]);
+ }
};
/**
@@ -1136,6 +1237,48 @@ Contact.prototype.remove = function(successCB, errorCB) {
Contact.prototype.clone = function() {
var clonedContact = PhoneGap.clone(this);
clonedContact.id = null;
+ clonedContact.rawId = null;
+ // Loop through and clear out any id's in phones, emails, etc.
+ if (clonedContact.phoneNumbers) {
+ for (i=0; i<clonedContact.phoneNumbers.length; i++) {
+ clonedContact.phoneNumbers[i].id = null;
+ }
+ }
+ if (clonedContact.emails) {
+ for (i=0; i<clonedContact.emails.length; i++) {
+ clonedContact.emails[i].id = null;
+ }
+ }
+ if (clonedContact.addresses) {
+ for (i=0; i<clonedContact.addresses.length; i++) {
+ clonedContact.addresses[i].id = null;
+ }
+ }
+ if (clonedContact.ims) {
+ for (i=0; i<clonedContact.ims.length; i++) {
+ clonedContact.ims[i].id = null;
+ }
+ }
+ if (clonedContact.organizations) {
+ for (i=0; i<clonedContact.organizations.length; i++) {
+ clonedContact.organizations[i].id = null;
+ }
+ }
+ if (clonedContact.tags) {
+ for (i=0; i<clonedContact.tags.length; i++) {
+ clonedContact.tags[i].id = null;
+ }
+ }
+ if (clonedContact.relationships) {
+ for (i=0; i<clonedContact.relationships.length; i++) {
+ clonedContact.relationships[i].id = null;
+ }
+ }
+ if (clonedContact.urls) {
+ for (i=0; i<clonedContact.urls.length; i++) {
+ clonedContact.urls[i].id = null;
+ }
+ }
return clonedContact;
};
@@ -1145,6 +1288,7 @@ Contact.prototype.clone = function() {
* @param errorCB error callback
*/
Contact.prototype.save = function(successCB, errorCB) {
+ PhoneGap.exec(successCB, errorCB, "Contacts", "save", [this]);
};
/**
@@ -1167,11 +1311,13 @@ var ContactName = function(formatted, familyName, givenName, middle, prefix, suf
/**
* Generic contact field.
+* @param {DOMString} id unique identifier, should only be set by native code
* @param type
* @param value
* @param primary
*/
var ContactField = function(type, value, primary) {
+ this.id = null;
this.type = type || null;
this.value = value || null;
this.primary = primary || null;
@@ -1179,6 +1325,7 @@ var ContactField = function(type, value, primary) {
/**
* Contact address.
+* @param {DOMString} id unique identifier, should only be set by native code
* @param formatted
* @param streetAddress
* @param locality
@@ -1187,6 +1334,7 @@ var ContactField = function(type, value, primary) {
* @param country
*/
var ContactAddress = function(formatted, streetAddress, locality, region, postalCode, country) {
+ this.id = null;
this.formatted = formatted || null;
this.streetAddress = streetAddress || null;
this.locality = locality || null;
@@ -1197,6 +1345,7 @@ var ContactAddress = function(formatted, streetAddress, locality, region, postal
/**
* Contact organization.
+* @param {DOMString} id unique identifier, should only be set by native code
* @param name
* @param dept
* @param title
@@ -1206,6 +1355,7 @@ var ContactAddress = function(formatted, streetAddress, locality, region, postal
* @param desc
*/
var ContactOrganization = function(name, dept, title, startDate, endDate, location, desc) {
+ this.id = null;
this.name = name || null;
this.department = dept || null;
this.title = title || null;
@@ -1217,11 +1367,13 @@ var ContactOrganization = function(name, dept, title, startDate, endDate, locati
/**
* Contact account.
+* @param {DOMString} id unique identifier, should only be set by native code
* @param domain
* @param username
* @param userid
*/
var ContactAccount = function(domain, username, userid) {
+ this.id = null;
this.domain = domain || null;
this.username = username || null;
this.userid = userid || null;
@@ -1254,7 +1406,7 @@ Contacts.prototype.find = function(fields, successCB, errorCB, options) {
* @returns new Contact object
*/
Contacts.prototype.create = function(properties) {
- var contact = new Contact();
+ var contact = new Contact();
for (i in properties) {
if (contact[i]!='undefined') {
contact[i]=properties[i];
@@ -1264,6 +1416,23 @@ Contacts.prototype.create = function(properties) {
};
/**
+* This function returns and array of contacts. It is required as we need to convert raw
+* JSON objects into concrete Contact objects. Currently this method is called after
+* navigator.service.contacts.find but before the find methods success call back.
+*
+* @param jsonArray an array of JSON Objects that need to be converted to Contact objects.
+* @returns an array of Contact objects
+*/
+Contacts.prototype.cast = function(pluginResult) {
+ var contacts = new Array();
+ for (var i=0; i<pluginResult.message.length; i++) {
+ contacts.push(navigator.service.contacts.create(pluginResult.message[i]));
+ }
+ pluginResult.message = contacts;
+ return pluginResult;
+}
+
+/**
* ContactFindOptions.
* @param filter used to match contacts against
* @param multiple boolean used to determine if more than one contact should be returned
@@ -1452,19 +1621,14 @@ PhoneGap.addConstructor(function() {
*/
/**
- * List of files
- */
-function FileList() {
- this.files = {};
-};
-
-/**
- * Describes a single file in a FileList
+ * This class provides some useful information about a file.
+ * This is the fields returned when navigator.fileMgr.getFileProperties()
+ * is called.
*/
-function File() {
- this.name = null;
- this.type = null;
- this.urn = null;
+function FileProperties(filePath) {
+ this.filePath = filePath;
+ this.size = 0;
+ this.lastModifiedDate = null;
};
/**
@@ -1484,22 +1648,22 @@ File._createEvent = function(type, target) {
};
function FileError() {
- // File error codes
- // Found in DOMException
- this.NOT_FOUND_ERR = 1;
- this.SECURITY_ERR = 2;
- this.ABORT_ERR = 3;
-
- // Added by this specification
- this.NOT_READABLE_ERR = 4;
- this.ENCODING_ERR = 5;
- this.NO_MODIFICATION_ALLOWED_ERR = 6;
- this.INVALID_STATE_ERR = 7;
- this.SYNTAX_ERR = 8;
-
this.code = null;
};
+// File error codes
+// Found in DOMException
+FileError.NOT_FOUND_ERR = 1;
+FileError.SECURITY_ERR = 2;
+FileError.ABORT_ERR = 3;
+
+// Added by this specification
+FileError.NOT_READABLE_ERR = 4;
+FileError.ENCODING_ERR = 5;
+FileError.NO_MODIFICATION_ALLOWED_ERR = 6;
+FileError.INVALID_STATE_ERR = 7;
+FileError.SYNTAX_ERR = 8;
+
//-----------------------------------------------------------------------------
// File manager
//-----------------------------------------------------------------------------
@@ -1507,41 +1671,53 @@ function FileError() {
function FileMgr() {
};
+FileMgr.prototype.getFileProperties = function(filePath) {
+ return PhoneGap.exec(null, null, "File", "getFile", [filePath]);
+};
+
FileMgr.prototype.getFileBasePaths = function() {
};
+FileMgr.prototype.getRootPaths = function() {
+ return PhoneGap.exec(null, null, "File", "getRootPaths", []);
+};
+
FileMgr.prototype.testSaveLocationExists = function(successCallback, errorCallback) {
- PhoneGap.exec(successCallback, errorCallback, "File", "testSaveLocationExists", []);
+ return PhoneGap.exec(successCallback, errorCallback, "File", "testSaveLocationExists", []);
};
FileMgr.prototype.testFileExists = function(fileName, successCallback, errorCallback) {
- PhoneGap.exec(successCallback, errorCallback, "File", "testFileExists", [fileName]);
+ return PhoneGap.exec(successCallback, errorCallback, "File", "testFileExists", [fileName]);
};
FileMgr.prototype.testDirectoryExists = function(dirName, successCallback, errorCallback) {
- PhoneGap.exec(successCallback, errorCallback, "File", "testDirectoryExists", [dirName]);
+ return PhoneGap.exec(successCallback, errorCallback, "File", "testDirectoryExists", [dirName]);
};
FileMgr.prototype.createDirectory = function(dirName, successCallback, errorCallback) {
- PhoneGap.exec(successCallback, errorCallback, "File", "createDirectory", [dirName]);
+ return PhoneGap.exec(successCallback, errorCallback, "File", "createDirectory", [dirName]);
};
FileMgr.prototype.deleteDirectory = function(dirName, successCallback, errorCallback) {
- PhoneGap.exec(successCallback, errorCallback, "File", "deleteDirectory", [dirName]);
+ return PhoneGap.exec(successCallback, errorCallback, "File", "deleteDirectory", [dirName]);
};
FileMgr.prototype.deleteFile = function(fileName, successCallback, errorCallback) {
- PhoneGap.exec(successCallback, errorCallback, "File", "deleteFile", [fileName]);
+ return PhoneGap.exec(successCallback, errorCallback, "File", "deleteFile", [fileName]);
};
FileMgr.prototype.getFreeDiskSpace = function(successCallback, errorCallback) {
- PhoneGap.exec(successCallback, errorCallback, "File", "getFreeDiskSpace", []);
+ return PhoneGap.exec(successCallback, errorCallback, "File", "getFreeDiskSpace", []);
};
FileMgr.prototype.writeAsText = function(fileName, data, append, successCallback, errorCallback) {
PhoneGap.exec(successCallback, errorCallback, "File", "writeAsText", [fileName, data, append]);
};
+FileMgr.prototype.write = function(fileName, data, position, successCallback, errorCallback) {
+ PhoneGap.exec(successCallback, errorCallback, "File", "write", [fileName, data, position]);
+};
+
FileMgr.prototype.truncate = function(fileName, size, successCallback, errorCallback) {
PhoneGap.exec(successCallback, errorCallback, "File", "truncate", [fileName, size]);
};
@@ -1601,14 +1777,28 @@ FileReader.DONE = 2;
*/
FileReader.prototype.abort = function() {
this.readyState = FileReader.DONE;
+ this.result = null;
+ // set error
+ var error = new FileError();
+ error.code = error.ABORT_ERR;
+ this.error = error;
+
+ // If error callback
+ if (typeof this.onerror == "function") {
+ var evt = File._createEvent("error", this);
+ this.onerror(evt);
+ }
// If abort callback
if (typeof this.onabort == "function") {
var evt = File._createEvent("abort", this);
this.onabort(evt);
}
-
- // TODO: Anything else to do? Maybe sent to native?
+ // If load end callback
+ if (typeof this.onloadend == "function") {
+ var evt = File._createEvent("loadend", this);
+ this.onloadend(evt);
+ }
};
/**
@@ -1648,15 +1838,15 @@ FileReader.prototype.readAsText = function(file, encoding) {
// Save result
me.result = r;
- // DONE state
- me.readyState = FileReader.DONE;
-
// If onload callback
if (typeof me.onload == "function") {
var evt = File._createEvent("load", me);
me.onload(evt);
}
+ // DONE state
+ me.readyState = FileReader.DONE;
+
// If onloadend callback
if (typeof me.onloadend == "function") {
var evt = File._createEvent("loadend", me);
@@ -1675,15 +1865,15 @@ FileReader.prototype.readAsText = function(file, encoding) {
// Save error
me.error = e;
- // DONE state
- me.readyState = FileReader.DONE;
-
// If onerror callback
if (typeof me.onerror == "function") {
var evt = File._createEvent("error", me);
me.onerror(evt);
}
+ // DONE state
+ me.readyState = FileReader.DONE;
+
// If onloadend callback
if (typeof me.onloadend == "function") {
var evt = File._createEvent("loadend", me);
@@ -1729,15 +1919,15 @@ FileReader.prototype.readAsDataURL = function(file) {
// Save result
me.result = r;
- // DONE state
- me.readyState = FileReader.DONE;
-
// If onload callback
if (typeof me.onload == "function") {
var evt = File._createEvent("load", me);
me.onload(evt);
}
+ // DONE state
+ me.readyState = FileReader.DONE;
+
// If onloadend callback
if (typeof me.onloadend == "function") {
var evt = File._createEvent("loadend", me);
@@ -1756,15 +1946,15 @@ FileReader.prototype.readAsDataURL = function(file) {
// Save error
me.error = e;
- // DONE state
- me.readyState = FileReader.DONE;
-
// If onerror callback
if (typeof me.onerror == "function") {
var evt = File._createEvent("error", me);
me.onerror(evt);
}
+ // DONE state
+ me.readyState = FileReader.DONE;
+
// If onloadend callback
if (typeof me.onloadend == "function") {
var evt = File._createEvent("loadend", me);
@@ -1804,9 +1994,20 @@ FileReader.prototype.readAsArrayBuffer = function(file) {
* For Android:
* The root directory is the root of the file system.
* To write to the SD card, the file name is "sdcard/my_file.txt"
+ *
+ * @param filePath the file to write to
+ * @param append if true write to the end of the file, otherwise overwrite the file
*/
-function FileWriter() {
+function FileWriter(filePath, append) {
this.fileName = "";
+ this.length = 0;
+ if (filePath) {
+ var f = navigator.fileMgr.getFileProperties(filePath);
+ this.fileName = f.name;
+ this.length = f.size;
+ }
+ // default is to write at the beginning of the file
+ this.position = (append !== true) ? 0 : this.length;
this.readyState = 0; // EMPTY
@@ -1833,17 +2034,38 @@ FileWriter.DONE = 2;
* Abort writing file.
*/
FileWriter.prototype.abort = function() {
- this.readyState = FileWriter.DONE;
-
+ // set error
+ var error = new FileError();
+ error.code = error.ABORT_ERR;
+ this.error = error;
+
+ // If error callback
+ if (typeof this.onerror == "function") {
+ var evt = File._createEvent("error", this);
+ this.onerror(evt);
+ }
// If abort callback
if (typeof this.onabort == "function") {
var evt = File._createEvent("abort", this);
this.onabort(evt);
}
+
+ this.readyState = FileWriter.DONE;
- // TODO: Anything else to do? Maybe sent to native?
+ // If load end callback
+ if (typeof this.onloadend == "function") {
+ var evt = File._createEvent("writeend", this);
+ this.onloadend(evt);
+ }
};
+/**
+ * @Deprecated: use write instead
+ *
+ * @param file to write the data to
+ * @param text to be written
+ * @param bAppend if true write to end of file, otherwise overwrite the file
+ */
FileWriter.prototype.writeAsText = function(file, text, bAppend) {
// Throw an exception if we are already writing a file
if (this.readyState == FileWriter.WRITING) {