You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by za...@apache.org on 2014/06/10 12:00:53 UTC

[01/12] Manual tests fixed

Repository: cordova-mobile-spec
Updated Branches:
  refs/heads/master 9a8914fdf -> 4322b9c7f


http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/sql/index.js
----------------------------------------------------------------------
diff --git a/sql/index.js b/sql/index.js
new file mode 100644
index 0000000..b5d5653
--- /dev/null
+++ b/sql/index.js
@@ -0,0 +1,125 @@
+//-------------------------------------------------------------------------
+// HTML5 Database
+//-------------------------------------------------------------------------
+var dbs = [];
+var quotas = [2000000, 2000000];
+var names = ['mydb', 'rand' + Math.random()];
+function openDb(index) {
+    try {
+        databaseOutput('Openning db with name: ' + names[index]);
+        return openDatabase(names[index], "1.0", "Apache Cordova Demo", quotas[index]);
+    } catch (e) {
+        databaseOutput('Got exception: ' + e);
+    }
+}
+
+var callDatabase = function(index) {
+    var db = dbs[index] = openDb(index);
+    if (!db) {
+        return;
+    }
+    databaseOutput("Database opened.");
+    db.transaction(function (tx) {
+        tx.executeSql('DROP TABLE IF EXISTS DEMO');
+        tx.executeSql('CREATE TABLE IF NOT EXISTS DEMO (id unique, data)', [],
+             function(tx,results) { console.log("Created table"); },
+             function(tx,err) { alert("Error creating table: "+err.message); });
+        tx.executeSql('INSERT INTO DEMO (id, data) VALUES (1, "First row")', [],
+             function(tx,results) { console.log("Insert row1 success"); },
+             function(tx,err) { alert("Error adding 1st row: "+err.message); });
+        tx.executeSql('INSERT INTO DEMO (id, data) VALUES (2, "Second row")', [],
+             function(tx,results) { console.log("Insert row2 success"); },
+             function(tx,err) { alert("Error adding 2nd row: "+err.message); });
+        databaseOutput("Data written to DEMO table.");
+        console.log("Data written to DEMO table.");
+
+        tx.executeSql('SELECT * FROM DEMO', [], function (tx, results) {
+            var len = results.rows.length;
+            var text = "DEMO table: " + len + " rows found.<br>";
+            text = text + "<table border='1'><tr><td>Row</td><td>Data</td></tr>";
+            for (var i=0; i<len; i++){
+                text = text + "<tr><td>" + i + "</td><td>" + results.rows.item(i).id + ", " + results.rows.item(i).data + "</td></tr>";
+            }
+            text = text + "</table>";
+            databaseOutput(text);
+        }, function(tx, err) {
+            alert("Error processing SELECT * SQL: "+err.message);
+        });
+        tx.executeSql('SELECT ID FROM DEMO', [], function (tx, results) {
+            var len = results.rows.length;
+            var text = "DEMO table: " + len + " rows found.<br>";
+            text = text + "<table border='1'><tr><td>Row</td><td>Data</td></tr>";
+            for (var i=0; i<len; i++){
+                text = text + "<tr><td>" + i + "</td><td>" + results.rows.item(i).id + "</td></tr>";
+            }
+            text = text + "</table>";
+            databaseOutput(text);
+        }, function(tx, err) {
+            alert("Error processing SELECT ID SQL: "+err.message);
+        });
+        
+    },
+    function(err) {
+        console.log("Transaction failed: " + err.message);
+    });
+
+
+};
+
+var readDatabase = function(index) {
+    var db = dbs[index];
+  if (!db) {
+        db = dbs[index] = openDb(index);
+        if (!db) {
+            return;
+        }
+    }
+    db.transaction(function (tx) {
+        tx.executeSql('SELECT * FROM DEMO WHERE id=2', [], function (tx, results) {
+            var len = results.rows.length;
+            var text = "DEMO table: " + len + " rows found.<br>";
+            text = text + "<table border='1'><tr><td>Row</td><td>Data</td></tr>";
+            for (var i=0; i<len; i++){
+                text = text + "<tr><td>" + i + "</td><td>" + results.rows.item(i).id + ", " + results.rows.item(i).data + "</td></tr>";
+            }
+            text = text + "</table>";
+            databaseOutput(text);
+        }, function(tx, err) {
+            alert("Error processing SELECT * WHERE id=2 SQL: "+err.message);
+        });
+    });
+}
+
+function increaseQuota(index) {
+    quotas[index] *= 2;
+    databaseOutput('quota ' + index + ' is now ' + quotas[index]);
+}
+
+var databaseOutput = function(s) {
+    var el = document.getElementById("database_results");
+    el.innerHTML = el.innerHTML + s + "<br>";
+    el.scrollByLines(20000);
+};
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+        console.log("Device="+device.platform+" "+device.version);
+    }, false);
+}
+
+window.onload = function() {
+  addListenerToClass('callDatabase0', callDatabase, [0]);
+  addListenerToClass('readDatabase0', readDatabase, [0]);
+  addListenerToClass('increaseQuota0', increaseQuota, [0]);
+  addListenerToClass('callDatabase1', callDatabase, 1);
+  addListenerToClass('readDatabase1', readDatabase, 1);
+  addListenerToClass('increaseQuota1', increaseQuota, 1);
+  addListenerToClass('reloadPage', function() {
+    location = location.href;
+  });
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/storage/index.html
----------------------------------------------------------------------
diff --git a/storage/index.html b/storage/index.html
index 20e2951..0b713a2 100644
--- a/storage/index.html
+++ b/storage/index.html
@@ -28,45 +28,14 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>      
-
-      
-<script type="text/javascript" charset="utf-8">
-
-    var deviceReady = false;
-    
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-                deviceReady = true;
-                console.log("Device="+device.platform+" "+device.version);
-            }, false);
-        window.setTimeout(function() {
-        	if (!deviceReady) {
-        		alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
-        	}
-        },1000);
-    }
-
-</script>
-
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>Local Storage</h1>
     <div id="info">
         You have run this app <span id="count">an untold number of</span> time(s).
     </div>
-
-    <script>
-    if (!localStorage.pageLoadCount) {
-        localStorage.pageLoadCount = 0;
-    }
-    localStorage.pageLoadCount = parseInt(localStorage.pageLoadCount) + 1;
-    document.getElementById('count').textContent = localStorage.pageLoadCount;
-    </script>
-
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>      

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/storage/index.js
----------------------------------------------------------------------
diff --git a/storage/index.js b/storage/index.js
new file mode 100644
index 0000000..00ae7e1
--- /dev/null
+++ b/storage/index.js
@@ -0,0 +1,27 @@
+var deviceReady = false;
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+            deviceReady = true;
+            console.log("Device="+device.platform+" "+device.version);
+        }, false);
+    window.setTimeout(function() {
+      if (!deviceReady) {
+        alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
+      }
+    },1000);
+}
+
+window.onload = function() {
+  addListenerToClass('backBtn', backHome);
+  init();
+
+  if (!localStorage.pageLoadCount) {
+      localStorage.pageLoadCount = 0;
+  }
+  localStorage.pageLoadCount = parseInt(localStorage.pageLoadCount) + 1;
+  document.getElementById('count').textContent = localStorage.pageLoadCount;
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/vibration/index.html
----------------------------------------------------------------------
diff --git a/vibration/index.html b/vibration/index.html
index ef9b76e..a24110e 100644
--- a/vibration/index.html
+++ b/vibration/index.html
@@ -28,47 +28,16 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>      
-
-      
-<script type="text/javascript" charset="utf-8">
-
-    var deviceReady = false;
-
-    //-------------------------------------------------------------------------
-    // Vibrations
-    //-------------------------------------------------------------------------
-
-    var vibrate = function(){
-      navigator.notification.vibrate(2500);
-    };
-
-    
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-                deviceReady = true;
-                console.log("Device="+device.platform+" "+device.version);
-            }, false);
-        window.setTimeout(function() {
-            if (!deviceReady) {
-                alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
-            }
-        },1000);
-    }
-
-</script>
-
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>Vibrations</h1>
     <div id="info">
     </div>
     
     <h2>Action</h2>
-    <div class="btn large" onclick="vibrate();">Vibrate</div>
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <div class="btn large vibrate">Vibrate</div>
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>      

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/vibration/index.js
----------------------------------------------------------------------
diff --git a/vibration/index.js b/vibration/index.js
new file mode 100644
index 0000000..0d28902
--- /dev/null
+++ b/vibration/index.js
@@ -0,0 +1,31 @@
+var deviceReady = false;
+
+//-------------------------------------------------------------------------
+// Vibrations
+//-------------------------------------------------------------------------
+
+var vibrate = function(){
+  navigator.notification.vibrate(2500);
+};
+
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+            deviceReady = true;
+            console.log("Device="+device.platform+" "+device.version);
+        }, false);
+    window.setTimeout(function() {
+        if (!deviceReady) {
+            alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
+        }
+    },1000);
+}
+
+window.onload = function() {
+  addListenerToClass('vibrate', vibrate);
+  addListenerToClass('backBtn', backHome);
+  init();
+}


[12/12] spec commit: Merge branch 'ffos_privileged_compatible'

Posted by za...@apache.org.
Merge branch 'ffos_privileged_compatible'

Conflicts:
	battery/index.html


Project: http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/commit/4322b9c7
Tree: http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/tree/4322b9c7
Diff: http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/diff/4322b9c7

Branch: refs/heads/master
Commit: 4322b9c7f7b7b4672104a847bfc2a9ee99e2971a
Parents: 9a8914f 46c0918
Author: Piotr Zalewa <pi...@zalewa.info>
Authored: Tue Jun 10 12:00:22 2014 +0200
Committer: Piotr Zalewa <pi...@zalewa.info>
Committed: Tue Jun 10 12:00:22 2014 +0200

----------------------------------------------------------------------
 accelerometer/index.html                  | 120 +-------
 accelerometer/index.js                    | 111 ++++++++
 audio/index.html                          | 370 +------------------------
 audio/index.js                            | 356 ++++++++++++++++++++++++
 autotest/index.html                       |   3 +-
 autotest/index.js                         |   4 +
 autotest/pages/accelerometer.html         |  20 +-
 autotest/pages/all.html                   |  47 +---
 autotest/pages/all.js                     |  46 +++
 autotest/pages/battery.html               |  19 +-
 autotest/pages/bridge.html                |  20 +-
 autotest/pages/camera.html                |  20 +-
 autotest/pages/capture.html               |  20 +-
 autotest/pages/compass.html               |  20 +-
 autotest/pages/contacts.html              |  19 +-
 autotest/pages/datauri.html               |  18 +-
 autotest/pages/device.html                |  20 +-
 autotest/pages/file.html                  |  41 +--
 autotest/pages/file.js                    |  39 +++
 autotest/pages/filetransfer.html          |  41 +--
 autotest/pages/geolocation.html           |  20 +-
 autotest/pages/globalization.html         |  20 +-
 autotest/pages/localXHR.html              |  20 +-
 autotest/pages/media.html                 |  20 +-
 autotest/pages/network.html               |  20 +-
 autotest/pages/notification.html          |  20 +-
 autotest/pages/platform.html              |  20 +-
 autotest/pages/run-tests.js               |  18 ++
 autotest/pages/splashscreen.html          |  20 +-
 autotest/pages/storage.html               |  20 +-
 autotest/pages/vibration.html             |  20 +-
 autotest/pages/whitelist.html             |  20 +-
 battery/index.html                        |  83 +-----
 battery/index.js                          |  72 +++++
 camera/index.html                         | 361 +-----------------------
 camera/index.js                           | 344 +++++++++++++++++++++++
 capture/index.html                        | 147 +---------
 capture/index.js                          | 137 +++++++++
 compass/index.html                        | 114 +-------
 compass/index.js                          | 104 +++++++
 contacts/index.html                       |  99 +------
 contacts/index.js                         |  90 ++++++
 cordova-incl.js                           |  22 ++
 events/index.html                         |  86 ++----
 events/index.js                           |  94 +++++++
 file/index.html                           | 158 +----------
 file/index.js                             | 153 ++++++++++
 inappbrowser/index.html                   | 266 ++++--------------
 inappbrowser/index.js                     | 242 ++++++++++++++++
 index.html                                |   2 +-
 keyboard/index.html                       |  68 +----
 keyboard/index.js                         |  69 +++++
 keyboard/window-onerror.js                |   1 +
 lazyloadjs/do-not-write-cordova-script.js |   1 +
 lazyloadjs/index.html                     |  20 +-
 lazyloadjs/index.js                       |  16 ++
 location/index.html                       | 143 +---------
 location/index.js                         | 128 +++++++++
 main.js                                   |   2 +
 misc/index.html                           |  35 +--
 misc/index.js                             |  30 ++
 misc/page2.html                           |  14 +-
 misc/page2.js                             |  12 +
 misc/page3.html                           |  30 +-
 misc/page3A.js                            |  27 ++
 network/index.html                        |  45 +--
 network/index.js                          |  38 +++
 notification/index.html                   | 110 +-------
 notification/index.js                     | 100 +++++++
 sql/index.html                            | 137 +--------
 sql/index.js                              | 125 +++++++++
 storage/index.html                        |  37 +--
 storage/index.js                          |  27 ++
 vibration/index.html                      |  39 +--
 vibration/index.js                        |  31 +++
 75 files changed, 2687 insertions(+), 2764 deletions(-)
----------------------------------------------------------------------



[04/12] spec commit: Manual tests fixed

Posted by za...@apache.org.
Manual tests fixed

Removing inline scripts from mobile-spec to make it compatible with FFOS priveleged type apps (i.e. using contacts)

added addListenerToClass function which is used to connect buttons with test functions.

Please check it on all platforms and r+ if working.

moved test initialization to JS file (for DRY and privileged apps compatibility)


Project: http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/commit/a7c88d8f
Tree: http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/tree/a7c88d8f
Diff: http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/diff/a7c88d8f

Branch: refs/heads/master
Commit: a7c88d8fc6999996179356db7759db82782fee4e
Parents: d099137
Author: Piotr Zalewa <pi...@zalewa.info>
Authored: Wed Apr 30 15:14:04 2014 +0200
Committer: Piotr Zalewa <pi...@zalewa.info>
Committed: Wed May 14 15:39:24 2014 +0200

----------------------------------------------------------------------
 accelerometer/index.html                  | 120 +-------
 accelerometer/index.js                    | 111 ++++++++
 audio/index.html                          | 370 +------------------------
 audio/index.js                            | 356 ++++++++++++++++++++++++
 autotest/index.html                       |   3 +-
 autotest/index.js                         |   4 +
 autotest/pages/accelerometer.html         |  20 +-
 autotest/pages/all.html                   |  47 +---
 autotest/pages/all.js                     |  46 +++
 autotest/pages/battery.html               |  19 +-
 autotest/pages/bridge.html                |  20 +-
 autotest/pages/camera.html                |  20 +-
 autotest/pages/capture.html               |  20 +-
 autotest/pages/compass.html               |  20 +-
 autotest/pages/contacts.html              |  19 +-
 autotest/pages/datauri.html               |  18 +-
 autotest/pages/device.html                |  20 +-
 autotest/pages/file.html                  |  41 +--
 autotest/pages/file.js                    |  39 +++
 autotest/pages/filetransfer.html          |  41 +--
 autotest/pages/geolocation.html           |  20 +-
 autotest/pages/globalization.html         |  20 +-
 autotest/pages/localXHR.html              |  20 +-
 autotest/pages/media.html                 |  20 +-
 autotest/pages/network.html               |  20 +-
 autotest/pages/notification.html          |  20 +-
 autotest/pages/platform.html              |  20 +-
 autotest/pages/run-tests.js               |  18 ++
 autotest/pages/splashscreen.html          |  20 +-
 autotest/pages/storage.html               |  20 +-
 autotest/pages/vibration.html             |  20 +-
 autotest/pages/whitelist.html             |  20 +-
 battery/index.html                        |  83 +-----
 battery/index.js                          |  72 +++++
 camera/index.html                         | 361 +-----------------------
 camera/index.js                           | 344 +++++++++++++++++++++++
 capture/index.html                        | 147 +---------
 capture/index.js                          | 137 +++++++++
 compass/index.html                        | 114 +-------
 compass/index.js                          | 104 +++++++
 contacts/index.html                       |  99 +------
 contacts/index.js                         |  90 ++++++
 cordova-incl.js                           |  22 ++
 events/index.html                         |  86 ++----
 events/index.js                           |  94 +++++++
 file/index.html                           | 158 +----------
 file/index.js                             | 153 ++++++++++
 inappbrowser/index.html                   | 266 ++++--------------
 inappbrowser/index.js                     | 242 ++++++++++++++++
 index.html                                |   2 +-
 keyboard/index.html                       |  68 +----
 keyboard/index.js                         |  69 +++++
 keyboard/window-onerror.js                |   1 +
 lazyloadjs/do-not-write-cordova-script.js |   1 +
 lazyloadjs/index.html                     |  20 +-
 lazyloadjs/index.js                       |  16 ++
 location/index.html                       | 143 +---------
 location/index.js                         | 128 +++++++++
 main.js                                   |   2 +
 misc/index.html                           |  35 +--
 misc/index.js                             |  30 ++
 misc/page2.html                           |  14 +-
 misc/page2.js                             |  12 +
 misc/page3.html                           |  30 +-
 misc/page3A.js                            |  27 ++
 network/index.html                        |  45 +--
 network/index.js                          |  38 +++
 notification/index.html                   | 110 +-------
 notification/index.js                     | 100 +++++++
 sql/index.html                            | 137 +--------
 sql/index.js                              | 125 +++++++++
 storage/index.html                        |  37 +--
 storage/index.js                          |  27 ++
 vibration/index.html                      |  39 +--
 vibration/index.js                        |  31 +++
 75 files changed, 2687 insertions(+), 2764 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/accelerometer/index.html
----------------------------------------------------------------------
diff --git a/accelerometer/index.html b/accelerometer/index.html
index bbec57f..71000b8 100644
--- a/accelerometer/index.html
+++ b/accelerometer/index.html
@@ -27,118 +27,10 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>      
-
-      
-<script type="text/javascript" charset="utf-8">
-
-    var deviceReady = false;
-
-    function roundNumber(num) {
-        var dec = 3;
-        var result = Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
-        return result;
-    }
-
-    //-------------------------------------------------------------------------
-    // Acceleration
-    //-------------------------------------------------------------------------
-    var watchAccelId = null;
-    
-    /**
-     * Start watching acceleration
-     */
-    var watchAccel = function() {
-        console.log("watchAccel()");
-
-        // Success callback
-        var success = function(a){
-            document.getElementById('x').innerHTML = roundNumber(a.x);
-            document.getElementById('y').innerHTML = roundNumber(a.y);
-            document.getElementById('z').innerHTML = roundNumber(a.z);
-            console.log("watchAccel success callback");
-        };
-
-        // Fail callback
-        var fail = function(e){
-            console.log("watchAccel fail callback with error code "+e);
-            stopAccel();
-            setAccelStatus(Accelerometer.ERROR_MSG[e]);
-        };
-
-        // Update acceleration every 1 sec
-        var opt = {};
-        opt.frequency = 1000;
-        watchAccelId = navigator.accelerometer.watchAcceleration(success, fail, opt);
-
-        setAccelStatus("Running");
-    };
-
-    /**
-     * Stop watching the acceleration
-     */
-    var stopAccel = function() {
-    	console.log("stopAccel()");
-        setAccelStatus("Stopped");
-        if (watchAccelId) {
-            navigator.accelerometer.clearWatch(watchAccelId);
-            watchAccelId = null;
-        }
-    };
-
-    /**
-     * Get current acceleration
-     */
-    var getAccel = function() {
-        console.log("getAccel()");
-
-        // Stop accel if running
-        stopAccel();
-
-        // Success callback
-        var success = function(a){
-            document.getElementById('x').innerHTML = roundNumber(a.x);
-            document.getElementById('y').innerHTML = roundNumber(a.y);
-            document.getElementById('z').innerHTML = roundNumber(a.z);
-        };
-
-        // Fail callback
-        var fail = function(e){
-            console.log("getAccel fail callback with error code "+e);
-            setAccelStatus(Accelerometer.ERROR_MSG[e]);
-        };
-
-        // Make call
-        var opt = {};
-        navigator.accelerometer.getCurrentAcceleration(success, fail, opt);
-    };
-
-    /**
-     * Set accelerometer status
-     */
-    var setAccelStatus = function(status) {
-        document.getElementById('accel_status').innerHTML = status;
-    };
-    
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        console.log("accelerometer.init()");
-        document.addEventListener("deviceready", function() {
-                deviceReady = true;
-                console.log("Device="+device.platform+" "+device.version);
-            }, false);
-        window.setTimeout(function() {
-        	if (!deviceReady) {
-        		alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
-        	}
-        },1000);
-    }
-
-</script>
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
 
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>Acceleration</h1>
     <div id="info">
@@ -151,9 +43,9 @@
     </div>
 
     <h2>Action</h2>
-    <div class="btn large" onclick="getAccel();">Get Acceleration</div>
-    <div class="btn large" onclick="watchAccel();">Start Watch</div>
-    <div class="btn large" onclick="stopAccel();">Clear Watch</div>
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <div class="btn large getAccel">Get Acceleration</div>
+    <div class="btn large watchAccel">Start Watch</div>
+    <div class="btn large stopAccel">Clear Watch</div>
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>      

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/accelerometer/index.js
----------------------------------------------------------------------
diff --git a/accelerometer/index.js b/accelerometer/index.js
new file mode 100644
index 0000000..946cfe2
--- /dev/null
+++ b/accelerometer/index.js
@@ -0,0 +1,111 @@
+var deviceReady = false;
+
+function roundNumber(num) {
+    var dec = 3;
+    var result = Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
+    return result;
+}
+
+//-------------------------------------------------------------------------
+// Acceleration
+//-------------------------------------------------------------------------
+var watchAccelId = null;
+
+/**
+ * Start watching acceleration
+ */
+var watchAccel = function() {
+    console.log("watchAccel()");
+
+    // Success callback
+    var success = function(a){
+        document.getElementById('x').innerHTML = roundNumber(a.x);
+        document.getElementById('y').innerHTML = roundNumber(a.y);
+        document.getElementById('z').innerHTML = roundNumber(a.z);
+        console.log("watchAccel success callback");
+    };
+
+    // Fail callback
+    var fail = function(e){
+        console.log("watchAccel fail callback with error code "+e);
+        stopAccel();
+        setAccelStatus(Accelerometer.ERROR_MSG[e]);
+    };
+
+    // Update acceleration every 1 sec
+    var opt = {};
+    opt.frequency = 1000;
+    watchAccelId = navigator.accelerometer.watchAcceleration(success, fail, opt);
+
+    setAccelStatus("Running");
+};
+
+/**
+ * Stop watching the acceleration
+ */
+var stopAccel = function() {
+	console.log("stopAccel()");
+    setAccelStatus("Stopped");
+    if (watchAccelId) {
+        navigator.accelerometer.clearWatch(watchAccelId);
+        watchAccelId = null;
+    }
+};
+
+/**
+ * Get current acceleration
+ */
+var getAccel = function() {
+    console.log("getAccel()");
+
+    // Stop accel if running
+    stopAccel();
+
+    // Success callback
+    var success = function(a){
+        document.getElementById('x').innerHTML = roundNumber(a.x);
+        document.getElementById('y').innerHTML = roundNumber(a.y);
+        document.getElementById('z').innerHTML = roundNumber(a.z);
+    };
+
+    // Fail callback
+    var fail = function(e){
+        console.log("getAccel fail callback with error code "+e);
+        setAccelStatus(Accelerometer.ERROR_MSG[e]);
+    };
+
+    // Make call
+    var opt = {};
+    navigator.accelerometer.getCurrentAcceleration(success, fail, opt);
+};
+
+/**
+ * Set accelerometer status
+ */
+var setAccelStatus = function(status) {
+    document.getElementById('accel_status').innerHTML = status;
+};
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    console.log("accelerometer.init()");
+    document.addEventListener("deviceready", function() {
+            deviceReady = true;
+            console.log("Device="+device.platform+" "+device.version);
+        }, false);
+    window.setTimeout(function() {
+    	if (!deviceReady) {
+    		alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
+    	}
+    },1000);
+}
+
+window.onload = function() {
+  addListenerToClass('getAccel', getAccel);
+  addListenerToClass('watchAccel', watchAccel);
+  addListenerToClass('stopAccel', stopAccel);
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/audio/index.html
----------------------------------------------------------------------
diff --git a/audio/index.html b/audio/index.html
index a0286d0..a05ea04 100644
--- a/audio/index.html
+++ b/audio/index.html
@@ -28,354 +28,10 @@
     <title>Cordova Audio Tests</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="../cordova-incl.js"></script>      
-
-      
-<script type="text/javascript" charset="utf-8">
-
-	 var defaultaudio = "http://cordova.apache.org/downloads/BlueZedEx.mp3";
-    var deviceReady = false;
-
-    //-------------------------------------------------------------------------
-    // Audio player
-    //-------------------------------------------------------------------------
-    var media1 = null;
-    var media1Timer = null;
-    var audioSrc = null;
-    var recordSrc = "myRecording.mp3";
-
-    /**
-     * Play audio
-     */
-    function playAudio(url) {
-        console.log("playAudio()");
-        console.log(" -- media="+media1);
-
-	    var src = defaultaudio;
-        
-        if (url) {
-            src = url;
-        }
-
-        // Stop playing if src is different from currently playing source
-        if (src != audioSrc) {
-            if (media1 != null) {
-                stopAudio();
-                media1 = null;
-            }
-        }
-
-        if (media1 == null) {
-
-
-            // TEST STREAMING AUDIO PLAYBACK
-            //var src = "http://nunzioweb.com/misc/Bon_Jovi-Crush_Mystery_Train.mp3";   // works
-            //var src = "http://nunzioweb.com/misc/Bon_Jovi-Crush_Mystery_Train.m3u"; // doesn't work
-            //var src = "http://www.wav-sounds.com/cartoon/bugsbunny1.wav"; // works
-            //var src = "http://www.angelfire.com/fl5/html-tutorial/a/couldyou.mid"; // doesn't work
-            //var src = "MusicSearch/mp3/train.mp3";    // works
-            //var src = "bryce.mp3";  // works
-            //var src = "/android_asset/www/bryce.mp3"; // works
-
-            media1 = new Media(src,
-                function() {
-                    console.log("playAudio():Audio Success");
-                },
-                function(err) {
-                    console.log("playAudio():Audio Error: "+err.code);
-                    setAudioStatus("Error: " + err.code);
-                },
-                function(status) {
-                    console.log("playAudio():Audio Status: "+status);
-                    setAudioStatus(Media.MEDIA_MSG[status]);
-
-                    // If stopped, then stop getting current position
-                    if (Media.MEDIA_STOPPED == status) {
-                        clearInterval(media1Timer);
-                        media1Timer = null;
-                        setAudioPosition("0 sec");
-                    }
-                });
-        }
-        audioSrc = src;
-        document.getElementById('audio_duration').innerHTML = "";
-        // Play audio
-        media1.play();
-        if (media1Timer == null && media1.getCurrentPosition) {
-            media1Timer = setInterval(
-                function() {
-                    media1.getCurrentPosition(
-                        function(position) {
-                            console.log("Pos="+position);
-                            if (position >= 0.0) {
-                                setAudioPosition(position+" sec");
-                            }
-                        },
-                        function(e) {
-                            console.log("Error getting pos="+e);
-                            setAudioPosition("Error: "+e);
-                        }
-                    );
-                },
-                1000
-            );
-        }
-
-        // Get duration
-        var counter = 0;
-        var timerDur = setInterval(
-            function() {
-                counter = counter + 100;
-                if (counter > 2000) {
-                    clearInterval(timerDur);
-                }
-                var dur = media1.getDuration();
-                if (dur > 0) {
-                    clearInterval(timerDur);
-                    document.getElementById('audio_duration').innerHTML = dur + " sec";
-                }
-            }, 100);
-    }
-
-    /**
-     * Pause audio playback
-     */
-    function pauseAudio() {
-        console.log("pauseAudio()");
-        if (media1) {
-            media1.pause();
-        }
-    }
-
-    /**
-     * Stop audio
-     */
-    function stopAudio() {
-        console.log("stopAudio()");
-        if (media1) {
-            media1.stop();
-        }
-        clearInterval(media1Timer);
-        media1Timer = null;
-    }
-    
-    /**
-     * Release audio
-     */
-	function releaseAudio() {
-	    console.log("releaseAudio()");
-	    if (media1) {
-	    	media1.stop(); //imlied stop of playback, resets timer
-	    	media1.release();
-	    }
-	}
-	
-    /**
-     * Set audio status
-     */
-    var setAudioStatus = function(status) {
-        document.getElementById('audio_status').innerHTML = status;
-    };
-
-    /**
-     * Set audio position
-     */
-    var setAudioPosition = function(position) {
-        document.getElementById('audio_position').innerHTML = position;
-    };
-
-    //-------------------------------------------------------------------------
-    // Audio recorder
-    //-------------------------------------------------------------------------
-    var mediaRec = null;
-    var recTime = 0;
-
-    /**
-     * Record audio
-     */
-    function recordAudio() {
-        console.log("recordAudio()");
-        console.log(" -- media="+mediaRec);
-        if (mediaRec == null) {
-
-            var src = recordSrc;
-            mediaRec = new Media(src,
-                    function() {
-                        console.log("recordAudio():Audio Success");
-                    },
-                    function(err) {
-                        console.log("recordAudio():Audio Error: "+err.code);
-                        setAudioStatus("Error: " + err.code);
-                    },
-                    function(status) {
-                        console.log("recordAudio():Audio Status: "+status);
-                        setAudioStatus(Media.MEDIA_MSG[status]);
-                    }
-                );
-        }
-
-        navigator.notification.beep(1);
-
-        // Record audio
-        mediaRec.startRecord();
-
-        // Stop recording after 10 sec
-        recTime = 0;
-        var recInterval = setInterval(function() {
-            recTime = recTime + 1;
-            setAudioPosition(recTime+" sec");
-            if (recTime >= 10) {
-                clearInterval(recInterval);
-                if (mediaRec.stopAudioRecord){
-                    mediaRec.stopAudioRecord();
-                } else {
-                    mediaRec.stopRecord();
-                }
-                console.log("recordAudio(): stop");
-                navigator.notification.beep(1);
-            }
-        }, 1000);
-    }
-
-    /**
-     * Play back recorded audio
-     */
-    function playRecording() {
-        playAudio(recordSrc);
-    }
-    
-    /**
-     * Function to create a file for iOS recording
-     */
-    function getRecordSrc() {
-        var fsFail = function(error) {
-            console.log("error creating file for iOS recording");
-        };
-        var gotFile = function(file) {
-            recordSrc = file.fullPath;
-            //console.log("recording Src: " + recordSrc);
-        };
-        var gotFS = function(fileSystem) {
-            fileSystem.root.getFile("iOSRecording.wav", {create: true}, gotFile, fsFail);
-        };
-        window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, gotFS, fsFail);
-    }
-    
-    /**
-     * Function to create a file for BB recording
-     */
-    function getRecordSrcBB() {
-        var fsFail = function(error) {
-            console.log("error creating file for BB recording");
-        };
-        var gotFile = function(file) {
-            recordSrc = file.fullPath;
-        };
-        var gotFS = function(fileSystem) {
-            fileSystem.root.getFile("BBRecording.amr", {create: true}, gotFile, fsFail);
-        };
-        window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, gotFS, fsFail);
-    }
-
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-                deviceReady = true;
-                if (device.platform.indexOf("iOS") !=-1)
-                {
-                     getRecordSrc();
-                } else if (typeof blackberry !== 'undefined') {
-                    getRecordSrcBB();
-                }
-                console.log("Device="+device.platform+" "+device.version);
-            }, false);
-        window.setTimeout(function() {
-        	if (!deviceReady) {
-        		alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
-        	}
-        },1000);
-    }
-    
-    /**
-     * for forced updates of position after a successful seek
-     */
-    function updatePosition() {
-        media1.getCurrentPosition(
-            function(position) {
-                console.log("Pos="+position);
-                if (position >= 0.0) {
-                    setAudioPosition(position+" sec");
-                }
-            },
-            function(e) {
-                console.log("Error getting pos="+e);
-                setAudioPosition("Error: "+e);
-            });
-    }
-
-    /**
-     *
-     */
-    function seekAudio(mode) {
-        var time = document.getElementById("seekinput").value;
-        if (time == "") {
-            time = 5000;
-        } else {
-            time = time * 1000; //we expect the input to be in seconds
-        }
-        if (media1 == null) {
-            console.log("seekTo requested while media1 is null");
-            if (audioSrc == null) {
-                audioSrc = defaultaudio;
-            }
-            media1 = new Media(audioSrc,
-                function() {
-                    console.log("seekToAudio():Audio Success");
-                },
-                function(err) {
-                    console.log("seekAudio():Audio Error: "+err.code);
-                    setAudioStatus("Error: " + err.code);
-                },
-                function(status) {
-                    console.log("seekAudio():Audio Status: "+status);
-                    setAudioStatus(Media.MEDIA_MSG[status]);
-
-                    // If stopped, then stop getting current position
-                    if (Media.MEDIA_STOPPED == status) {
-                        clearInterval(media1Timer);
-                        media1Timer = null;
-                        setAudioPosition("0 sec");
-                    }
-                });
-        }
-        
-        media1.getCurrentPosition(
-            function (position) {
-                var deltat = time;
-                if (mode == "by") {
-                    deltat = time + position * 1000;   
-                }
-                media1.seekTo(deltat,
-                    function () {
-                        console.log("seekAudioTo():Audio Success");
-                        //force an update on the position display
-                        updatePosition();
-                    },
-                    function (err) {
-                        console.log("seekAudioTo():Audio Error: " + err.code);
-                    });
-            },
-            function(e) {
-                console.log("Error getting pos="+e);
-                setAudioPosition("Error: "+e);
-            });
-    }
-    
-</script>
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
 
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>Audio</h1>  
     <div id="info">
@@ -391,19 +47,19 @@
             <th colspan=3>Play Sample Audio</th>
         </tr>
         <tr>
-            <td><div class="btn wide" onclick="playAudio();">Play</div></td>
-            <td><div class="btn wide" onclick="pauseAudio();">Pause</div></td>
+            <td><div class="btn wide playAudio">Play</div></td>
+            <td><div class="btn wide pauseAudio">Pause</div></td>
         </tr>
         <tr>
-            <td><div class="btn wide" onclick="stopAudio();">Stop</div></td>
-            <td><div class="btn wide" onclick="releaseAudio();">Release</div></td>
+            <td><div class="btn wide stopAudio">Stop</div></td>
+            <td><div class="btn wide releaseAudio">Release</div></td>
         </tr>
     </table>
     
     <table style="width:80%;">
         <tr>
-            <td><div class="btn wide" onclick="seekAudio('by');">Seek By</div></td>
-            <td><div class="btn wide" onclick="seekAudio('to');">Seek To</div></td>
+            <td><div class="btn wide seekAudioBy">Seek By</div></td>
+            <td><div class="btn wide seekAudioTo">Seek To</div></td>
             <td>
                 <div>
                     <input class="input numeric" type="number" id="seekinput" value="in seconds">
@@ -417,16 +73,16 @@
             <th colspan=3><br><br>Record Audio</th>
         </tr>
         <tr>
-            <td colspan=3><div class="btn wide" onclick="recordAudio();">Record Audio for 10 sec</a></td>
+            <td colspan=3><div class="btn wide recordAudio">Record Audio for 10 sec</a></td>
         </tr>
         <tr>
-            <td><div class="btn wide" onclick="playRecording();">Play</div></td>
-            <td><div class="btn wide" onclick="pauseAudio();">Pause</div></td>
-            <td><div class="btn wide" onclick="stopAudio();">Stop</div></td>
+            <td><div class="btn wide playRecording">Play</div></td>
+            <td><div class="btn wide pauseAudio">Pause</div></td>
+            <td><div class="btn wide stopAudio">Stop</div></td>
         </tr>
     </table>
     
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <h2> </h2><div class="backBtn">Back</div>
     
   </body>
 </html>      

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/audio/index.js
----------------------------------------------------------------------
diff --git a/audio/index.js b/audio/index.js
new file mode 100644
index 0000000..e7ca9b6
--- /dev/null
+++ b/audio/index.js
@@ -0,0 +1,356 @@
+var defaultaudio = "http://cordova.apache.org/downloads/BlueZedEx.mp3";
+var deviceReady = false;
+
+//-------------------------------------------------------------------------
+// Audio player
+//-------------------------------------------------------------------------
+var media1 = null;
+var media1Timer = null;
+var audioSrc = null;
+var recordSrc = "myRecording.mp3";
+
+/**
+ * Play audio
+ */
+function playAudio(url) {
+    console.log("playAudio()");
+    console.log(" -- media="+media1);
+
+  var src = defaultaudio;
+    
+    if (url) {
+        src = url;
+    }
+
+    // Stop playing if src is different from currently playing source
+    if (src != audioSrc) {
+        if (media1 != null) {
+            stopAudio();
+            media1 = null;
+        }
+    }
+
+    if (media1 == null) {
+
+
+        // TEST STREAMING AUDIO PLAYBACK
+        //var src = "http://nunzioweb.com/misc/Bon_Jovi-Crush_Mystery_Train.mp3";   // works
+        //var src = "http://nunzioweb.com/misc/Bon_Jovi-Crush_Mystery_Train.m3u"; // doesn't work
+        //var src = "http://www.wav-sounds.com/cartoon/bugsbunny1.wav"; // works
+        //var src = "http://www.angelfire.com/fl5/html-tutorial/a/couldyou.mid"; // doesn't work
+        //var src = "MusicSearch/mp3/train.mp3";    // works
+        //var src = "bryce.mp3";  // works
+        //var src = "/android_asset/www/bryce.mp3"; // works
+
+        media1 = new Media(src,
+            function() {
+                console.log("playAudio():Audio Success");
+            },
+            function(err) {
+                console.log("playAudio():Audio Error: "+err.code);
+                setAudioStatus("Error: " + err.code);
+            },
+            function(status) {
+                console.log("playAudio():Audio Status: "+status);
+                setAudioStatus(Media.MEDIA_MSG[status]);
+
+                // If stopped, then stop getting current position
+                if (Media.MEDIA_STOPPED == status) {
+                    clearInterval(media1Timer);
+                    media1Timer = null;
+                    setAudioPosition("0 sec");
+                }
+            });
+    }
+    audioSrc = src;
+    document.getElementById('audio_duration').innerHTML = "";
+    // Play audio
+    media1.play();
+    if (media1Timer == null && media1.getCurrentPosition) {
+        media1Timer = setInterval(
+            function() {
+                media1.getCurrentPosition(
+                    function(position) {
+                        console.log("Pos="+position);
+                        if (position >= 0.0) {
+                            setAudioPosition(position+" sec");
+                        }
+                    },
+                    function(e) {
+                        console.log("Error getting pos="+e);
+                        setAudioPosition("Error: "+e);
+                    }
+                );
+            },
+            1000
+        );
+    }
+
+    // Get duration
+    var counter = 0;
+    var timerDur = setInterval(
+        function() {
+            counter = counter + 100;
+            if (counter > 2000) {
+                clearInterval(timerDur);
+            }
+            var dur = media1.getDuration();
+            if (dur > 0) {
+                clearInterval(timerDur);
+                document.getElementById('audio_duration').innerHTML = dur + " sec";
+            }
+        }, 100);
+}
+
+/**
+ * Pause audio playback
+ */
+function pauseAudio() {
+    console.log("pauseAudio()");
+    if (media1) {
+        media1.pause();
+    }
+}
+
+/**
+ * Stop audio
+ */
+function stopAudio() {
+    console.log("stopAudio()");
+    if (media1) {
+        media1.stop();
+    }
+    clearInterval(media1Timer);
+    media1Timer = null;
+}
+
+/**
+ * Release audio
+ */
+function releaseAudio() {
+  console.log("releaseAudio()");
+  if (media1) {
+  	media1.stop(); //imlied stop of playback, resets timer
+  	media1.release();
+  }
+}
+
+
+/**
+ * Set audio status
+ */
+function setAudioStatus(status) {
+    document.getElementById('audio_status').innerHTML = status;
+};
+
+/**
+ * Set audio position
+ */
+function setAudioPosition(position) {
+    document.getElementById('audio_position').innerHTML = position;
+};
+
+//-------------------------------------------------------------------------
+// Audio recorder
+//-------------------------------------------------------------------------
+var mediaRec = null;
+var recTime = 0;
+
+/**
+ * Record audio
+ */
+function recordAudio() {
+    console.log("recordAudio()");
+    console.log(" -- media="+mediaRec);
+    if (mediaRec == null) {
+
+        var src = recordSrc;
+        mediaRec = new Media(src,
+                function() {
+                    console.log("recordAudio():Audio Success");
+                },
+                function(err) {
+                    console.log("recordAudio():Audio Error: "+err.code);
+                    setAudioStatus("Error: " + err.code);
+                },
+                function(status) {
+                    console.log("recordAudio():Audio Status: "+status);
+                    setAudioStatus(Media.MEDIA_MSG[status]);
+                }
+            );
+    }
+
+    navigator.notification.beep(1);
+
+    // Record audio
+    mediaRec.startRecord();
+
+    // Stop recording after 10 sec
+    recTime = 0;
+    var recInterval = setInterval(function() {
+        recTime = recTime + 1;
+        setAudioPosition(recTime+" sec");
+        if (recTime >= 10) {
+            clearInterval(recInterval);
+            if (mediaRec.stopAudioRecord){
+                mediaRec.stopAudioRecord();
+            } else {
+                mediaRec.stopRecord();
+            }
+            console.log("recordAudio(): stop");
+            navigator.notification.beep(1);
+        }
+    }, 1000);
+}
+
+/**
+ * Play back recorded audio
+ */
+function playRecording() {
+    playAudio(recordSrc);
+}
+
+/**
+ * Function to create a file for iOS recording
+ */
+function getRecordSrc() {
+    var fsFail = function(error) {
+        console.log("error creating file for iOS recording");
+    };
+    var gotFile = function(file) {
+        recordSrc = file.fullPath;
+        //console.log("recording Src: " + recordSrc);
+    };
+    var gotFS = function(fileSystem) {
+        fileSystem.root.getFile("iOSRecording.wav", {create: true}, gotFile, fsFail);
+    };
+    window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, gotFS, fsFail);
+}
+
+/**
+ * Function to create a file for BB recording
+ */
+function getRecordSrcBB() {
+    var fsFail = function(error) {
+        console.log("error creating file for BB recording");
+    };
+    var gotFile = function(file) {
+        recordSrc = file.fullPath;
+    };
+    var gotFS = function(fileSystem) {
+        fileSystem.root.getFile("BBRecording.amr", {create: true}, gotFile, fsFail);
+    };
+    window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, gotFS, fsFail);
+}
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+            deviceReady = true;
+            if (device.platform.indexOf("iOS") !=-1)
+            {
+                 getRecordSrc();
+            } else if (typeof blackberry !== 'undefined') {
+                getRecordSrcBB();
+            }
+            console.log("Device="+device.platform+" "+device.version);
+        }, false);
+    window.setTimeout(function() {
+    	if (!deviceReady) {
+    		alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
+    	}
+    },1000);
+}
+
+/**
+ * for forced updates of position after a successful seek
+ */
+function updatePosition() {
+    media1.getCurrentPosition(
+        function(position) {
+            console.log("Pos="+position);
+            if (position >= 0.0) {
+                setAudioPosition(position+" sec");
+            }
+        },
+        function(e) {
+            console.log("Error getting pos="+e);
+            setAudioPosition("Error: "+e);
+        });
+}
+
+/**
+ *
+ */
+function seekAudio(mode) {
+    var time = document.getElementById("seekinput").value;
+    if (time == "") {
+        time = 5000;
+    } else {
+        time = time * 1000; //we expect the input to be in seconds
+    }
+    if (media1 == null) {
+        console.log("seekTo requested while media1 is null");
+        if (audioSrc == null) {
+            audioSrc = defaultaudio;
+        }
+        media1 = new Media(audioSrc,
+            function() {
+                console.log("seekToAudio():Audio Success");
+            },
+            function(err) {
+                console.log("seekAudio():Audio Error: "+err.code);
+                setAudioStatus("Error: " + err.code);
+            },
+            function(status) {
+                console.log("seekAudio():Audio Status: "+status);
+                setAudioStatus(Media.MEDIA_MSG[status]);
+
+                // If stopped, then stop getting current position
+                if (Media.MEDIA_STOPPED == status) {
+                    clearInterval(media1Timer);
+                    media1Timer = null;
+                    setAudioPosition("0 sec");
+                }
+            });
+    }
+    
+    media1.getCurrentPosition(
+        function (position) {
+            var deltat = time;
+            if (mode == "by") {
+                deltat = time + position * 1000;   
+            }
+            media1.seekTo(deltat,
+                function () {
+                    console.log("seekAudioTo():Audio Success");
+                    //force an update on the position display
+                    updatePosition();
+                },
+                function (err) {
+                    console.log("seekAudioTo():Audio Error: " + err.code);
+                });
+        },
+        function(e) {
+            console.log("Error getting pos="+e);
+            setAudioPosition("Error: "+e);
+        });
+}
+
+window.onload = function() {
+  addListenerToClass('playAudio', function () {
+    playAudio();
+  });
+  addListenerToClass('pauseAudio', pauseAudio);
+  addListenerToClass('stopAudio', stopAudio);
+  addListenerToClass('releaseAudio', releaseAudio);
+  addListenerToClass('seekAudioBy', seekAudio, 'by');
+  addListenerToClass('seekAudioTo', seekAudio, 'to');
+  addListenerToClass('recordAudio', recordAudio);
+  addListenerToClass('playRecording', playRecording);
+
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/autotest/index.html
----------------------------------------------------------------------
diff --git a/autotest/index.html b/autotest/index.html
index a699870..3a41d78 100644
--- a/autotest/index.html
+++ b/autotest/index.html
@@ -30,6 +30,7 @@
 
     <link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title" charset="utf-8">
     <script type="text/javascript" src="../cordova-incl.js"></script>
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
   </head>
   <body id="stage" class="theme">
     <h1>Cordova API Specs</h1>
@@ -57,6 +58,6 @@
     <a href="pages/whitelist.html" class="btn large" style="width:100%;">Run Whitelist Tests</a>
     <a href="pages/localXHR.html" class="btn large" style="width:100%;">Run local XHR Tests</a>
     <a href="pages/vibration.html" class="btn large" style="width:100%;">Run Vibration Tests</a>
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/autotest/index.js
----------------------------------------------------------------------
diff --git a/autotest/index.js b/autotest/index.js
new file mode 100644
index 0000000..aec19b4
--- /dev/null
+++ b/autotest/index.js
@@ -0,0 +1,4 @@
+window.onload = function() {
+  addListenerToClass('backBtn', backHome);
+}
+

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/autotest/pages/accelerometer.html
----------------------------------------------------------------------
diff --git a/autotest/pages/accelerometer.html b/autotest/pages/accelerometer.html
index 856dc70..52b333b 100644
--- a/autotest/pages/accelerometer.html
+++ b/autotest/pages/accelerometer.html
@@ -45,26 +45,10 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/accelerometer.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/autotest/pages/all.html
----------------------------------------------------------------------
diff --git a/autotest/pages/all.html b/autotest/pages/all.html
index ef656bc..e381ef4 100644
--- a/autotest/pages/all.html
+++ b/autotest/pages/all.html
@@ -63,53 +63,10 @@
   <script type="text/javascript" src="../tests/storage.tests.js"></script>
   <script type="text/javascript" src="../tests/splashscreen.tests.js"></script>
   <script type="text/javascript" src="../tests/localXHR.tests.js"></script>
-
-  <script type="text/javascript">
-      var root, temp_root, persistent_root;
-
-      document.addEventListener('deviceready', function () {
-          // one-time retrieval of the root file system entry
-          var onError = function(e) {
-              console.log('[ERROR] Problem setting up root filesystem for test running! Error to follow.');
-              console.log(JSON.stringify(e));
-          };
-
-          window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,
-              function(fileSystem) {
-                  console.log('File API test Init: Setting PERSISTENT FS.');
-                  root = fileSystem.root; // set in file.tests.js
-                  persistent_root = root;
-
-                  // Once root is set up, fire off tests
-                  var jasmineEnv = jasmine.getEnv();
-                  jasmineEnv.updateInterval = 1000;
-
-                  var htmlReporter = new jasmine.HtmlReporter();
-                  jasmineEnv.addReporter(htmlReporter);
-
-                  // the following will only be defined if the Medic plugin is loaded
-                  if('medic' in window) {
-                      if( medic.isEnabled() ) {
-                          jasmineEnv.addReporter(medic.getJSReporter());
-                      }
-                  }
-
-                  jasmineEnv.specFilter = function(spec) {
-                    return htmlReporter.specFilter(spec);
-                  };
-
-                  jasmineEnv.execute();
-              }, onError);
-          window.requestFileSystem(LocalFileSystem.TEMPORARY, 0,
-              function(fileSystem) {
-                  console.log('File API test Init: Setting TEMPORARY FS.');
-                  temp_root = fileSystem.root; // set in file.tests.js
-              }, onError);
-      }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./all.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a class="backBtn">Back</a>
 </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/autotest/pages/all.js
----------------------------------------------------------------------
diff --git a/autotest/pages/all.js b/autotest/pages/all.js
new file mode 100644
index 0000000..bc72b29
--- /dev/null
+++ b/autotest/pages/all.js
@@ -0,0 +1,46 @@
+var root, temp_root, persistent_root;
+
+document.addEventListener('deviceready', function () {
+    // one-time retrieval of the root file system entry
+    var onError = function(e) {
+        console.log('[ERROR] Problem setting up root filesystem for test running! Error to follow.');
+        console.log(JSON.stringify(e));
+    };
+
+    window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,
+        function(fileSystem) {
+            console.log('File API test Init: Setting PERSISTENT FS.');
+            root = fileSystem.root; // set in file.tests.js
+            persistent_root = root;
+
+            // Once root is set up, fire off tests
+            var jasmineEnv = jasmine.getEnv();
+            jasmineEnv.updateInterval = 1000;
+
+            var htmlReporter = new jasmine.HtmlReporter();
+            jasmineEnv.addReporter(htmlReporter);
+
+            // the following will only be defined if the Medic plugin is loaded
+            if('medic' in window) {
+                if( medic.isEnabled() ) {
+                    jasmineEnv.addReporter(medic.getJSReporter());
+                }
+            }
+
+            jasmineEnv.specFilter = function(spec) {
+              return htmlReporter.specFilter(spec);
+            };
+
+            jasmineEnv.execute();
+        }, onError);
+    window.requestFileSystem(LocalFileSystem.TEMPORARY, 0,
+        function(fileSystem) {
+            console.log('File API test Init: Setting TEMPORARY FS.');
+            temp_root = fileSystem.root; // set in file.tests.js
+        }, onError);
+}, false);
+
+window.onload = function() {
+  addListenerToClass('backBtn', backHome);
+}
+

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/autotest/pages/battery.html
----------------------------------------------------------------------
diff --git a/autotest/pages/battery.html b/autotest/pages/battery.html
index cb430de..2063417 100644
--- a/autotest/pages/battery.html
+++ b/autotest/pages/battery.html
@@ -42,25 +42,10 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/battery.tests.js"></script>
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a class="backBtn">Back</a>
 </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/autotest/pages/bridge.html
----------------------------------------------------------------------
diff --git a/autotest/pages/bridge.html b/autotest/pages/bridge.html
index ca03e79..822d9ec 100644
--- a/autotest/pages/bridge.html
+++ b/autotest/pages/bridge.html
@@ -45,27 +45,11 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/bridge.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/autotest/pages/camera.html
----------------------------------------------------------------------
diff --git a/autotest/pages/camera.html b/autotest/pages/camera.html
index c1dafee..91843d7 100644
--- a/autotest/pages/camera.html
+++ b/autotest/pages/camera.html
@@ -46,26 +46,10 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/camera.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/autotest/pages/capture.html
----------------------------------------------------------------------
diff --git a/autotest/pages/capture.html b/autotest/pages/capture.html
index 39faa2b..bac570f 100644
--- a/autotest/pages/capture.html
+++ b/autotest/pages/capture.html
@@ -45,27 +45,11 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/capture.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a class="backBtn">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/autotest/pages/compass.html
----------------------------------------------------------------------
diff --git a/autotest/pages/compass.html b/autotest/pages/compass.html
index d97b680..80de16f 100644
--- a/autotest/pages/compass.html
+++ b/autotest/pages/compass.html
@@ -45,27 +45,11 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/compass.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/autotest/pages/contacts.html
----------------------------------------------------------------------
diff --git a/autotest/pages/contacts.html b/autotest/pages/contacts.html
index 1518f19..e8e5fae 100644
--- a/autotest/pages/contacts.html
+++ b/autotest/pages/contacts.html
@@ -46,26 +46,11 @@
   <!-- Tests -->
   <script type="text/javascript" src="../tests/contacts.tests.js"></script>
 
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn" id="backHome">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/autotest/pages/datauri.html
----------------------------------------------------------------------
diff --git a/autotest/pages/datauri.html b/autotest/pages/datauri.html
index b64b21a..33474dd 100644
--- a/autotest/pages/datauri.html
+++ b/autotest/pages/datauri.html
@@ -43,23 +43,7 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/datauri.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/autotest/pages/device.html
----------------------------------------------------------------------
diff --git a/autotest/pages/device.html b/autotest/pages/device.html
index 7252e67..b1bed1d 100644
--- a/autotest/pages/device.html
+++ b/autotest/pages/device.html
@@ -45,27 +45,11 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/device.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/autotest/pages/file.html
----------------------------------------------------------------------
diff --git a/autotest/pages/file.html b/autotest/pages/file.html
index d143c74..d201791 100644
--- a/autotest/pages/file.html
+++ b/autotest/pages/file.html
@@ -44,47 +44,10 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/file.tests.js"></script>
-
-  <script type="text/javascript">
-      var root, temp_root, persistent_root;
-
-      document.addEventListener('deviceready', function () {
-          // one-time retrieval of the root file system entry
-          var onError = function(e) {
-              console.log('[ERROR] Problem setting up root filesystem for test running! Error to follow.');
-              console.log(JSON.stringify(e));
-          };
-
-          window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,
-              function(fileSystem) {
-                  console.log('File API test Init: Setting PERSISTENT FS.');
-                  root = fileSystem.root; // set in file.tests.js
-                  persistent_root = root;
-
-                  // Once root is set up, fire off tests
-                  var jasmineEnv = jasmine.getEnv();
-                  jasmineEnv.updateInterval = 1000;
-
-                  var htmlReporter = new jasmine.HtmlReporter();
-
-                  jasmineEnv.addReporter(htmlReporter);
-
-                  jasmineEnv.specFilter = function(spec) {
-                    return htmlReporter.specFilter(spec);
-                  };
-
-                  jasmineEnv.execute();
-              }, onError);
-          window.requestFileSystem(LocalFileSystem.TEMPORARY, 0,
-              function(fileSystem) {
-                  console.log('File API test Init: Setting TEMPORARY FS.');
-                  temp_root = fileSystem.root; // set in file.tests.js
-              }, onError);
-      }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./file.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/autotest/pages/file.js
----------------------------------------------------------------------
diff --git a/autotest/pages/file.js b/autotest/pages/file.js
new file mode 100644
index 0000000..9b1a67a
--- /dev/null
+++ b/autotest/pages/file.js
@@ -0,0 +1,39 @@
+var root, temp_root, persistent_root;
+
+document.addEventListener('deviceready', function () {
+    // one-time retrieval of the root file system entry
+    var onError = function(e) {
+        console.log('[ERROR] Problem setting up root filesystem for test running! Error to follow.');
+        console.log(JSON.stringify(e));
+    };
+
+    window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,
+        function(fileSystem) {
+            console.log('File API test Init: Setting PERSISTENT FS.');
+            root = fileSystem.root; // set in file.tests.js
+            persistent_root = root;
+
+            // Once root is set up, fire off tests
+            var jasmineEnv = jasmine.getEnv();
+            jasmineEnv.updateInterval = 1000;
+
+            var htmlReporter = new jasmine.HtmlReporter();
+
+            jasmineEnv.addReporter(htmlReporter);
+
+            jasmineEnv.specFilter = function(spec) {
+              return htmlReporter.specFilter(spec);
+            };
+
+            jasmineEnv.execute();
+        }, onError);
+    window.requestFileSystem(LocalFileSystem.TEMPORARY, 0,
+        function(fileSystem) {
+            console.log('File API test Init: Setting TEMPORARY FS.');
+            temp_root = fileSystem.root; // set in file.tests.js
+        }, onError);
+}, false);
+
+window.onload = function() {
+  addListenerToClass('backBtn', backHome);
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/autotest/pages/filetransfer.html
----------------------------------------------------------------------
diff --git a/autotest/pages/filetransfer.html b/autotest/pages/filetransfer.html
index 60cfcff..09809d8 100644
--- a/autotest/pages/filetransfer.html
+++ b/autotest/pages/filetransfer.html
@@ -44,48 +44,11 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/filetransfer.tests.js"></script>
-
-  <script type="text/javascript">
-      var root, temp_root, persistent_root;
-
-      document.addEventListener('deviceready', function () {
-          // one-time retrieval of the root file system entry
-          var onError = function(e) {
-              console.log('[ERROR] Problem setting up root filesystem for test running! Error to follow.');
-              console.log(JSON.stringify(e));
-          };
-
-          window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,
-              function(fileSystem) {
-                  console.log('File API test Init: Setting PERSISTENT FS.');
-                  root = fileSystem.root; // set in file.tests.js
-                  persistent_root = root;
-
-                  // Once root is set up, fire off tests
-                  var jasmineEnv = jasmine.getEnv();
-                  jasmineEnv.updateInterval = 1000;
-
-                  var htmlReporter = new jasmine.HtmlReporter();
-
-                  jasmineEnv.addReporter(htmlReporter);
-
-                  jasmineEnv.specFilter = function(spec) {
-                    return htmlReporter.specFilter(spec);
-                  };
-
-                  jasmineEnv.execute();
-              }, onError);
-          window.requestFileSystem(LocalFileSystem.TEMPORARY, 0,
-              function(fileSystem) {
-                  console.log('File API test Init: Setting TEMPORARY FS.');
-                  temp_root = fileSystem.root; // set in file.tests.js
-              }, onError);
-      }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./file.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/autotest/pages/geolocation.html
----------------------------------------------------------------------
diff --git a/autotest/pages/geolocation.html b/autotest/pages/geolocation.html
index 39f634e..b7a0698 100644
--- a/autotest/pages/geolocation.html
+++ b/autotest/pages/geolocation.html
@@ -45,27 +45,11 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/geolocation.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/autotest/pages/globalization.html
----------------------------------------------------------------------
diff --git a/autotest/pages/globalization.html b/autotest/pages/globalization.html
index 6ca5aaf..295067e 100644
--- a/autotest/pages/globalization.html
+++ b/autotest/pages/globalization.html
@@ -45,26 +45,10 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/globalization.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/autotest/pages/localXHR.html
----------------------------------------------------------------------
diff --git a/autotest/pages/localXHR.html b/autotest/pages/localXHR.html
index 2e64007..10415f0 100644
--- a/autotest/pages/localXHR.html
+++ b/autotest/pages/localXHR.html
@@ -45,26 +45,10 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/localXHR.tests.js"></script>
-
-  <script type="text/javascript">
-      document.addEventListener('deviceready', function () {
-          var jasmineEnv = jasmine.getEnv();
-          jasmineEnv.updateInterval = 1000;
-
-          var htmlReporter = new jasmine.HtmlReporter();
-
-          jasmineEnv.addReporter(htmlReporter);
-
-          jasmineEnv.specFilter = function (spec) {
-              return htmlReporter.specFilter(spec);
-          };
-
-          jasmineEnv.execute();
-      }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/autotest/pages/media.html
----------------------------------------------------------------------
diff --git a/autotest/pages/media.html b/autotest/pages/media.html
index 7e2c9e5..ac1fa75 100644
--- a/autotest/pages/media.html
+++ b/autotest/pages/media.html
@@ -45,27 +45,11 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/media.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/autotest/pages/network.html
----------------------------------------------------------------------
diff --git a/autotest/pages/network.html b/autotest/pages/network.html
index dcdec18..6af5521 100644
--- a/autotest/pages/network.html
+++ b/autotest/pages/network.html
@@ -45,27 +45,11 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/network.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/autotest/pages/notification.html
----------------------------------------------------------------------
diff --git a/autotest/pages/notification.html b/autotest/pages/notification.html
index 5ebfb86..50777bf 100644
--- a/autotest/pages/notification.html
+++ b/autotest/pages/notification.html
@@ -45,27 +45,11 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/notification.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/autotest/pages/platform.html
----------------------------------------------------------------------
diff --git a/autotest/pages/platform.html b/autotest/pages/platform.html
index e6ae3af..3ddecd0 100644
--- a/autotest/pages/platform.html
+++ b/autotest/pages/platform.html
@@ -45,27 +45,11 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/platform.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/autotest/pages/run-tests.js
----------------------------------------------------------------------
diff --git a/autotest/pages/run-tests.js b/autotest/pages/run-tests.js
new file mode 100644
index 0000000..8e079ad
--- /dev/null
+++ b/autotest/pages/run-tests.js
@@ -0,0 +1,18 @@
+document.addEventListener('deviceready', function () {
+  var jasmineEnv = jasmine.getEnv();
+  jasmineEnv.updateInterval = 1000;
+
+  var htmlReporter = new jasmine.HtmlReporter();
+
+  jasmineEnv.addReporter(htmlReporter);
+
+  jasmineEnv.specFilter = function(spec) {
+    return htmlReporter.specFilter(spec);
+  };
+
+  jasmineEnv.execute();
+}, false);
+
+window.onload = function() {
+  addListenerToClass('backBtn', backHome);
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/autotest/pages/splashscreen.html
----------------------------------------------------------------------
diff --git a/autotest/pages/splashscreen.html b/autotest/pages/splashscreen.html
index d830f9e..6ac1c4d 100644
--- a/autotest/pages/splashscreen.html
+++ b/autotest/pages/splashscreen.html
@@ -45,27 +45,11 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/splashscreen.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/autotest/pages/storage.html
----------------------------------------------------------------------
diff --git a/autotest/pages/storage.html b/autotest/pages/storage.html
index 9ca226b..0f836e9 100644
--- a/autotest/pages/storage.html
+++ b/autotest/pages/storage.html
@@ -45,27 +45,11 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/storage.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/autotest/pages/vibration.html
----------------------------------------------------------------------
diff --git a/autotest/pages/vibration.html b/autotest/pages/vibration.html
index b6bd03f..04db2ec 100644
--- a/autotest/pages/vibration.html
+++ b/autotest/pages/vibration.html
@@ -45,27 +45,11 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/vibration.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/autotest/pages/whitelist.html
----------------------------------------------------------------------
diff --git a/autotest/pages/whitelist.html b/autotest/pages/whitelist.html
index ca3712c..ececfa2 100644
--- a/autotest/pages/whitelist.html
+++ b/autotest/pages/whitelist.html
@@ -45,27 +45,11 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/whitelist.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/battery/index.html
----------------------------------------------------------------------
diff --git a/battery/index.html b/battery/index.html
index 70b0db7..016dc87 100644
--- a/battery/index.html
+++ b/battery/index.html
@@ -28,75 +28,10 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>      
-
-      
-<script type="text/javascript" charset="utf-8">
-
-    var deviceReady = false;
-    
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-                deviceReady = true;
-                console.log("Device="+device.platform+" "+device.version);
-            }, false);
-        window.setTimeout(function() {
-            if (!deviceReady) {
-                alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
-            }
-        },1000);
-    }
-
-    /* Battery */
-    function updateInfo(info) {
-        document.getElementById('level').innerText = info.level;
-        document.getElementById('isPlugged').innerText = info.isPlugged;
-        if (info.level > 5) {
-            document.getElementById('crit').innerText = "false";
-        }
-        if (info.level > 20) {
-            document.getElementById('low').innerText = "false";
-        }
-    }
-    
-    function batteryLow(info) {
-        document.getElementById('low').innerText = "true";
-    }
-    
-    function batteryCritical(info) {
-        document.getElementById('crit').innerText = "true";
-    }
-    
-    function addBattery() {
-        window.addEventListener("batterystatus", updateInfo, false);
-    }
-    
-    function removeBattery() {
-        window.removeEventListener("batterystatus", updateInfo, false);
-    }
-    
-    function addLow() {
-        window.addEventListener("batterylow", batteryLow, false);
-    }
-    
-    function removeLow() {
-        window.removeEventListener("batterylow", batteryLow, false);
-    }
-    
-    function addCritical() {
-        window.addEventListener("batterycritical", batteryCritical, false);
-    }
-    
-    function removeCritical() {
-        window.removeEventListener("batterycritical", batteryCritical, false);
-    }
-
-</script>
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
 
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>Battery</h1>
     <div id="info">
@@ -107,12 +42,12 @@
         Critical: <span id="crit"></span><br/>
     </div>
     <h2>Action</h2>
-    <div class="btn large" onclick="addBattery();">Add "batterystatus" listener</div>
-    <div class="btn large" onclick="removeBattery();">Remove "batterystatus" listener</div>
-    <div class="btn large" onclick="addLow();">Add "batterylow" listener</div>
-    <div class="btn large" onclick="removeLow();">Remove "batterylow" listener</div>
-    <div class="btn large" onclick="addCritical();">Add "batterycritical" listener</div>
-    <div class="btn large" onclick="removeCritical();">Remove "batterycritical" listener</div>
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <div class="btn large addBattery">Add "batterystatus" listener</div>
+    <div class="btn large removeBattery">Remove "batterystatus" listener</div>
+    <div class="btn large addLow">Add "batterylow" listener</div>
+    <div class="btn large removeLow">Remove "batterylow" listener</div>
+    <div class="btn large addCritical">Add "batterycritical" listener</div>
+    <div class="btn large removeCritical">Remove "batterycritical" listener</div>
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>      

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/battery/index.js
----------------------------------------------------------------------
diff --git a/battery/index.js b/battery/index.js
new file mode 100644
index 0000000..1a0d488
--- /dev/null
+++ b/battery/index.js
@@ -0,0 +1,72 @@
+var deviceReady = false;
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+            deviceReady = true;
+            console.log("Device="+device.platform+" "+device.version);
+        }, false);
+    window.setTimeout(function() {
+        if (!deviceReady) {
+            alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
+        }
+    },1000);
+}
+
+/* Battery */
+function updateInfo(info) {
+    document.getElementById('level').innerText = info.level;
+    document.getElementById('isPlugged').innerText = info.isPlugged;
+    if (info.level > 5) {
+        document.getElementById('crit').innerText = "false";
+    }
+    if (info.level > 20) {
+        document.getElementById('low').innerText = "false";
+    }
+}
+
+function batteryLow(info) {
+    document.getElementById('low').innerText = "true";
+}
+
+function batteryCritical(info) {
+    document.getElementById('crit').innerText = "true";
+}
+
+function addBattery() {
+    window.addEventListener("batterystatus", updateInfo, false);
+}
+
+function removeBattery() {
+    window.removeEventListener("batterystatus", updateInfo, false);
+}
+
+function addLow() {
+    window.addEventListener("batterylow", batteryLow, false);
+}
+
+function removeLow() {
+    window.removeEventListener("batterylow", batteryLow, false);
+}
+
+function addCritical() {
+    window.addEventListener("batterycritical", batteryCritical, false);
+}
+
+function removeCritical() {
+    window.removeEventListener("batterycritical", batteryCritical, false);
+}
+
+window.onload = function() {
+  addListenerToClass('addBattery', addBattery);
+  addListenerToClass('removeBattery', removeBattery);
+  addListenerToClass('addLow', addLow);
+  addListenerToClass('removeLow', removeLow);
+  addListenerToClass('addCritical', addCritical);
+  addListenerToClass('removeCritical', removeCritical);
+  
+  addListenerToClass('backBtn', backHome);
+  init();
+}


[09/12] spec commit: Manual tests fixed

Posted by za...@apache.org.
Manual tests fixed

Removing inline scripts from mobile-spec to make it compatible with FFOS priveleged type apps (i.e. using contacts)

added addListenerToClass function which is used to connect buttons with test functions.

Please check it on all platforms and r+ if working.

moved test initialization to JS file (for DRY and privileged apps compatibility)


Project: http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/commit/0de5e956
Tree: http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/tree/0de5e956
Diff: http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/diff/0de5e956

Branch: refs/heads/master
Commit: 0de5e956d2f677d5ea770bb97ae6b9a1ed10c33b
Parents: 508f29f
Author: Piotr Zalewa <pi...@zalewa.info>
Authored: Wed Apr 30 15:14:04 2014 +0200
Committer: Piotr Zalewa <pi...@zalewa.info>
Committed: Wed May 14 15:53:27 2014 +0200

----------------------------------------------------------------------
 accelerometer/index.html                  | 120 +-------
 accelerometer/index.js                    | 111 ++++++++
 audio/index.html                          | 370 +------------------------
 audio/index.js                            | 356 ++++++++++++++++++++++++
 autotest/index.html                       |   3 +-
 autotest/index.js                         |   4 +
 autotest/pages/accelerometer.html         |  20 +-
 autotest/pages/all.html                   |  47 +---
 autotest/pages/all.js                     |  46 +++
 autotest/pages/battery.html               |  19 +-
 autotest/pages/bridge.html                |  20 +-
 autotest/pages/camera.html                |  20 +-
 autotest/pages/capture.html               |  20 +-
 autotest/pages/compass.html               |  20 +-
 autotest/pages/contacts.html              |  19 +-
 autotest/pages/datauri.html               |  18 +-
 autotest/pages/device.html                |  20 +-
 autotest/pages/file.html                  |  41 +--
 autotest/pages/file.js                    |  39 +++
 autotest/pages/filetransfer.html          |  41 +--
 autotest/pages/geolocation.html           |  20 +-
 autotest/pages/globalization.html         |  20 +-
 autotest/pages/localXHR.html              |  20 +-
 autotest/pages/media.html                 |  20 +-
 autotest/pages/network.html               |  20 +-
 autotest/pages/notification.html          |  20 +-
 autotest/pages/platform.html              |  20 +-
 autotest/pages/run-tests.js               |  18 ++
 autotest/pages/splashscreen.html          |  20 +-
 autotest/pages/storage.html               |  20 +-
 autotest/pages/vibration.html             |  20 +-
 autotest/pages/whitelist.html             |  20 +-
 battery/index.html                        |  83 +-----
 battery/index.js                          |  72 +++++
 camera/index.html                         | 361 +-----------------------
 camera/index.js                           | 344 +++++++++++++++++++++++
 capture/index.html                        | 147 +---------
 capture/index.js                          | 137 +++++++++
 compass/index.html                        | 114 +-------
 compass/index.js                          | 104 +++++++
 contacts/index.html                       |  99 +------
 contacts/index.js                         |  90 ++++++
 cordova-incl.js                           |  22 ++
 events/index.html                         |  86 ++----
 events/index.js                           |  94 +++++++
 file/index.html                           | 158 +----------
 file/index.js                             | 153 ++++++++++
 inappbrowser/index.html                   | 266 ++++--------------
 inappbrowser/index.js                     | 242 ++++++++++++++++
 index.html                                |   2 +-
 keyboard/index.html                       |  68 +----
 keyboard/index.js                         |  69 +++++
 keyboard/window-onerror.js                |   1 +
 lazyloadjs/do-not-write-cordova-script.js |   1 +
 lazyloadjs/index.html                     |  20 +-
 lazyloadjs/index.js                       |  16 ++
 location/index.html                       | 143 +---------
 location/index.js                         | 128 +++++++++
 main.js                                   |   2 +
 misc/index.html                           |  35 +--
 misc/index.js                             |  30 ++
 misc/page2.html                           |  14 +-
 misc/page2.js                             |  12 +
 misc/page3.html                           |  30 +-
 misc/page3A.js                            |  27 ++
 network/index.html                        |  45 +--
 network/index.js                          |  38 +++
 notification/index.html                   | 110 +-------
 notification/index.js                     | 100 +++++++
 sql/index.html                            | 137 +--------
 sql/index.js                              | 125 +++++++++
 storage/index.html                        |  37 +--
 storage/index.js                          |  27 ++
 vibration/index.html                      |  39 +--
 vibration/index.js                        |  31 +++
 75 files changed, 2687 insertions(+), 2764 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/accelerometer/index.html
----------------------------------------------------------------------
diff --git a/accelerometer/index.html b/accelerometer/index.html
index bbec57f..71000b8 100644
--- a/accelerometer/index.html
+++ b/accelerometer/index.html
@@ -27,118 +27,10 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>      
-
-      
-<script type="text/javascript" charset="utf-8">
-
-    var deviceReady = false;
-
-    function roundNumber(num) {
-        var dec = 3;
-        var result = Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
-        return result;
-    }
-
-    //-------------------------------------------------------------------------
-    // Acceleration
-    //-------------------------------------------------------------------------
-    var watchAccelId = null;
-    
-    /**
-     * Start watching acceleration
-     */
-    var watchAccel = function() {
-        console.log("watchAccel()");
-
-        // Success callback
-        var success = function(a){
-            document.getElementById('x').innerHTML = roundNumber(a.x);
-            document.getElementById('y').innerHTML = roundNumber(a.y);
-            document.getElementById('z').innerHTML = roundNumber(a.z);
-            console.log("watchAccel success callback");
-        };
-
-        // Fail callback
-        var fail = function(e){
-            console.log("watchAccel fail callback with error code "+e);
-            stopAccel();
-            setAccelStatus(Accelerometer.ERROR_MSG[e]);
-        };
-
-        // Update acceleration every 1 sec
-        var opt = {};
-        opt.frequency = 1000;
-        watchAccelId = navigator.accelerometer.watchAcceleration(success, fail, opt);
-
-        setAccelStatus("Running");
-    };
-
-    /**
-     * Stop watching the acceleration
-     */
-    var stopAccel = function() {
-    	console.log("stopAccel()");
-        setAccelStatus("Stopped");
-        if (watchAccelId) {
-            navigator.accelerometer.clearWatch(watchAccelId);
-            watchAccelId = null;
-        }
-    };
-
-    /**
-     * Get current acceleration
-     */
-    var getAccel = function() {
-        console.log("getAccel()");
-
-        // Stop accel if running
-        stopAccel();
-
-        // Success callback
-        var success = function(a){
-            document.getElementById('x').innerHTML = roundNumber(a.x);
-            document.getElementById('y').innerHTML = roundNumber(a.y);
-            document.getElementById('z').innerHTML = roundNumber(a.z);
-        };
-
-        // Fail callback
-        var fail = function(e){
-            console.log("getAccel fail callback with error code "+e);
-            setAccelStatus(Accelerometer.ERROR_MSG[e]);
-        };
-
-        // Make call
-        var opt = {};
-        navigator.accelerometer.getCurrentAcceleration(success, fail, opt);
-    };
-
-    /**
-     * Set accelerometer status
-     */
-    var setAccelStatus = function(status) {
-        document.getElementById('accel_status').innerHTML = status;
-    };
-    
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        console.log("accelerometer.init()");
-        document.addEventListener("deviceready", function() {
-                deviceReady = true;
-                console.log("Device="+device.platform+" "+device.version);
-            }, false);
-        window.setTimeout(function() {
-        	if (!deviceReady) {
-        		alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
-        	}
-        },1000);
-    }
-
-</script>
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
 
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>Acceleration</h1>
     <div id="info">
@@ -151,9 +43,9 @@
     </div>
 
     <h2>Action</h2>
-    <div class="btn large" onclick="getAccel();">Get Acceleration</div>
-    <div class="btn large" onclick="watchAccel();">Start Watch</div>
-    <div class="btn large" onclick="stopAccel();">Clear Watch</div>
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <div class="btn large getAccel">Get Acceleration</div>
+    <div class="btn large watchAccel">Start Watch</div>
+    <div class="btn large stopAccel">Clear Watch</div>
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>      

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/accelerometer/index.js
----------------------------------------------------------------------
diff --git a/accelerometer/index.js b/accelerometer/index.js
new file mode 100644
index 0000000..946cfe2
--- /dev/null
+++ b/accelerometer/index.js
@@ -0,0 +1,111 @@
+var deviceReady = false;
+
+function roundNumber(num) {
+    var dec = 3;
+    var result = Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
+    return result;
+}
+
+//-------------------------------------------------------------------------
+// Acceleration
+//-------------------------------------------------------------------------
+var watchAccelId = null;
+
+/**
+ * Start watching acceleration
+ */
+var watchAccel = function() {
+    console.log("watchAccel()");
+
+    // Success callback
+    var success = function(a){
+        document.getElementById('x').innerHTML = roundNumber(a.x);
+        document.getElementById('y').innerHTML = roundNumber(a.y);
+        document.getElementById('z').innerHTML = roundNumber(a.z);
+        console.log("watchAccel success callback");
+    };
+
+    // Fail callback
+    var fail = function(e){
+        console.log("watchAccel fail callback with error code "+e);
+        stopAccel();
+        setAccelStatus(Accelerometer.ERROR_MSG[e]);
+    };
+
+    // Update acceleration every 1 sec
+    var opt = {};
+    opt.frequency = 1000;
+    watchAccelId = navigator.accelerometer.watchAcceleration(success, fail, opt);
+
+    setAccelStatus("Running");
+};
+
+/**
+ * Stop watching the acceleration
+ */
+var stopAccel = function() {
+	console.log("stopAccel()");
+    setAccelStatus("Stopped");
+    if (watchAccelId) {
+        navigator.accelerometer.clearWatch(watchAccelId);
+        watchAccelId = null;
+    }
+};
+
+/**
+ * Get current acceleration
+ */
+var getAccel = function() {
+    console.log("getAccel()");
+
+    // Stop accel if running
+    stopAccel();
+
+    // Success callback
+    var success = function(a){
+        document.getElementById('x').innerHTML = roundNumber(a.x);
+        document.getElementById('y').innerHTML = roundNumber(a.y);
+        document.getElementById('z').innerHTML = roundNumber(a.z);
+    };
+
+    // Fail callback
+    var fail = function(e){
+        console.log("getAccel fail callback with error code "+e);
+        setAccelStatus(Accelerometer.ERROR_MSG[e]);
+    };
+
+    // Make call
+    var opt = {};
+    navigator.accelerometer.getCurrentAcceleration(success, fail, opt);
+};
+
+/**
+ * Set accelerometer status
+ */
+var setAccelStatus = function(status) {
+    document.getElementById('accel_status').innerHTML = status;
+};
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    console.log("accelerometer.init()");
+    document.addEventListener("deviceready", function() {
+            deviceReady = true;
+            console.log("Device="+device.platform+" "+device.version);
+        }, false);
+    window.setTimeout(function() {
+    	if (!deviceReady) {
+    		alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
+    	}
+    },1000);
+}
+
+window.onload = function() {
+  addListenerToClass('getAccel', getAccel);
+  addListenerToClass('watchAccel', watchAccel);
+  addListenerToClass('stopAccel', stopAccel);
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/audio/index.html
----------------------------------------------------------------------
diff --git a/audio/index.html b/audio/index.html
index a0286d0..a05ea04 100644
--- a/audio/index.html
+++ b/audio/index.html
@@ -28,354 +28,10 @@
     <title>Cordova Audio Tests</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="../cordova-incl.js"></script>      
-
-      
-<script type="text/javascript" charset="utf-8">
-
-	 var defaultaudio = "http://cordova.apache.org/downloads/BlueZedEx.mp3";
-    var deviceReady = false;
-
-    //-------------------------------------------------------------------------
-    // Audio player
-    //-------------------------------------------------------------------------
-    var media1 = null;
-    var media1Timer = null;
-    var audioSrc = null;
-    var recordSrc = "myRecording.mp3";
-
-    /**
-     * Play audio
-     */
-    function playAudio(url) {
-        console.log("playAudio()");
-        console.log(" -- media="+media1);
-
-	    var src = defaultaudio;
-        
-        if (url) {
-            src = url;
-        }
-
-        // Stop playing if src is different from currently playing source
-        if (src != audioSrc) {
-            if (media1 != null) {
-                stopAudio();
-                media1 = null;
-            }
-        }
-
-        if (media1 == null) {
-
-
-            // TEST STREAMING AUDIO PLAYBACK
-            //var src = "http://nunzioweb.com/misc/Bon_Jovi-Crush_Mystery_Train.mp3";   // works
-            //var src = "http://nunzioweb.com/misc/Bon_Jovi-Crush_Mystery_Train.m3u"; // doesn't work
-            //var src = "http://www.wav-sounds.com/cartoon/bugsbunny1.wav"; // works
-            //var src = "http://www.angelfire.com/fl5/html-tutorial/a/couldyou.mid"; // doesn't work
-            //var src = "MusicSearch/mp3/train.mp3";    // works
-            //var src = "bryce.mp3";  // works
-            //var src = "/android_asset/www/bryce.mp3"; // works
-
-            media1 = new Media(src,
-                function() {
-                    console.log("playAudio():Audio Success");
-                },
-                function(err) {
-                    console.log("playAudio():Audio Error: "+err.code);
-                    setAudioStatus("Error: " + err.code);
-                },
-                function(status) {
-                    console.log("playAudio():Audio Status: "+status);
-                    setAudioStatus(Media.MEDIA_MSG[status]);
-
-                    // If stopped, then stop getting current position
-                    if (Media.MEDIA_STOPPED == status) {
-                        clearInterval(media1Timer);
-                        media1Timer = null;
-                        setAudioPosition("0 sec");
-                    }
-                });
-        }
-        audioSrc = src;
-        document.getElementById('audio_duration').innerHTML = "";
-        // Play audio
-        media1.play();
-        if (media1Timer == null && media1.getCurrentPosition) {
-            media1Timer = setInterval(
-                function() {
-                    media1.getCurrentPosition(
-                        function(position) {
-                            console.log("Pos="+position);
-                            if (position >= 0.0) {
-                                setAudioPosition(position+" sec");
-                            }
-                        },
-                        function(e) {
-                            console.log("Error getting pos="+e);
-                            setAudioPosition("Error: "+e);
-                        }
-                    );
-                },
-                1000
-            );
-        }
-
-        // Get duration
-        var counter = 0;
-        var timerDur = setInterval(
-            function() {
-                counter = counter + 100;
-                if (counter > 2000) {
-                    clearInterval(timerDur);
-                }
-                var dur = media1.getDuration();
-                if (dur > 0) {
-                    clearInterval(timerDur);
-                    document.getElementById('audio_duration').innerHTML = dur + " sec";
-                }
-            }, 100);
-    }
-
-    /**
-     * Pause audio playback
-     */
-    function pauseAudio() {
-        console.log("pauseAudio()");
-        if (media1) {
-            media1.pause();
-        }
-    }
-
-    /**
-     * Stop audio
-     */
-    function stopAudio() {
-        console.log("stopAudio()");
-        if (media1) {
-            media1.stop();
-        }
-        clearInterval(media1Timer);
-        media1Timer = null;
-    }
-    
-    /**
-     * Release audio
-     */
-	function releaseAudio() {
-	    console.log("releaseAudio()");
-	    if (media1) {
-	    	media1.stop(); //imlied stop of playback, resets timer
-	    	media1.release();
-	    }
-	}
-	
-    /**
-     * Set audio status
-     */
-    var setAudioStatus = function(status) {
-        document.getElementById('audio_status').innerHTML = status;
-    };
-
-    /**
-     * Set audio position
-     */
-    var setAudioPosition = function(position) {
-        document.getElementById('audio_position').innerHTML = position;
-    };
-
-    //-------------------------------------------------------------------------
-    // Audio recorder
-    //-------------------------------------------------------------------------
-    var mediaRec = null;
-    var recTime = 0;
-
-    /**
-     * Record audio
-     */
-    function recordAudio() {
-        console.log("recordAudio()");
-        console.log(" -- media="+mediaRec);
-        if (mediaRec == null) {
-
-            var src = recordSrc;
-            mediaRec = new Media(src,
-                    function() {
-                        console.log("recordAudio():Audio Success");
-                    },
-                    function(err) {
-                        console.log("recordAudio():Audio Error: "+err.code);
-                        setAudioStatus("Error: " + err.code);
-                    },
-                    function(status) {
-                        console.log("recordAudio():Audio Status: "+status);
-                        setAudioStatus(Media.MEDIA_MSG[status]);
-                    }
-                );
-        }
-
-        navigator.notification.beep(1);
-
-        // Record audio
-        mediaRec.startRecord();
-
-        // Stop recording after 10 sec
-        recTime = 0;
-        var recInterval = setInterval(function() {
-            recTime = recTime + 1;
-            setAudioPosition(recTime+" sec");
-            if (recTime >= 10) {
-                clearInterval(recInterval);
-                if (mediaRec.stopAudioRecord){
-                    mediaRec.stopAudioRecord();
-                } else {
-                    mediaRec.stopRecord();
-                }
-                console.log("recordAudio(): stop");
-                navigator.notification.beep(1);
-            }
-        }, 1000);
-    }
-
-    /**
-     * Play back recorded audio
-     */
-    function playRecording() {
-        playAudio(recordSrc);
-    }
-    
-    /**
-     * Function to create a file for iOS recording
-     */
-    function getRecordSrc() {
-        var fsFail = function(error) {
-            console.log("error creating file for iOS recording");
-        };
-        var gotFile = function(file) {
-            recordSrc = file.fullPath;
-            //console.log("recording Src: " + recordSrc);
-        };
-        var gotFS = function(fileSystem) {
-            fileSystem.root.getFile("iOSRecording.wav", {create: true}, gotFile, fsFail);
-        };
-        window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, gotFS, fsFail);
-    }
-    
-    /**
-     * Function to create a file for BB recording
-     */
-    function getRecordSrcBB() {
-        var fsFail = function(error) {
-            console.log("error creating file for BB recording");
-        };
-        var gotFile = function(file) {
-            recordSrc = file.fullPath;
-        };
-        var gotFS = function(fileSystem) {
-            fileSystem.root.getFile("BBRecording.amr", {create: true}, gotFile, fsFail);
-        };
-        window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, gotFS, fsFail);
-    }
-
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-                deviceReady = true;
-                if (device.platform.indexOf("iOS") !=-1)
-                {
-                     getRecordSrc();
-                } else if (typeof blackberry !== 'undefined') {
-                    getRecordSrcBB();
-                }
-                console.log("Device="+device.platform+" "+device.version);
-            }, false);
-        window.setTimeout(function() {
-        	if (!deviceReady) {
-        		alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
-        	}
-        },1000);
-    }
-    
-    /**
-     * for forced updates of position after a successful seek
-     */
-    function updatePosition() {
-        media1.getCurrentPosition(
-            function(position) {
-                console.log("Pos="+position);
-                if (position >= 0.0) {
-                    setAudioPosition(position+" sec");
-                }
-            },
-            function(e) {
-                console.log("Error getting pos="+e);
-                setAudioPosition("Error: "+e);
-            });
-    }
-
-    /**
-     *
-     */
-    function seekAudio(mode) {
-        var time = document.getElementById("seekinput").value;
-        if (time == "") {
-            time = 5000;
-        } else {
-            time = time * 1000; //we expect the input to be in seconds
-        }
-        if (media1 == null) {
-            console.log("seekTo requested while media1 is null");
-            if (audioSrc == null) {
-                audioSrc = defaultaudio;
-            }
-            media1 = new Media(audioSrc,
-                function() {
-                    console.log("seekToAudio():Audio Success");
-                },
-                function(err) {
-                    console.log("seekAudio():Audio Error: "+err.code);
-                    setAudioStatus("Error: " + err.code);
-                },
-                function(status) {
-                    console.log("seekAudio():Audio Status: "+status);
-                    setAudioStatus(Media.MEDIA_MSG[status]);
-
-                    // If stopped, then stop getting current position
-                    if (Media.MEDIA_STOPPED == status) {
-                        clearInterval(media1Timer);
-                        media1Timer = null;
-                        setAudioPosition("0 sec");
-                    }
-                });
-        }
-        
-        media1.getCurrentPosition(
-            function (position) {
-                var deltat = time;
-                if (mode == "by") {
-                    deltat = time + position * 1000;   
-                }
-                media1.seekTo(deltat,
-                    function () {
-                        console.log("seekAudioTo():Audio Success");
-                        //force an update on the position display
-                        updatePosition();
-                    },
-                    function (err) {
-                        console.log("seekAudioTo():Audio Error: " + err.code);
-                    });
-            },
-            function(e) {
-                console.log("Error getting pos="+e);
-                setAudioPosition("Error: "+e);
-            });
-    }
-    
-</script>
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
 
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>Audio</h1>  
     <div id="info">
@@ -391,19 +47,19 @@
             <th colspan=3>Play Sample Audio</th>
         </tr>
         <tr>
-            <td><div class="btn wide" onclick="playAudio();">Play</div></td>
-            <td><div class="btn wide" onclick="pauseAudio();">Pause</div></td>
+            <td><div class="btn wide playAudio">Play</div></td>
+            <td><div class="btn wide pauseAudio">Pause</div></td>
         </tr>
         <tr>
-            <td><div class="btn wide" onclick="stopAudio();">Stop</div></td>
-            <td><div class="btn wide" onclick="releaseAudio();">Release</div></td>
+            <td><div class="btn wide stopAudio">Stop</div></td>
+            <td><div class="btn wide releaseAudio">Release</div></td>
         </tr>
     </table>
     
     <table style="width:80%;">
         <tr>
-            <td><div class="btn wide" onclick="seekAudio('by');">Seek By</div></td>
-            <td><div class="btn wide" onclick="seekAudio('to');">Seek To</div></td>
+            <td><div class="btn wide seekAudioBy">Seek By</div></td>
+            <td><div class="btn wide seekAudioTo">Seek To</div></td>
             <td>
                 <div>
                     <input class="input numeric" type="number" id="seekinput" value="in seconds">
@@ -417,16 +73,16 @@
             <th colspan=3><br><br>Record Audio</th>
         </tr>
         <tr>
-            <td colspan=3><div class="btn wide" onclick="recordAudio();">Record Audio for 10 sec</a></td>
+            <td colspan=3><div class="btn wide recordAudio">Record Audio for 10 sec</a></td>
         </tr>
         <tr>
-            <td><div class="btn wide" onclick="playRecording();">Play</div></td>
-            <td><div class="btn wide" onclick="pauseAudio();">Pause</div></td>
-            <td><div class="btn wide" onclick="stopAudio();">Stop</div></td>
+            <td><div class="btn wide playRecording">Play</div></td>
+            <td><div class="btn wide pauseAudio">Pause</div></td>
+            <td><div class="btn wide stopAudio">Stop</div></td>
         </tr>
     </table>
     
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <h2> </h2><div class="backBtn">Back</div>
     
   </body>
 </html>      

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/audio/index.js
----------------------------------------------------------------------
diff --git a/audio/index.js b/audio/index.js
new file mode 100644
index 0000000..e7ca9b6
--- /dev/null
+++ b/audio/index.js
@@ -0,0 +1,356 @@
+var defaultaudio = "http://cordova.apache.org/downloads/BlueZedEx.mp3";
+var deviceReady = false;
+
+//-------------------------------------------------------------------------
+// Audio player
+//-------------------------------------------------------------------------
+var media1 = null;
+var media1Timer = null;
+var audioSrc = null;
+var recordSrc = "myRecording.mp3";
+
+/**
+ * Play audio
+ */
+function playAudio(url) {
+    console.log("playAudio()");
+    console.log(" -- media="+media1);
+
+  var src = defaultaudio;
+    
+    if (url) {
+        src = url;
+    }
+
+    // Stop playing if src is different from currently playing source
+    if (src != audioSrc) {
+        if (media1 != null) {
+            stopAudio();
+            media1 = null;
+        }
+    }
+
+    if (media1 == null) {
+
+
+        // TEST STREAMING AUDIO PLAYBACK
+        //var src = "http://nunzioweb.com/misc/Bon_Jovi-Crush_Mystery_Train.mp3";   // works
+        //var src = "http://nunzioweb.com/misc/Bon_Jovi-Crush_Mystery_Train.m3u"; // doesn't work
+        //var src = "http://www.wav-sounds.com/cartoon/bugsbunny1.wav"; // works
+        //var src = "http://www.angelfire.com/fl5/html-tutorial/a/couldyou.mid"; // doesn't work
+        //var src = "MusicSearch/mp3/train.mp3";    // works
+        //var src = "bryce.mp3";  // works
+        //var src = "/android_asset/www/bryce.mp3"; // works
+
+        media1 = new Media(src,
+            function() {
+                console.log("playAudio():Audio Success");
+            },
+            function(err) {
+                console.log("playAudio():Audio Error: "+err.code);
+                setAudioStatus("Error: " + err.code);
+            },
+            function(status) {
+                console.log("playAudio():Audio Status: "+status);
+                setAudioStatus(Media.MEDIA_MSG[status]);
+
+                // If stopped, then stop getting current position
+                if (Media.MEDIA_STOPPED == status) {
+                    clearInterval(media1Timer);
+                    media1Timer = null;
+                    setAudioPosition("0 sec");
+                }
+            });
+    }
+    audioSrc = src;
+    document.getElementById('audio_duration').innerHTML = "";
+    // Play audio
+    media1.play();
+    if (media1Timer == null && media1.getCurrentPosition) {
+        media1Timer = setInterval(
+            function() {
+                media1.getCurrentPosition(
+                    function(position) {
+                        console.log("Pos="+position);
+                        if (position >= 0.0) {
+                            setAudioPosition(position+" sec");
+                        }
+                    },
+                    function(e) {
+                        console.log("Error getting pos="+e);
+                        setAudioPosition("Error: "+e);
+                    }
+                );
+            },
+            1000
+        );
+    }
+
+    // Get duration
+    var counter = 0;
+    var timerDur = setInterval(
+        function() {
+            counter = counter + 100;
+            if (counter > 2000) {
+                clearInterval(timerDur);
+            }
+            var dur = media1.getDuration();
+            if (dur > 0) {
+                clearInterval(timerDur);
+                document.getElementById('audio_duration').innerHTML = dur + " sec";
+            }
+        }, 100);
+}
+
+/**
+ * Pause audio playback
+ */
+function pauseAudio() {
+    console.log("pauseAudio()");
+    if (media1) {
+        media1.pause();
+    }
+}
+
+/**
+ * Stop audio
+ */
+function stopAudio() {
+    console.log("stopAudio()");
+    if (media1) {
+        media1.stop();
+    }
+    clearInterval(media1Timer);
+    media1Timer = null;
+}
+
+/**
+ * Release audio
+ */
+function releaseAudio() {
+  console.log("releaseAudio()");
+  if (media1) {
+  	media1.stop(); //imlied stop of playback, resets timer
+  	media1.release();
+  }
+}
+
+
+/**
+ * Set audio status
+ */
+function setAudioStatus(status) {
+    document.getElementById('audio_status').innerHTML = status;
+};
+
+/**
+ * Set audio position
+ */
+function setAudioPosition(position) {
+    document.getElementById('audio_position').innerHTML = position;
+};
+
+//-------------------------------------------------------------------------
+// Audio recorder
+//-------------------------------------------------------------------------
+var mediaRec = null;
+var recTime = 0;
+
+/**
+ * Record audio
+ */
+function recordAudio() {
+    console.log("recordAudio()");
+    console.log(" -- media="+mediaRec);
+    if (mediaRec == null) {
+
+        var src = recordSrc;
+        mediaRec = new Media(src,
+                function() {
+                    console.log("recordAudio():Audio Success");
+                },
+                function(err) {
+                    console.log("recordAudio():Audio Error: "+err.code);
+                    setAudioStatus("Error: " + err.code);
+                },
+                function(status) {
+                    console.log("recordAudio():Audio Status: "+status);
+                    setAudioStatus(Media.MEDIA_MSG[status]);
+                }
+            );
+    }
+
+    navigator.notification.beep(1);
+
+    // Record audio
+    mediaRec.startRecord();
+
+    // Stop recording after 10 sec
+    recTime = 0;
+    var recInterval = setInterval(function() {
+        recTime = recTime + 1;
+        setAudioPosition(recTime+" sec");
+        if (recTime >= 10) {
+            clearInterval(recInterval);
+            if (mediaRec.stopAudioRecord){
+                mediaRec.stopAudioRecord();
+            } else {
+                mediaRec.stopRecord();
+            }
+            console.log("recordAudio(): stop");
+            navigator.notification.beep(1);
+        }
+    }, 1000);
+}
+
+/**
+ * Play back recorded audio
+ */
+function playRecording() {
+    playAudio(recordSrc);
+}
+
+/**
+ * Function to create a file for iOS recording
+ */
+function getRecordSrc() {
+    var fsFail = function(error) {
+        console.log("error creating file for iOS recording");
+    };
+    var gotFile = function(file) {
+        recordSrc = file.fullPath;
+        //console.log("recording Src: " + recordSrc);
+    };
+    var gotFS = function(fileSystem) {
+        fileSystem.root.getFile("iOSRecording.wav", {create: true}, gotFile, fsFail);
+    };
+    window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, gotFS, fsFail);
+}
+
+/**
+ * Function to create a file for BB recording
+ */
+function getRecordSrcBB() {
+    var fsFail = function(error) {
+        console.log("error creating file for BB recording");
+    };
+    var gotFile = function(file) {
+        recordSrc = file.fullPath;
+    };
+    var gotFS = function(fileSystem) {
+        fileSystem.root.getFile("BBRecording.amr", {create: true}, gotFile, fsFail);
+    };
+    window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, gotFS, fsFail);
+}
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+            deviceReady = true;
+            if (device.platform.indexOf("iOS") !=-1)
+            {
+                 getRecordSrc();
+            } else if (typeof blackberry !== 'undefined') {
+                getRecordSrcBB();
+            }
+            console.log("Device="+device.platform+" "+device.version);
+        }, false);
+    window.setTimeout(function() {
+    	if (!deviceReady) {
+    		alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
+    	}
+    },1000);
+}
+
+/**
+ * for forced updates of position after a successful seek
+ */
+function updatePosition() {
+    media1.getCurrentPosition(
+        function(position) {
+            console.log("Pos="+position);
+            if (position >= 0.0) {
+                setAudioPosition(position+" sec");
+            }
+        },
+        function(e) {
+            console.log("Error getting pos="+e);
+            setAudioPosition("Error: "+e);
+        });
+}
+
+/**
+ *
+ */
+function seekAudio(mode) {
+    var time = document.getElementById("seekinput").value;
+    if (time == "") {
+        time = 5000;
+    } else {
+        time = time * 1000; //we expect the input to be in seconds
+    }
+    if (media1 == null) {
+        console.log("seekTo requested while media1 is null");
+        if (audioSrc == null) {
+            audioSrc = defaultaudio;
+        }
+        media1 = new Media(audioSrc,
+            function() {
+                console.log("seekToAudio():Audio Success");
+            },
+            function(err) {
+                console.log("seekAudio():Audio Error: "+err.code);
+                setAudioStatus("Error: " + err.code);
+            },
+            function(status) {
+                console.log("seekAudio():Audio Status: "+status);
+                setAudioStatus(Media.MEDIA_MSG[status]);
+
+                // If stopped, then stop getting current position
+                if (Media.MEDIA_STOPPED == status) {
+                    clearInterval(media1Timer);
+                    media1Timer = null;
+                    setAudioPosition("0 sec");
+                }
+            });
+    }
+    
+    media1.getCurrentPosition(
+        function (position) {
+            var deltat = time;
+            if (mode == "by") {
+                deltat = time + position * 1000;   
+            }
+            media1.seekTo(deltat,
+                function () {
+                    console.log("seekAudioTo():Audio Success");
+                    //force an update on the position display
+                    updatePosition();
+                },
+                function (err) {
+                    console.log("seekAudioTo():Audio Error: " + err.code);
+                });
+        },
+        function(e) {
+            console.log("Error getting pos="+e);
+            setAudioPosition("Error: "+e);
+        });
+}
+
+window.onload = function() {
+  addListenerToClass('playAudio', function () {
+    playAudio();
+  });
+  addListenerToClass('pauseAudio', pauseAudio);
+  addListenerToClass('stopAudio', stopAudio);
+  addListenerToClass('releaseAudio', releaseAudio);
+  addListenerToClass('seekAudioBy', seekAudio, 'by');
+  addListenerToClass('seekAudioTo', seekAudio, 'to');
+  addListenerToClass('recordAudio', recordAudio);
+  addListenerToClass('playRecording', playRecording);
+
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/autotest/index.html
----------------------------------------------------------------------
diff --git a/autotest/index.html b/autotest/index.html
index a699870..3a41d78 100644
--- a/autotest/index.html
+++ b/autotest/index.html
@@ -30,6 +30,7 @@
 
     <link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title" charset="utf-8">
     <script type="text/javascript" src="../cordova-incl.js"></script>
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
   </head>
   <body id="stage" class="theme">
     <h1>Cordova API Specs</h1>
@@ -57,6 +58,6 @@
     <a href="pages/whitelist.html" class="btn large" style="width:100%;">Run Whitelist Tests</a>
     <a href="pages/localXHR.html" class="btn large" style="width:100%;">Run local XHR Tests</a>
     <a href="pages/vibration.html" class="btn large" style="width:100%;">Run Vibration Tests</a>
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/autotest/index.js
----------------------------------------------------------------------
diff --git a/autotest/index.js b/autotest/index.js
new file mode 100644
index 0000000..aec19b4
--- /dev/null
+++ b/autotest/index.js
@@ -0,0 +1,4 @@
+window.onload = function() {
+  addListenerToClass('backBtn', backHome);
+}
+

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/autotest/pages/accelerometer.html
----------------------------------------------------------------------
diff --git a/autotest/pages/accelerometer.html b/autotest/pages/accelerometer.html
index 856dc70..52b333b 100644
--- a/autotest/pages/accelerometer.html
+++ b/autotest/pages/accelerometer.html
@@ -45,26 +45,10 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/accelerometer.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/autotest/pages/all.html
----------------------------------------------------------------------
diff --git a/autotest/pages/all.html b/autotest/pages/all.html
index ef656bc..e381ef4 100644
--- a/autotest/pages/all.html
+++ b/autotest/pages/all.html
@@ -63,53 +63,10 @@
   <script type="text/javascript" src="../tests/storage.tests.js"></script>
   <script type="text/javascript" src="../tests/splashscreen.tests.js"></script>
   <script type="text/javascript" src="../tests/localXHR.tests.js"></script>
-
-  <script type="text/javascript">
-      var root, temp_root, persistent_root;
-
-      document.addEventListener('deviceready', function () {
-          // one-time retrieval of the root file system entry
-          var onError = function(e) {
-              console.log('[ERROR] Problem setting up root filesystem for test running! Error to follow.');
-              console.log(JSON.stringify(e));
-          };
-
-          window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,
-              function(fileSystem) {
-                  console.log('File API test Init: Setting PERSISTENT FS.');
-                  root = fileSystem.root; // set in file.tests.js
-                  persistent_root = root;
-
-                  // Once root is set up, fire off tests
-                  var jasmineEnv = jasmine.getEnv();
-                  jasmineEnv.updateInterval = 1000;
-
-                  var htmlReporter = new jasmine.HtmlReporter();
-                  jasmineEnv.addReporter(htmlReporter);
-
-                  // the following will only be defined if the Medic plugin is loaded
-                  if('medic' in window) {
-                      if( medic.isEnabled() ) {
-                          jasmineEnv.addReporter(medic.getJSReporter());
-                      }
-                  }
-
-                  jasmineEnv.specFilter = function(spec) {
-                    return htmlReporter.specFilter(spec);
-                  };
-
-                  jasmineEnv.execute();
-              }, onError);
-          window.requestFileSystem(LocalFileSystem.TEMPORARY, 0,
-              function(fileSystem) {
-                  console.log('File API test Init: Setting TEMPORARY FS.');
-                  temp_root = fileSystem.root; // set in file.tests.js
-              }, onError);
-      }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./all.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a class="backBtn">Back</a>
 </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/autotest/pages/all.js
----------------------------------------------------------------------
diff --git a/autotest/pages/all.js b/autotest/pages/all.js
new file mode 100644
index 0000000..bc72b29
--- /dev/null
+++ b/autotest/pages/all.js
@@ -0,0 +1,46 @@
+var root, temp_root, persistent_root;
+
+document.addEventListener('deviceready', function () {
+    // one-time retrieval of the root file system entry
+    var onError = function(e) {
+        console.log('[ERROR] Problem setting up root filesystem for test running! Error to follow.');
+        console.log(JSON.stringify(e));
+    };
+
+    window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,
+        function(fileSystem) {
+            console.log('File API test Init: Setting PERSISTENT FS.');
+            root = fileSystem.root; // set in file.tests.js
+            persistent_root = root;
+
+            // Once root is set up, fire off tests
+            var jasmineEnv = jasmine.getEnv();
+            jasmineEnv.updateInterval = 1000;
+
+            var htmlReporter = new jasmine.HtmlReporter();
+            jasmineEnv.addReporter(htmlReporter);
+
+            // the following will only be defined if the Medic plugin is loaded
+            if('medic' in window) {
+                if( medic.isEnabled() ) {
+                    jasmineEnv.addReporter(medic.getJSReporter());
+                }
+            }
+
+            jasmineEnv.specFilter = function(spec) {
+              return htmlReporter.specFilter(spec);
+            };
+
+            jasmineEnv.execute();
+        }, onError);
+    window.requestFileSystem(LocalFileSystem.TEMPORARY, 0,
+        function(fileSystem) {
+            console.log('File API test Init: Setting TEMPORARY FS.');
+            temp_root = fileSystem.root; // set in file.tests.js
+        }, onError);
+}, false);
+
+window.onload = function() {
+  addListenerToClass('backBtn', backHome);
+}
+

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/autotest/pages/battery.html
----------------------------------------------------------------------
diff --git a/autotest/pages/battery.html b/autotest/pages/battery.html
index cb430de..2063417 100644
--- a/autotest/pages/battery.html
+++ b/autotest/pages/battery.html
@@ -42,25 +42,10 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/battery.tests.js"></script>
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a class="backBtn">Back</a>
 </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/autotest/pages/bridge.html
----------------------------------------------------------------------
diff --git a/autotest/pages/bridge.html b/autotest/pages/bridge.html
index ca03e79..822d9ec 100644
--- a/autotest/pages/bridge.html
+++ b/autotest/pages/bridge.html
@@ -45,27 +45,11 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/bridge.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/autotest/pages/camera.html
----------------------------------------------------------------------
diff --git a/autotest/pages/camera.html b/autotest/pages/camera.html
index c1dafee..91843d7 100644
--- a/autotest/pages/camera.html
+++ b/autotest/pages/camera.html
@@ -46,26 +46,10 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/camera.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/autotest/pages/capture.html
----------------------------------------------------------------------
diff --git a/autotest/pages/capture.html b/autotest/pages/capture.html
index 39faa2b..bac570f 100644
--- a/autotest/pages/capture.html
+++ b/autotest/pages/capture.html
@@ -45,27 +45,11 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/capture.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a class="backBtn">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/autotest/pages/compass.html
----------------------------------------------------------------------
diff --git a/autotest/pages/compass.html b/autotest/pages/compass.html
index d97b680..80de16f 100644
--- a/autotest/pages/compass.html
+++ b/autotest/pages/compass.html
@@ -45,27 +45,11 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/compass.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/autotest/pages/contacts.html
----------------------------------------------------------------------
diff --git a/autotest/pages/contacts.html b/autotest/pages/contacts.html
index 1518f19..e8e5fae 100644
--- a/autotest/pages/contacts.html
+++ b/autotest/pages/contacts.html
@@ -46,26 +46,11 @@
   <!-- Tests -->
   <script type="text/javascript" src="../tests/contacts.tests.js"></script>
 
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn" id="backHome">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/autotest/pages/datauri.html
----------------------------------------------------------------------
diff --git a/autotest/pages/datauri.html b/autotest/pages/datauri.html
index b64b21a..33474dd 100644
--- a/autotest/pages/datauri.html
+++ b/autotest/pages/datauri.html
@@ -43,23 +43,7 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/datauri.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/autotest/pages/device.html
----------------------------------------------------------------------
diff --git a/autotest/pages/device.html b/autotest/pages/device.html
index 7252e67..b1bed1d 100644
--- a/autotest/pages/device.html
+++ b/autotest/pages/device.html
@@ -45,27 +45,11 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/device.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/autotest/pages/file.html
----------------------------------------------------------------------
diff --git a/autotest/pages/file.html b/autotest/pages/file.html
index d143c74..d201791 100644
--- a/autotest/pages/file.html
+++ b/autotest/pages/file.html
@@ -44,47 +44,10 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/file.tests.js"></script>
-
-  <script type="text/javascript">
-      var root, temp_root, persistent_root;
-
-      document.addEventListener('deviceready', function () {
-          // one-time retrieval of the root file system entry
-          var onError = function(e) {
-              console.log('[ERROR] Problem setting up root filesystem for test running! Error to follow.');
-              console.log(JSON.stringify(e));
-          };
-
-          window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,
-              function(fileSystem) {
-                  console.log('File API test Init: Setting PERSISTENT FS.');
-                  root = fileSystem.root; // set in file.tests.js
-                  persistent_root = root;
-
-                  // Once root is set up, fire off tests
-                  var jasmineEnv = jasmine.getEnv();
-                  jasmineEnv.updateInterval = 1000;
-
-                  var htmlReporter = new jasmine.HtmlReporter();
-
-                  jasmineEnv.addReporter(htmlReporter);
-
-                  jasmineEnv.specFilter = function(spec) {
-                    return htmlReporter.specFilter(spec);
-                  };
-
-                  jasmineEnv.execute();
-              }, onError);
-          window.requestFileSystem(LocalFileSystem.TEMPORARY, 0,
-              function(fileSystem) {
-                  console.log('File API test Init: Setting TEMPORARY FS.');
-                  temp_root = fileSystem.root; // set in file.tests.js
-              }, onError);
-      }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./file.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/autotest/pages/file.js
----------------------------------------------------------------------
diff --git a/autotest/pages/file.js b/autotest/pages/file.js
new file mode 100644
index 0000000..9b1a67a
--- /dev/null
+++ b/autotest/pages/file.js
@@ -0,0 +1,39 @@
+var root, temp_root, persistent_root;
+
+document.addEventListener('deviceready', function () {
+    // one-time retrieval of the root file system entry
+    var onError = function(e) {
+        console.log('[ERROR] Problem setting up root filesystem for test running! Error to follow.');
+        console.log(JSON.stringify(e));
+    };
+
+    window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,
+        function(fileSystem) {
+            console.log('File API test Init: Setting PERSISTENT FS.');
+            root = fileSystem.root; // set in file.tests.js
+            persistent_root = root;
+
+            // Once root is set up, fire off tests
+            var jasmineEnv = jasmine.getEnv();
+            jasmineEnv.updateInterval = 1000;
+
+            var htmlReporter = new jasmine.HtmlReporter();
+
+            jasmineEnv.addReporter(htmlReporter);
+
+            jasmineEnv.specFilter = function(spec) {
+              return htmlReporter.specFilter(spec);
+            };
+
+            jasmineEnv.execute();
+        }, onError);
+    window.requestFileSystem(LocalFileSystem.TEMPORARY, 0,
+        function(fileSystem) {
+            console.log('File API test Init: Setting TEMPORARY FS.');
+            temp_root = fileSystem.root; // set in file.tests.js
+        }, onError);
+}, false);
+
+window.onload = function() {
+  addListenerToClass('backBtn', backHome);
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/autotest/pages/filetransfer.html
----------------------------------------------------------------------
diff --git a/autotest/pages/filetransfer.html b/autotest/pages/filetransfer.html
index 60cfcff..09809d8 100644
--- a/autotest/pages/filetransfer.html
+++ b/autotest/pages/filetransfer.html
@@ -44,48 +44,11 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/filetransfer.tests.js"></script>
-
-  <script type="text/javascript">
-      var root, temp_root, persistent_root;
-
-      document.addEventListener('deviceready', function () {
-          // one-time retrieval of the root file system entry
-          var onError = function(e) {
-              console.log('[ERROR] Problem setting up root filesystem for test running! Error to follow.');
-              console.log(JSON.stringify(e));
-          };
-
-          window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,
-              function(fileSystem) {
-                  console.log('File API test Init: Setting PERSISTENT FS.');
-                  root = fileSystem.root; // set in file.tests.js
-                  persistent_root = root;
-
-                  // Once root is set up, fire off tests
-                  var jasmineEnv = jasmine.getEnv();
-                  jasmineEnv.updateInterval = 1000;
-
-                  var htmlReporter = new jasmine.HtmlReporter();
-
-                  jasmineEnv.addReporter(htmlReporter);
-
-                  jasmineEnv.specFilter = function(spec) {
-                    return htmlReporter.specFilter(spec);
-                  };
-
-                  jasmineEnv.execute();
-              }, onError);
-          window.requestFileSystem(LocalFileSystem.TEMPORARY, 0,
-              function(fileSystem) {
-                  console.log('File API test Init: Setting TEMPORARY FS.');
-                  temp_root = fileSystem.root; // set in file.tests.js
-              }, onError);
-      }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./file.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/autotest/pages/geolocation.html
----------------------------------------------------------------------
diff --git a/autotest/pages/geolocation.html b/autotest/pages/geolocation.html
index 39f634e..b7a0698 100644
--- a/autotest/pages/geolocation.html
+++ b/autotest/pages/geolocation.html
@@ -45,27 +45,11 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/geolocation.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/autotest/pages/globalization.html
----------------------------------------------------------------------
diff --git a/autotest/pages/globalization.html b/autotest/pages/globalization.html
index 6ca5aaf..295067e 100644
--- a/autotest/pages/globalization.html
+++ b/autotest/pages/globalization.html
@@ -45,26 +45,10 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/globalization.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/autotest/pages/localXHR.html
----------------------------------------------------------------------
diff --git a/autotest/pages/localXHR.html b/autotest/pages/localXHR.html
index 2e64007..10415f0 100644
--- a/autotest/pages/localXHR.html
+++ b/autotest/pages/localXHR.html
@@ -45,26 +45,10 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/localXHR.tests.js"></script>
-
-  <script type="text/javascript">
-      document.addEventListener('deviceready', function () {
-          var jasmineEnv = jasmine.getEnv();
-          jasmineEnv.updateInterval = 1000;
-
-          var htmlReporter = new jasmine.HtmlReporter();
-
-          jasmineEnv.addReporter(htmlReporter);
-
-          jasmineEnv.specFilter = function (spec) {
-              return htmlReporter.specFilter(spec);
-          };
-
-          jasmineEnv.execute();
-      }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/autotest/pages/media.html
----------------------------------------------------------------------
diff --git a/autotest/pages/media.html b/autotest/pages/media.html
index 7e2c9e5..ac1fa75 100644
--- a/autotest/pages/media.html
+++ b/autotest/pages/media.html
@@ -45,27 +45,11 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/media.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/autotest/pages/network.html
----------------------------------------------------------------------
diff --git a/autotest/pages/network.html b/autotest/pages/network.html
index dcdec18..6af5521 100644
--- a/autotest/pages/network.html
+++ b/autotest/pages/network.html
@@ -45,27 +45,11 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/network.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/autotest/pages/notification.html
----------------------------------------------------------------------
diff --git a/autotest/pages/notification.html b/autotest/pages/notification.html
index 5ebfb86..50777bf 100644
--- a/autotest/pages/notification.html
+++ b/autotest/pages/notification.html
@@ -45,27 +45,11 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/notification.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/autotest/pages/platform.html
----------------------------------------------------------------------
diff --git a/autotest/pages/platform.html b/autotest/pages/platform.html
index e6ae3af..3ddecd0 100644
--- a/autotest/pages/platform.html
+++ b/autotest/pages/platform.html
@@ -45,27 +45,11 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/platform.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/autotest/pages/run-tests.js
----------------------------------------------------------------------
diff --git a/autotest/pages/run-tests.js b/autotest/pages/run-tests.js
new file mode 100644
index 0000000..8e079ad
--- /dev/null
+++ b/autotest/pages/run-tests.js
@@ -0,0 +1,18 @@
+document.addEventListener('deviceready', function () {
+  var jasmineEnv = jasmine.getEnv();
+  jasmineEnv.updateInterval = 1000;
+
+  var htmlReporter = new jasmine.HtmlReporter();
+
+  jasmineEnv.addReporter(htmlReporter);
+
+  jasmineEnv.specFilter = function(spec) {
+    return htmlReporter.specFilter(spec);
+  };
+
+  jasmineEnv.execute();
+}, false);
+
+window.onload = function() {
+  addListenerToClass('backBtn', backHome);
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/autotest/pages/splashscreen.html
----------------------------------------------------------------------
diff --git a/autotest/pages/splashscreen.html b/autotest/pages/splashscreen.html
index d830f9e..6ac1c4d 100644
--- a/autotest/pages/splashscreen.html
+++ b/autotest/pages/splashscreen.html
@@ -45,27 +45,11 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/splashscreen.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/autotest/pages/storage.html
----------------------------------------------------------------------
diff --git a/autotest/pages/storage.html b/autotest/pages/storage.html
index 9ca226b..0f836e9 100644
--- a/autotest/pages/storage.html
+++ b/autotest/pages/storage.html
@@ -45,27 +45,11 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/storage.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/autotest/pages/vibration.html
----------------------------------------------------------------------
diff --git a/autotest/pages/vibration.html b/autotest/pages/vibration.html
index b6bd03f..04db2ec 100644
--- a/autotest/pages/vibration.html
+++ b/autotest/pages/vibration.html
@@ -45,27 +45,11 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/vibration.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/autotest/pages/whitelist.html
----------------------------------------------------------------------
diff --git a/autotest/pages/whitelist.html b/autotest/pages/whitelist.html
index ca3712c..ececfa2 100644
--- a/autotest/pages/whitelist.html
+++ b/autotest/pages/whitelist.html
@@ -45,27 +45,11 @@
 
   <!-- Tests -->
   <script type="text/javascript" src="../tests/whitelist.tests.js"></script>
-
-  <script type="text/javascript">
-    document.addEventListener('deviceready', function () {
-      var jasmineEnv = jasmine.getEnv();
-      jasmineEnv.updateInterval = 1000;
-
-      var htmlReporter = new jasmine.HtmlReporter();
-
-      jasmineEnv.addReporter(htmlReporter);
-
-      jasmineEnv.specFilter = function(spec) {
-        return htmlReporter.specFilter(spec);
-      };
-
-      jasmineEnv.execute();
-    }, false);
-  </script>
+  <script type="text/javascript" charset="utf-8" src="./run-tests.js"></script>      
 </head>
 
 <body>
-  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+  <a href="javascript:" class="backBtn">Back</a>
 </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/battery/index.html
----------------------------------------------------------------------
diff --git a/battery/index.html b/battery/index.html
index 70b0db7..016dc87 100644
--- a/battery/index.html
+++ b/battery/index.html
@@ -28,75 +28,10 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>      
-
-      
-<script type="text/javascript" charset="utf-8">
-
-    var deviceReady = false;
-    
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-                deviceReady = true;
-                console.log("Device="+device.platform+" "+device.version);
-            }, false);
-        window.setTimeout(function() {
-            if (!deviceReady) {
-                alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
-            }
-        },1000);
-    }
-
-    /* Battery */
-    function updateInfo(info) {
-        document.getElementById('level').innerText = info.level;
-        document.getElementById('isPlugged').innerText = info.isPlugged;
-        if (info.level > 5) {
-            document.getElementById('crit').innerText = "false";
-        }
-        if (info.level > 20) {
-            document.getElementById('low').innerText = "false";
-        }
-    }
-    
-    function batteryLow(info) {
-        document.getElementById('low').innerText = "true";
-    }
-    
-    function batteryCritical(info) {
-        document.getElementById('crit').innerText = "true";
-    }
-    
-    function addBattery() {
-        window.addEventListener("batterystatus", updateInfo, false);
-    }
-    
-    function removeBattery() {
-        window.removeEventListener("batterystatus", updateInfo, false);
-    }
-    
-    function addLow() {
-        window.addEventListener("batterylow", batteryLow, false);
-    }
-    
-    function removeLow() {
-        window.removeEventListener("batterylow", batteryLow, false);
-    }
-    
-    function addCritical() {
-        window.addEventListener("batterycritical", batteryCritical, false);
-    }
-    
-    function removeCritical() {
-        window.removeEventListener("batterycritical", batteryCritical, false);
-    }
-
-</script>
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
 
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>Battery</h1>
     <div id="info">
@@ -107,12 +42,12 @@
         Critical: <span id="crit"></span><br/>
     </div>
     <h2>Action</h2>
-    <div class="btn large" onclick="addBattery();">Add "batterystatus" listener</div>
-    <div class="btn large" onclick="removeBattery();">Remove "batterystatus" listener</div>
-    <div class="btn large" onclick="addLow();">Add "batterylow" listener</div>
-    <div class="btn large" onclick="removeLow();">Remove "batterylow" listener</div>
-    <div class="btn large" onclick="addCritical();">Add "batterycritical" listener</div>
-    <div class="btn large" onclick="removeCritical();">Remove "batterycritical" listener</div>
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <div class="btn large addBattery">Add "batterystatus" listener</div>
+    <div class="btn large removeBattery">Remove "batterystatus" listener</div>
+    <div class="btn large addLow">Add "batterylow" listener</div>
+    <div class="btn large removeLow">Remove "batterylow" listener</div>
+    <div class="btn large addCritical">Add "batterycritical" listener</div>
+    <div class="btn large removeCritical">Remove "batterycritical" listener</div>
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>      

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/battery/index.js
----------------------------------------------------------------------
diff --git a/battery/index.js b/battery/index.js
new file mode 100644
index 0000000..1a0d488
--- /dev/null
+++ b/battery/index.js
@@ -0,0 +1,72 @@
+var deviceReady = false;
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+            deviceReady = true;
+            console.log("Device="+device.platform+" "+device.version);
+        }, false);
+    window.setTimeout(function() {
+        if (!deviceReady) {
+            alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
+        }
+    },1000);
+}
+
+/* Battery */
+function updateInfo(info) {
+    document.getElementById('level').innerText = info.level;
+    document.getElementById('isPlugged').innerText = info.isPlugged;
+    if (info.level > 5) {
+        document.getElementById('crit').innerText = "false";
+    }
+    if (info.level > 20) {
+        document.getElementById('low').innerText = "false";
+    }
+}
+
+function batteryLow(info) {
+    document.getElementById('low').innerText = "true";
+}
+
+function batteryCritical(info) {
+    document.getElementById('crit').innerText = "true";
+}
+
+function addBattery() {
+    window.addEventListener("batterystatus", updateInfo, false);
+}
+
+function removeBattery() {
+    window.removeEventListener("batterystatus", updateInfo, false);
+}
+
+function addLow() {
+    window.addEventListener("batterylow", batteryLow, false);
+}
+
+function removeLow() {
+    window.removeEventListener("batterylow", batteryLow, false);
+}
+
+function addCritical() {
+    window.addEventListener("batterycritical", batteryCritical, false);
+}
+
+function removeCritical() {
+    window.removeEventListener("batterycritical", batteryCritical, false);
+}
+
+window.onload = function() {
+  addListenerToClass('addBattery', addBattery);
+  addListenerToClass('removeBattery', removeBattery);
+  addListenerToClass('addLow', addLow);
+  addListenerToClass('removeLow', removeLow);
+  addListenerToClass('addCritical', addCritical);
+  addListenerToClass('removeCritical', removeCritical);
+  
+  addListenerToClass('backBtn', backHome);
+  init();
+}


[03/12] Manual tests fixed

Posted by za...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/camera/index.html
----------------------------------------------------------------------
diff --git a/camera/index.html b/camera/index.html
index b74dabb..4f48190 100644
--- a/camera/index.html
+++ b/camera/index.html
@@ -28,341 +28,10 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>
-
-
-<script type="text/javascript" charset="utf-8">
-
-    var deviceReady = false;
-    var platformId = cordova.require('cordova/platform').id;
-    var pictureUrl = null;
-    var fileObj = null;
-    var fileEntry = null;
-    var pageStartTime = +new Date();
-    
-    //default camera options
-    var camQualityDefault = ['quality value', 50];
-    var camDestinationTypeDefault = ['FILE_URI', 1];
-    var camPictureSourceTypeDefault = ['CAMERA', 1];
-    var camAllowEditDefault = ['allowEdit', false];
-    var camEncodingTypeDefault = ['JPEG', 0];
-    var camMediaTypeDefault = ['mediaType', 0];
-    var camCorrectOrientationDefault = ['correctOrientation', false];
-    var camSaveToPhotoAlbumDefault = ['saveToPhotoAlbum', true];
-    
-
-    //-------------------------------------------------------------------------
-    // Camera
-    //-------------------------------------------------------------------------
-
-    function log(value) {
-        console.log(value);
-        document.getElementById('camera_status').textContent += (new Date() - pageStartTime) / 1000 + ': ' + value + '\n';
-    }
-
-    function clearStatus() {
-        document.getElementById('camera_status').innerHTML = '';
-        document.getElementById('camera_image').src = 'about:blank';
-        var canvas = document.getElementById('canvas');
-        canvas.width = canvas.height = 1;
-        pictureUrl = null;
-        fileObj = null;
-        fileEntry = null;
-    }
-
-    function setPicture(url, callback) {
-		try {
-			window.atob(url);
-			// if we got here it is a base64 string (DATA_URL)
-			url = "data:image/jpeg;base64," + url;
-		} catch (e) {
-			// not DATA_URL
-		    log('URL: ' + url.slice(0, 100));
-		}    
-    
-        pictureUrl = url;
-        var img = document.getElementById('camera_image');
-        var startTime = new Date();
-        img.src = url;
-        img.onloadend = function() {
-            log('Image tag load time: ' + (new Date() - startTime));
-            callback && callback();
-        };
-    }
-
-    function onGetPictureError(e) {
-        log('Error getting picture: ' + e.code);
-    }
-
-    function getPictureWin(data) {
-        setPicture(data);
-        // TODO: Fix resolveLocalFileSystemURI to work with native-uri.
-        if (pictureUrl.indexOf('file:') == 0 || pictureUrl.indexOf('content:') == 0) {
-            resolveLocalFileSystemURI(data, function(e) {
-                fileEntry = e;
-                logCallback('resolveLocalFileSystemURI()', true)(e.toURL());
-            }, logCallback('resolveLocalFileSystemURI()', false));
-        } else if (pictureUrl.indexOf('data:image/jpeg;base64' == 0)) {
-        	// do nothing
-        } else {
-            var path = pictureUrl.replace(/^file:\/\/(localhost)?/, '').replace(/%20/g, ' ');
-            fileEntry = new FileEntry('image_name.png', path);
-        }
-    }
-
-    function getPicture() {
-        clearStatus();
-        var options = extractOptions();
-        log('Getting picture with options: ' + JSON.stringify(options));
-        var popoverHandle = navigator.camera.getPicture(getPictureWin, onGetPictureError, options);
-
-        // Reposition the popover if the orientation changes.
-        window.onorientationchange = function() {
-            var newPopoverOptions = new CameraPopoverOptions(0, 0, 100, 100, 0);
-            popoverHandle.setPosition(newPopoverOptions);
-        }
-    }
-
-    function uploadImage() {
-        var ft = new FileTransfer(),
-            uploadcomplete=0,
-            progress = 0,
-            options = new FileUploadOptions();
-        options.fileKey="photo";
-        options.fileName='test.jpg';
-        options.mimeType="image/jpeg";
-        ft.onprogress = function(progressEvent) {
-            log('progress: ' + progressEvent.loaded + ' of ' + progressEvent.total);
-        };
-        var server = "http://cordova-filetransfer.jitsu.com";
-
-        ft.upload(pictureUrl, server + '/upload', win, fail, options);
-        function win(information_back){
-            log('upload complete');
-        }
-        function fail(message) {
-            log('upload failed: ' + JSON.stringify(message));
-        }
-    }
-
-    function logCallback(apiName, success) {
-        return function() {
-            log('Call to ' + apiName + (success ? ' success: ' : ' failed: ') + JSON.stringify([].slice.call(arguments)));
-        };
-    }
-
-    /**
-     * Select image from library using a NATIVE_URI destination type
-     * This calls FileEntry.getMetadata, FileEntry.setMetadata, FileEntry.getParent, FileEntry.file, and FileReader.readAsDataURL.
-     */
-    function readFile() {
-        function onFileReadAsDataURL(evt) {
-            var img = document.getElementById('camera_image');
-            img.style.visibility = "visible";
-            img.style.display = "block";
-            img.src = evt.target.result;
-            log("FileReader.readAsDataURL success");
-        };
-
-        function onFileReceived(file) {
-            log('Got file: ' + JSON.stringify(file));
-            fileObj = file;
-
-            var reader = new FileReader();
-            reader.onload = function() {
-                log('FileReader.readAsDataURL() - length = ' + reader.result.length);
-            };
-            reader.onerror = logCallback('FileReader.readAsDataURL', false);
-            reader.readAsDataURL(file);
-        };
-        // Test out onFileReceived when the file object was set via a native <input> elements.
-        if (fileObj) {
-            onFileReceived(fileObj);
-        } else {
-            fileEntry.file(onFileReceived, logCallback('FileEntry.file', false));
-        }
-    }
-    function getFileInfo() {
-        // Test FileEntry API here.
-        fileEntry.getMetadata(logCallback('FileEntry.getMetadata', true), logCallback('FileEntry.getMetadata', false));
-        fileEntry.setMetadata(logCallback('FileEntry.setMetadata', true), logCallback('FileEntry.setMetadata', false), { "com.apple.MobileBackup": 1 });
-        fileEntry.getParent(logCallback('FileEntry.getParent', true), logCallback('FileEntry.getParent', false));
-        fileEntry.getParent(logCallback('FileEntry.getParent', true), logCallback('FileEntry.getParent', false));
-    };
-
-    /**
-     * Copy image from library using a NATIVE_URI destination type
-     * This calls FileEntry.copyTo and FileEntry.moveTo.
-     */
-    function copyImage() {
-        var onFileSystemReceived = function(fileSystem) {
-            var destDirEntry = fileSystem.root;
-
-            // Test FileEntry API here.
-            fileEntry.copyTo(destDirEntry, 'copied_file.png', logCallback('FileEntry.copyTo', true), logCallback('FileEntry.copyTo', false));
-            fileEntry.moveTo(destDirEntry, 'moved_file.png', logCallback('FileEntry.moveTo', true), logCallback('FileEntry.moveTo', false));
-        };
-
-        window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, onFileSystemReceived, null);
-    };
-
-    /**
-     * Write image to library using a NATIVE_URI destination type
-     * This calls FileEntry.createWriter, FileWriter.write, and FileWriter.truncate.
-     */
-    function writeImage() {
-        var onFileWriterReceived = function(fileWriter) {
-            fileWriter.onwrite = logCallback('FileWriter.write', true);
-            fileWriter.onerror = logCallback('FileWriter.write', false);
-            fileWriter.write("some text!");
-        };
-
-        var onFileTruncateWriterReceived = function(fileWriter) {
-            fileWriter.onwrite = logCallback('FileWriter.truncate', true);
-            fileWriter.onerror = logCallback('FileWriter.truncate', false);
-            fileWriter.truncate(10);
-        };
-
-        fileEntry.createWriter(onFileWriterReceived, logCallback('FileEntry.createWriter', false));
-        fileEntry.createWriter(onFileTruncateWriterReceived, null);
-    };
-
-    function displayImageUsingCanvas() {
-        var canvas = document.getElementById('canvas');
-        var img = document.getElementById('camera_image');
-        var w = img.width;
-        var h = img.height;
-        h = 100 / w * h;
-        w = 100;
-        canvas.width = w;
-        canvas.height= h;
-        var context = canvas.getContext('2d');
-        context.drawImage(img, 0, 0, w, h);
-    };
-
-    /**
-     * Remove image from library using a NATIVE_URI destination type
-     * This calls FileEntry.remove.
-     */
-    function removeImage() {
-        fileEntry.remove(logCallback('FileEntry.remove', true), logCallback('FileEntry.remove', false));
-    };
-
-    function testInputTag(inputEl) {
-        clearStatus();
-        // iOS 6 likes to dead-lock in the onchange context if you
-        // do any alerts or try to remote-debug.
-        window.setTimeout(function() {
-            testNativeFile2(inputEl);
-        }, 0);
-    };
-
-    function testNativeFile2(inputEl) {
-        if (!inputEl.value) {
-            alert('No file selected.');
-            return;
-        }
-        fileObj = inputEl.files[0];
-        if (!fileObj) {
-            alert('Got value but no file.');
-            return;
-        }
-        var URLApi = window.URL || window.webkitURL;
-        if (URLApi) {
-            var blobURL = URLApi.createObjectURL(fileObj);
-            if (blobURL) {
-                setPicture(blobURL, function() {
-                    URLApi.revokeObjectURL(blobURL);
-                });
-            } else {
-                log('URL.createObjectURL returned null');
-            }
-        } else {
-            log('URL.createObjectURL() not supported.');
-        }
-    }
-
-    function extractOptions() {
-        var els = document.querySelectorAll('#image-options select');
-        var ret = {};
-        for (var i = 0, el; el = els[i]; ++i) {
-            var value = el.value;
-            if (value === '') continue;
-            if (el.isBool) {
-                ret[el.keyName] = !!+value;
-            } else {
-                ret[el.keyName] = +value;
-            }
-        }
-        return ret;
-    }
-
-    function createOptionsEl(name, values, selectionDefault) {
-        var container = document.createElement('div');
-        container.style.display = 'inline-block';
-        container.appendChild(document.createTextNode(name + ': '));
-        var select = document.createElement('select');
-        select.keyName = name;
-        container.appendChild(select);
-        
-        // if we didn't get a default value, insert the blank <default> entry
-        if (selectionDefault == undefined) {
-            var opt = document.createElement('option');
-            opt.value = '';
-            opt.text = '<default>';
-            select.appendChild(opt);
-        }
-        
-        select.isBool = typeof values == 'boolean';
-        if (select.isBool) {
-            values = {'true': 1, 'false': 0};
-        }
-        
-        for (var k in values) {
-            var opt = document.createElement('option');
-            opt.value = values[k];
-            opt.textContent = k;
-            if (selectionDefault) {
-                if (selectionDefault[0] == k) {
-                    opt.selected = true;
-                }
-            }
-            select.appendChild(opt);
-        }
-        var optionsDiv = document.getElementById('image-options');
-        optionsDiv.appendChild(container);
-    }
-
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-            deviceReady = true;
-            console.log("Device="+device.platform+" "+device.version);
-            createOptionsEl('sourceType', Camera.PictureSourceType, camPictureSourceTypeDefault);
-            createOptionsEl('destinationType', Camera.DestinationType, camDestinationTypeDefault);
-            createOptionsEl('encodingType', Camera.EncodingType, camEncodingTypeDefault);
-            createOptionsEl('mediaType', Camera.MediaType, camMediaTypeDefault);
-            createOptionsEl('quality', {'0': 0, '50': 50, '80': 80, '100': 100}, camQualityDefault);
-            createOptionsEl('targetWidth', {'50': 50, '200': 200, '800': 800, '2048': 2048});
-            createOptionsEl('targetHeight', {'50': 50, '200': 200, '800': 800, '2048': 2048});
-            createOptionsEl('allowEdit', true, camAllowEditDefault);
-            createOptionsEl('correctOrientation', true, camCorrectOrientationDefault);
-            createOptionsEl('saveToPhotoAlbum', true, camSaveToPhotoAlbumDefault);
-            createOptionsEl('cameraDirection', Camera.Direction);
-                          
-        }, false);
-        window.setTimeout(function() {
-            if (!deviceReady) {
-                alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
-            }
-        },1000);
-    };
-
-</script>
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
 
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
 
     <h1>Camera</h1>
     <div id="info" style="white-space: pre-wrap">
@@ -372,20 +41,20 @@
     </div>
     <h2>Cordova Camera API</h2>
     <div id="image-options"></div>
-    <div class="btn large" onclick="getPicture();">camera.getPicture()</div>
+    <div class="btn large getPicture">camera.getPicture()</div>
     <h2>Native File Inputs</h2>
-    <div>input type=file <input type="file" onchange="testInputTag(this)"></div>
-    <div>capture=camera <input type="file" accept="image/*;capture=camera" onchange="testInputTag(this)"></div>
-    <div>capture=camcorder <input type="file" accept="video/*;capture=camcorder" onchange="testInputTag(this)"></div>
-    <div>capture=microphone <input type="file" accept="audio/*;capture=microphone" onchange="testInputTag(this)"></div>
+    <div>input type=file <input type="file" class="testInputTag"></div>
+    <div>capture=camera <input type="file" accept="image/*;capture=camera" class="testInputTag"></div>
+    <div>capture=camcorder <input type="file" accept="video/*;capture=camcorder" class="testInputTag"></div>
+    <div>capture=microphone <input type="file" accept="audio/*;capture=microphone" class="testInputTag"></div>
     <h2>Actions</h2>
-    <div class="btn large" onclick="getFileInfo();">Get File Metadata</div>
-    <div class="btn large" onclick="readFile();">Read with FileReader</div>
-    <div class="btn large" onclick="copyImage();">Copy Image</div>
-    <div class="btn large" onclick="writeImage();">Write Image</div>
-    <div class="btn large" onclick="uploadImage();">Upload Image</div>
-    <div class="btn large" onclick="displayImageUsingCanvas();">Draw Using Canvas</div>
-    <div class="btn large" onclick="removeImage();">Remove Image</div>
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <div class="btn large getFileInfo">Get File Metadata</div>
+    <div class="btn large readFile">Read with FileReader</div>
+    <div class="btn large copyImage">Copy Image</div>
+    <div class="btn large writeImage">Write Image</div>
+    <div class="btn large uploadImage">Upload Image</div>
+    <div class="btn large displayImageUsingCanvas">Draw Using Canvas</div>
+    <div class="btn large removeImage">Remove Image</div>
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/camera/index.js
----------------------------------------------------------------------
diff --git a/camera/index.js b/camera/index.js
new file mode 100644
index 0000000..f9435d0
--- /dev/null
+++ b/camera/index.js
@@ -0,0 +1,344 @@
+var deviceReady = false;
+var platformId = cordova.require('cordova/platform').id;
+var pictureUrl = null;
+var fileObj = null;
+var fileEntry = null;
+var pageStartTime = +new Date();
+
+//default camera options
+var camQualityDefault = ['quality value', 50];
+var camDestinationTypeDefault = ['FILE_URI', 1];
+var camPictureSourceTypeDefault = ['CAMERA', 1];
+var camAllowEditDefault = ['allowEdit', false];
+var camEncodingTypeDefault = ['JPEG', 0];
+var camMediaTypeDefault = ['mediaType', 0];
+var camCorrectOrientationDefault = ['correctOrientation', false];
+var camSaveToPhotoAlbumDefault = ['saveToPhotoAlbum', true];
+
+
+//-------------------------------------------------------------------------
+// Camera
+//-------------------------------------------------------------------------
+
+function log(value) {
+    console.log(value);
+    document.getElementById('camera_status').textContent += (new Date() - pageStartTime) / 1000 + ': ' + value + '\n';
+}
+
+function clearStatus() {
+    document.getElementById('camera_status').innerHTML = '';
+    document.getElementById('camera_image').src = 'about:blank';
+    var canvas = document.getElementById('canvas');
+    canvas.width = canvas.height = 1;
+    pictureUrl = null;
+    fileObj = null;
+    fileEntry = null;
+}
+
+function setPicture(url, callback) {
+try {
+  window.atob(url);
+  // if we got here it is a base64 string (DATA_URL)
+  url = "data:image/jpeg;base64," + url;
+} catch (e) {
+  // not DATA_URL
+    log('URL: ' + url.slice(0, 100));
+}    
+
+    pictureUrl = url;
+    var img = document.getElementById('camera_image');
+    var startTime = new Date();
+    img.src = url;
+    img.onloadend = function() {
+        log('Image tag load time: ' + (new Date() - startTime));
+        callback && callback();
+    };
+}
+
+function onGetPictureError(e) {
+    log('Error getting picture: ' + e.code);
+}
+
+function getPictureWin(data) {
+    setPicture(data);
+    // TODO: Fix resolveLocalFileSystemURI to work with native-uri.
+    if (pictureUrl.indexOf('file:') == 0 || pictureUrl.indexOf('content:') == 0) {
+        resolveLocalFileSystemURI(data, function(e) {
+            fileEntry = e;
+            logCallback('resolveLocalFileSystemURI()', true)(e.toURL());
+        }, logCallback('resolveLocalFileSystemURI()', false));
+    } else if (pictureUrl.indexOf('data:image/jpeg;base64' == 0)) {
+      // do nothing
+    } else {
+        var path = pictureUrl.replace(/^file:\/\/(localhost)?/, '').replace(/%20/g, ' ');
+        fileEntry = new FileEntry('image_name.png', path);
+    }
+}
+
+function getPicture() {
+    clearStatus();
+    var options = extractOptions();
+    log('Getting picture with options: ' + JSON.stringify(options));
+    var popoverHandle = navigator.camera.getPicture(getPictureWin, onGetPictureError, options);
+
+    // Reposition the popover if the orientation changes.
+    window.onorientationchange = function() {
+        var newPopoverOptions = new CameraPopoverOptions(0, 0, 100, 100, 0);
+        popoverHandle.setPosition(newPopoverOptions);
+    }
+}
+
+function uploadImage() {
+    var ft = new FileTransfer(),
+        uploadcomplete=0,
+        progress = 0,
+        options = new FileUploadOptions();
+    options.fileKey="photo";
+    options.fileName='test.jpg';
+    options.mimeType="image/jpeg";
+    ft.onprogress = function(progressEvent) {
+        log('progress: ' + progressEvent.loaded + ' of ' + progressEvent.total);
+    };
+    var server = "http://cordova-filetransfer.jitsu.com";
+
+    ft.upload(pictureUrl, server + '/upload', win, fail, options);
+    function win(information_back){
+        log('upload complete');
+    }
+    function fail(message) {
+        log('upload failed: ' + JSON.stringify(message));
+    }
+}
+
+function logCallback(apiName, success) {
+    return function() {
+        log('Call to ' + apiName + (success ? ' success: ' : ' failed: ') + JSON.stringify([].slice.call(arguments)));
+    };
+}
+
+/**
+ * Select image from library using a NATIVE_URI destination type
+ * This calls FileEntry.getMetadata, FileEntry.setMetadata, FileEntry.getParent, FileEntry.file, and FileReader.readAsDataURL.
+ */
+function readFile() {
+    function onFileReadAsDataURL(evt) {
+        var img = document.getElementById('camera_image');
+        img.style.visibility = "visible";
+        img.style.display = "block";
+        img.src = evt.target.result;
+        log("FileReader.readAsDataURL success");
+    };
+
+    function onFileReceived(file) {
+        log('Got file: ' + JSON.stringify(file));
+        fileObj = file;
+
+        var reader = new FileReader();
+        reader.onload = function() {
+            log('FileReader.readAsDataURL() - length = ' + reader.result.length);
+        };
+        reader.onerror = logCallback('FileReader.readAsDataURL', false);
+        reader.readAsDataURL(file);
+    };
+    // Test out onFileReceived when the file object was set via a native <input> elements.
+    if (fileObj) {
+        onFileReceived(fileObj);
+    } else {
+        fileEntry.file(onFileReceived, logCallback('FileEntry.file', false));
+    }
+}
+function getFileInfo() {
+    // Test FileEntry API here.
+    fileEntry.getMetadata(logCallback('FileEntry.getMetadata', true), logCallback('FileEntry.getMetadata', false));
+    fileEntry.setMetadata(logCallback('FileEntry.setMetadata', true), logCallback('FileEntry.setMetadata', false), { "com.apple.MobileBackup": 1 });
+    fileEntry.getParent(logCallback('FileEntry.getParent', true), logCallback('FileEntry.getParent', false));
+    fileEntry.getParent(logCallback('FileEntry.getParent', true), logCallback('FileEntry.getParent', false));
+};
+
+/**
+ * Copy image from library using a NATIVE_URI destination type
+ * This calls FileEntry.copyTo and FileEntry.moveTo.
+ */
+function copyImage() {
+    var onFileSystemReceived = function(fileSystem) {
+        var destDirEntry = fileSystem.root;
+
+        // Test FileEntry API here.
+        fileEntry.copyTo(destDirEntry, 'copied_file.png', logCallback('FileEntry.copyTo', true), logCallback('FileEntry.copyTo', false));
+        fileEntry.moveTo(destDirEntry, 'moved_file.png', logCallback('FileEntry.moveTo', true), logCallback('FileEntry.moveTo', false));
+    };
+
+    window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, onFileSystemReceived, null);
+};
+
+/**
+ * Write image to library using a NATIVE_URI destination type
+ * This calls FileEntry.createWriter, FileWriter.write, and FileWriter.truncate.
+ */
+function writeImage() {
+    var onFileWriterReceived = function(fileWriter) {
+        fileWriter.onwrite = logCallback('FileWriter.write', true);
+        fileWriter.onerror = logCallback('FileWriter.write', false);
+        fileWriter.write("some text!");
+    };
+
+    var onFileTruncateWriterReceived = function(fileWriter) {
+        fileWriter.onwrite = logCallback('FileWriter.truncate', true);
+        fileWriter.onerror = logCallback('FileWriter.truncate', false);
+        fileWriter.truncate(10);
+    };
+
+    fileEntry.createWriter(onFileWriterReceived, logCallback('FileEntry.createWriter', false));
+    fileEntry.createWriter(onFileTruncateWriterReceived, null);
+};
+
+function displayImageUsingCanvas() {
+    var canvas = document.getElementById('canvas');
+    var img = document.getElementById('camera_image');
+    var w = img.width;
+    var h = img.height;
+    h = 100 / w * h;
+    w = 100;
+    canvas.width = w;
+    canvas.height= h;
+    var context = canvas.getContext('2d');
+    context.drawImage(img, 0, 0, w, h);
+};
+
+/**
+ * Remove image from library using a NATIVE_URI destination type
+ * This calls FileEntry.remove.
+ */
+function removeImage() {
+    fileEntry.remove(logCallback('FileEntry.remove', true), logCallback('FileEntry.remove', false));
+};
+
+function testInputTag(inputEl) {
+    clearStatus();
+    // iOS 6 likes to dead-lock in the onchange context if you
+    // do any alerts or try to remote-debug.
+    window.setTimeout(function() {
+        testNativeFile2(inputEl);
+    }, 0);
+};
+
+function testNativeFile2(inputEl) {
+    if (!inputEl.value) {
+        alert('No file selected.');
+        return;
+    }
+    fileObj = inputEl.files[0];
+    if (!fileObj) {
+        alert('Got value but no file.');
+        return;
+    }
+    var URLApi = window.URL || window.webkitURL;
+    if (URLApi) {
+        var blobURL = URLApi.createObjectURL(fileObj);
+        if (blobURL) {
+            setPicture(blobURL, function() {
+                URLApi.revokeObjectURL(blobURL);
+            });
+        } else {
+            log('URL.createObjectURL returned null');
+        }
+    } else {
+        log('URL.createObjectURL() not supported.');
+    }
+}
+
+function extractOptions() {
+    var els = document.querySelectorAll('#image-options select');
+    var ret = {};
+    for (var i = 0, el; el = els[i]; ++i) {
+        var value = el.value;
+        if (value === '') continue;
+        if (el.isBool) {
+            ret[el.keyName] = !!+value;
+        } else {
+            ret[el.keyName] = +value;
+        }
+    }
+    return ret;
+}
+
+function createOptionsEl(name, values, selectionDefault) {
+    var container = document.createElement('div');
+    container.style.display = 'inline-block';
+    container.appendChild(document.createTextNode(name + ': '));
+    var select = document.createElement('select');
+    select.keyName = name;
+    container.appendChild(select);
+    
+    // if we didn't get a default value, insert the blank <default> entry
+    if (selectionDefault == undefined) {
+        var opt = document.createElement('option');
+        opt.value = '';
+        opt.text = '<default>';
+        select.appendChild(opt);
+    }
+    
+    select.isBool = typeof values == 'boolean';
+    if (select.isBool) {
+        values = {'true': 1, 'false': 0};
+    }
+    
+    for (var k in values) {
+        var opt = document.createElement('option');
+        opt.value = values[k];
+        opt.textContent = k;
+        if (selectionDefault) {
+            if (selectionDefault[0] == k) {
+                opt.selected = true;
+            }
+        }
+        select.appendChild(opt);
+    }
+    var optionsDiv = document.getElementById('image-options');
+    optionsDiv.appendChild(container);
+}
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+        deviceReady = true;
+        console.log("Device="+device.platform+" "+device.version);
+        createOptionsEl('sourceType', Camera.PictureSourceType, camPictureSourceTypeDefault);
+        createOptionsEl('destinationType', Camera.DestinationType, camDestinationTypeDefault);
+        createOptionsEl('encodingType', Camera.EncodingType, camEncodingTypeDefault);
+        createOptionsEl('mediaType', Camera.MediaType, camMediaTypeDefault);
+        createOptionsEl('quality', {'0': 0, '50': 50, '80': 80, '100': 100}, camQualityDefault);
+        createOptionsEl('targetWidth', {'50': 50, '200': 200, '800': 800, '2048': 2048});
+        createOptionsEl('targetHeight', {'50': 50, '200': 200, '800': 800, '2048': 2048});
+        createOptionsEl('allowEdit', true, camAllowEditDefault);
+        createOptionsEl('correctOrientation', true, camCorrectOrientationDefault);
+        createOptionsEl('saveToPhotoAlbum', true, camSaveToPhotoAlbumDefault);
+        createOptionsEl('cameraDirection', Camera.Direction);
+                      
+    }, false);
+    window.setTimeout(function() {
+        if (!deviceReady) {
+            alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
+        }
+    },1000);
+};
+
+window.onload = function() {
+  addListenerToClass('getPicture', getPicture);
+  addListenerToClass('testInputTag', function(e) {
+    testInputTag(e.target);
+  }, null, 'change', true);
+  addListenerToClass('getFileInfo', getFileInfo);
+  addListenerToClass('readFile', readFile);
+  addListenerToClass('copyImage', copyImage);
+  addListenerToClass('writeImage', writeImage);
+  addListenerToClass('uploadImage', uploadImage);
+  addListenerToClass('displayImageUsingCanvas', displayImageUsingCanvas);
+  addListenerToClass('removeImage', removeImage);
+
+  addListenerToClass('backBtn', backHome);
+  init();
+}
+

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/capture/index.html
----------------------------------------------------------------------
diff --git a/capture/index.html b/capture/index.html
index 67c35e3..9543341 100644
--- a/capture/index.html
+++ b/capture/index.html
@@ -28,142 +28,9 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>
-
-
-<script type="text/javascript" charset="utf-8">
-
-    var deviceReady = false;
-    var platformId = cordova.require('cordova/platform').id;
-    var pageStartTime = +new Date();
-
-    //-------------------------------------------------------------------------
-    // Camera
-    //-------------------------------------------------------------------------
-
-    function log(value) {
-        console.log(value);
-        document.getElementById('camera_status').textContent += (new Date() - pageStartTime) / 1000 + ': ' + value + '\n';
-    }
-
-    function captureAudioWin(mediaFiles){
-        var path = mediaFiles[0].fullPath;
-        log('Audio captured: ' + path);
-        var m = new Media(path);
-        m.play(); 
-    }
-    
-    function captureAudioFail(e){
-        log('Error getting audio: ' + e.code);
-    }
-    
-    function getAudio(){
-        clearStatus();
-        var options = { limit: 1, duration: 10};
-        navigator.device.capture.captureAudio(captureAudioWin, captureAudioFail, options);
-    }
-    
-    function captureImageWin(mediaFiles){
-        var path = mediaFiles[0].fullPath;
-        log('Image captured: ' + path);    
-        document.getElementById('camera_image').src = path;    
-    }
-    
-    function captureImageFail(e){
-        log('Error getting image: ' + e.code);
-    }
-    
-    function getImage(){
-        clearStatus();
-        var options = { limit: 1 };
-        navigator.device.capture.captureImage(captureImageWin, captureImageFail, options);    
-    }    
-    
-    function captureVideoWin(mediaFiles){
-        var path = mediaFiles[0].fullPath;
-        log('Video captured: ' + path);
-        
-        // need to inject the video element into the html
-        // doesn't seem to work if you have a pre-existing video element and
-        // add in a source tag
-        var vid = document.createElement('video');
-        vid.id="theVideo";
-        vid.width = "320";
-        vid.height= "240";
-        vid.controls = "true";
-        var source_vid = document.createElement('source');
-        source_vid.id = "theSource";
-        source_vid.src = path;
-        vid.appendChild(source_vid);
-        document.getElementById('video_container').appendChild(vid);    
-    }
-    
-    function captureVideoFail(e){
-        log('Error getting video: ' + e.code);
-    }
-    
-    function getVideo(){
-        clearStatus();
-        var options = { limit: 1, duration: 10 };
-        navigator.device.capture.captureVideo(captureVideoWin, captureVideoFail, options);      
-    }
-
-    function resolveMediaFileURL(mediaFile, callback) {
-        resolveLocalFileSystemURL(mediaFile.localURL, function(entry) {
-            log("Resolved by URL: " + mediaFile.localURL);
-            if (callback) callback();
-        }, function(err) {
-            log("Failed to resolve by URL: " + mediaFile.localURL);
-            log("Error: " + JSON.stringify(err));
-            if (callback) callback();
-        });
-    }
-
-    function resolveMediaFile(mediaFile, callback) {
-        resolveLocalFileSystemURL(mediaFile.fullPath, function(entry) {
-            log("Resolved by path: " + mediaFile.fullPath);
-            if (callback) callback();
-        }, function(err) {
-            log("Failed to resolve by path: " + mediaFile.fullPath);
-            log("Error: " + JSON.stringify(err));
-            if (callback) callback();
-        });
-    }
-        
-    function resolveVideo() {
-        clearStatus();
-        var options = { limit: 1, duration: 5 };
-        navigator.device.capture.captureVideo(function(mediaFiles) {
-            captureVideoWin(mediaFiles);
-            resolveMediaFile(mediaFiles[0], function() {
-                resolveMediaFileURL(mediaFiles[0]);
-            });
-        }, captureVideoFail, options);      
-    }
-    
-    function clearStatus() {
-        document.getElementById('camera_status').innerHTML = '';
-        document.getElementById('camera_image').src = 'about:blank';
-    }
-
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-            deviceReady = true;
-            console.log("Device="+device.platform+" "+device.version);
-        }, false);
-        window.setTimeout(function() {
-            if (!deviceReady) {
-                alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
-            }
-        },1000);
-    };
-    
-</script>
-
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
 
     <h1>Capture</h1>
     <div id="info" style="white-space: pre-wrap">
@@ -176,10 +43,10 @@
     <div id="image-options"></div>
 
     <h2>Actions</h2>
-    <div class="btn large" onclick="getAudio();">Capture 10 secs of audio and play</div>
-    <div class="btn large" onclick="getImage();">Capture 1 image</div>
-    <div class="btn large" onclick="getVideo();">Capture 10 secs of video</div>
-    <div class="btn large" onclick="resolveVideo();">Capture 5 secs of video and resolve</div>
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <div class="btn large getAudio">Capture 10 secs of audio and play</div>
+    <div class="btn large getImage">Capture 1 image</div>
+    <div class="btn large getVideo">Capture 10 secs of video</div>
+    <div class="btn large resolveVideo">Capture 5 secs of video and resolve</div>
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/capture/index.js
----------------------------------------------------------------------
diff --git a/capture/index.js b/capture/index.js
new file mode 100644
index 0000000..0f98549
--- /dev/null
+++ b/capture/index.js
@@ -0,0 +1,137 @@
+var deviceReady = false;
+var platformId = cordova.require('cordova/platform').id;
+var pageStartTime = +new Date();
+
+//-------------------------------------------------------------------------
+// Camera
+//-------------------------------------------------------------------------
+
+function log(value) {
+    console.log(value);
+    document.getElementById('camera_status').textContent += (new Date() - pageStartTime) / 1000 + ': ' + value + '\n';
+}
+
+function captureAudioWin(mediaFiles){
+    var path = mediaFiles[0].fullPath;
+    log('Audio captured: ' + path);
+    var m = new Media(path);
+    m.play(); 
+}
+
+function captureAudioFail(e){
+    log('Error getting audio: ' + e.code);
+}
+
+function getAudio(){
+    clearStatus();
+    var options = { limit: 1, duration: 10};
+    navigator.device.capture.captureAudio(captureAudioWin, captureAudioFail, options);
+}
+
+function captureImageWin(mediaFiles){
+    var path = mediaFiles[0].fullPath;
+    log('Image captured: ' + path);    
+    document.getElementById('camera_image').src = path;    
+}
+
+function captureImageFail(e){
+    log('Error getting image: ' + e.code);
+}
+
+function getImage(){
+    clearStatus();
+    var options = { limit: 1 };
+    navigator.device.capture.captureImage(captureImageWin, captureImageFail, options);    
+}    
+
+function captureVideoWin(mediaFiles){
+    var path = mediaFiles[0].fullPath;
+    log('Video captured: ' + path);
+    
+    // need to inject the video element into the html
+    // doesn't seem to work if you have a pre-existing video element and
+    // add in a source tag
+    var vid = document.createElement('video');
+    vid.id="theVideo";
+    vid.width = "320";
+    vid.height= "240";
+    vid.controls = "true";
+    var source_vid = document.createElement('source');
+    source_vid.id = "theSource";
+    source_vid.src = path;
+    vid.appendChild(source_vid);
+    document.getElementById('video_container').appendChild(vid);    
+}
+
+function captureVideoFail(e){
+    log('Error getting video: ' + e.code);
+}
+
+function getVideo(){
+    clearStatus();
+    var options = { limit: 1, duration: 10 };
+    navigator.device.capture.captureVideo(captureVideoWin, captureVideoFail, options);      
+}
+
+function resolveMediaFileURL(mediaFile, callback) {
+    resolveLocalFileSystemURL(mediaFile.localURL, function(entry) {
+        log("Resolved by URL: " + mediaFile.localURL);
+        if (callback) callback();
+    }, function(err) {
+        log("Failed to resolve by URL: " + mediaFile.localURL);
+        log("Error: " + JSON.stringify(err));
+        if (callback) callback();
+    });
+}
+
+function resolveMediaFile(mediaFile, callback) {
+    resolveLocalFileSystemURL(mediaFile.fullPath, function(entry) {
+        log("Resolved by path: " + mediaFile.fullPath);
+        if (callback) callback();
+    }, function(err) {
+        log("Failed to resolve by path: " + mediaFile.fullPath);
+        log("Error: " + JSON.stringify(err));
+        if (callback) callback();
+    });
+}
+    
+function resolveVideo() {
+    clearStatus();
+    var options = { limit: 1, duration: 5 };
+    navigator.device.capture.captureVideo(function(mediaFiles) {
+        captureVideoWin(mediaFiles);
+        resolveMediaFile(mediaFiles[0], function() {
+            resolveMediaFileURL(mediaFiles[0]);
+        });
+    }, captureVideoFail, options);      
+}
+
+function clearStatus() {
+    document.getElementById('camera_status').innerHTML = '';
+    document.getElementById('camera_image').src = 'about:blank';
+}
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+        deviceReady = true;
+        console.log("Device="+device.platform+" "+device.version);
+    }, false);
+    window.setTimeout(function() {
+        if (!deviceReady) {
+            alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
+        }
+    },1000);
+};
+
+
+window.onload = function() {
+  addListenerToClass('getAudio', getAudio);
+  addListenerToClass('getImage', getImage);
+  addListenerToClass('getVideo', getVideo);
+  addListenerToClass('resolveVideo', resolveVideo);
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/compass/index.html
----------------------------------------------------------------------
diff --git a/compass/index.html b/compass/index.html
index 4d6af2c..1734caa 100644
--- a/compass/index.html
+++ b/compass/index.html
@@ -28,111 +28,9 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>      
-
-      
-<script type="text/javascript" charset="utf-8">
-
-    var deviceReady = false;
-
-    function roundNumber(num) {
-        var dec = 3;
-        var result = Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
-        return result;
-    }
-
-    //-------------------------------------------------------------------------
-    // Compass
-    //-------------------------------------------------------------------------
-    var watchCompassId = null;
-
-    /**
-     * Start watching compass
-     */
-    var watchCompass = function() {
-        console.log("watchCompass()");
-
-        // Success callback
-        var success = function(a){
-            document.getElementById('compassHeading').innerHTML = roundNumber(a.magneticHeading);
-        };
-
-        // Fail callback
-        var fail = function(e){
-            console.log("watchCompass fail callback with error code "+e);
-            stopCompass();
-            setCompassStatus(e);
-        };
-
-        // Update heading every 1 sec
-        var opt = {};
-        opt.frequency = 1000;
-        watchCompassId = navigator.compass.watchHeading(success, fail, opt);
-
-        setCompassStatus("Running");
-    };
-
-    /**
-     * Stop watching the acceleration
-     */
-    var stopCompass = function() {
-        setCompassStatus("Stopped");
-        if (watchCompassId) {
-            navigator.compass.clearWatch(watchCompassId);
-            watchCompassId = null;
-        }
-    };
-
-    /**
-     * Get current compass
-     */
-    var getCompass = function() {
-        console.log("getCompass()");
-
-        // Stop compass if running
-        stopCompass();
-
-        // Success callback
-        var success = function(a){
-            document.getElementById('compassHeading').innerHTML = roundNumber(a.magneticHeading);
-        };
-
-        // Fail callback
-        var fail = function(e){
-            console.log("getCompass fail callback with error code "+e);
-            setCompassStatus(e);
-        };
-
-        // Make call
-        var opt = {};
-        navigator.compass.getCurrentHeading(success, fail, opt);
-    };
-
-    /**
-     * Set compass status
-     */
-    var setCompassStatus = function(status) {
-        document.getElementById('compass_status').innerHTML = status;
-    };
-    
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-                deviceReady = true;
-                console.log("Device="+device.platform+" "+device.version);
-            }, false);
-        window.setTimeout(function() {
-        	if (!deviceReady) {
-        		alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
-        	}
-        },1000);
-    }
-
-</script>
-
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>Compass</h1>
     <div id="info">
@@ -142,9 +40,9 @@
         </tr></table>
     </div>
     <h2>Action</h2>
-    <div class="btn large" onclick="getCompass();">Get Compass</div>
-    <div class="btn large" onclick="watchCompass();">Start Watching Compass</div>
-    <div class="btn large" onclick="stopCompass();">Stop Watching Compass</div>
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <div class="btn large getCompass">Get Compass</div>
+    <div class="btn large watchCompass">Start Watching Compass</div>
+    <div class="btn large stopCompass">Stop Watching Compass</div>
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>      

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/compass/index.js
----------------------------------------------------------------------
diff --git a/compass/index.js b/compass/index.js
new file mode 100644
index 0000000..0735ab2
--- /dev/null
+++ b/compass/index.js
@@ -0,0 +1,104 @@
+var deviceReady = false;
+
+function roundNumber(num) {
+    var dec = 3;
+    var result = Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
+    return result;
+}
+
+//-------------------------------------------------------------------------
+// Compass
+//-------------------------------------------------------------------------
+var watchCompassId = null;
+
+/**
+ * Start watching compass
+ */
+var watchCompass = function() {
+    console.log("watchCompass()");
+
+    // Success callback
+    var success = function(a){
+        document.getElementById('compassHeading').innerHTML = roundNumber(a.magneticHeading);
+    };
+
+    // Fail callback
+    var fail = function(e){
+        console.log("watchCompass fail callback with error code "+e);
+        stopCompass();
+        setCompassStatus(e);
+    };
+
+    // Update heading every 1 sec
+    var opt = {};
+    opt.frequency = 1000;
+    watchCompassId = navigator.compass.watchHeading(success, fail, opt);
+
+    setCompassStatus("Running");
+};
+
+/**
+ * Stop watching the acceleration
+ */
+var stopCompass = function() {
+    setCompassStatus("Stopped");
+    if (watchCompassId) {
+        navigator.compass.clearWatch(watchCompassId);
+        watchCompassId = null;
+    }
+};
+
+/**
+ * Get current compass
+ */
+var getCompass = function() {
+    console.log("getCompass()");
+
+    // Stop compass if running
+    stopCompass();
+
+    // Success callback
+    var success = function(a){
+        document.getElementById('compassHeading').innerHTML = roundNumber(a.magneticHeading);
+    };
+
+    // Fail callback
+    var fail = function(e){
+        console.log("getCompass fail callback with error code "+e);
+        setCompassStatus(e);
+    };
+
+    // Make call
+    var opt = {};
+    navigator.compass.getCurrentHeading(success, fail, opt);
+};
+
+/**
+ * Set compass status
+ */
+var setCompassStatus = function(status) {
+    document.getElementById('compass_status').innerHTML = status;
+};
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+            deviceReady = true;
+            console.log("Device="+device.platform+" "+device.version);
+        }, false);
+    window.setTimeout(function() {
+      if (!deviceReady) {
+        alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
+      }
+    },1000);
+}
+
+window.onload = function() {
+  addListenerToClass('getCompass', getCompass);
+  addListenerToClass('watchCompass', watchCompass);
+  addListenerToClass('stopCompass', stopCompass);
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/contacts/index.html
----------------------------------------------------------------------
diff --git a/contacts/index.html b/contacts/index.html
index b6a3a92..5782713 100644
--- a/contacts/index.html
+++ b/contacts/index.html
@@ -28,98 +28,10 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>      
-
-      
-<script type="text/javascript" charset="utf-8">
-
-    var deviceReady = false;
-
-    //-------------------------------------------------------------------------
-    // Contacts
-    //-------------------------------------------------------------------------
-    function getContacts() {
-        obj = new ContactFindOptions();
-        // show all contacts, so don't filter
-        obj.multiple = true;
-        navigator.contacts.find(
-            ["displayName", "name", "phoneNumbers", "emails", "urls", "note"],
-            function(contacts) {
-                var s = "";
-                if (contacts.length == 0) {
-                    s = "No contacts found";
-                }
-                else {
-                    s = "Number of contacts: "+contacts.length+"<br><table width='100%'><tr><th>Name</th><td>Phone</td><td>Email</td></tr>";
-                    for (var i=0; i<contacts.length; i++) {
-                        var contact = contacts[i];
-                        s = s + "<tr><td>" + contact.name.formatted + "</td><td>";
-                        if (contact.phoneNumbers && contact.phoneNumbers.length > 0) {
-                            s = s + contact.phoneNumbers[0].value;
-                        }
-                        s = s + "</td><td>"
-                        if (contact.emails && contact.emails.length > 0) {
-                            s = s + contact.emails[0].value;
-                        }
-                        s = s + "</td></tr>";
-                    }
-                    s = s + "</table>";
-                }
-                document.getElementById('contacts_results').innerHTML = s;
-            },
-            function(e) {
-                document.getElementById('contacts_results').innerHTML = "Error: "+e.code;
-            },
-            obj);
-    };
-
-    function addContact(){
-        console.log("addContact()");
-        try{
-            var contact = navigator.contacts.create({"displayName": "Dooney Evans"});
-            var contactName = {
-                formatted: "Dooney Evans",
-                familyName: "Evans",
-                givenName: "Dooney",
-                middleName: ""
-            };
-
-            contact.name = contactName;
-
-            var phoneNumbers = [1];
-            phoneNumbers[0] = new ContactField('work', '512-555-1234', true);
-            contact.phoneNumbers = phoneNumbers;
-
-            contact.save(
-                function() { alert("Contact saved.");},
-                function(e) { alert("Contact save failed: " + e.code); }
-            );
-            console.log("you have saved the contact");
-        }
-        catch (e){
-            alert(e);
-        }
-
-    };
-    
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-                deviceReady = true;
-                console.log("Device="+device.platform+" "+device.version);
-            }, false);
-        window.setTimeout(function() {
-        	if (!deviceReady) {
-        		alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
-        	}
-        },1000);
-    }
-
-</script>
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
 
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>Contacts</h1>    
     <div id="info">
@@ -127,8 +39,9 @@
         <span id="contacts_results"> </span>
     </div>
     <h2>Action</h2>
-    <div class="btn large" onclick="getContacts();">Get phone's contacts</div>
-    <div class="btn large" onclick="addContact();">Add a new contact 'Dooney Evans'</div>
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+
+    <div class="btn large getContacts">Get phone's contacts</div>
+    <div class="btn large addContact">Add a new contact 'Dooney Evans'</div>
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>      

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/contacts/index.js
----------------------------------------------------------------------
diff --git a/contacts/index.js b/contacts/index.js
new file mode 100644
index 0000000..d3f3312
--- /dev/null
+++ b/contacts/index.js
@@ -0,0 +1,90 @@
+var deviceReady = false;
+
+//-------------------------------------------------------------------------
+// Contacts
+//-------------------------------------------------------------------------
+function getContacts() {
+    obj = new ContactFindOptions();
+    // show all contacts, so don't filter
+    obj.multiple = true;
+    navigator.contacts.find(
+        ["displayName", "name", "phoneNumbers", "emails", "urls", "note"],
+        function(contacts) {
+            var s = "";
+            if (contacts.length == 0) {
+                s = "No contacts found";
+            }
+            else {
+                s = "Number of contacts: "+contacts.length+"<br><table width='100%'><tr><th>Name</th><td>Phone</td><td>Email</td></tr>";
+                for (var i=0; i<contacts.length; i++) {
+                    var contact = contacts[i];
+                    s = s + "<tr><td>" + contact.name.formatted + "</td><td>";
+                    if (contact.phoneNumbers && contact.phoneNumbers.length > 0) {
+                        s = s + contact.phoneNumbers[0].value;
+                    }
+                    s = s + "</td><td>"
+                    if (contact.emails && contact.emails.length > 0) {
+                        s = s + contact.emails[0].value;
+                    }
+                    s = s + "</td></tr>";
+                }
+                s = s + "</table>";
+            }
+            document.getElementById('contacts_results').innerHTML = s;
+        },
+        function(e) {
+            document.getElementById('contacts_results').innerHTML = "Error: "+e.code;
+        },
+        obj);
+};
+
+function addContact(){
+    try{
+        var contact = navigator.contacts.create({"displayName": "Dooney Evans"});
+        var contactName = {
+            formatted: "Dooney Evans",
+            familyName: "Evans",
+            givenName: "Dooney",
+            middleName: ""
+        };
+
+        contact.name = contactName;
+
+        var phoneNumbers = [1];
+        phoneNumbers[0] = new ContactField('work', '512-555-1234', true);
+        contact.phoneNumbers = phoneNumbers;
+
+        contact.save(
+            function() { alert("Contact saved.");},
+            function(e) { alert("Contact save failed: " + e.code); }
+        );
+        console.log("you have saved the contact");
+    }
+    catch (e){
+        alert(e);
+    }
+
+};
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+            deviceReady = true;
+            console.log("Device="+device.platform+" "+device.version);
+        }, false);
+    window.setTimeout(function() {
+      if (!deviceReady) {
+        alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
+      }
+    },1000);
+}
+
+
+window.onload = function() {
+  addListenerToClass('getContacts', getContacts);
+  addListenerToClass('addContact', addContact);
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/cordova-incl.js
----------------------------------------------------------------------
diff --git a/cordova-incl.js b/cordova-incl.js
index 2712063..cc059b8 100644
--- a/cordova-incl.js
+++ b/cordova-incl.js
@@ -56,6 +56,28 @@ if (!window._doNotWriteCordovaScript) {
     }
 }
 
+function addListenerToClass(className, listener, argsArray, action, doNotWrap) {
+    if (!action) {
+      action='click';
+    }
+    var elements = document.getElementsByClassName(className);
+    // choose Event target as a scope (like inline scripts)
+    if (!doNotWrap) {
+      if (argsArray && !Array.isArray(argsArray)) {
+        argsArray = [argsArray];
+      }
+      function callListener(e) {
+        listener.apply(null, argsArray);
+      }
+    } else {
+      callListener = listener;
+    }
+    for (var i = 0; i < elements.length; ++i) {
+      var item = elements[i];  
+      item.addEventListener(action, callListener, false);
+    }
+};
+
 function backHome() {
     if (window.device && device.platform && (device.platform.toLowerCase() == 'android' || device.platform.toLowerCase() == 'amazon-fireos')) {
         navigator.app.backHistory();

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/events/index.html
----------------------------------------------------------------------
diff --git a/events/index.html b/events/index.html
index d2ad8d4..3f45021 100644
--- a/events/index.html
+++ b/events/index.html
@@ -28,60 +28,10 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>      
-
-      
-<script type="text/javascript" charset="utf-8">
-
-    var deviceReady = false;
-
-    function interceptBackbutton() {
-    	eventOutput("Back button intercepted");
-    }
-    function interceptMenubutton() {
-    	eventOutput("Menu button intercepted");
-    }
-    function interceptSearchbutton() {
-    	eventOutput("Search button intercepted");
-    }
-    function interceptResume() {
-      eventOutput("Resume event intercepted");
-    }
-    function interceptPause() {
-      eventOutput("Pause event intercepted");
-    }
-    function interceptOnline() {
-      eventOutput("Online event intercepted");
-    }
-    function interceptOffline() {
-      eventOutput("Offline event intercepted");
-    }
-    
-    var eventOutput = function(s) {
-        var el = document.getElementById("results");
-        el.innerHTML = el.innerHTML + s + "<br>";
-    };
-
-    
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-                deviceReady = true;
-                console.log("Device="+device.platform+" "+device.version);
-                eventOutput("deviceready event: "+device.platform+" "+device.version);
-            }, false);
-        window.setTimeout(function() {
-        	if (!deviceReady) {
-        		alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
-        	}
-        },1000);
-    }
-
-</script>
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
 
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>Events</h1>
     <div id="info">
@@ -90,21 +40,21 @@
     </div>
     <input type="text" value="Type here to test events when fields are focused" />
     <h2>Action</h2>
-    <div class="btn large" onclick="document.addEventListener('backbutton', interceptBackbutton, false);">Intercept backbutton</div>
-    <div class="btn large" onclick="document.removeEventListener('backbutton', interceptBackbutton, false);">Stop intercept of backbutton</div>
-    <div class="btn large" onclick="document.addEventListener('menubutton', interceptMenubutton, false);">Intercept menubutton</div>
-    <div class="btn large" onclick="document.removeEventListener('menubutton', interceptMenubutton, false);">Stop intercept of menubutton</div>
-    <div class="btn large" onclick="document.addEventListener('searchbutton', interceptSearchbutton, false);">Intercept searchbutton</div>
-    <div class="btn large" onclick="document.removeEventListener('searchbutton', interceptSearchbutton, false);">Stop intercept of searchbutton</div>
-    <div class="btn large" onclick="document.addEventListener('resume', interceptResume, false);">Intercept resume</div>
-    <div class="btn large" onclick="document.removeEventListener('resume', interceptResume, false);">Stop intercept of resume</div>
-    <div class="btn large" onclick="document.addEventListener('pause', interceptPause, false);">Intercept pause</div>
-    <div class="btn large" onclick="document.removeEventListener('pause', interceptPause, false);">Stop intercept of pause</div>
-    <div class="btn large" onclick="document.addEventListener('online', interceptOnline, false);">Intercept online</div>
-    <div class="btn large" onclick="document.removeEventListener('online', interceptOnline, false);">Stop intercept of online</div>
-    <div class="btn large" onclick="document.addEventListener('offline', interceptOffline, false);">Intercept offline</div>
-    <div class="btn large" onclick="document.removeEventListener('offline', interceptOffline, false);">Stop intercept of offline</div>
-
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <div class="btn large interceptBackButton">Intercept backbutton</div>
+    <div class="btn large stopInterceptOfBackButton">Stop intercept of backbutton</div>
+    <div class="btn large interceptMenuButton">Intercept menubutton</div>
+    <div class="btn large stopInterceptOfMenuButton">Stop intercept of menubutton</div>
+    <div class="btn large interceptSearchButton">Intercept searchbutton</div>
+    <div class="btn large stopInterceptOfSearchButton">Stop intercept of searchbutton</div>
+    <div class="btn large interceptResume">Intercept resume</div>
+    <div class="btn large stopInterceptOfResume">Stop intercept of resume</div>
+    <div class="btn large interceptPause">Intercept pause</div>
+    <div class="btn large stopInterceptOfPause">Stop intercept of pause</div>
+    <div class="btn large interceptOnline">Intercept online</div>
+    <div class="btn large stopInterceptOfOnline">Stop intercept of online</div>
+    <div class="btn large interceptOffline">Intercept offline</div>
+    <div class="btn large stopInterceptOfOffline">Stop intercept of offline</div>
+
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/events/index.js
----------------------------------------------------------------------
diff --git a/events/index.js b/events/index.js
new file mode 100644
index 0000000..e1bb922
--- /dev/null
+++ b/events/index.js
@@ -0,0 +1,94 @@
+var deviceReady = false;
+
+function interceptBackbutton() {
+  eventOutput("Back button intercepted");
+}
+function interceptMenubutton() {
+  eventOutput("Menu button intercepted");
+}
+function interceptSearchbutton() {
+  eventOutput("Search button intercepted");
+}
+function interceptResume() {
+  eventOutput("Resume event intercepted");
+}
+function interceptPause() {
+  eventOutput("Pause event intercepted");
+}
+function interceptOnline() {
+  eventOutput("Online event intercepted");
+}
+function interceptOffline() {
+  eventOutput("Offline event intercepted");
+}
+
+var eventOutput = function(s) {
+    var el = document.getElementById("results");
+    el.innerHTML = el.innerHTML + s + "<br>";
+};
+
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+            deviceReady = true;
+            console.log("Device="+device.platform+" "+device.version);
+            eventOutput("deviceready event: "+device.platform+" "+device.version);
+        }, false);
+    window.setTimeout(function() {
+      if (!deviceReady) {
+        alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
+      }
+    },1000);
+}
+
+
+window.onload = function() {
+  addListenerToClass('interceptBackButton', function() {
+    document.addEventListener('backbutton', interceptBackbutton, false);
+  });
+  addListenerToClass('stopInterceptOfBackButton', function() {
+    document.removeEventListener('backbutton', interceptBackbutton, false);
+  });
+  addListenerToClass('interceptMenuButton', function() {
+    document.addEventListener('menubutton', interceptMenubutton, false);
+  });
+  addListenerToClass('stopInterceptOfMenuButton', function() {
+    document.removeEventListener('menubutton', interceptMenubutton, false);
+  });
+  addListenerToClass('interceptSearchButton', function() {
+    document.addEventListener('searchbutton', interceptSearchbutton, false);
+  });
+  addListenerToClass('stopInterceptOfSearchButton', function() {
+    document.removeEventListener('searchbutton', interceptSearchbutton, false);
+  });
+  addListenerToClass('interceptResume', function() {
+    document.addEventListener('resume', interceptResume, false);
+  });
+  addListenerToClass('stopInterceptOfResume', function() {
+    document.removeEventListener('resume', interceptResume, false);
+  });
+  addListenerToClass('interceptPause', function() {
+    document.addEventListener('pause', interceptPause, false);
+  });
+  addListenerToClass('stopInterceptOfPause', function() {
+    document.removeEventListener('pause', interceptPause, false);
+  });
+  addListenerToClass('interceptOnline', function() {
+    document.addEventListener('online', interceptOnline, false);
+  });
+  addListenerToClass('stopInterceptOfOnline', function() {
+    document.removeEventListener('online', interceptOnline, false);
+  });
+  addListenerToClass('interceptOffline', function() {
+    document.addEventListener('offline', interceptOffline, false);
+  });
+  addListenerToClass('stopInterceptOfOffline', function() {
+    document.removeEventListener('offline', interceptOffline, false);
+  });
+
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/file/index.html
----------------------------------------------------------------------
diff --git a/file/index.html b/file/index.html
index 033b97d..8f00e86 100644
--- a/file/index.html
+++ b/file/index.html
@@ -28,162 +28,10 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>
-
-
-<script type="text/javascript" charset="utf-8">
-
-    var deviceReady = false;
-
-    var imageURL = "http://apache.org/images/feather-small.gif";
-    var videoURL = "http://techslides.com/demos/sample-videos/small.mp4";
-
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-                deviceReady = true;
-                console.log("Device="+device.platform+" "+device.version);
-                bindEvents();
-                document.body.classList.add(device.platform.toLowerCase() + "-platform");
-            }, false);
-        window.setTimeout(function() {
-            if (!deviceReady) {
-                alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
-            }
-        },1000);
-    }
-
-    function bindEvents() {
-        document.getElementById('downloadImgCDV').addEventListener('click', downloadImgCDV, false);
-        document.getElementById('downloadImgNative').addEventListener('click', downloadImgNative, false);
-        document.getElementById('downloadVideoCDV').addEventListener('click', downloadVideoCDV, false);
-        document.getElementById('downloadVideoNative').addEventListener('click', downloadVideoNative, false);
-        document.getElementById('testPrivateURL').addEventListener('click', testPrivateURL, false);
-        var fsButtons = document.querySelectorAll('.resolveFs');
-        for (var i=0; i < fsButtons.length; ++i) {
-            fsButtons[i].addEventListener('click', resolveFs, false);
-        }
-    }
-
-    function clearLog() {
-        var log = document.getElementById("log");
-        log.innerHTML = "";
-    }
-
-    function logMessage(message, color) {
-        var log = document.getElementById("log");
-        var logLine = document.createElement('div');
-        if (color) {
-            logLine.style.color = color;
-        }
-        logLine.innerHTML = message;
-        log.appendChild(logLine);
-    }
-
-    function logError(serviceName) {
-        return function(err) {
-            logMessage("ERROR: " + serviceName + " " + JSON.stringify(err), "red");
-        };
-    }
-
-    function downloadImgCDV(ev) {
-        ev.preventDefault();
-        ev.stopPropagation();
-        downloadImg(imageURL, function(entry) { return entry.toURL(); }, new Image());
-    }
-
-    function downloadImgNative(ev) {
-        ev.preventDefault();
-        ev.stopPropagation();
-        downloadImg(imageURL, function(entry) { return entry.toNativeURL(); }, new Image);
-    }
-
-    function downloadVideoCDV(ev) {
-        ev.preventDefault();
-        ev.stopPropagation();
-        var videoElement = document.createElement('video');
-        videoElement.controls = "controls";
-        downloadImg(videoURL, function(entry) { return entry.toURL(); }, videoElement);
-    }
-
-    function downloadVideoNative(ev) {
-        ev.preventDefault();
-        ev.stopPropagation();
-        var videoElement = document.createElement('video');
-        videoElement.controls = "controls";
-        downloadImg(videoURL, function(entry) { return entry.toNativeURL(); }, videoElement);
-    }
-
-    function downloadImg(source, urlFn, element) {
-        var filename = source.substring(source.lastIndexOf("/")+1);
-        function download(fileSystem) {
-            var ft = new FileTransfer();
-            logMessage("Starting download");
-            ft.download(source, fileSystem.root.toURL() + filename, function(entry) {
-                logMessage("Download complete")
-                element.src = urlFn(entry)
-                logMessage("Src URL is " + element.src, "green");
-                logMessage("Inserting element");
-                document.getElementById("output").appendChild(element);
-            }, logError("ft.download"));
-        }
-        clearLog();
-        logMessage("Requesting filesystem");
-        requestFileSystem(TEMPORARY, 0, function(fileSystem) {
-            logMessage("Checking for existing file");
-            fileSystem.root.getFile(filename, {create: false}, function(entry) {
-                logMessage("Removing existing file");
-                entry.remove(function() {
-                    download(fileSystem);
-                }, logError("entry.remove"));
-            }, function() {
-                download(fileSystem);
-            });
-        }, logError("requestFileSystem"));
-    }
-
-    function testPrivateURL(ev) {
-        ev.preventDefault();
-        ev.stopPropagation();
-        requestFileSystem(TEMPORARY, 0, function(fileSystem) {
-            logMessage("Temporary root is at " + fileSystem.root.toNativeURL());
-            fileSystem.root.getFile("testfile", {create: true}, function(entry) {
-                logMessage("Temporary file is at " + entry.toNativeURL());
-                if (entry.toNativeURL().substring(0,12) == "file:///var/") {
-                    logMessage("File starts with /var/, trying /private/var");
-                    var newURL = "file://localhost/private/var/" + entry.toNativeURL().substring(12) + "?and=another_thing";
-                    //var newURL = entry.toNativeURL();
-                    logMessage(newURL, 'blue');
-                    resolveLocalFileSystemURL(newURL, function(newEntry) {
-                        logMessage("Successfully resolved.", 'green');
-                        logMessage(newEntry.toURL(), 'blue');
-                        logMessage(newEntry.toNativeURL(), 'blue');
-                    }, logError("resolveLocalFileSystemURL"));
-                }
-            }, logError("getFile"));
-        }, logError("requestFileSystem"));
-    }
-
-    function resolveFs(ev) {
-        var fsURL = "cdvfile://localhost/" + ev.target.getAttribute('data-fsname') + "/";
-        logMessage("Resolving URL: " + fsURL);
-        resolveLocalFileSystemURL(fsURL, function(entry) {
-            logMessage("Success", 'green');
-            logMessage(entry.toURL(), 'blue');
-            logMessage(entry.toInternalURL(), 'blue');
-            logMessage("Resolving URL: " + entry.toURL());
-            resolveLocalFileSystemURL(entry.toURL(), function(entry2) {
-                logMessage("Success", 'green');
-                logMessage(entry2.toURL(), 'blue');
-                logMessage(entry2.toInternalURL(), 'blue');
-            }, logError("resolveLocalFileSystemURL"));
-        }, logError("resolveLocalFileSystemURL"));
-    }
-</script>
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
 
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
 
     <h1>File and File Transfer</h1>
     <h2>File</h2>
@@ -219,6 +67,6 @@
 
     <div id="log"></div>
     <div id="output"></div>
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/file/index.js
----------------------------------------------------------------------
diff --git a/file/index.js b/file/index.js
new file mode 100644
index 0000000..1f570dd
--- /dev/null
+++ b/file/index.js
@@ -0,0 +1,153 @@
+var deviceReady = false;
+
+var imageURL = "http://apache.org/images/feather-small.gif";
+var videoURL = "http://techslides.com/demos/sample-videos/small.mp4";
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+            deviceReady = true;
+            console.log("Device="+device.platform+" "+device.version);
+            bindEvents();
+            document.body.classList.add(device.platform.toLowerCase() + "-platform");
+        }, false);
+    window.setTimeout(function() {
+        if (!deviceReady) {
+            alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
+        }
+    },1000);
+}
+
+function bindEvents() {
+    document.getElementById('downloadImgCDV').addEventListener('click', downloadImgCDV, false);
+    document.getElementById('downloadImgNative').addEventListener('click', downloadImgNative, false);
+    document.getElementById('downloadVideoCDV').addEventListener('click', downloadVideoCDV, false);
+    document.getElementById('downloadVideoNative').addEventListener('click', downloadVideoNative, false);
+    document.getElementById('testPrivateURL').addEventListener('click', testPrivateURL, false);
+    var fsButtons = document.querySelectorAll('.resolveFs');
+    for (var i=0; i < fsButtons.length; ++i) {
+        fsButtons[i].addEventListener('click', resolveFs, false);
+    }
+}
+
+function clearLog() {
+    var log = document.getElementById("log");
+    log.innerHTML = "";
+}
+
+function logMessage(message, color) {
+    var log = document.getElementById("log");
+    var logLine = document.createElement('div');
+    if (color) {
+        logLine.style.color = color;
+    }
+    logLine.innerHTML = message;
+    log.appendChild(logLine);
+}
+
+function logError(serviceName) {
+    return function(err) {
+        logMessage("ERROR: " + serviceName + " " + JSON.stringify(err), "red");
+    };
+}
+
+function downloadImgCDV(ev) {
+    ev.preventDefault();
+    ev.stopPropagation();
+    downloadImg(imageURL, function(entry) { return entry.toURL(); }, new Image());
+}
+
+function downloadImgNative(ev) {
+    ev.preventDefault();
+    ev.stopPropagation();
+    downloadImg(imageURL, function(entry) { return entry.toNativeURL(); }, new Image);
+}
+
+function downloadVideoCDV(ev) {
+    ev.preventDefault();
+    ev.stopPropagation();
+    var videoElement = document.createElement('video');
+    videoElement.controls = "controls";
+    downloadImg(videoURL, function(entry) { return entry.toURL(); }, videoElement);
+}
+
+function downloadVideoNative(ev) {
+    ev.preventDefault();
+    ev.stopPropagation();
+    var videoElement = document.createElement('video');
+    videoElement.controls = "controls";
+    downloadImg(videoURL, function(entry) { return entry.toNativeURL(); }, videoElement);
+}
+
+function downloadImg(source, urlFn, element) {
+    var filename = source.substring(source.lastIndexOf("/")+1);
+    function download(fileSystem) {
+        var ft = new FileTransfer();
+        logMessage("Starting download");
+        ft.download(source, fileSystem.root.toURL() + filename, function(entry) {
+            logMessage("Download complete")
+            element.src = urlFn(entry)
+            logMessage("Src URL is " + element.src, "green");
+            logMessage("Inserting element");
+            document.getElementById("output").appendChild(element);
+        }, logError("ft.download"));
+    }
+    clearLog();
+    logMessage("Requesting filesystem");
+    requestFileSystem(TEMPORARY, 0, function(fileSystem) {
+        logMessage("Checking for existing file");
+        fileSystem.root.getFile(filename, {create: false}, function(entry) {
+            logMessage("Removing existing file");
+            entry.remove(function() {
+                download(fileSystem);
+            }, logError("entry.remove"));
+        }, function() {
+            download(fileSystem);
+        });
+    }, logError("requestFileSystem"));
+}
+
+function testPrivateURL(ev) {
+    ev.preventDefault();
+    ev.stopPropagation();
+    requestFileSystem(TEMPORARY, 0, function(fileSystem) {
+        logMessage("Temporary root is at " + fileSystem.root.toNativeURL());
+        fileSystem.root.getFile("testfile", {create: true}, function(entry) {
+            logMessage("Temporary file is at " + entry.toNativeURL());
+            if (entry.toNativeURL().substring(0,12) == "file:///var/") {
+                logMessage("File starts with /var/, trying /private/var");
+                var newURL = "file://localhost/private/var/" + entry.toNativeURL().substring(12) + "?and=another_thing";
+                //var newURL = entry.toNativeURL();
+                logMessage(newURL, 'blue');
+                resolveLocalFileSystemURL(newURL, function(newEntry) {
+                    logMessage("Successfully resolved.", 'green');
+                    logMessage(newEntry.toURL(), 'blue');
+                    logMessage(newEntry.toNativeURL(), 'blue');
+                }, logError("resolveLocalFileSystemURL"));
+            }
+        }, logError("getFile"));
+    }, logError("requestFileSystem"));
+}
+
+function resolveFs(ev) {
+    var fsURL = "cdvfile://localhost/" + ev.target.getAttribute('data-fsname') + "/";
+    logMessage("Resolving URL: " + fsURL);
+    resolveLocalFileSystemURL(fsURL, function(entry) {
+        logMessage("Success", 'green');
+        logMessage(entry.toURL(), 'blue');
+        logMessage(entry.toInternalURL(), 'blue');
+        logMessage("Resolving URL: " + entry.toURL());
+        resolveLocalFileSystemURL(entry.toURL(), function(entry2) {
+            logMessage("Success", 'green');
+            logMessage(entry2.toURL(), 'blue');
+            logMessage(entry2.toInternalURL(), 'blue');
+        }, logError("resolveLocalFileSystemURL"));
+    }, logError("resolveLocalFileSystemURL"));
+}
+
+window.onload = function() {
+  addListenerToClass('backBtn', backHome);
+  init();
+}


[10/12] spec commit: Merge branch 'master' into ffos_privileged_compatible

Posted by za...@apache.org.
Merge branch 'master' into ffos_privileged_compatible


Project: http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/commit/55709765
Tree: http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/tree/55709765
Diff: http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/diff/55709765

Branch: refs/heads/master
Commit: 5570976581ec6983d11ba498453788ad9f205c4f
Parents: 0de5e95 b0ef368
Author: Piotr Zalewa <pi...@zalewa.info>
Authored: Mon May 19 14:38:50 2014 +0200
Committer: Piotr Zalewa <pi...@zalewa.info>
Committed: Mon May 19 14:38:50 2014 +0200

----------------------------------------------------------------------
 autotest/tests/battery.tests.js      | 153 +++++++++++++++++++++++++++++-
 autotest/tests/file.tests.js         |  21 +++-
 createmobilespec/createmobilespec.js | 133 +++++++++++++++++---------
 3 files changed, 261 insertions(+), 46 deletions(-)
----------------------------------------------------------------------



[05/12] spec commit: Merge branch 'master' into ffos_privileged_compatible

Posted by za...@apache.org.
Merge branch 'master' into ffos_privileged_compatible


Project: http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/commit/53a34221
Tree: http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/tree/53a34221
Diff: http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/diff/53a34221

Branch: refs/heads/master
Commit: 53a34221c2c78ccfb742e8e793225bec195be0ff
Parents: a7c88d8 508f29f
Author: Piotr Zalewa <pi...@zalewa.info>
Authored: Wed May 14 15:42:17 2014 +0200
Committer: Piotr Zalewa <pi...@zalewa.info>
Committed: Wed May 14 15:42:17 2014 +0200

----------------------------------------------------------------------
 config.xml      | 8 +++++++-
 cordova-incl.js | 2 +-
 2 files changed, 8 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/53a34221/cordova-incl.js
----------------------------------------------------------------------


[07/12] Manual tests fixed

Posted by za...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/inappbrowser/index.html
----------------------------------------------------------------------
diff --git a/inappbrowser/index.html b/inappbrowser/index.html
index b0c1ad0..b06ed11 100644
--- a/inappbrowser/index.html
+++ b/inappbrowser/index.html
@@ -28,177 +28,9 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>      
-
-      
-    <script type="text/javascript" charset="utf-8">
-
-    var deviceReady = false;
-    
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-                deviceReady = true;
-                console.log("Device="+device.platform+" "+device.version);
-            }, false);
-        function updateUserAgent() {
-            document.getElementById("user-agent").textContent = navigator.userAgent;
-        }
-        updateUserAgent();
-        window.setInterval(updateUserAgent, 1500);
-        window.setTimeout(function() {
-        	if (!deviceReady) {
-        		alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
-        	}
-        },1000);
-    }
-
-    function doOpen(url, target, params, numExpectedRedirects) {
-        numExpectedRedirects = numExpectedRedirects || 0;
-        var iab = window.open(url, target, params);
-        if (!iab) {
-            alert('window.open returned ' + iab);
-            return;
-        }
-        var counts;
-        var lastLoadStartURL;
-        var wasReset = false;
-        function reset()  {
-            counts = {
-                'loaderror': 0,
-                'loadstart': 0,
-                'loadstop': 0,
-                'exit': 0
-            };
-            lastLoadStartURL = '';
-        }
-        reset();
-
-        function logEvent(e) {
-            console.log('IAB event=' + JSON.stringify(e));
-            counts[e.type]++;
-            // Verify that event.url gets updated on redirects.
-            if (e.type == 'loadstart') {
-                if (e.url == lastLoadStartURL) {
-                    alert('Unexpected: loadstart fired multiple times for the same URL.');
-                }
-                lastLoadStartURL = e.url;
-            }
-            // Verify the right number of loadstart events were fired.
-            if (e.type == 'loadstop' || e.type == 'loaderror') {
-                if (e.url != lastLoadStartURL) {
-                    alert('Unexpected: ' + e.type + ' event.url != loadstart\'s event.url');
-                }
-                if (numExpectedRedirects === 0 && counts['loadstart'] !== 1) {
-                    // Do allow a loaderror without a loadstart (e.g. in the case of an invalid URL).
-                    if (!(e.type == 'loaderror' && counts['loadstart'] === 0)) {
-                        alert('Unexpected: got multiple loadstart events. (' + counts['loadstart'] + ')');
-                    }
-                } else if (numExpectedRedirects > 0 && counts['loadstart'] < (numExpectedRedirects+1)) {
-                    alert('Unexpected: should have got at least ' + (numExpectedRedirects+1) + ' loadstart events, but got ' + counts['loadstart']);
-                }
-                wasReset = true;
-                numExpectedRedirects = 0;
-                reset();
-            }
-            // Verify that loadend / loaderror was called.
-            if (e.type == 'exit') {
-                var numStopEvents = counts['loadstop'] + counts['loaderror'];
-                if (numStopEvents === 0 && !wasReset) {
-                    alert('Unexpected: browser closed without a loadstop or loaderror.')
-                } else if (numStopEvents > 1) {
-                    alert('Unexpected: got multiple loadstop/loaderror events.');
-                }
-            }
-        }
-        iab.addEventListener('loaderror', logEvent);
-        iab.addEventListener('loadstart', logEvent);
-        iab.addEventListener('loadstop', logEvent);
-        iab.addEventListener('exit', logEvent);
-
-        return iab;
-    }
-
-    function openWithStyle(url, cssUrl, useCallback) {
-        var iab = doOpen(url, '_blank', 'location=yes');
-        var callback = function(results) {
-            if (results && results.length === 0) {
-                alert('Results verified');
-            } else {
-                console.log(results);
-                alert('Got: ' + typeof(results) + '\n' + JSON.stringify(results));
-            }
-        };
-        if (cssUrl) {
-            iab.addEventListener('loadstop', function(event) {
-                iab.insertCSS({file: cssUrl}, useCallback && callback);
-            });
-        } else {
-            iab.addEventListener('loadstop', function(event) {
-                iab.insertCSS({code:'#style-update-literal { \ndisplay: block !important; \n}'},
-                              useCallback && callback);
-            });
-        }
-    }
-
-    function openWithScript(url, jsUrl, useCallback) {
-        var iab = doOpen(url, '_blank', 'location=yes');
-        if (jsUrl) {
-            iab.addEventListener('loadstop', function(event) {
-                iab.executeScript({file: jsUrl}, useCallback && function(results) {
-                    if (results && results.length === 0) {
-                        alert('Results verified');
-                    } else {
-                        console.log(results);
-                        alert('Got: ' + typeof(results) + '\n' + JSON.stringify(results));
-                    }
-                });
-            });
-        } else {
-            iab.addEventListener('loadstop', function(event) {
-                var code = '(function(){\n' +
-                  '    var header = document.getElementById("header");\n' +
-                  '    header.innerHTML = "Script literal successfully injected";\n' +
-                  '    return "abc";\n' +
-                  '})()';
-                iab.executeScript({code:code}, useCallback && function(results) {
-                    if (results && results.length === 1 && results[0] === 'abc') {
-                        alert('Results verified');
-                    } else {
-                        console.log(results);
-                        alert('Got: ' + typeof(results) + '\n' + JSON.stringify(results));
-                    }
-                });
-            });
-        }
-    }
-    var hiddenwnd=null;
-    var loadlistener = function(event) { alert('background window loaded ' ); };
-    function openHidden(url, startHidden) {
-        var shopt =(startHidden) ? 'hidden=yes' : '';
-        hiddenwnd = window.open(url,'random_string',shopt);
-        if (!hiddenwnd) {
-            alert('window.open returned ' + hiddenwnd);
-            return;
-        }
-        if(startHidden) hiddenwnd.addEventListener('loadstop', loadlistener);
-    }
-    function showHidden() {
-        if(!!hiddenwnd ) {
-            hiddenwnd.show();
-        }
-    }
-    function closeHidden() {
-       if(!!hiddenwnd ) {
-           hiddenwnd.removeEventListener('loadstop',loadlistener);
-           hiddenwnd.close();
-           hiddenwnd=null;
-       }
-    }
-    </script>
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>InAppBrowser</h1>
     <div id="info">
@@ -206,199 +38,199 @@
         Make sure http://www.apple.com is not in the white list.</br>  In iOS, starred <span style="vertical-align:super">*</span> tests will put the app in a state with no way to return.  </br>
         <h4>User-Agent: <span id="user-agent"> </span></h4>
     </div>
-    <div class="btn small" onclick="backHome();">Back</div>
+    <div class="btn small backBtn">Back</div>
 
     <h1>Local URL</h1>
-    <div class="btn large" onclick="doOpen('local.html');">target = Default</div>
+    <div class="btn large openLocal">target = Default</div>
     Expected result: opens successfully in CordovaWebView.
 
     <p/>
-    <div class="btn large" onclick="doOpen('local.html', '_self');">target=_self</div>
+    <div class="btn large openLocalSelf">target=_self</div>
     Expected result: opens successfully in CordovaWebView.
 
     <p/>
-    <div class="btn large" onclick="doOpen('local.html', '_system');">target=_system</div>
+    <div class="btn large openLocalSystem">target=_system</div>
     Expected result: fails to open.
 
     <p/>
-    <div class="btn large" onclick="doOpen('local.html', '_blank');">target=_blank</div>
+    <div class="btn large openLocalBlank">target=_blank</div>
     Expected result: opens successfully in InAppBrowser with locationBar at top.
 
     <p/>
-    <div class="btn large" onclick="doOpen('local.html', 'random_string', 'location=no,disallowoverscroll=yes');">target=Random, location=no,disallowoverscroll=yes</div>
+    <div class="btn large openLocalRandomNoLocation">target=Random, location=no,disallowoverscroll=yes</div>
     Expected result: opens successfully in InAppBrowser without locationBar.
 
     <p/>
-    <div class="btn large" onclick="doOpen('local.html', 'random_string', 'toolbarposition=bottom');">target=Random, toolbarposition=bottom</div>
+    <div class="btn large openLocalRandomToolBarBottom">target=Random, toolbarposition=bottom</div>
     Expected result: opens successfully in InAppBrowser with locationBar. On iOS the toolbar is at the bottom.
 
     <p/>
-    <div class="btn large" onclick="doOpen('local.html', 'random_string', 'toolbarposition=top');">target=Random, toolbarposition=top</div>
+    <div class="btn large openLocalRandomToolBarTop">target=Random, toolbarposition=top</div>
     Expected result: opens successfully in InAppBrowser with locationBar. On iOS the toolbar is at the top.
 
     <p/>
-    <div class="btn large" onclick="doOpen('local.html', 'random_string', 'toolbarposition=top,location=no');">target=Random, toolbarposition=top,location=no</div>
+    <div class="btn large openLocalRandomToolBarTopNoLocation">target=Random, toolbarposition=top,location=no</div>
     Expected result: opens successfully in InAppBrowser with no locationBar. On iOS the toolbar is at the top.
 
     <h1>White Listed URL</h1>
 
-    <div class="btn large" onclick="doOpen('http://www.google.com');">target=Default<span style="vertical-align:super">*</span></div>
+    <div class="btn large openWhiteListed">target=Default<span style="vertical-align:super">*</span></div>
     Expected result: open successfully in CordovaWebView to www.google.com.
 
     <p/>
-    <div class="btn large" onclick="doOpen('http://www.google.com', '_self');">target=_self<span style="vertical-align:super">*</span></div>
+    <div class="btn large openWhiteListedSelf">target=_self<span style="vertical-align:super">*</span></div>
     Expected result: open successfully in CordovaWebView to www.google.com.
 
     <p/>
-    <div class="btn large" onclick="doOpen('http://www.google.com', '_system');">target=_system</div>
+    <div class="btn large openWhiteListedSystem">target=_system</div>
     Expected result: open successfully in system browser to www.google.com.
 
     <p/>
-    <div class="btn large" onclick="doOpen('http://www.google.com', '_blank');">target=_blank</div>
+    <div class="btn large openWhiteListedBlank">target=_blank</div>
     Expected result: open successfully in InAppBrowser to www.google.com.
 
     <p/>
-    <div class="btn large" onclick="doOpen('http://www.google.com', 'random_string');">target=Random</div>
+    <div class="btn large openWhiteListedRandom">target=Random</div>
     Expected result: open successfully in InAppBrowser to www.google.com.
 
     <p/>
-    <div class="btn large" onclick="doOpen('http://www.google.com', 'random_string', 'location=no');">target=Random, no location bar<span style="vertical-align:super">*</span></div>
+    <div class="btn large openWhiteListedRandomNoLocation">target=Random, no location bar<span style="vertical-align:super">*</span></div>
     Expected result: open successfully in InAppBrowser to www.google.com with no location bar.
 
     <h1>Non White Listed URL</h1>
 
-    <div class="btn large" onclick="doOpen('http://www.apple.com');">target=Default</div>
+    <div class="btn large openNonWhiteListed">target=Default</div>
     Expected result: open successfully in InAppBrowser to apple.com (_self enforces whitelist).
 
     <p/>
-    <div class="btn large" onclick="doOpen('http://www.apple.com', '_self');">target=_self</div>
+    <div class="btn larg openNonWhiteListedSelf">target=_self</div>
     Expected result: open successfully in InAppBrowser to apple.com (_self enforces whitelist).
 
     <p/>
-    <div class="btn large" onclick="doOpen('http://www.apple.com', '_system');">target=_system</div>
+    <div class="btn large openNonWhiteListedSystem">target=_system</div>
     Expected result: open successfully in system browser to apple.com.
 
     <p/>
-    <div class="btn large" onclick="doOpen('http://www.apple.com', '_blank');">target=_blank</div>
+    <div class="btn large openNonWhiteListedBlank">target=_blank</div>
     Expected result: open successfully in InAppBrowser to apple.com.
 
     <p/>
-    <div class="btn large" onclick="doOpen('http://www.apple.com', 'random_string');">target=Random</div>
+    <div class="btn large openNonWhiteListedRandom">target=Random</div>
     Expected result: open successfully in InAppBrowser to apple.com.
 
     <p/>
-    <div class="btn large" onclick="doOpen('http://www.apple.com', 'random_string', 'location=no');">target=Random, no location bar<span style="vertical-align:super">*</span></div>
+    <div class="btn large openNonWhiteListedRandomNoLocation">target=Random, no location bar<span style="vertical-align:super">*</span></div>
     Expected result: open successfully in InAppBrowser to apple.com without locationBar.
 
     <h1>Page with redirect</h1>
 
-    <div class="btn large" onclick="doOpen('http://google.com', 'random_string', '', 1);">http://google.com</div>
+    <div class="btn large openRedirect301">http://google.com</div>
     Expected result: should 301 and open successfully in InAppBrowser to www.google.com.
 
     <p/>
-    <div class="btn large" onclick="doOpen('http://goo.gl/pUFqg', 'random_string', '', 2);">http://goo.gl/pUFqg</div>
+    <div class="btn large openRedirect302">http://goo.gl/pUFqg</div>
     Expected result: should 302 and open successfully in InAppBrowser to www.zhihu.com/answer/16714076.
 
     <h1>PDF URL</h1>
 
-    <div class="btn large" onclick="doOpen('http://www.stluciadance.com/prospectus_file/sample.pdf');">Remote URL</div>
+    <div class="btn large openPDF">Remote URL</div>
     Expected result: InAppBrowser opens. PDF should render on iOS.
 
     <p/>
-    <div class="btn large" onclick="doOpen('local.pdf', '_blank');">Local URL</div>
+    <div class="btn large openPDFBlank">Local URL</div>
     Expected result: InAppBrowser opens. PDF should render on iOS.
 
     <h1>Invalid URL</h1>
 
-    <div class="btn large" onclick="doOpen('x-ttp://www.invalid.com/', '_blank');">Invalid Scheme</div>
+    <div class="btn large openInvalidScheme">Invalid Scheme</div>
     Expected result: fail to load in InAppBrowser.
 
     <p/>
-    <div class="btn large" onclick="doOpen('http://www.inv;alid.com/', '_blank');">Invalid Host</div>
+    <div class="btn large openInvalidHost">Invalid Host</div>
     Expected result: fail to load in InAppBrowser.
 
     <p/>
-    <div class="btn large" onclick="doOpen('nonexistent.html', '_blank');">Missing Local File</div>
+    <div class="btn large openInvalidMissing">Missing Local File</div>
     Expected result: fail to load in InAppBrowser (404).
 
     <h1>CSS / JS Injection</h1>
 
-    <div class="btn large" onclick="doOpen('inject.html', '_blank');">Original Document</div>
+    <div class="btn large openOriginalDocument">Original Document</div>
     Expected result: open successfully in InAppBrowser without text "Style updated from..."
 
     <p/> 
-    <div class="btn large" onclick="openWithStyle('inject.html','inject.css');">CSS File Injection</div>
+    <div class="btn large openCSSInjection">CSS File Injection</div>
     Expected result: open successfully in InAppBrowser with "Style updated from file".
 
     <p/>
-    <div class="btn large" onclick="openWithStyle('inject.html','inject.css', true);">CSS File Injection (callback)</div>
+    <div class="btn large openCSSInjectionCallback">CSS File Injection (callback)</div>
     Expected result: open successfully in InAppBrowser with "Style updated from file", and alert dialog with text "Results verified".
 
     <p/>
-    <div class="btn large" onclick="openWithStyle('inject.html');">CSS Literal Injection</div>
+    <div class="btn large openCSSLiteralInjection">CSS Literal Injection</div>
     Expected result: open successfully in InAppBrowser with "Style updated from literal".
 
     <p/>
-    <div class="btn large" onclick="openWithStyle('inject.html', null, true);">CSS Literal Injection (callback)</div>
+    <div class="btn large openCSSLiteralInjectionCallback">CSS Literal Injection (callback)</div>
     Expected result: open successfully in InAppBrowser with "Style updated from literal", and alert dialog with text "Results verified".
 
     <p/>
-    <div class="btn large" onclick="openWithScript('inject.html', 'inject.js');">Script File Injection</div>
+    <div class="btn large openScriptInjection">Script File Injection</div>
     Expected result: open successfully in InAppBrowser with text "Script file successfully injected".
 
     <p/>
-    <div class="btn large" onclick="openWithScript('inject.html', 'inject.js', true);">Script File Injection (callback)</div>
+    <div class="btn large openScriptInjectionCallback">Script File Injection (callback)</div>
     Expected result: open successfully in InAppBrowser with text "Script file successfully injected" and alert dialog with the text "Results verified".
 
     <p/>
-    <div class="btn large" onclick="openWithScript('inject.html');">Script Literal Injection</div>
+    <div class="btn large openScriptLiteralInjection">Script Literal Injection</div>
     Expected result: open successfully in InAppBrowser with the text "Script literal successfully injected" .
 
     <p/>
-    <div class="btn large" onclick="openWithScript('inject.html', null, true);">Script Literal Injection (callback)</div>
+    <div class="btn large openScriptLiteralInjectionCallback">Script Literal Injection (callback)</div>
     Expected result: open successfully in InAppBrowser with the text "Script literal successfully injected" and alert dialog with the text "Results verified".
 
     <h1>Open Hidden </h1>
-    <div class="btn large" onclick="openHidden('http://google.com',true);">create hidden</div>
+    <div class="btn large openHidden">create hidden</div>
     Expected result: no additional browser window. Alert appears with the text "background window loaded".
 
     <p/>
-    <div class="btn large" onclick="showHidden();">show hidden</div>
+    <div class="btn large showHidden">show hidden</div>
     Expected result: after first clicking on previous test "create hidden", open successfully in InAppBrowser to google.com.
 
     <p/>
-    <div class="btn large" onclick="closeHidden();">close hidden</div>
+    <div class="btn large closeHidden">close hidden</div>
     Expected result: no output. But click on "show hidden" again and nothing should be shown.
 
     <p/>
-    <div class="btn large" onclick="openHidden('http://google.com',false);">google.com not hidden</div>
+    <div class="btn large openHiddenShow">google.com not hidden</div>
     Expected result: open successfully in InAppBrowser to www.google.com
 
     <h1>Clearing Cache</h1>
 
-    <div class="btn large" onclick="doOpen('http://www.google.com', '_blank', 'clearcache=yes');">Clear Browser Cache</div>
+    <div class="btn large openClearCache">Clear Browser Cache</div>
     Expected result: ?
 
     <p/>
-    <div class="btn large" onclick="doOpen('http://www.google.com', '_blank', 'clearsessioncache=yes');">Clear Session Cache</div>
+    <div class="btn large openClearSessionCache">Clear Session Cache</div>
     Expected result: ?
 
     <h1>Video tag</h1>
 
-    <div class="btn large" onclick="doOpen('video.html', '_blank');">remote video</div>
+    <div class="btn large openRemoteVideo">remote video</div>
     Expected result: open successfully in InAppBrowser with an embedded video that works after clicking the "play" button.
 
     <h1>Local with anchor tag</h1>
 
-    <div class="btn large" onclick="doOpen('local.html#anchor1', '_blank');">Anchor1</div>
+    <div class="btn large openAnchor1">Anchor1</div>
     Expected result: open successfully in InAppBrowser to the local page, scrolled to the top.
 
     <p/>
-    <div class="btn large" onclick="doOpen('local.html#anchor2', '_blank');">Anchor2</div>
+    <div class="btn large openAnchor2">Anchor2</div>
     Expected result: open successfully in InAppBrowser to the local page, scrolled to the beginning of the tall div with border.
     
     <p/>
-    <div class="backBtn" onclick="backHome();">Back</div>
+    <div class="backBtn">Back</div>
 
   </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/inappbrowser/index.js
----------------------------------------------------------------------
diff --git a/inappbrowser/index.js b/inappbrowser/index.js
new file mode 100644
index 0000000..a08c30d
--- /dev/null
+++ b/inappbrowser/index.js
@@ -0,0 +1,242 @@
+var deviceReady = false;
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+            deviceReady = true;
+            console.log("Device="+device.platform+" "+device.version);
+        }, false);
+    function updateUserAgent() {
+        document.getElementById("user-agent").textContent = navigator.userAgent;
+    }
+    updateUserAgent();
+    window.setInterval(updateUserAgent, 1500);
+    window.setTimeout(function() {
+      if (!deviceReady) {
+        alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
+      }
+    },1000);
+}
+
+function doOpen(url, target, params, numExpectedRedirects) {
+    numExpectedRedirects = numExpectedRedirects || 0;
+    var iab = window.open(url, target, params);
+    if (!iab) {
+        alert('window.open returned ' + iab);
+        return;
+    }
+    var counts;
+    var lastLoadStartURL;
+    var wasReset = false;
+    function reset()  {
+        counts = {
+            'loaderror': 0,
+            'loadstart': 0,
+            'loadstop': 0,
+            'exit': 0
+        };
+        lastLoadStartURL = '';
+    }
+    reset();
+
+    function logEvent(e) {
+        console.log('IAB event=' + JSON.stringify(e));
+        counts[e.type]++;
+        // Verify that event.url gets updated on redirects.
+        if (e.type == 'loadstart') {
+            if (e.url == lastLoadStartURL) {
+                alert('Unexpected: loadstart fired multiple times for the same URL.');
+            }
+            lastLoadStartURL = e.url;
+        }
+        // Verify the right number of loadstart events were fired.
+        if (e.type == 'loadstop' || e.type == 'loaderror') {
+            if (e.url != lastLoadStartURL) {
+                alert('Unexpected: ' + e.type + ' event.url != loadstart\'s event.url');
+            }
+            if (numExpectedRedirects === 0 && counts['loadstart'] !== 1) {
+                // Do allow a loaderror without a loadstart (e.g. in the case of an invalid URL).
+                if (!(e.type == 'loaderror' && counts['loadstart'] === 0)) {
+                    alert('Unexpected: got multiple loadstart events. (' + counts['loadstart'] + ')');
+                }
+            } else if (numExpectedRedirects > 0 && counts['loadstart'] < (numExpectedRedirects+1)) {
+                alert('Unexpected: should have got at least ' + (numExpectedRedirects+1) + ' loadstart events, but got ' + counts['loadstart']);
+            }
+            wasReset = true;
+            numExpectedRedirects = 0;
+            reset();
+        }
+        // Verify that loadend / loaderror was called.
+        if (e.type == 'exit') {
+            var numStopEvents = counts['loadstop'] + counts['loaderror'];
+            if (numStopEvents === 0 && !wasReset) {
+                alert('Unexpected: browser closed without a loadstop or loaderror.')
+            } else if (numStopEvents > 1) {
+                alert('Unexpected: got multiple loadstop/loaderror events.');
+            }
+        }
+    }
+    iab.addEventListener('loaderror', logEvent);
+    iab.addEventListener('loadstart', logEvent);
+    iab.addEventListener('loadstop', logEvent);
+    iab.addEventListener('exit', logEvent);
+
+    return iab;
+}
+
+function openWithStyle(url, cssUrl, useCallback) {
+    var iab = doOpen(url, '_blank', 'location=yes');
+    var callback = function(results) {
+        if (results && results.length === 0) {
+            alert('Results verified');
+        } else {
+            console.log(results);
+            alert('Got: ' + typeof(results) + '\n' + JSON.stringify(results));
+        }
+    };
+    if (cssUrl) {
+        iab.addEventListener('loadstop', function(event) {
+            iab.insertCSS({file: cssUrl}, useCallback && callback);
+        });
+    } else {
+        iab.addEventListener('loadstop', function(event) {
+            iab.insertCSS({code:'#style-update-literal { \ndisplay: block !important; \n}'},
+                          useCallback && callback);
+        });
+    }
+}
+
+function openWithScript(url, jsUrl, useCallback) {
+    var iab = doOpen(url, '_blank', 'location=yes');
+    if (jsUrl) {
+        iab.addEventListener('loadstop', function(event) {
+            iab.executeScript({file: jsUrl}, useCallback && function(results) {
+                if (results && results.length === 0) {
+                    alert('Results verified');
+                } else {
+                    console.log(results);
+                    alert('Got: ' + typeof(results) + '\n' + JSON.stringify(results));
+                }
+            });
+        });
+    } else {
+        iab.addEventListener('loadstop', function(event) {
+            var code = '(function(){\n' +
+              '    var header = document.getElementById("header");\n' +
+              '    header.innerHTML = "Script literal successfully injected";\n' +
+              '    return "abc";\n' +
+              '})()';
+            iab.executeScript({code:code}, useCallback && function(results) {
+                if (results && results.length === 1 && results[0] === 'abc') {
+                    alert('Results verified');
+                } else {
+                    console.log(results);
+                    alert('Got: ' + typeof(results) + '\n' + JSON.stringify(results));
+                }
+            });
+        });
+    }
+}
+var hiddenwnd=null;
+var loadlistener = function(event) { alert('background window loaded ' ); };
+function openHidden(url, startHidden) {
+    var shopt =(startHidden) ? 'hidden=yes' : '';
+    hiddenwnd = window.open(url,'random_string',shopt);
+    if (!hiddenwnd) {
+        alert('window.open returned ' + hiddenwnd);
+        return;
+    }
+    if(startHidden) hiddenwnd.addEventListener('loadstop', loadlistener);
+}
+function showHidden() {
+    if(!!hiddenwnd ) {
+        hiddenwnd.show();
+    }
+}
+function closeHidden() {
+   if(!!hiddenwnd ) {
+       hiddenwnd.removeEventListener('loadstop',loadlistener);
+       hiddenwnd.close();
+       hiddenwnd=null;
+   }
+}
+
+window.onload = function() {
+  addListenerToClass('openLocal', doOpen, 'local.html');
+  addListenerToClass('openLocalSelf', doOpen, ['local.html', '_self']);
+  addListenerToClass('openLocalSystem', doOpen, ['local.html', '_system']);
+  addListenerToClass('openLocalBlank', doOpen, ['local.html', '_blank']);
+  addListenerToClass('openLocalRandomNoLocation', doOpen, 
+      ['local.html', 'random_string', 'location=no,disallowoverscroll=yes']);
+  addListenerToClass('openLocalRandomToolBarBottom', doOpen,
+      ['local.html', 'random_string', 'toolbarposition=bottom']);
+  addListenerToClass('openLocalRandomToolBarTop', doOpen, 
+      ['local.html', 'random_string', 'toolbarposition=top']);
+  addListenerToClass('openLocalRandomToolBarTopNoLocation', doOpen, 
+      ['local.html', 'random_string', 'toolbarposition=top,location=no']);
+  addListenerToClass('openWhiteListed', doOpen, 'http://www.google.com');
+  addListenerToClass('openWhiteListedSelf', doOpen, 
+      ['http://www.google.com', '_self']);
+  addListenerToClass('openWhiteListedSystem', doOpen,
+      ['http://www.google.com', '_system']);
+  addListenerToClass('openWhiteListedBlank', doOpen, 
+      ['http://www.google.com', '_blank']);
+  addListenerToClass('openWhiteListedRandom', doOpen,
+      ['http://www.google.com', 'random_string']);
+  addListenerToClass('openWhiteListedRandomNoLocation', doOpen,
+      ['http://www.google.com', 'random_string', 'location=no']);
+  addListenerToClass('openNonWhiteListed', doOpen, 'http://www.apple.com');
+  addListenerToClass('openNonWhiteListedSelf', doOpen, 
+      ['http://www.apple.com', '_self']);
+  addListenerToClass('openNonWhiteListedSystem', doOpen, 
+      ['http://www.apple.com', '_system']);
+  addListenerToClass('openNonWhiteListedBlank', doOpen, 
+      ['http://www.apple.com', '_blank']);
+  addListenerToClass('openNonWhiteListedRandom', doOpen,
+      ['http://www.apple.com', 'random_string']);
+  addListenerToClass('openNonWhiteListedRandomNoLocation', doOpen, 
+      ['http://www.apple.com', 'random_string', 'location=no']);
+  addListenerToClass('openRedirect301', doOpen, 
+      ['http://google.com', 'random_string', '', 1]);
+  addListenerToClass('openRedirect302', doOpen, 
+      ['http://goo.gl/pUFqg', 'random_string', '', 2]);
+  addListenerToClass('openPDF', doOpen, 'http://www.stluciadance.com/prospectus_file/sample.pdf');
+  addListenerToClass('openPDFBlank', doOpen, ['local.pdf', '_blank']);
+  addListenerToClass('openInvalidScheme', doOpen, 
+      ['x-ttp://www.invalid.com/', '_blank']);
+  addListenerToClass('openInvalidHost', doOpen, 
+      ['http://www.inv;alid.com/', '_blank']);
+  addListenerToClass('openInvalidMissing', doOpen, ['nonexistent.html', '_blank']);
+  addListenerToClass('openOriginalDocument', doOpen, ['inject.html', '_blank']);
+  addListenerToClass('openCSSInjection', openWithStyle, 
+      ['inject.html','inject.css']);
+  addListenerToClass('openCSSInjectionCallback', openWithStyle, 
+      ['inject.html','inject.css', true]);
+  addListenerToClass('openCSSLiteralInjection', openWithStyle, 'inject.html');
+  addListenerToClass('openCSSLiteralInjectionCallback', openWithStyle, 
+    ['inject.html', null, true]);
+  addListenerToClass('openScriptInjection', openWithScript, 
+    ['inject.html', 'inject.js']);
+  addListenerToClass('openScriptInjectionCallback', openWithScript, 
+    ['inject.html', 'inject.js', true]);
+  addListenerToClass('openScriptLiteralInjection', openWithScript, 'inject.html');
+  addListenerToClass('openScriptLiteralInjectionCallback', openWithScript, 
+    ['inject.html', null, true]);
+  addListenerToClass('openHidden', openHidden, ['http://google.com', true]);
+  addListenerToClass('showHidden', showHidden);
+  addListenerToClass('closeHidden', closeHidden);
+  addListenerToClass('openHiddenShow', openHidden, ['http://google.com', false]);
+  addListenerToClass('openClearCache', doOpen, 
+    ['http://www.google.com', '_blank', 'clearcache=yes']);
+  addListenerToClass('openClearSessionCache', doOpen, 
+    ['http://www.google.com', '_blank', 'clearsessioncache=yes']);
+  addListenerToClass('openRemoteVideo', doOpen, ['video.html', '_blank']);
+  addListenerToClass('openAnchor1', doOpen, ['local.html#anchor1', '_blank']);
+  addListenerToClass('openAnchor2', doOpen, ['local.html#anchor2', '_blank']);
+
+
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/index.html
----------------------------------------------------------------------
diff --git a/index.html b/index.html
index 314d847..86b1173 100644
--- a/index.html
+++ b/index.html
@@ -31,7 +31,7 @@
 	  <script type="text/javascript" charset="utf-8" src="main.js"></script>
 
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
     <h1>Apache Cordova Tests</h1>
     <div id="info">
         <h4>cordova.version: <span id="cordova"> </span></h4>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/keyboard/index.html
----------------------------------------------------------------------
diff --git a/keyboard/index.html b/keyboard/index.html
index 23b47a3..9a66add 100644
--- a/keyboard/index.html
+++ b/keyboard/index.html
@@ -64,53 +64,11 @@
     }
 
     </style>
-    <script>
-        window.onerror = function(err,fn,ln) {alert("ERROR:" + err + ", " + fn + ":" + ln);};
-    </script>
+    <script type="text/javascript" charset="utf-8" src="./window-onerror.js"></script>      
     <script type="text/javascript" charset="utf-8" src="../cordova-incl.js"></script>      
-    
-    <script type="text/javascript" charset="utf-8">
-
-    var deviceReady = false;
-    var keyboardPlugin = null;
-    
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-                deviceReady = true;
-                keyboardPlugin = window.Keyboard; // for now, before plugin re-factor
-                                  
-                if (keyboardPlugin == null) {
-                    var msg = 'The plugin org.apache.cordova.keyboard was not found. Check that you have it installed.';
-                    alert(msg);
-                }
-
-            }, false);
-        window.setTimeout(function() {
-        	if (!deviceReady) {
-                var msg = 'Error: Apache Cordova did not initialize.  Demo will not run correctly.';
-                alert(msg);
-        	}
-        },1000);
-    }
-    
-    function setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(shrinkView, hideFormAccessoryBar, disableScrollingInShrinkView)
-    {
-        keyboardPlugin.shrinkView(shrinkView);
-        document.getElementById("shrinkView-arg").innerHTML = shrinkView;
-        
-        keyboardPlugin.hideFormAccessoryBar(hideFormAccessoryBar);
-        document.getElementById("hideFormAccessoryBar-arg").innerHTML = hideFormAccessoryBar;
-
-        keyboardPlugin.disableScrollingInShrinkView(disableScrollingInShrinkView);
-        document.getElementById("disableScrollingInShrinkView-arg").innerHTML = disableScrollingInShrinkView;
-    }
-
-    </script>
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>Keyboard (iOS)</h1>
 
@@ -121,7 +79,7 @@
 
     <h1>isVisible</h1>
     <br />
-    <div class="btn large" onclick="alert('Keyboard.isVisible: ' + Keyboard.isVisible);">Keyboard.isVisible</div>
+    <div class="btn large keyboardIsVisible">Keyboard.isVisible</div>
     
     <h1>API Tests</h1>
     <br />
@@ -143,7 +101,7 @@
         </tr>
         <tr>
             <td class="highlight-w">
-                <div class="btn small" onclick="setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(false, false, false)">1</div>
+                <div class="btn small set_1">1</div>
             </td>
             <td>&#x2717;</td>
             <td>&#x2717;</td>
@@ -151,7 +109,7 @@
         </tr>
         <tr>
             <td class="highlight-w">
-                <div class="btn small" onclick="setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(false, false, true)">2</div>
+                <div class="btn small set_2">2</div>
             </td>
             <td>&#x2717;</td>
             <td>&#x2717;</td>
@@ -159,7 +117,7 @@
         </tr>
         <tr>
             <td class="highlight-w">
-                <div class="btn small" onclick="setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(false, true, true)">3</div>
+                <div class="btn small set_3">3</div>
             </td>
             <td>&#x2717;</td>
             <td class="highlight-w">&#10004;</td>
@@ -167,7 +125,7 @@
         </tr>
         <tr>
             <td class="highlight-w">
-                <div class="btn small" onclick="setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(false, true, false)">4</div>
+                <div class="btn small set_4">4</div>
             </td>
             <td>&#x2717;</td>
             <td class="highlight-w">&#10004;</td>
@@ -175,7 +133,7 @@
         </tr>
         <tr>
             <td class="highlight-w">
-                <div class="btn small" onclick="setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(true, false, false)">5</div>
+                <div class="btn small set_5">5</div>
             </td>
             <td class="highlight-w">&#10004;</td>
             <td>&#x2717;</td>
@@ -183,7 +141,7 @@
         </tr>
         <tr>
             <td class="highlight-w">
-                <div class="btn small" onclick="setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(true, false, true)">6</div>
+                <div class="btn small set_6">6</div>
             </td>
             <td class="highlight-w">&#10004;</td>
             <td>&#x2717;</td>
@@ -191,7 +149,7 @@
         </tr>
         <tr>
             <td class="highlight-w">
-                <div class="btn small" onclick="setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(true, true, true)">7</div>
+                <div class="btn small set_7">7</div>
             </td>
             <td class="highlight-w">&#10004;</td>
             <td class="highlight-w">&#10004;</td>
@@ -199,7 +157,7 @@
         </tr>
         <tr>
             <td class="highlight-w">
-                <div class="btn small" onclick="setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(true, true, false)">8</div>
+                <div class="btn small set_8">8</div>
             </td>
             <td class="highlight-w">&#10004;</td>
             <td class="highlight-w">&#10004;</td>
@@ -211,7 +169,7 @@
         <input type="text" placeholder="touch to see keyboard" /><button class="btn-dismiss">dismiss</button>
     </div>
     <br />
-    <div class="backBtn" onclick="backHome();">Back</div>
+    <div class="backBtn">Back</div>
     
   </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/keyboard/index.js
----------------------------------------------------------------------
diff --git a/keyboard/index.js b/keyboard/index.js
new file mode 100644
index 0000000..2302f31
--- /dev/null
+++ b/keyboard/index.js
@@ -0,0 +1,69 @@
+
+var deviceReady = false;
+var keyboardPlugin = null;
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+            deviceReady = true;
+            keyboardPlugin = window.Keyboard; // for now, before plugin re-factor
+                              
+            if (keyboardPlugin == null) {
+                var msg = 'The plugin org.apache.cordova.keyboard was not found. Check that you have it installed.';
+                alert(msg);
+            }
+
+        }, false);
+    window.setTimeout(function() {
+      if (!deviceReady) {
+            var msg = 'Error: Apache Cordova did not initialize.  Demo will not run correctly.';
+            alert(msg);
+      }
+    },1000);
+}
+
+function setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(shrinkView, hideFormAccessoryBar, disableScrollingInShrinkView)
+{
+    keyboardPlugin.shrinkView(shrinkView);
+    document.getElementById("shrinkView-arg").innerHTML = shrinkView;
+    
+    keyboardPlugin.hideFormAccessoryBar(hideFormAccessoryBar);
+    document.getElementById("hideFormAccessoryBar-arg").innerHTML = hideFormAccessoryBar;
+
+    keyboardPlugin.disableScrollingInShrinkView(disableScrollingInShrinkView);
+    document.getElementById("disableScrollingInShrinkView-arg").innerHTML = disableScrollingInShrinkView;
+}
+
+window.onload = function() {
+  addListenerToClass('keyboardIsVisible', function() {
+    alert('Keyboard.isVisible: ' + Keyboard.isVisible);
+  });
+  addListenerToClass('set_1', function() {
+    setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(false, false, false)
+  });
+  addListenerToClass('set_2', function() {
+    setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(false, false, true)
+  });
+  addListenerToClass('set_3', function() {
+    setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(false, true, true)
+  });
+  addListenerToClass('set_4', function() {
+    setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(false, true, false)
+  });
+  addListenerToClass('set_5', function() {
+    setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(true, false, false)
+  });
+  addListenerToClass('set_6', function() {
+    setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(true, false, true)
+  });
+  addListenerToClass('set_7', function() {
+    setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(true, true, true)
+  });
+  addListenerToClass('set_8', function() {
+    setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(true, true, false)
+  });
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/keyboard/window-onerror.js
----------------------------------------------------------------------
diff --git a/keyboard/window-onerror.js b/keyboard/window-onerror.js
new file mode 100644
index 0000000..f833882
--- /dev/null
+++ b/keyboard/window-onerror.js
@@ -0,0 +1 @@
+window.onerror = function(err,fn,ln) {alert("ERROR:" + err + ", " + fn + ":" + ln);};

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/lazyloadjs/do-not-write-cordova-script.js
----------------------------------------------------------------------
diff --git a/lazyloadjs/do-not-write-cordova-script.js b/lazyloadjs/do-not-write-cordova-script.js
new file mode 100644
index 0000000..0f20c76
--- /dev/null
+++ b/lazyloadjs/do-not-write-cordova-script.js
@@ -0,0 +1 @@
+_doNotWriteCordovaScript = true;

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/lazyloadjs/index.html
----------------------------------------------------------------------
diff --git a/lazyloadjs/index.html b/lazyloadjs/index.html
index 7a0c06f..5816349 100644
--- a/lazyloadjs/index.html
+++ b/lazyloadjs/index.html
@@ -27,27 +27,15 @@
     <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <!-- ISO-8859-1 -->
     <title>Lazy-Loading of cordova-incl.js test</title>
     <link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title" charset="utf-8"/>
-    <script>_doNotWriteCordovaScript = true</script>
+    <script type="text/javascript" charset="utf-8" src="./do-not-write-cordova-script.js"></script>      
     <script type="text/javascript" charset="utf-8" src="../cordova-incl.js"></script>
-<script type="text/javascript" charset="utf-8">
-    function init() {
-        document.addEventListener("deviceready", function() {
-            console.log("Device="+device.platform+" "+device.version);
-            document.getElementById('info').innerHTML = 'Cordova loaded just fine.';
-        }, false);
-        window.setTimeout(function() {
-            var s = document.createElement('script');
-            s.src = cordovaPath;
-            document.body.appendChild(s);
-        }, 0);
-    }
-</script>
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
     <h1>Lazy-Loading of cordova-incl.js</h1>
     <div id="info">
       onDeviceReady has not yet fired.
     </div>
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/lazyloadjs/index.js
----------------------------------------------------------------------
diff --git a/lazyloadjs/index.js b/lazyloadjs/index.js
new file mode 100644
index 0000000..6559319
--- /dev/null
+++ b/lazyloadjs/index.js
@@ -0,0 +1,16 @@
+function init() {
+    document.addEventListener("deviceready", function() {
+        console.log("Device="+device.platform+" "+device.version);
+        document.getElementById('info').innerHTML = 'Cordova loaded just fine.';
+    }, false);
+    window.setTimeout(function() {
+        var s = document.createElement('script');
+        s.src = cordovaPath;
+        document.body.appendChild(s);
+    }, 0);
+}
+
+window.onload = function() {
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/location/index.html
----------------------------------------------------------------------
diff --git a/location/index.html b/location/index.html
index 542f264..f0cc7de 100644
--- a/location/index.html
+++ b/location/index.html
@@ -28,130 +28,9 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>      
-
-      
-<script type="text/javascript" charset="utf-8">
-
-    var origGeolocation = null;
-    var newGeolocation = null;
-
-    //-------------------------------------------------------------------------
-    // Location
-    //-------------------------------------------------------------------------
-    var watchLocationId = null;
-
-    /**
-     * Start watching location
-     */
-    var watchLocation = function(usePlugin) {
-        var geo = usePlugin ? newGeolocation : origGeolocation;
-        if (!geo) {
-            alert('geolocation object is missing. usePlugin = ' + usePlugin);
-            return;
-        }
-
-        // Success callback
-        var success = function(p){
-              console.log('watch location success');
-              setLocationDetails(p);
-        };
-
-        // Fail callback
-        var fail = function(e){
-            console.log("watchLocation fail callback with error code "+e);
-            stopLocation(geo);
-        };
-
-        // Get location
-        watchLocationId = geo.watchPosition(success, fail, {enableHighAccuracy: true});
-        setLocationStatus("Running");
-    };
-
-    /**
-     * Stop watching the location
-     */
-    var stopLocation = function(usePlugin) {
-        var geo = usePlugin ? newGeolocation : origGeolocation;
-        if (!geo) {
-            alert('geolocation object is missing. usePlugin = ' + usePlugin);
-            return;
-        }
-        setLocationStatus("Stopped");
-        if (watchLocationId) {
-            geo.clearWatch(watchLocationId);
-            watchLocationId = null;
-        }
-    };
-
-    /**
-     * Get current location
-     */
-    var getLocation = function(usePlugin, opts) {
-        var geo = usePlugin ? newGeolocation : origGeolocation;
-        if (!geo) {
-            alert('geolocation object is missing. usePlugin = ' + usePlugin);
-            return;
-        }
-
-        // Stop location if running
-        stopLocation(geo);
-
-        // Success callback
-        var success = function(p){
-            console.log('get location success');
-            setLocationDetails(p);
-            setLocationStatus("Done");
-        };
-
-        // Fail callback
-        var fail = function(e){
-            console.log("getLocation fail callback with error code "+e.code);
-            setLocationStatus("Error: "+e.code);
-        };
-
-        setLocationStatus("Retrieving location...");
-
-        // Get location
-        geo.getCurrentPosition(success, fail, opts || {enableHighAccuracy: true}); //, {timeout: 10000});
-
-    };
-
-    /**
-     * Set location status
-     */
-    var setLocationStatus = function(status) {
-        document.getElementById('location_status').innerHTML = status;
-    };
-var setLocationDetails = function(p) {
-var date = (new Date(p.timestamp));
-            document.getElementById('latitude').innerHTML = p.coords.latitude;
-            document.getElementById('longitude').innerHTML = p.coords.longitude;
-            document.getElementById('altitude').innerHTML = p.coords.altitude;
-            document.getElementById('accuracy').innerHTML = p.coords.accuracy;
-            document.getElementById('heading').innerHTML = p.coords.heading;
-            document.getElementById('speed').innerHTML = p.coords.speed;
-            document.getElementById('altitude_accuracy').innerHTML = p.coords.altitudeAccuracy;
-            document.getElementById('timestamp').innerHTML =  date.toDateString() + " " + date.toTimeString();
-    }
-    
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-            newGeolocation = navigator.geolocation;
-            origGeolocation = cordova.require('cordova/modulemapper').getOriginalSymbol(window, 'navigator.geolocation');
-            if (!origGeolocation) {
-                origGeolocation = newGeolocation;
-                newGeolocation = null;
-            }
-        }, false);
-    }
-
-</script>
-
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>Location</h1>
     <div id="info">
@@ -205,15 +84,15 @@ var date = (new Date(p.timestamp));
     </div>
     <h2>Action</h2>
     <h3>Use Built-in WebView navigator.geolocation</h3>
-    <a href="javascript:" class="btn large" onclick="getLocation(false);">Get Location</a>
-    <a href="javascript:" class="btn large" onclick="watchLocation(false);">Start Watching Location</a>
-    <a href="javascript:" class="btn large" onclick="stopLocation(false);">Stop Watching Location</a>
-    <a href="javascript:" class="btn large" onclick="getLocation(false, {maximumAge:30000});">Get Location Up to 30 Seconds Old</a>
+    <a href="javascript:" class="btn large getWebViewLocation">Get Location</a>
+    <a href="javascript:" class="btn large watchWebViewLocation">Start Watching Location</a>
+    <a href="javascript:" class="btn large stopWebViewLocation">Stop Watching Location</a>
+    <a href="javascript:" class="btn large getWebViewLocation30">Get Location Up to 30 Seconds Old</a>
     <h3>Use Cordova Geolocation Plugin</h3>
-    <a href="javascript:" class="btn large" onclick="getLocation(true);">Get Location</a>
-    <a href="javascript:" class="btn large" onclick="watchLocation(true);">Start Watching Location</a>
-    <a href="javascript:" class="btn large" onclick="stopLocation(true);">Stop Watching Location</a>
-    <a href="javascript:" class="btn large" onclick="getLocation(true, {maximumAge:30000});">Get Location Up to 30 Seconds Old</a>
-    <h2>&nbsp;</h2><a href="javascript:" class="backBtn" onclick="backHome();">Back</a>    
+    <a href="javascript:" class="btn large getLocation">Get Location</a>
+    <a href="javascript:" class="btn large watchLocation">Start Watching Location</a>
+    <a href="javascript:" class="btn large stopLocation">Stop Watching Location</a>
+    <a href="javascript:" class="btn large getLocation30">Get Location Up to 30 Seconds Old</a>
+    <h2>&nbsp;</h2><a href="javascript:" class="backBtn"">Back</a>    
   </body>
 </html>      

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/location/index.js
----------------------------------------------------------------------
diff --git a/location/index.js b/location/index.js
new file mode 100644
index 0000000..242919d
--- /dev/null
+++ b/location/index.js
@@ -0,0 +1,128 @@
+var origGeolocation = null;
+var newGeolocation = null;
+
+//-------------------------------------------------------------------------
+// Location
+//-------------------------------------------------------------------------
+var watchLocationId = null;
+
+/**
+ * Start watching location
+ */
+var watchLocation = function(usePlugin) {
+    var geo = usePlugin ? newGeolocation : origGeolocation;
+    if (!geo) {
+        alert('geolocation object is missing. usePlugin = ' + usePlugin);
+        return;
+    }
+
+    // Success callback
+    var success = function(p){
+          console.log('watch location success');
+          setLocationDetails(p);
+    };
+
+    // Fail callback
+    var fail = function(e){
+        console.log("watchLocation fail callback with error code "+e);
+        stopLocation(geo);
+    };
+
+    // Get location
+    watchLocationId = geo.watchPosition(success, fail, {enableHighAccuracy: true});
+    setLocationStatus("Running");
+};
+
+/**
+ * Stop watching the location
+ */
+var stopLocation = function(usePlugin) {
+    var geo = usePlugin ? newGeolocation : origGeolocation;
+    if (!geo) {
+        alert('geolocation object is missing. usePlugin = ' + usePlugin);
+        return;
+    }
+    setLocationStatus("Stopped");
+    if (watchLocationId) {
+        geo.clearWatch(watchLocationId);
+        watchLocationId = null;
+    }
+};
+
+/**
+ * Get current location
+ */
+var getLocation = function(usePlugin, opts) {
+    var geo = usePlugin ? newGeolocation : origGeolocation;
+    if (!geo) {
+        alert('geolocation object is missing. usePlugin = ' + usePlugin);
+        return;
+    }
+
+    // Stop location if running
+    stopLocation(geo);
+
+    // Success callback
+    var success = function(p){
+        console.log('get location success');
+        setLocationDetails(p);
+        setLocationStatus("Done");
+    };
+
+    // Fail callback
+    var fail = function(e){
+        console.log("getLocation fail callback with error code "+e.code);
+        setLocationStatus("Error: "+e.code);
+    };
+
+    setLocationStatus("Retrieving location...");
+
+    // Get location
+    geo.getCurrentPosition(success, fail, opts || {enableHighAccuracy: true}); //, {timeout: 10000});
+
+};
+
+/**
+ * Set location status
+ */
+var setLocationStatus = function(status) {
+    document.getElementById('location_status').innerHTML = status;
+};
+var setLocationDetails = function(p) {
+var date = (new Date(p.timestamp));
+        document.getElementById('latitude').innerHTML = p.coords.latitude;
+        document.getElementById('longitude').innerHTML = p.coords.longitude;
+        document.getElementById('altitude').innerHTML = p.coords.altitude;
+        document.getElementById('accuracy').innerHTML = p.coords.accuracy;
+        document.getElementById('heading').innerHTML = p.coords.heading;
+        document.getElementById('speed').innerHTML = p.coords.speed;
+        document.getElementById('altitude_accuracy').innerHTML = p.coords.altitudeAccuracy;
+        document.getElementById('timestamp').innerHTML =  date.toDateString() + " " + date.toTimeString();
+}
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+        newGeolocation = navigator.geolocation;
+        origGeolocation = cordova.require('cordova/modulemapper').getOriginalSymbol(window, 'navigator.geolocation');
+        if (!origGeolocation) {
+            origGeolocation = newGeolocation;
+            newGeolocation = null;
+        }
+    }, false);
+}
+
+window.onload = function() {
+  addListenerToClass('getWebViewLocation', getLocation, [false]);
+  addListenerToClass('watchWebViewLocation', watchLocation, [false]);
+  addListenerToClass('stopWebViewLocation', stopLocation, [false]);
+  addListenerToClass('getWebViewLocation30', getLocation, [false, {maximumAge:30000}]);
+  addListenerToClass('getLocation', getLocation, [true]);
+  addListenerToClass('watchLocation', watchLocation, [true]);
+  addListenerToClass('stopLocation', stopLocation, [true]);
+  addListenerToClass('getLocation30', getLocation, [true, {maximumAge:30000}]);
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/main.js
----------------------------------------------------------------------
diff --git a/main.js b/main.js
index 9508770..42e9edd 100644
--- a/main.js
+++ b/main.js
@@ -161,3 +161,5 @@ function init() {
     document.addEventListener("deviceready", deviceInfo, true);
     document.getElementById("user-agent").textContent = navigator.userAgent;
 }
+
+window.onload = init;

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/misc/index.html
----------------------------------------------------------------------
diff --git a/misc/index.html b/misc/index.html
index 2245ed9..0ebb217 100644
--- a/misc/index.html
+++ b/misc/index.html
@@ -28,43 +28,16 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>      
-
-      
-<script type="text/javascript" charset="utf-8">
-
-    var deviceReady = false;
-
-    function roundNumber(num) {
-        var dec = 3;
-        var result = Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
-        return result;
-    }
-    
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-                deviceReady = true;
-                console.log("Device="+device.platform+" "+device.version);
-            }, false);
-        window.setTimeout(function() {
-        	if (!deviceReady) {
-        		alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
-        	}
-        },1000);
-    }
-
-</script>
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
 
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>Display Other Content</h1>
     <div id="info">
     </div>
     <h2>Action</h2>
-    <div class="btn large" onclick="document.location='tel:5551212';" >Call 411</div>
+    <div class="btn large telLocation">Call 411</div>
     <a href="mailto:bob@abc.org?subject=My Subject&body=This is the body.%0D%0ANew line." class="btn large">Send Mail</a>
     <a href="sms:5125551234?body=The SMS message." class="btn large">Send SMS</a>
     <a href="http://www.google.com" class="btn large">Load Web Site</a>
@@ -82,6 +55,6 @@
     <a href="market://search?q=google" class="btn large">Search Android market</a>
     <a href="content://media/external/images/media" class="btn large">View image app</a>
 
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>      

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/misc/index.js
----------------------------------------------------------------------
diff --git a/misc/index.js b/misc/index.js
new file mode 100644
index 0000000..e38ade7
--- /dev/null
+++ b/misc/index.js
@@ -0,0 +1,30 @@
+var deviceReady = false;
+
+function roundNumber(num) {
+    var dec = 3;
+    var result = Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
+    return result;
+}
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+            deviceReady = true;
+            console.log("Device="+device.platform+" "+device.version);
+        }, false);
+    window.setTimeout(function() {
+      if (!deviceReady) {
+        alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
+      }
+    },1000);
+}
+
+window.onload = function() {
+  addListenerToClass('telLocation', function() {
+    document.location='tel:5551212';
+  });
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/misc/page2.html
----------------------------------------------------------------------
diff --git a/misc/page2.html b/misc/page2.html
index 6b4eba1..1d370a9 100644
--- a/misc/page2.html
+++ b/misc/page2.html
@@ -29,6 +29,7 @@
     <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="../cordova-incl.js"></script>
     <script type="text/javascript" charset="utf-8" src="../main.js"></script>
+    <script type="text/javascript" charset="utf-8" src="./page2.js"></script>      
     <style>
       iframe, .iframe_container {
         height:100px;
@@ -36,7 +37,7 @@
       }
     </style>
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
     <h1>Page2 App</h1>
     <h2>This is page 2 of a Apache Cordova app</h2>
     <div id="info">
@@ -58,15 +59,6 @@
      <div class="iframe_container">
        <iframe src="" id="apacheiframe"></iframe>
      </div>
-     <div><button class="backBtn" onclick="backHome();">Back</button></div>
+     <div><button class="backBtn">Back</button></div>
   </body>
-  <script>
-    setTimeout(function() {
-        console.log('loading iframe after timeout.');
-        document.querySelector('#apacheiframe').src = 'http://apache.org';
-    }, 2000);
-    document.addEventListener("deviceready", function() {
-        document.getElementById('info').textContent += '\nDevice is ready.';
-    }, false);
-  </script>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/misc/page2.js
----------------------------------------------------------------------
diff --git a/misc/page2.js b/misc/page2.js
new file mode 100644
index 0000000..1f489c2
--- /dev/null
+++ b/misc/page2.js
@@ -0,0 +1,12 @@
+setTimeout(function() {
+    console.log('loading iframe after timeout.');
+    document.querySelector('#apacheiframe').src = 'http://apache.org';
+}, 2000);
+document.addEventListener("deviceready", function() {
+    document.getElementById('info').textContent += '\nDevice is ready.';
+}, false);
+
+window.onload = function() {
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/misc/page3.html
----------------------------------------------------------------------
diff --git a/misc/page3.html b/misc/page3.html
index da90d39..6677677 100644
--- a/misc/page3.html
+++ b/misc/page3.html
@@ -27,35 +27,7 @@
     <meta http-equiv="Content-type" content="text/html; charset=utf-8">
     <title>Cordova Mobile Spec</title>
     <link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title" charset="utf-8">
-    <script>
-      console.log('Changing hash #1.');
-      if (location.search.indexOf('hash1') != -1) {
-        location.hash = 'a';
-      } else if (location.search.indexOf('hash2') != -1) {
-        location.replace('#replaced');
-      }
-      var hashCount = 0;
-      function changeHash() {
-        hashCount += 1;
-        if (hashCount % 1) {
-          location.hash = hashCount;
-        } else {
-          location.replace('#' + hashCount);
-        }
-      }
-      if (location.search.indexOf('changeURL') != -1) {
-        history.replaceState(null, null, 'fakepage.html');
-      }
-      function loadFrame() {
-        var ifr = document.createElement('iframe');
-        ifr.src="data:text/html;base64,PGh0bWw+";
-        document.body.appendChild(ifr);
-      }
-      function reload() {
-        // Test that iOS CDVWebViewDelegate doesn't ignore changes when URL doesn't change.
-        location.reload();
-      }
-    </script>
+    <script type="text/javascript" charset="utf-8" src="./page3A.js"></script>      
     <script type="text/javascript" charset="utf-8" src="../cordova-incl.js"></script>
     <script type="text/javascript" charset="utf-8" src="../main.js"></script>
   </head>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/misc/page3A.js
----------------------------------------------------------------------
diff --git a/misc/page3A.js b/misc/page3A.js
new file mode 100644
index 0000000..8efad58
--- /dev/null
+++ b/misc/page3A.js
@@ -0,0 +1,27 @@
+console.log('Changing hash #1.');
+if (location.search.indexOf('hash1') != -1) {
+  location.hash = 'a';
+} else if (location.search.indexOf('hash2') != -1) {
+  location.replace('#replaced');
+}
+var hashCount = 0;
+function changeHash() {
+  hashCount += 1;
+  if (hashCount % 1) {
+    location.hash = hashCount;
+  } else {
+    location.replace('#' + hashCount);
+  }
+}
+if (location.search.indexOf('changeURL') != -1) {
+  history.replaceState(null, null, 'fakepage.html');
+}
+function loadFrame() {
+  var ifr = document.createElement('iframe');
+  ifr.src="data:text/html;base64,PGh0bWw+";
+  document.body.appendChild(ifr);
+}
+function reload() {
+  // Test that iOS CDVWebViewDelegate doesn't ignore changes when URL doesn't change.
+  location.reload();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/network/index.html
----------------------------------------------------------------------
diff --git a/network/index.html b/network/index.html
index 2902849..b750f6c 100644
--- a/network/index.html
+++ b/network/index.html
@@ -28,48 +28,11 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>
-
-      
-<script type="text/javascript" charset="utf-8">
-
-
-    function eventOutput(s) {
-        var el = document.getElementById("results");
-        el.innerHTML = el.innerHTML + s + "<br>";
-    }
-
-    function printNetwork() {
-        eventOutput("navigator.connection.type=" + navigator.connection.type);
-        eventOutput("navigator.network.connection.type=" + navigator.network.connection.type);
-    }
-
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        var deviceReady = false;
-        function onEvent(e) {
-            eventOutput('Event of type: ' + e.type);
-            printNetwork();
-        }
-        document.addEventListener('online', onEvent, false);
-        document.addEventListener('offline', onEvent, false);
-        document.addEventListener("deviceready", function() {
-            deviceReady = true;
-            eventOutput("Device="+device.platform+" "+device.version);
-            printNetwork();
-        }, false);
-        window.setTimeout(function() {
-            if (!deviceReady) {
-                alert("Error: Cordova did not initialize.  Demo will not run correctly.");
-            }
-        }, 1000);
-    }
-
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
 </script>
 
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>Network Events and State</h1>
     <div id="info">
@@ -78,8 +41,8 @@
     </div>
 
     <h2>Action</h2>
-    <div class="btn large" onclick="printNetwork();">Show Network Connection</div>
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <div class="btn large printNetwork">Show Network Connection</div>
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/network/index.js
----------------------------------------------------------------------
diff --git a/network/index.js b/network/index.js
new file mode 100644
index 0000000..41c2c47
--- /dev/null
+++ b/network/index.js
@@ -0,0 +1,38 @@
+function eventOutput(s) {
+    var el = document.getElementById("results");
+    el.innerHTML = el.innerHTML + s + "<br>";
+}
+
+function printNetwork() {
+    eventOutput("navigator.connection.type=" + navigator.connection.type);
+    eventOutput("navigator.network.connection.type=" + navigator.network.connection.type);
+}
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    var deviceReady = false;
+    function onEvent(e) {
+        eventOutput('Event of type: ' + e.type);
+        printNetwork();
+    }
+    document.addEventListener('online', onEvent, false);
+    document.addEventListener('offline', onEvent, false);
+    document.addEventListener("deviceready", function() {
+        deviceReady = true;
+        eventOutput("Device="+device.platform+" "+device.version);
+        printNetwork();
+    }, false);
+    window.setTimeout(function() {
+        if (!deviceReady) {
+            alert("Error: Cordova did not initialize.  Demo will not run correctly.");
+        }
+    }, 1000);
+}
+
+window.onload = function() {
+  addListenerToClass('printNetwork', printNetwork);
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/notification/index.html
----------------------------------------------------------------------
diff --git a/notification/index.html b/notification/index.html
index 16aad7d..ab648df 100644
--- a/notification/index.html
+++ b/notification/index.html
@@ -28,112 +28,24 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>      
-
-      
-<script type="text/javascript" charset="utf-8">
-
-    var deviceReady = false;
-
-    //-------------------------------------------------------------------------
-    // Notifications
-    //-------------------------------------------------------------------------
-
-    var beep = function(){
-        navigator.notification.beep(3);
-    };
-
-    var alertDialog = function(message, title, button) {
-        console.log("alertDialog()");
-        navigator.notification.alert(message,
-            function(){
-                console.log("Alert dismissed.");
-            },
-            title, button);
-        console.log("After alert");
-    };
-
-    var confirmDialogA = function(message, title, buttons) {
-        navigator.notification.confirm(message,
-            function(r) {
-                if(r===0){
-                    console.log("Dismissed dialog without making a selection.");
-                    alert("Dismissed dialog without making a selection.");
-                }else{
-                    console.log("You selected " + r);
-                    alert("You selected " + (buttons.split(","))[r-1]);
-                }
-            },
-            title,
-            buttons);
-    };
-
-    var confirmDialogB = function(message, title, buttons) {
-        navigator.notification.confirm(message,
-            function(r) {
-                if(r===0){
-                    console.log("Dismissed dialog without making a selection.");
-                    alert("Dismissed dialog without making a selection.");
-                }else{
-                    console.log("You selected " + r);
-                    alert("You selected " + buttons[r-1]);
-                }
-            },
-            title,
-            buttons);
-    };
-
-    var promptDialog = function(message, title, buttons) {
-        navigator.notification.prompt(message,
-            function(r) {
-                if(r && r.buttonIndex===0){
-                    var msg = "Dismissed dialog";
-                    if( r.input1 ){
-                        msg+=" with input: " + r.input1
-                    }
-                    console.log(msg);
-                    alert(msg);
-                }else{
-                    console.log("You selected " + r.buttonIndex + " and entered: " + r.input1);
-                    alert("You selected " + buttons[r.buttonIndex-1] + " and entered: " + r.input1);
-                }
-            },
-            title,
-            buttons);
-    };
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-                deviceReady = true;
-                console.log("Device="+device.platform+" "+device.version);
-            }, false);
-        window.setTimeout(function() {
-            if (!deviceReady) {
-                alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
-            }
-        },1000);
-    }
-
-</script>
-
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>Notifications and Dialogs</h1>
     <div id="info">
     </div>
     
     <h2>Action</h2>
-    <div class="btn large" onclick="beep();">Beep</div>
-    <div class="btn large" onclick="alertDialog('You pressed alert.', 'Alert Dialog', 'Continue');">Alert Dialog</div>
-    <div class="btn large" onclick="confirmDialogA('You pressed confirm.', 'Confirm Dialog', 'Yes,No,Maybe');">Confirm Dialog - Deprecated</div>
-    <div class="btn large" onclick="confirmDialogB('You pressed confirm.', 'Confirm Dialog', ['Yes', 'No', 'Maybe, Not Sure']);">Confirm Dialog</div>
-    <div class="btn large" onclick="promptDialog('You pressed prompt.', 'Prompt Dialog', ['Yes', 'No', 'Maybe, Not Sure']);">Prompt Dialog</div>
+    <div class="btn large beep">Beep</div>
+    <div class="btn large alertDialog">Alert Dialog</div>
+    <div class="btn large confirmDialogA">Confirm Dialog - Deprecated</div>
+    <div class="btn large confirmDialogB">Confirm Dialog</div>
+    <div class="btn large promptDialog">Prompt Dialog</div>
     
-    <div class="btn large" onclick="alert('You pressed alert.');">Built-in Alert Dialog</div>
-    <div class="btn large" onclick="confirm('You selected confirm');">Built-in Confirm Dialog</div>
-    <div class="btn large" onclick="prompt('This is a prompt.', 'Default value');">Built-in Prompt Dialog</div>
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <div class="btn large builtInAlert">Built-in Alert Dialog</div>
+    <div class="btn large builtInConfirm">Built-in Confirm Dialog</div>
+    <div class="btn large builtInPrompt">Built-in Prompt Dialog</div>
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>      

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/notification/index.js
----------------------------------------------------------------------
diff --git a/notification/index.js b/notification/index.js
new file mode 100644
index 0000000..12e672f
--- /dev/null
+++ b/notification/index.js
@@ -0,0 +1,100 @@
+var deviceReady = false;
+
+//-------------------------------------------------------------------------
+// Notifications
+//-------------------------------------------------------------------------
+
+var beep = function(){
+    navigator.notification.beep(3);
+};
+
+var alertDialog = function(message, title, button) {
+    console.log("alertDialog()");
+    navigator.notification.alert(message,
+        function(){
+            console.log("Alert dismissed.");
+        },
+        title, button);
+    console.log("After alert");
+};
+
+var confirmDialogA = function(message, title, buttons) {
+    navigator.notification.confirm(message,
+        function(r) {
+            if(r===0){
+                console.log("Dismissed dialog without making a selection.");
+                alert("Dismissed dialog without making a selection.");
+            }else{
+                console.log("You selected " + r);
+                alert("You selected " + (buttons.split(","))[r-1]);
+            }
+        },
+        title,
+        buttons);
+};
+
+var confirmDialogB = function(message, title, buttons) {
+    navigator.notification.confirm(message,
+        function(r) {
+            if(r===0){
+                console.log("Dismissed dialog without making a selection.");
+                alert("Dismissed dialog without making a selection.");
+            }else{
+                console.log("You selected " + r);
+                alert("You selected " + buttons[r-1]);
+            }
+        },
+        title,
+        buttons);
+};
+
+var promptDialog = function(message, title, buttons) {
+    navigator.notification.prompt(message,
+        function(r) {
+            if(r && r.buttonIndex===0){
+                var msg = "Dismissed dialog";
+                if( r.input1 ){
+                    msg+=" with input: " + r.input1
+                }
+                console.log(msg);
+                alert(msg);
+            }else{
+                console.log("You selected " + r.buttonIndex + " and entered: " + r.input1);
+                alert("You selected " + buttons[r.buttonIndex-1] + " and entered: " + r.input1);
+            }
+        },
+        title,
+        buttons);
+};
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+            deviceReady = true;
+            console.log("Device="+device.platform+" "+device.version);
+        }, false);
+    window.setTimeout(function() {
+        if (!deviceReady) {
+            alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
+        }
+    },1000);
+}
+
+window.onload = function() {
+  addListenerToClass('beep', beep);
+  addListenerToClass('alertDialog', alertDialog, 
+      ['You pressed alert.', 'Alert Dialog', 'Continue']);
+  addListenerToClass('confirmDialogA', confirmDialogA, 
+      ['You pressed confirm.', 'Confirm Dialog', 'Yes,No,Maybe']);
+  addListenerToClass('confirmDialogB', confirmDialogB,
+      ['You pressed confirm.', 'Confirm Dialog', ['Yes', 'No', 'Maybe, Not Sure']]);
+  addListenerToClass('promptDialog', promptDialog,
+      ['You pressed prompt.', 'Prompt Dialog', ['Yes', 'No', 'Maybe, Not Sure']]);
+  addListenerToClass('builtInAlert', alert, 'You pressed alert.');
+  addListenerToClass('builtInConfirm', confirm, 'You selected confirm');
+  addListenerToClass('builtInPrompt', prompt, ['This is a prompt.', 'Default value']);
+
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/sql/index.html
----------------------------------------------------------------------
diff --git a/sql/index.html b/sql/index.html
index 5827521..da0d809 100644
--- a/sql/index.html
+++ b/sql/index.html
@@ -28,126 +28,9 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>      
-
-      
-<script type="text/javascript" charset="utf-8">
-
-    //-------------------------------------------------------------------------
-    // HTML5 Database
-    //-------------------------------------------------------------------------
-    var dbs = [];
-    var quotas = [2000000, 2000000];
-    var names = ['mydb', 'rand' + Math.random()];
-    function openDb(index) {
-        try {
-            databaseOutput('Openning db with name: ' + names[index]);
-            return openDatabase(names[index], "1.0", "Apache Cordova Demo", quotas[index]);
-        } catch (e) {
-            databaseOutput('Got exception: ' + e);
-        }
-    }
-
-    var callDatabase = function(index) {
-        var db = dbs[index] = openDb(index);
-        if (!db) {
-            return;
-        }
-        databaseOutput("Database opened.");
-        db.transaction(function (tx) {
-            tx.executeSql('DROP TABLE IF EXISTS DEMO');
-            tx.executeSql('CREATE TABLE IF NOT EXISTS DEMO (id unique, data)', [],
-                 function(tx,results) { console.log("Created table"); },
-                 function(tx,err) { alert("Error creating table: "+err.message); });
-            tx.executeSql('INSERT INTO DEMO (id, data) VALUES (1, "First row")', [],
-                 function(tx,results) { console.log("Insert row1 success"); },
-                 function(tx,err) { alert("Error adding 1st row: "+err.message); });
-            tx.executeSql('INSERT INTO DEMO (id, data) VALUES (2, "Second row")', [],
-                 function(tx,results) { console.log("Insert row2 success"); },
-                 function(tx,err) { alert("Error adding 2nd row: "+err.message); });
-            databaseOutput("Data written to DEMO table.");
-            console.log("Data written to DEMO table.");
-
-            tx.executeSql('SELECT * FROM DEMO', [], function (tx, results) {
-                var len = results.rows.length;
-                var text = "DEMO table: " + len + " rows found.<br>";
-                text = text + "<table border='1'><tr><td>Row</td><td>Data</td></tr>";
-                for (var i=0; i<len; i++){
-                    text = text + "<tr><td>" + i + "</td><td>" + results.rows.item(i).id + ", " + results.rows.item(i).data + "</td></tr>";
-                }
-                text = text + "</table>";
-                databaseOutput(text);
-            }, function(tx, err) {
-                alert("Error processing SELECT * SQL: "+err.message);
-            });
-            tx.executeSql('SELECT ID FROM DEMO', [], function (tx, results) {
-                var len = results.rows.length;
-                var text = "DEMO table: " + len + " rows found.<br>";
-                text = text + "<table border='1'><tr><td>Row</td><td>Data</td></tr>";
-                for (var i=0; i<len; i++){
-                    text = text + "<tr><td>" + i + "</td><td>" + results.rows.item(i).id + "</td></tr>";
-                }
-                text = text + "</table>";
-                databaseOutput(text);
-            }, function(tx, err) {
-                alert("Error processing SELECT ID SQL: "+err.message);
-            });
-            
-        },
-        function(err) {
-            console.log("Transaction failed: " + err.message);
-        });
-
-
-    };
-
-    var readDatabase = function(index) {
-        var db = dbs[index];
-    	if (!db) {
-            db = dbs[index] = openDb(index);
-            if (!db) {
-                return;
-            }
-        }
-        db.transaction(function (tx) {
-            tx.executeSql('SELECT * FROM DEMO WHERE id=2', [], function (tx, results) {
-                var len = results.rows.length;
-                var text = "DEMO table: " + len + " rows found.<br>";
-                text = text + "<table border='1'><tr><td>Row</td><td>Data</td></tr>";
-                for (var i=0; i<len; i++){
-                    text = text + "<tr><td>" + i + "</td><td>" + results.rows.item(i).id + ", " + results.rows.item(i).data + "</td></tr>";
-                }
-                text = text + "</table>";
-                databaseOutput(text);
-            }, function(tx, err) {
-                alert("Error processing SELECT * WHERE id=2 SQL: "+err.message);
-            });
-        });
-    }
-
-    function increaseQuota(index) {
-        quotas[index] *= 2;
-        databaseOutput('quota ' + index + ' is now ' + quotas[index]);
-    }
-
-    var databaseOutput = function(s) {
-        var el = document.getElementById("database_results");
-        el.innerHTML = el.innerHTML + s + "<br>";
-        el.scrollByLines(20000);
-    };
-    
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-            console.log("Device="+device.platform+" "+device.version);
-        }, false);
-    }
-
-</script>
-
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>HTML5 Database</h1>   
     <div id="info">
@@ -155,13 +38,13 @@
         <span id="database_results"></span>
     </div>
     <h2>Action</h2>
-    <div class="btn large" onclick="callDatabase(0);">Create, Add, Read Database (Constant name)</div>
-    <div class="btn large" onclick="readDatabase(0);">Read Database (Constant name)</div>
-    <div class="btn large" onclick="increaseQuota(0);">Increase Quota (Constant name)</div>
-    <div class="btn large" onclick="callDatabase(1);">Create, Add, Read Database (Random Name)</div>
-    <div class="btn large" onclick="readDatabase(1);">Read Database (Random Name)</div>
-    <div class="btn large" onclick="increaseQuota(1);">Increase Quota (Random Name)</div>
-    <div class="btn large" onclick="location = location.href">Reload Page</div>
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>    
+    <div class="btn large callDatabase0">Create, Add, Read Database (Constant name)</div>
+    <div class="btn large readDatabase0">Read Database (Constant name)</div>
+    <div class="btn large increaseQuota0">Increase Quota (Constant name)</div>
+    <div class="btn large callDatabase1">Create, Add, Read Database (Random Name)</div>
+    <div class="btn large readDatabase1">Read Database (Random Name)</div>
+    <div class="btn large increaseQuota1">Increase Quota (Random Name)</div>
+    <div class="btn large reloadPage">Reload Page</div>
+    <h2> </h2><div class="backBtn">Back</div>    
   </body>
 </html>      


[11/12] spec commit: Merge branch 'ffos_privileged_compatible' of github.com:zalun/cordova-mobile-spec into ffos_privileged_compatible

Posted by za...@apache.org.
Merge branch 'ffos_privileged_compatible' of github.com:zalun/cordova-mobile-spec into ffos_privileged_compatible


Project: http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/commit/46c0918b
Tree: http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/tree/46c0918b
Diff: http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/diff/46c0918b

Branch: refs/heads/master
Commit: 46c0918b1bc76d9d1e079cd4dbbb2849f90aae87
Parents: 5570976 53a3422
Author: Piotr Zalewa <pi...@zalewa.info>
Authored: Mon May 19 14:39:12 2014 +0200
Committer: Piotr Zalewa <pi...@zalewa.info>
Committed: Mon May 19 14:39:12 2014 +0200

----------------------------------------------------------------------

----------------------------------------------------------------------



[06/12] Manual tests fixed

Posted by za...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/sql/index.js
----------------------------------------------------------------------
diff --git a/sql/index.js b/sql/index.js
new file mode 100644
index 0000000..b5d5653
--- /dev/null
+++ b/sql/index.js
@@ -0,0 +1,125 @@
+//-------------------------------------------------------------------------
+// HTML5 Database
+//-------------------------------------------------------------------------
+var dbs = [];
+var quotas = [2000000, 2000000];
+var names = ['mydb', 'rand' + Math.random()];
+function openDb(index) {
+    try {
+        databaseOutput('Openning db with name: ' + names[index]);
+        return openDatabase(names[index], "1.0", "Apache Cordova Demo", quotas[index]);
+    } catch (e) {
+        databaseOutput('Got exception: ' + e);
+    }
+}
+
+var callDatabase = function(index) {
+    var db = dbs[index] = openDb(index);
+    if (!db) {
+        return;
+    }
+    databaseOutput("Database opened.");
+    db.transaction(function (tx) {
+        tx.executeSql('DROP TABLE IF EXISTS DEMO');
+        tx.executeSql('CREATE TABLE IF NOT EXISTS DEMO (id unique, data)', [],
+             function(tx,results) { console.log("Created table"); },
+             function(tx,err) { alert("Error creating table: "+err.message); });
+        tx.executeSql('INSERT INTO DEMO (id, data) VALUES (1, "First row")', [],
+             function(tx,results) { console.log("Insert row1 success"); },
+             function(tx,err) { alert("Error adding 1st row: "+err.message); });
+        tx.executeSql('INSERT INTO DEMO (id, data) VALUES (2, "Second row")', [],
+             function(tx,results) { console.log("Insert row2 success"); },
+             function(tx,err) { alert("Error adding 2nd row: "+err.message); });
+        databaseOutput("Data written to DEMO table.");
+        console.log("Data written to DEMO table.");
+
+        tx.executeSql('SELECT * FROM DEMO', [], function (tx, results) {
+            var len = results.rows.length;
+            var text = "DEMO table: " + len + " rows found.<br>";
+            text = text + "<table border='1'><tr><td>Row</td><td>Data</td></tr>";
+            for (var i=0; i<len; i++){
+                text = text + "<tr><td>" + i + "</td><td>" + results.rows.item(i).id + ", " + results.rows.item(i).data + "</td></tr>";
+            }
+            text = text + "</table>";
+            databaseOutput(text);
+        }, function(tx, err) {
+            alert("Error processing SELECT * SQL: "+err.message);
+        });
+        tx.executeSql('SELECT ID FROM DEMO', [], function (tx, results) {
+            var len = results.rows.length;
+            var text = "DEMO table: " + len + " rows found.<br>";
+            text = text + "<table border='1'><tr><td>Row</td><td>Data</td></tr>";
+            for (var i=0; i<len; i++){
+                text = text + "<tr><td>" + i + "</td><td>" + results.rows.item(i).id + "</td></tr>";
+            }
+            text = text + "</table>";
+            databaseOutput(text);
+        }, function(tx, err) {
+            alert("Error processing SELECT ID SQL: "+err.message);
+        });
+        
+    },
+    function(err) {
+        console.log("Transaction failed: " + err.message);
+    });
+
+
+};
+
+var readDatabase = function(index) {
+    var db = dbs[index];
+  if (!db) {
+        db = dbs[index] = openDb(index);
+        if (!db) {
+            return;
+        }
+    }
+    db.transaction(function (tx) {
+        tx.executeSql('SELECT * FROM DEMO WHERE id=2', [], function (tx, results) {
+            var len = results.rows.length;
+            var text = "DEMO table: " + len + " rows found.<br>";
+            text = text + "<table border='1'><tr><td>Row</td><td>Data</td></tr>";
+            for (var i=0; i<len; i++){
+                text = text + "<tr><td>" + i + "</td><td>" + results.rows.item(i).id + ", " + results.rows.item(i).data + "</td></tr>";
+            }
+            text = text + "</table>";
+            databaseOutput(text);
+        }, function(tx, err) {
+            alert("Error processing SELECT * WHERE id=2 SQL: "+err.message);
+        });
+    });
+}
+
+function increaseQuota(index) {
+    quotas[index] *= 2;
+    databaseOutput('quota ' + index + ' is now ' + quotas[index]);
+}
+
+var databaseOutput = function(s) {
+    var el = document.getElementById("database_results");
+    el.innerHTML = el.innerHTML + s + "<br>";
+    el.scrollByLines(20000);
+};
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+        console.log("Device="+device.platform+" "+device.version);
+    }, false);
+}
+
+window.onload = function() {
+  addListenerToClass('callDatabase0', callDatabase, [0]);
+  addListenerToClass('readDatabase0', readDatabase, [0]);
+  addListenerToClass('increaseQuota0', increaseQuota, [0]);
+  addListenerToClass('callDatabase1', callDatabase, 1);
+  addListenerToClass('readDatabase1', readDatabase, 1);
+  addListenerToClass('increaseQuota1', increaseQuota, 1);
+  addListenerToClass('reloadPage', function() {
+    location = location.href;
+  });
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/storage/index.html
----------------------------------------------------------------------
diff --git a/storage/index.html b/storage/index.html
index 20e2951..0b713a2 100644
--- a/storage/index.html
+++ b/storage/index.html
@@ -28,45 +28,14 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>      
-
-      
-<script type="text/javascript" charset="utf-8">
-
-    var deviceReady = false;
-    
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-                deviceReady = true;
-                console.log("Device="+device.platform+" "+device.version);
-            }, false);
-        window.setTimeout(function() {
-        	if (!deviceReady) {
-        		alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
-        	}
-        },1000);
-    }
-
-</script>
-
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>Local Storage</h1>
     <div id="info">
         You have run this app <span id="count">an untold number of</span> time(s).
     </div>
-
-    <script>
-    if (!localStorage.pageLoadCount) {
-        localStorage.pageLoadCount = 0;
-    }
-    localStorage.pageLoadCount = parseInt(localStorage.pageLoadCount) + 1;
-    document.getElementById('count').textContent = localStorage.pageLoadCount;
-    </script>
-
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>      

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/storage/index.js
----------------------------------------------------------------------
diff --git a/storage/index.js b/storage/index.js
new file mode 100644
index 0000000..00ae7e1
--- /dev/null
+++ b/storage/index.js
@@ -0,0 +1,27 @@
+var deviceReady = false;
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+            deviceReady = true;
+            console.log("Device="+device.platform+" "+device.version);
+        }, false);
+    window.setTimeout(function() {
+      if (!deviceReady) {
+        alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
+      }
+    },1000);
+}
+
+window.onload = function() {
+  addListenerToClass('backBtn', backHome);
+  init();
+
+  if (!localStorage.pageLoadCount) {
+      localStorage.pageLoadCount = 0;
+  }
+  localStorage.pageLoadCount = parseInt(localStorage.pageLoadCount) + 1;
+  document.getElementById('count').textContent = localStorage.pageLoadCount;
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/vibration/index.html
----------------------------------------------------------------------
diff --git a/vibration/index.html b/vibration/index.html
index ef9b76e..a24110e 100644
--- a/vibration/index.html
+++ b/vibration/index.html
@@ -28,47 +28,16 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>      
-
-      
-<script type="text/javascript" charset="utf-8">
-
-    var deviceReady = false;
-
-    //-------------------------------------------------------------------------
-    // Vibrations
-    //-------------------------------------------------------------------------
-
-    var vibrate = function(){
-      navigator.notification.vibrate(2500);
-    };
-
-    
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-                deviceReady = true;
-                console.log("Device="+device.platform+" "+device.version);
-            }, false);
-        window.setTimeout(function() {
-            if (!deviceReady) {
-                alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
-            }
-        },1000);
-    }
-
-</script>
-
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>Vibrations</h1>
     <div id="info">
     </div>
     
     <h2>Action</h2>
-    <div class="btn large" onclick="vibrate();">Vibrate</div>
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <div class="btn large vibrate">Vibrate</div>
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>      

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/vibration/index.js
----------------------------------------------------------------------
diff --git a/vibration/index.js b/vibration/index.js
new file mode 100644
index 0000000..0d28902
--- /dev/null
+++ b/vibration/index.js
@@ -0,0 +1,31 @@
+var deviceReady = false;
+
+//-------------------------------------------------------------------------
+// Vibrations
+//-------------------------------------------------------------------------
+
+var vibrate = function(){
+  navigator.notification.vibrate(2500);
+};
+
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+            deviceReady = true;
+            console.log("Device="+device.platform+" "+device.version);
+        }, false);
+    window.setTimeout(function() {
+        if (!deviceReady) {
+            alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
+        }
+    },1000);
+}
+
+window.onload = function() {
+  addListenerToClass('vibrate', vibrate);
+  addListenerToClass('backBtn', backHome);
+  init();
+}


[08/12] Manual tests fixed

Posted by za...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/camera/index.html
----------------------------------------------------------------------
diff --git a/camera/index.html b/camera/index.html
index b74dabb..4f48190 100644
--- a/camera/index.html
+++ b/camera/index.html
@@ -28,341 +28,10 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>
-
-
-<script type="text/javascript" charset="utf-8">
-
-    var deviceReady = false;
-    var platformId = cordova.require('cordova/platform').id;
-    var pictureUrl = null;
-    var fileObj = null;
-    var fileEntry = null;
-    var pageStartTime = +new Date();
-    
-    //default camera options
-    var camQualityDefault = ['quality value', 50];
-    var camDestinationTypeDefault = ['FILE_URI', 1];
-    var camPictureSourceTypeDefault = ['CAMERA', 1];
-    var camAllowEditDefault = ['allowEdit', false];
-    var camEncodingTypeDefault = ['JPEG', 0];
-    var camMediaTypeDefault = ['mediaType', 0];
-    var camCorrectOrientationDefault = ['correctOrientation', false];
-    var camSaveToPhotoAlbumDefault = ['saveToPhotoAlbum', true];
-    
-
-    //-------------------------------------------------------------------------
-    // Camera
-    //-------------------------------------------------------------------------
-
-    function log(value) {
-        console.log(value);
-        document.getElementById('camera_status').textContent += (new Date() - pageStartTime) / 1000 + ': ' + value + '\n';
-    }
-
-    function clearStatus() {
-        document.getElementById('camera_status').innerHTML = '';
-        document.getElementById('camera_image').src = 'about:blank';
-        var canvas = document.getElementById('canvas');
-        canvas.width = canvas.height = 1;
-        pictureUrl = null;
-        fileObj = null;
-        fileEntry = null;
-    }
-
-    function setPicture(url, callback) {
-		try {
-			window.atob(url);
-			// if we got here it is a base64 string (DATA_URL)
-			url = "data:image/jpeg;base64," + url;
-		} catch (e) {
-			// not DATA_URL
-		    log('URL: ' + url.slice(0, 100));
-		}    
-    
-        pictureUrl = url;
-        var img = document.getElementById('camera_image');
-        var startTime = new Date();
-        img.src = url;
-        img.onloadend = function() {
-            log('Image tag load time: ' + (new Date() - startTime));
-            callback && callback();
-        };
-    }
-
-    function onGetPictureError(e) {
-        log('Error getting picture: ' + e.code);
-    }
-
-    function getPictureWin(data) {
-        setPicture(data);
-        // TODO: Fix resolveLocalFileSystemURI to work with native-uri.
-        if (pictureUrl.indexOf('file:') == 0 || pictureUrl.indexOf('content:') == 0) {
-            resolveLocalFileSystemURI(data, function(e) {
-                fileEntry = e;
-                logCallback('resolveLocalFileSystemURI()', true)(e.toURL());
-            }, logCallback('resolveLocalFileSystemURI()', false));
-        } else if (pictureUrl.indexOf('data:image/jpeg;base64' == 0)) {
-        	// do nothing
-        } else {
-            var path = pictureUrl.replace(/^file:\/\/(localhost)?/, '').replace(/%20/g, ' ');
-            fileEntry = new FileEntry('image_name.png', path);
-        }
-    }
-
-    function getPicture() {
-        clearStatus();
-        var options = extractOptions();
-        log('Getting picture with options: ' + JSON.stringify(options));
-        var popoverHandle = navigator.camera.getPicture(getPictureWin, onGetPictureError, options);
-
-        // Reposition the popover if the orientation changes.
-        window.onorientationchange = function() {
-            var newPopoverOptions = new CameraPopoverOptions(0, 0, 100, 100, 0);
-            popoverHandle.setPosition(newPopoverOptions);
-        }
-    }
-
-    function uploadImage() {
-        var ft = new FileTransfer(),
-            uploadcomplete=0,
-            progress = 0,
-            options = new FileUploadOptions();
-        options.fileKey="photo";
-        options.fileName='test.jpg';
-        options.mimeType="image/jpeg";
-        ft.onprogress = function(progressEvent) {
-            log('progress: ' + progressEvent.loaded + ' of ' + progressEvent.total);
-        };
-        var server = "http://cordova-filetransfer.jitsu.com";
-
-        ft.upload(pictureUrl, server + '/upload', win, fail, options);
-        function win(information_back){
-            log('upload complete');
-        }
-        function fail(message) {
-            log('upload failed: ' + JSON.stringify(message));
-        }
-    }
-
-    function logCallback(apiName, success) {
-        return function() {
-            log('Call to ' + apiName + (success ? ' success: ' : ' failed: ') + JSON.stringify([].slice.call(arguments)));
-        };
-    }
-
-    /**
-     * Select image from library using a NATIVE_URI destination type
-     * This calls FileEntry.getMetadata, FileEntry.setMetadata, FileEntry.getParent, FileEntry.file, and FileReader.readAsDataURL.
-     */
-    function readFile() {
-        function onFileReadAsDataURL(evt) {
-            var img = document.getElementById('camera_image');
-            img.style.visibility = "visible";
-            img.style.display = "block";
-            img.src = evt.target.result;
-            log("FileReader.readAsDataURL success");
-        };
-
-        function onFileReceived(file) {
-            log('Got file: ' + JSON.stringify(file));
-            fileObj = file;
-
-            var reader = new FileReader();
-            reader.onload = function() {
-                log('FileReader.readAsDataURL() - length = ' + reader.result.length);
-            };
-            reader.onerror = logCallback('FileReader.readAsDataURL', false);
-            reader.readAsDataURL(file);
-        };
-        // Test out onFileReceived when the file object was set via a native <input> elements.
-        if (fileObj) {
-            onFileReceived(fileObj);
-        } else {
-            fileEntry.file(onFileReceived, logCallback('FileEntry.file', false));
-        }
-    }
-    function getFileInfo() {
-        // Test FileEntry API here.
-        fileEntry.getMetadata(logCallback('FileEntry.getMetadata', true), logCallback('FileEntry.getMetadata', false));
-        fileEntry.setMetadata(logCallback('FileEntry.setMetadata', true), logCallback('FileEntry.setMetadata', false), { "com.apple.MobileBackup": 1 });
-        fileEntry.getParent(logCallback('FileEntry.getParent', true), logCallback('FileEntry.getParent', false));
-        fileEntry.getParent(logCallback('FileEntry.getParent', true), logCallback('FileEntry.getParent', false));
-    };
-
-    /**
-     * Copy image from library using a NATIVE_URI destination type
-     * This calls FileEntry.copyTo and FileEntry.moveTo.
-     */
-    function copyImage() {
-        var onFileSystemReceived = function(fileSystem) {
-            var destDirEntry = fileSystem.root;
-
-            // Test FileEntry API here.
-            fileEntry.copyTo(destDirEntry, 'copied_file.png', logCallback('FileEntry.copyTo', true), logCallback('FileEntry.copyTo', false));
-            fileEntry.moveTo(destDirEntry, 'moved_file.png', logCallback('FileEntry.moveTo', true), logCallback('FileEntry.moveTo', false));
-        };
-
-        window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, onFileSystemReceived, null);
-    };
-
-    /**
-     * Write image to library using a NATIVE_URI destination type
-     * This calls FileEntry.createWriter, FileWriter.write, and FileWriter.truncate.
-     */
-    function writeImage() {
-        var onFileWriterReceived = function(fileWriter) {
-            fileWriter.onwrite = logCallback('FileWriter.write', true);
-            fileWriter.onerror = logCallback('FileWriter.write', false);
-            fileWriter.write("some text!");
-        };
-
-        var onFileTruncateWriterReceived = function(fileWriter) {
-            fileWriter.onwrite = logCallback('FileWriter.truncate', true);
-            fileWriter.onerror = logCallback('FileWriter.truncate', false);
-            fileWriter.truncate(10);
-        };
-
-        fileEntry.createWriter(onFileWriterReceived, logCallback('FileEntry.createWriter', false));
-        fileEntry.createWriter(onFileTruncateWriterReceived, null);
-    };
-
-    function displayImageUsingCanvas() {
-        var canvas = document.getElementById('canvas');
-        var img = document.getElementById('camera_image');
-        var w = img.width;
-        var h = img.height;
-        h = 100 / w * h;
-        w = 100;
-        canvas.width = w;
-        canvas.height= h;
-        var context = canvas.getContext('2d');
-        context.drawImage(img, 0, 0, w, h);
-    };
-
-    /**
-     * Remove image from library using a NATIVE_URI destination type
-     * This calls FileEntry.remove.
-     */
-    function removeImage() {
-        fileEntry.remove(logCallback('FileEntry.remove', true), logCallback('FileEntry.remove', false));
-    };
-
-    function testInputTag(inputEl) {
-        clearStatus();
-        // iOS 6 likes to dead-lock in the onchange context if you
-        // do any alerts or try to remote-debug.
-        window.setTimeout(function() {
-            testNativeFile2(inputEl);
-        }, 0);
-    };
-
-    function testNativeFile2(inputEl) {
-        if (!inputEl.value) {
-            alert('No file selected.');
-            return;
-        }
-        fileObj = inputEl.files[0];
-        if (!fileObj) {
-            alert('Got value but no file.');
-            return;
-        }
-        var URLApi = window.URL || window.webkitURL;
-        if (URLApi) {
-            var blobURL = URLApi.createObjectURL(fileObj);
-            if (blobURL) {
-                setPicture(blobURL, function() {
-                    URLApi.revokeObjectURL(blobURL);
-                });
-            } else {
-                log('URL.createObjectURL returned null');
-            }
-        } else {
-            log('URL.createObjectURL() not supported.');
-        }
-    }
-
-    function extractOptions() {
-        var els = document.querySelectorAll('#image-options select');
-        var ret = {};
-        for (var i = 0, el; el = els[i]; ++i) {
-            var value = el.value;
-            if (value === '') continue;
-            if (el.isBool) {
-                ret[el.keyName] = !!+value;
-            } else {
-                ret[el.keyName] = +value;
-            }
-        }
-        return ret;
-    }
-
-    function createOptionsEl(name, values, selectionDefault) {
-        var container = document.createElement('div');
-        container.style.display = 'inline-block';
-        container.appendChild(document.createTextNode(name + ': '));
-        var select = document.createElement('select');
-        select.keyName = name;
-        container.appendChild(select);
-        
-        // if we didn't get a default value, insert the blank <default> entry
-        if (selectionDefault == undefined) {
-            var opt = document.createElement('option');
-            opt.value = '';
-            opt.text = '<default>';
-            select.appendChild(opt);
-        }
-        
-        select.isBool = typeof values == 'boolean';
-        if (select.isBool) {
-            values = {'true': 1, 'false': 0};
-        }
-        
-        for (var k in values) {
-            var opt = document.createElement('option');
-            opt.value = values[k];
-            opt.textContent = k;
-            if (selectionDefault) {
-                if (selectionDefault[0] == k) {
-                    opt.selected = true;
-                }
-            }
-            select.appendChild(opt);
-        }
-        var optionsDiv = document.getElementById('image-options');
-        optionsDiv.appendChild(container);
-    }
-
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-            deviceReady = true;
-            console.log("Device="+device.platform+" "+device.version);
-            createOptionsEl('sourceType', Camera.PictureSourceType, camPictureSourceTypeDefault);
-            createOptionsEl('destinationType', Camera.DestinationType, camDestinationTypeDefault);
-            createOptionsEl('encodingType', Camera.EncodingType, camEncodingTypeDefault);
-            createOptionsEl('mediaType', Camera.MediaType, camMediaTypeDefault);
-            createOptionsEl('quality', {'0': 0, '50': 50, '80': 80, '100': 100}, camQualityDefault);
-            createOptionsEl('targetWidth', {'50': 50, '200': 200, '800': 800, '2048': 2048});
-            createOptionsEl('targetHeight', {'50': 50, '200': 200, '800': 800, '2048': 2048});
-            createOptionsEl('allowEdit', true, camAllowEditDefault);
-            createOptionsEl('correctOrientation', true, camCorrectOrientationDefault);
-            createOptionsEl('saveToPhotoAlbum', true, camSaveToPhotoAlbumDefault);
-            createOptionsEl('cameraDirection', Camera.Direction);
-                          
-        }, false);
-        window.setTimeout(function() {
-            if (!deviceReady) {
-                alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
-            }
-        },1000);
-    };
-
-</script>
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
 
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
 
     <h1>Camera</h1>
     <div id="info" style="white-space: pre-wrap">
@@ -372,20 +41,20 @@
     </div>
     <h2>Cordova Camera API</h2>
     <div id="image-options"></div>
-    <div class="btn large" onclick="getPicture();">camera.getPicture()</div>
+    <div class="btn large getPicture">camera.getPicture()</div>
     <h2>Native File Inputs</h2>
-    <div>input type=file <input type="file" onchange="testInputTag(this)"></div>
-    <div>capture=camera <input type="file" accept="image/*;capture=camera" onchange="testInputTag(this)"></div>
-    <div>capture=camcorder <input type="file" accept="video/*;capture=camcorder" onchange="testInputTag(this)"></div>
-    <div>capture=microphone <input type="file" accept="audio/*;capture=microphone" onchange="testInputTag(this)"></div>
+    <div>input type=file <input type="file" class="testInputTag"></div>
+    <div>capture=camera <input type="file" accept="image/*;capture=camera" class="testInputTag"></div>
+    <div>capture=camcorder <input type="file" accept="video/*;capture=camcorder" class="testInputTag"></div>
+    <div>capture=microphone <input type="file" accept="audio/*;capture=microphone" class="testInputTag"></div>
     <h2>Actions</h2>
-    <div class="btn large" onclick="getFileInfo();">Get File Metadata</div>
-    <div class="btn large" onclick="readFile();">Read with FileReader</div>
-    <div class="btn large" onclick="copyImage();">Copy Image</div>
-    <div class="btn large" onclick="writeImage();">Write Image</div>
-    <div class="btn large" onclick="uploadImage();">Upload Image</div>
-    <div class="btn large" onclick="displayImageUsingCanvas();">Draw Using Canvas</div>
-    <div class="btn large" onclick="removeImage();">Remove Image</div>
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <div class="btn large getFileInfo">Get File Metadata</div>
+    <div class="btn large readFile">Read with FileReader</div>
+    <div class="btn large copyImage">Copy Image</div>
+    <div class="btn large writeImage">Write Image</div>
+    <div class="btn large uploadImage">Upload Image</div>
+    <div class="btn large displayImageUsingCanvas">Draw Using Canvas</div>
+    <div class="btn large removeImage">Remove Image</div>
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/camera/index.js
----------------------------------------------------------------------
diff --git a/camera/index.js b/camera/index.js
new file mode 100644
index 0000000..f9435d0
--- /dev/null
+++ b/camera/index.js
@@ -0,0 +1,344 @@
+var deviceReady = false;
+var platformId = cordova.require('cordova/platform').id;
+var pictureUrl = null;
+var fileObj = null;
+var fileEntry = null;
+var pageStartTime = +new Date();
+
+//default camera options
+var camQualityDefault = ['quality value', 50];
+var camDestinationTypeDefault = ['FILE_URI', 1];
+var camPictureSourceTypeDefault = ['CAMERA', 1];
+var camAllowEditDefault = ['allowEdit', false];
+var camEncodingTypeDefault = ['JPEG', 0];
+var camMediaTypeDefault = ['mediaType', 0];
+var camCorrectOrientationDefault = ['correctOrientation', false];
+var camSaveToPhotoAlbumDefault = ['saveToPhotoAlbum', true];
+
+
+//-------------------------------------------------------------------------
+// Camera
+//-------------------------------------------------------------------------
+
+function log(value) {
+    console.log(value);
+    document.getElementById('camera_status').textContent += (new Date() - pageStartTime) / 1000 + ': ' + value + '\n';
+}
+
+function clearStatus() {
+    document.getElementById('camera_status').innerHTML = '';
+    document.getElementById('camera_image').src = 'about:blank';
+    var canvas = document.getElementById('canvas');
+    canvas.width = canvas.height = 1;
+    pictureUrl = null;
+    fileObj = null;
+    fileEntry = null;
+}
+
+function setPicture(url, callback) {
+try {
+  window.atob(url);
+  // if we got here it is a base64 string (DATA_URL)
+  url = "data:image/jpeg;base64," + url;
+} catch (e) {
+  // not DATA_URL
+    log('URL: ' + url.slice(0, 100));
+}    
+
+    pictureUrl = url;
+    var img = document.getElementById('camera_image');
+    var startTime = new Date();
+    img.src = url;
+    img.onloadend = function() {
+        log('Image tag load time: ' + (new Date() - startTime));
+        callback && callback();
+    };
+}
+
+function onGetPictureError(e) {
+    log('Error getting picture: ' + e.code);
+}
+
+function getPictureWin(data) {
+    setPicture(data);
+    // TODO: Fix resolveLocalFileSystemURI to work with native-uri.
+    if (pictureUrl.indexOf('file:') == 0 || pictureUrl.indexOf('content:') == 0) {
+        resolveLocalFileSystemURI(data, function(e) {
+            fileEntry = e;
+            logCallback('resolveLocalFileSystemURI()', true)(e.toURL());
+        }, logCallback('resolveLocalFileSystemURI()', false));
+    } else if (pictureUrl.indexOf('data:image/jpeg;base64' == 0)) {
+      // do nothing
+    } else {
+        var path = pictureUrl.replace(/^file:\/\/(localhost)?/, '').replace(/%20/g, ' ');
+        fileEntry = new FileEntry('image_name.png', path);
+    }
+}
+
+function getPicture() {
+    clearStatus();
+    var options = extractOptions();
+    log('Getting picture with options: ' + JSON.stringify(options));
+    var popoverHandle = navigator.camera.getPicture(getPictureWin, onGetPictureError, options);
+
+    // Reposition the popover if the orientation changes.
+    window.onorientationchange = function() {
+        var newPopoverOptions = new CameraPopoverOptions(0, 0, 100, 100, 0);
+        popoverHandle.setPosition(newPopoverOptions);
+    }
+}
+
+function uploadImage() {
+    var ft = new FileTransfer(),
+        uploadcomplete=0,
+        progress = 0,
+        options = new FileUploadOptions();
+    options.fileKey="photo";
+    options.fileName='test.jpg';
+    options.mimeType="image/jpeg";
+    ft.onprogress = function(progressEvent) {
+        log('progress: ' + progressEvent.loaded + ' of ' + progressEvent.total);
+    };
+    var server = "http://cordova-filetransfer.jitsu.com";
+
+    ft.upload(pictureUrl, server + '/upload', win, fail, options);
+    function win(information_back){
+        log('upload complete');
+    }
+    function fail(message) {
+        log('upload failed: ' + JSON.stringify(message));
+    }
+}
+
+function logCallback(apiName, success) {
+    return function() {
+        log('Call to ' + apiName + (success ? ' success: ' : ' failed: ') + JSON.stringify([].slice.call(arguments)));
+    };
+}
+
+/**
+ * Select image from library using a NATIVE_URI destination type
+ * This calls FileEntry.getMetadata, FileEntry.setMetadata, FileEntry.getParent, FileEntry.file, and FileReader.readAsDataURL.
+ */
+function readFile() {
+    function onFileReadAsDataURL(evt) {
+        var img = document.getElementById('camera_image');
+        img.style.visibility = "visible";
+        img.style.display = "block";
+        img.src = evt.target.result;
+        log("FileReader.readAsDataURL success");
+    };
+
+    function onFileReceived(file) {
+        log('Got file: ' + JSON.stringify(file));
+        fileObj = file;
+
+        var reader = new FileReader();
+        reader.onload = function() {
+            log('FileReader.readAsDataURL() - length = ' + reader.result.length);
+        };
+        reader.onerror = logCallback('FileReader.readAsDataURL', false);
+        reader.readAsDataURL(file);
+    };
+    // Test out onFileReceived when the file object was set via a native <input> elements.
+    if (fileObj) {
+        onFileReceived(fileObj);
+    } else {
+        fileEntry.file(onFileReceived, logCallback('FileEntry.file', false));
+    }
+}
+function getFileInfo() {
+    // Test FileEntry API here.
+    fileEntry.getMetadata(logCallback('FileEntry.getMetadata', true), logCallback('FileEntry.getMetadata', false));
+    fileEntry.setMetadata(logCallback('FileEntry.setMetadata', true), logCallback('FileEntry.setMetadata', false), { "com.apple.MobileBackup": 1 });
+    fileEntry.getParent(logCallback('FileEntry.getParent', true), logCallback('FileEntry.getParent', false));
+    fileEntry.getParent(logCallback('FileEntry.getParent', true), logCallback('FileEntry.getParent', false));
+};
+
+/**
+ * Copy image from library using a NATIVE_URI destination type
+ * This calls FileEntry.copyTo and FileEntry.moveTo.
+ */
+function copyImage() {
+    var onFileSystemReceived = function(fileSystem) {
+        var destDirEntry = fileSystem.root;
+
+        // Test FileEntry API here.
+        fileEntry.copyTo(destDirEntry, 'copied_file.png', logCallback('FileEntry.copyTo', true), logCallback('FileEntry.copyTo', false));
+        fileEntry.moveTo(destDirEntry, 'moved_file.png', logCallback('FileEntry.moveTo', true), logCallback('FileEntry.moveTo', false));
+    };
+
+    window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, onFileSystemReceived, null);
+};
+
+/**
+ * Write image to library using a NATIVE_URI destination type
+ * This calls FileEntry.createWriter, FileWriter.write, and FileWriter.truncate.
+ */
+function writeImage() {
+    var onFileWriterReceived = function(fileWriter) {
+        fileWriter.onwrite = logCallback('FileWriter.write', true);
+        fileWriter.onerror = logCallback('FileWriter.write', false);
+        fileWriter.write("some text!");
+    };
+
+    var onFileTruncateWriterReceived = function(fileWriter) {
+        fileWriter.onwrite = logCallback('FileWriter.truncate', true);
+        fileWriter.onerror = logCallback('FileWriter.truncate', false);
+        fileWriter.truncate(10);
+    };
+
+    fileEntry.createWriter(onFileWriterReceived, logCallback('FileEntry.createWriter', false));
+    fileEntry.createWriter(onFileTruncateWriterReceived, null);
+};
+
+function displayImageUsingCanvas() {
+    var canvas = document.getElementById('canvas');
+    var img = document.getElementById('camera_image');
+    var w = img.width;
+    var h = img.height;
+    h = 100 / w * h;
+    w = 100;
+    canvas.width = w;
+    canvas.height= h;
+    var context = canvas.getContext('2d');
+    context.drawImage(img, 0, 0, w, h);
+};
+
+/**
+ * Remove image from library using a NATIVE_URI destination type
+ * This calls FileEntry.remove.
+ */
+function removeImage() {
+    fileEntry.remove(logCallback('FileEntry.remove', true), logCallback('FileEntry.remove', false));
+};
+
+function testInputTag(inputEl) {
+    clearStatus();
+    // iOS 6 likes to dead-lock in the onchange context if you
+    // do any alerts or try to remote-debug.
+    window.setTimeout(function() {
+        testNativeFile2(inputEl);
+    }, 0);
+};
+
+function testNativeFile2(inputEl) {
+    if (!inputEl.value) {
+        alert('No file selected.');
+        return;
+    }
+    fileObj = inputEl.files[0];
+    if (!fileObj) {
+        alert('Got value but no file.');
+        return;
+    }
+    var URLApi = window.URL || window.webkitURL;
+    if (URLApi) {
+        var blobURL = URLApi.createObjectURL(fileObj);
+        if (blobURL) {
+            setPicture(blobURL, function() {
+                URLApi.revokeObjectURL(blobURL);
+            });
+        } else {
+            log('URL.createObjectURL returned null');
+        }
+    } else {
+        log('URL.createObjectURL() not supported.');
+    }
+}
+
+function extractOptions() {
+    var els = document.querySelectorAll('#image-options select');
+    var ret = {};
+    for (var i = 0, el; el = els[i]; ++i) {
+        var value = el.value;
+        if (value === '') continue;
+        if (el.isBool) {
+            ret[el.keyName] = !!+value;
+        } else {
+            ret[el.keyName] = +value;
+        }
+    }
+    return ret;
+}
+
+function createOptionsEl(name, values, selectionDefault) {
+    var container = document.createElement('div');
+    container.style.display = 'inline-block';
+    container.appendChild(document.createTextNode(name + ': '));
+    var select = document.createElement('select');
+    select.keyName = name;
+    container.appendChild(select);
+    
+    // if we didn't get a default value, insert the blank <default> entry
+    if (selectionDefault == undefined) {
+        var opt = document.createElement('option');
+        opt.value = '';
+        opt.text = '<default>';
+        select.appendChild(opt);
+    }
+    
+    select.isBool = typeof values == 'boolean';
+    if (select.isBool) {
+        values = {'true': 1, 'false': 0};
+    }
+    
+    for (var k in values) {
+        var opt = document.createElement('option');
+        opt.value = values[k];
+        opt.textContent = k;
+        if (selectionDefault) {
+            if (selectionDefault[0] == k) {
+                opt.selected = true;
+            }
+        }
+        select.appendChild(opt);
+    }
+    var optionsDiv = document.getElementById('image-options');
+    optionsDiv.appendChild(container);
+}
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+        deviceReady = true;
+        console.log("Device="+device.platform+" "+device.version);
+        createOptionsEl('sourceType', Camera.PictureSourceType, camPictureSourceTypeDefault);
+        createOptionsEl('destinationType', Camera.DestinationType, camDestinationTypeDefault);
+        createOptionsEl('encodingType', Camera.EncodingType, camEncodingTypeDefault);
+        createOptionsEl('mediaType', Camera.MediaType, camMediaTypeDefault);
+        createOptionsEl('quality', {'0': 0, '50': 50, '80': 80, '100': 100}, camQualityDefault);
+        createOptionsEl('targetWidth', {'50': 50, '200': 200, '800': 800, '2048': 2048});
+        createOptionsEl('targetHeight', {'50': 50, '200': 200, '800': 800, '2048': 2048});
+        createOptionsEl('allowEdit', true, camAllowEditDefault);
+        createOptionsEl('correctOrientation', true, camCorrectOrientationDefault);
+        createOptionsEl('saveToPhotoAlbum', true, camSaveToPhotoAlbumDefault);
+        createOptionsEl('cameraDirection', Camera.Direction);
+                      
+    }, false);
+    window.setTimeout(function() {
+        if (!deviceReady) {
+            alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
+        }
+    },1000);
+};
+
+window.onload = function() {
+  addListenerToClass('getPicture', getPicture);
+  addListenerToClass('testInputTag', function(e) {
+    testInputTag(e.target);
+  }, null, 'change', true);
+  addListenerToClass('getFileInfo', getFileInfo);
+  addListenerToClass('readFile', readFile);
+  addListenerToClass('copyImage', copyImage);
+  addListenerToClass('writeImage', writeImage);
+  addListenerToClass('uploadImage', uploadImage);
+  addListenerToClass('displayImageUsingCanvas', displayImageUsingCanvas);
+  addListenerToClass('removeImage', removeImage);
+
+  addListenerToClass('backBtn', backHome);
+  init();
+}
+

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/capture/index.html
----------------------------------------------------------------------
diff --git a/capture/index.html b/capture/index.html
index 67c35e3..9543341 100644
--- a/capture/index.html
+++ b/capture/index.html
@@ -28,142 +28,9 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>
-
-
-<script type="text/javascript" charset="utf-8">
-
-    var deviceReady = false;
-    var platformId = cordova.require('cordova/platform').id;
-    var pageStartTime = +new Date();
-
-    //-------------------------------------------------------------------------
-    // Camera
-    //-------------------------------------------------------------------------
-
-    function log(value) {
-        console.log(value);
-        document.getElementById('camera_status').textContent += (new Date() - pageStartTime) / 1000 + ': ' + value + '\n';
-    }
-
-    function captureAudioWin(mediaFiles){
-        var path = mediaFiles[0].fullPath;
-        log('Audio captured: ' + path);
-        var m = new Media(path);
-        m.play(); 
-    }
-    
-    function captureAudioFail(e){
-        log('Error getting audio: ' + e.code);
-    }
-    
-    function getAudio(){
-        clearStatus();
-        var options = { limit: 1, duration: 10};
-        navigator.device.capture.captureAudio(captureAudioWin, captureAudioFail, options);
-    }
-    
-    function captureImageWin(mediaFiles){
-        var path = mediaFiles[0].fullPath;
-        log('Image captured: ' + path);    
-        document.getElementById('camera_image').src = path;    
-    }
-    
-    function captureImageFail(e){
-        log('Error getting image: ' + e.code);
-    }
-    
-    function getImage(){
-        clearStatus();
-        var options = { limit: 1 };
-        navigator.device.capture.captureImage(captureImageWin, captureImageFail, options);    
-    }    
-    
-    function captureVideoWin(mediaFiles){
-        var path = mediaFiles[0].fullPath;
-        log('Video captured: ' + path);
-        
-        // need to inject the video element into the html
-        // doesn't seem to work if you have a pre-existing video element and
-        // add in a source tag
-        var vid = document.createElement('video');
-        vid.id="theVideo";
-        vid.width = "320";
-        vid.height= "240";
-        vid.controls = "true";
-        var source_vid = document.createElement('source');
-        source_vid.id = "theSource";
-        source_vid.src = path;
-        vid.appendChild(source_vid);
-        document.getElementById('video_container').appendChild(vid);    
-    }
-    
-    function captureVideoFail(e){
-        log('Error getting video: ' + e.code);
-    }
-    
-    function getVideo(){
-        clearStatus();
-        var options = { limit: 1, duration: 10 };
-        navigator.device.capture.captureVideo(captureVideoWin, captureVideoFail, options);      
-    }
-
-    function resolveMediaFileURL(mediaFile, callback) {
-        resolveLocalFileSystemURL(mediaFile.localURL, function(entry) {
-            log("Resolved by URL: " + mediaFile.localURL);
-            if (callback) callback();
-        }, function(err) {
-            log("Failed to resolve by URL: " + mediaFile.localURL);
-            log("Error: " + JSON.stringify(err));
-            if (callback) callback();
-        });
-    }
-
-    function resolveMediaFile(mediaFile, callback) {
-        resolveLocalFileSystemURL(mediaFile.fullPath, function(entry) {
-            log("Resolved by path: " + mediaFile.fullPath);
-            if (callback) callback();
-        }, function(err) {
-            log("Failed to resolve by path: " + mediaFile.fullPath);
-            log("Error: " + JSON.stringify(err));
-            if (callback) callback();
-        });
-    }
-        
-    function resolveVideo() {
-        clearStatus();
-        var options = { limit: 1, duration: 5 };
-        navigator.device.capture.captureVideo(function(mediaFiles) {
-            captureVideoWin(mediaFiles);
-            resolveMediaFile(mediaFiles[0], function() {
-                resolveMediaFileURL(mediaFiles[0]);
-            });
-        }, captureVideoFail, options);      
-    }
-    
-    function clearStatus() {
-        document.getElementById('camera_status').innerHTML = '';
-        document.getElementById('camera_image').src = 'about:blank';
-    }
-
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-            deviceReady = true;
-            console.log("Device="+device.platform+" "+device.version);
-        }, false);
-        window.setTimeout(function() {
-            if (!deviceReady) {
-                alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
-            }
-        },1000);
-    };
-    
-</script>
-
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
 
     <h1>Capture</h1>
     <div id="info" style="white-space: pre-wrap">
@@ -176,10 +43,10 @@
     <div id="image-options"></div>
 
     <h2>Actions</h2>
-    <div class="btn large" onclick="getAudio();">Capture 10 secs of audio and play</div>
-    <div class="btn large" onclick="getImage();">Capture 1 image</div>
-    <div class="btn large" onclick="getVideo();">Capture 10 secs of video</div>
-    <div class="btn large" onclick="resolveVideo();">Capture 5 secs of video and resolve</div>
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <div class="btn large getAudio">Capture 10 secs of audio and play</div>
+    <div class="btn large getImage">Capture 1 image</div>
+    <div class="btn large getVideo">Capture 10 secs of video</div>
+    <div class="btn large resolveVideo">Capture 5 secs of video and resolve</div>
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/capture/index.js
----------------------------------------------------------------------
diff --git a/capture/index.js b/capture/index.js
new file mode 100644
index 0000000..0f98549
--- /dev/null
+++ b/capture/index.js
@@ -0,0 +1,137 @@
+var deviceReady = false;
+var platformId = cordova.require('cordova/platform').id;
+var pageStartTime = +new Date();
+
+//-------------------------------------------------------------------------
+// Camera
+//-------------------------------------------------------------------------
+
+function log(value) {
+    console.log(value);
+    document.getElementById('camera_status').textContent += (new Date() - pageStartTime) / 1000 + ': ' + value + '\n';
+}
+
+function captureAudioWin(mediaFiles){
+    var path = mediaFiles[0].fullPath;
+    log('Audio captured: ' + path);
+    var m = new Media(path);
+    m.play(); 
+}
+
+function captureAudioFail(e){
+    log('Error getting audio: ' + e.code);
+}
+
+function getAudio(){
+    clearStatus();
+    var options = { limit: 1, duration: 10};
+    navigator.device.capture.captureAudio(captureAudioWin, captureAudioFail, options);
+}
+
+function captureImageWin(mediaFiles){
+    var path = mediaFiles[0].fullPath;
+    log('Image captured: ' + path);    
+    document.getElementById('camera_image').src = path;    
+}
+
+function captureImageFail(e){
+    log('Error getting image: ' + e.code);
+}
+
+function getImage(){
+    clearStatus();
+    var options = { limit: 1 };
+    navigator.device.capture.captureImage(captureImageWin, captureImageFail, options);    
+}    
+
+function captureVideoWin(mediaFiles){
+    var path = mediaFiles[0].fullPath;
+    log('Video captured: ' + path);
+    
+    // need to inject the video element into the html
+    // doesn't seem to work if you have a pre-existing video element and
+    // add in a source tag
+    var vid = document.createElement('video');
+    vid.id="theVideo";
+    vid.width = "320";
+    vid.height= "240";
+    vid.controls = "true";
+    var source_vid = document.createElement('source');
+    source_vid.id = "theSource";
+    source_vid.src = path;
+    vid.appendChild(source_vid);
+    document.getElementById('video_container').appendChild(vid);    
+}
+
+function captureVideoFail(e){
+    log('Error getting video: ' + e.code);
+}
+
+function getVideo(){
+    clearStatus();
+    var options = { limit: 1, duration: 10 };
+    navigator.device.capture.captureVideo(captureVideoWin, captureVideoFail, options);      
+}
+
+function resolveMediaFileURL(mediaFile, callback) {
+    resolveLocalFileSystemURL(mediaFile.localURL, function(entry) {
+        log("Resolved by URL: " + mediaFile.localURL);
+        if (callback) callback();
+    }, function(err) {
+        log("Failed to resolve by URL: " + mediaFile.localURL);
+        log("Error: " + JSON.stringify(err));
+        if (callback) callback();
+    });
+}
+
+function resolveMediaFile(mediaFile, callback) {
+    resolveLocalFileSystemURL(mediaFile.fullPath, function(entry) {
+        log("Resolved by path: " + mediaFile.fullPath);
+        if (callback) callback();
+    }, function(err) {
+        log("Failed to resolve by path: " + mediaFile.fullPath);
+        log("Error: " + JSON.stringify(err));
+        if (callback) callback();
+    });
+}
+    
+function resolveVideo() {
+    clearStatus();
+    var options = { limit: 1, duration: 5 };
+    navigator.device.capture.captureVideo(function(mediaFiles) {
+        captureVideoWin(mediaFiles);
+        resolveMediaFile(mediaFiles[0], function() {
+            resolveMediaFileURL(mediaFiles[0]);
+        });
+    }, captureVideoFail, options);      
+}
+
+function clearStatus() {
+    document.getElementById('camera_status').innerHTML = '';
+    document.getElementById('camera_image').src = 'about:blank';
+}
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+        deviceReady = true;
+        console.log("Device="+device.platform+" "+device.version);
+    }, false);
+    window.setTimeout(function() {
+        if (!deviceReady) {
+            alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
+        }
+    },1000);
+};
+
+
+window.onload = function() {
+  addListenerToClass('getAudio', getAudio);
+  addListenerToClass('getImage', getImage);
+  addListenerToClass('getVideo', getVideo);
+  addListenerToClass('resolveVideo', resolveVideo);
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/compass/index.html
----------------------------------------------------------------------
diff --git a/compass/index.html b/compass/index.html
index 4d6af2c..1734caa 100644
--- a/compass/index.html
+++ b/compass/index.html
@@ -28,111 +28,9 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>      
-
-      
-<script type="text/javascript" charset="utf-8">
-
-    var deviceReady = false;
-
-    function roundNumber(num) {
-        var dec = 3;
-        var result = Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
-        return result;
-    }
-
-    //-------------------------------------------------------------------------
-    // Compass
-    //-------------------------------------------------------------------------
-    var watchCompassId = null;
-
-    /**
-     * Start watching compass
-     */
-    var watchCompass = function() {
-        console.log("watchCompass()");
-
-        // Success callback
-        var success = function(a){
-            document.getElementById('compassHeading').innerHTML = roundNumber(a.magneticHeading);
-        };
-
-        // Fail callback
-        var fail = function(e){
-            console.log("watchCompass fail callback with error code "+e);
-            stopCompass();
-            setCompassStatus(e);
-        };
-
-        // Update heading every 1 sec
-        var opt = {};
-        opt.frequency = 1000;
-        watchCompassId = navigator.compass.watchHeading(success, fail, opt);
-
-        setCompassStatus("Running");
-    };
-
-    /**
-     * Stop watching the acceleration
-     */
-    var stopCompass = function() {
-        setCompassStatus("Stopped");
-        if (watchCompassId) {
-            navigator.compass.clearWatch(watchCompassId);
-            watchCompassId = null;
-        }
-    };
-
-    /**
-     * Get current compass
-     */
-    var getCompass = function() {
-        console.log("getCompass()");
-
-        // Stop compass if running
-        stopCompass();
-
-        // Success callback
-        var success = function(a){
-            document.getElementById('compassHeading').innerHTML = roundNumber(a.magneticHeading);
-        };
-
-        // Fail callback
-        var fail = function(e){
-            console.log("getCompass fail callback with error code "+e);
-            setCompassStatus(e);
-        };
-
-        // Make call
-        var opt = {};
-        navigator.compass.getCurrentHeading(success, fail, opt);
-    };
-
-    /**
-     * Set compass status
-     */
-    var setCompassStatus = function(status) {
-        document.getElementById('compass_status').innerHTML = status;
-    };
-    
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-                deviceReady = true;
-                console.log("Device="+device.platform+" "+device.version);
-            }, false);
-        window.setTimeout(function() {
-        	if (!deviceReady) {
-        		alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
-        	}
-        },1000);
-    }
-
-</script>
-
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>Compass</h1>
     <div id="info">
@@ -142,9 +40,9 @@
         </tr></table>
     </div>
     <h2>Action</h2>
-    <div class="btn large" onclick="getCompass();">Get Compass</div>
-    <div class="btn large" onclick="watchCompass();">Start Watching Compass</div>
-    <div class="btn large" onclick="stopCompass();">Stop Watching Compass</div>
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <div class="btn large getCompass">Get Compass</div>
+    <div class="btn large watchCompass">Start Watching Compass</div>
+    <div class="btn large stopCompass">Stop Watching Compass</div>
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>      

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/compass/index.js
----------------------------------------------------------------------
diff --git a/compass/index.js b/compass/index.js
new file mode 100644
index 0000000..0735ab2
--- /dev/null
+++ b/compass/index.js
@@ -0,0 +1,104 @@
+var deviceReady = false;
+
+function roundNumber(num) {
+    var dec = 3;
+    var result = Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
+    return result;
+}
+
+//-------------------------------------------------------------------------
+// Compass
+//-------------------------------------------------------------------------
+var watchCompassId = null;
+
+/**
+ * Start watching compass
+ */
+var watchCompass = function() {
+    console.log("watchCompass()");
+
+    // Success callback
+    var success = function(a){
+        document.getElementById('compassHeading').innerHTML = roundNumber(a.magneticHeading);
+    };
+
+    // Fail callback
+    var fail = function(e){
+        console.log("watchCompass fail callback with error code "+e);
+        stopCompass();
+        setCompassStatus(e);
+    };
+
+    // Update heading every 1 sec
+    var opt = {};
+    opt.frequency = 1000;
+    watchCompassId = navigator.compass.watchHeading(success, fail, opt);
+
+    setCompassStatus("Running");
+};
+
+/**
+ * Stop watching the acceleration
+ */
+var stopCompass = function() {
+    setCompassStatus("Stopped");
+    if (watchCompassId) {
+        navigator.compass.clearWatch(watchCompassId);
+        watchCompassId = null;
+    }
+};
+
+/**
+ * Get current compass
+ */
+var getCompass = function() {
+    console.log("getCompass()");
+
+    // Stop compass if running
+    stopCompass();
+
+    // Success callback
+    var success = function(a){
+        document.getElementById('compassHeading').innerHTML = roundNumber(a.magneticHeading);
+    };
+
+    // Fail callback
+    var fail = function(e){
+        console.log("getCompass fail callback with error code "+e);
+        setCompassStatus(e);
+    };
+
+    // Make call
+    var opt = {};
+    navigator.compass.getCurrentHeading(success, fail, opt);
+};
+
+/**
+ * Set compass status
+ */
+var setCompassStatus = function(status) {
+    document.getElementById('compass_status').innerHTML = status;
+};
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+            deviceReady = true;
+            console.log("Device="+device.platform+" "+device.version);
+        }, false);
+    window.setTimeout(function() {
+      if (!deviceReady) {
+        alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
+      }
+    },1000);
+}
+
+window.onload = function() {
+  addListenerToClass('getCompass', getCompass);
+  addListenerToClass('watchCompass', watchCompass);
+  addListenerToClass('stopCompass', stopCompass);
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/contacts/index.html
----------------------------------------------------------------------
diff --git a/contacts/index.html b/contacts/index.html
index b6a3a92..5782713 100644
--- a/contacts/index.html
+++ b/contacts/index.html
@@ -28,98 +28,10 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>      
-
-      
-<script type="text/javascript" charset="utf-8">
-
-    var deviceReady = false;
-
-    //-------------------------------------------------------------------------
-    // Contacts
-    //-------------------------------------------------------------------------
-    function getContacts() {
-        obj = new ContactFindOptions();
-        // show all contacts, so don't filter
-        obj.multiple = true;
-        navigator.contacts.find(
-            ["displayName", "name", "phoneNumbers", "emails", "urls", "note"],
-            function(contacts) {
-                var s = "";
-                if (contacts.length == 0) {
-                    s = "No contacts found";
-                }
-                else {
-                    s = "Number of contacts: "+contacts.length+"<br><table width='100%'><tr><th>Name</th><td>Phone</td><td>Email</td></tr>";
-                    for (var i=0; i<contacts.length; i++) {
-                        var contact = contacts[i];
-                        s = s + "<tr><td>" + contact.name.formatted + "</td><td>";
-                        if (contact.phoneNumbers && contact.phoneNumbers.length > 0) {
-                            s = s + contact.phoneNumbers[0].value;
-                        }
-                        s = s + "</td><td>"
-                        if (contact.emails && contact.emails.length > 0) {
-                            s = s + contact.emails[0].value;
-                        }
-                        s = s + "</td></tr>";
-                    }
-                    s = s + "</table>";
-                }
-                document.getElementById('contacts_results').innerHTML = s;
-            },
-            function(e) {
-                document.getElementById('contacts_results').innerHTML = "Error: "+e.code;
-            },
-            obj);
-    };
-
-    function addContact(){
-        console.log("addContact()");
-        try{
-            var contact = navigator.contacts.create({"displayName": "Dooney Evans"});
-            var contactName = {
-                formatted: "Dooney Evans",
-                familyName: "Evans",
-                givenName: "Dooney",
-                middleName: ""
-            };
-
-            contact.name = contactName;
-
-            var phoneNumbers = [1];
-            phoneNumbers[0] = new ContactField('work', '512-555-1234', true);
-            contact.phoneNumbers = phoneNumbers;
-
-            contact.save(
-                function() { alert("Contact saved.");},
-                function(e) { alert("Contact save failed: " + e.code); }
-            );
-            console.log("you have saved the contact");
-        }
-        catch (e){
-            alert(e);
-        }
-
-    };
-    
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-                deviceReady = true;
-                console.log("Device="+device.platform+" "+device.version);
-            }, false);
-        window.setTimeout(function() {
-        	if (!deviceReady) {
-        		alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
-        	}
-        },1000);
-    }
-
-</script>
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
 
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>Contacts</h1>    
     <div id="info">
@@ -127,8 +39,9 @@
         <span id="contacts_results"> </span>
     </div>
     <h2>Action</h2>
-    <div class="btn large" onclick="getContacts();">Get phone's contacts</div>
-    <div class="btn large" onclick="addContact();">Add a new contact 'Dooney Evans'</div>
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+
+    <div class="btn large getContacts">Get phone's contacts</div>
+    <div class="btn large addContact">Add a new contact 'Dooney Evans'</div>
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>      

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/contacts/index.js
----------------------------------------------------------------------
diff --git a/contacts/index.js b/contacts/index.js
new file mode 100644
index 0000000..d3f3312
--- /dev/null
+++ b/contacts/index.js
@@ -0,0 +1,90 @@
+var deviceReady = false;
+
+//-------------------------------------------------------------------------
+// Contacts
+//-------------------------------------------------------------------------
+function getContacts() {
+    obj = new ContactFindOptions();
+    // show all contacts, so don't filter
+    obj.multiple = true;
+    navigator.contacts.find(
+        ["displayName", "name", "phoneNumbers", "emails", "urls", "note"],
+        function(contacts) {
+            var s = "";
+            if (contacts.length == 0) {
+                s = "No contacts found";
+            }
+            else {
+                s = "Number of contacts: "+contacts.length+"<br><table width='100%'><tr><th>Name</th><td>Phone</td><td>Email</td></tr>";
+                for (var i=0; i<contacts.length; i++) {
+                    var contact = contacts[i];
+                    s = s + "<tr><td>" + contact.name.formatted + "</td><td>";
+                    if (contact.phoneNumbers && contact.phoneNumbers.length > 0) {
+                        s = s + contact.phoneNumbers[0].value;
+                    }
+                    s = s + "</td><td>"
+                    if (contact.emails && contact.emails.length > 0) {
+                        s = s + contact.emails[0].value;
+                    }
+                    s = s + "</td></tr>";
+                }
+                s = s + "</table>";
+            }
+            document.getElementById('contacts_results').innerHTML = s;
+        },
+        function(e) {
+            document.getElementById('contacts_results').innerHTML = "Error: "+e.code;
+        },
+        obj);
+};
+
+function addContact(){
+    try{
+        var contact = navigator.contacts.create({"displayName": "Dooney Evans"});
+        var contactName = {
+            formatted: "Dooney Evans",
+            familyName: "Evans",
+            givenName: "Dooney",
+            middleName: ""
+        };
+
+        contact.name = contactName;
+
+        var phoneNumbers = [1];
+        phoneNumbers[0] = new ContactField('work', '512-555-1234', true);
+        contact.phoneNumbers = phoneNumbers;
+
+        contact.save(
+            function() { alert("Contact saved.");},
+            function(e) { alert("Contact save failed: " + e.code); }
+        );
+        console.log("you have saved the contact");
+    }
+    catch (e){
+        alert(e);
+    }
+
+};
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+            deviceReady = true;
+            console.log("Device="+device.platform+" "+device.version);
+        }, false);
+    window.setTimeout(function() {
+      if (!deviceReady) {
+        alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
+      }
+    },1000);
+}
+
+
+window.onload = function() {
+  addListenerToClass('getContacts', getContacts);
+  addListenerToClass('addContact', addContact);
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/cordova-incl.js
----------------------------------------------------------------------
diff --git a/cordova-incl.js b/cordova-incl.js
index 96f3354..713dc1b 100644
--- a/cordova-incl.js
+++ b/cordova-incl.js
@@ -56,6 +56,28 @@ if (!window._doNotWriteCordovaScript) {
     }
 }
 
+function addListenerToClass(className, listener, argsArray, action, doNotWrap) {
+    if (!action) {
+      action='click';
+    }
+    var elements = document.getElementsByClassName(className);
+    // choose Event target as a scope (like inline scripts)
+    if (!doNotWrap) {
+      if (argsArray && !Array.isArray(argsArray)) {
+        argsArray = [argsArray];
+      }
+      function callListener(e) {
+        listener.apply(null, argsArray);
+      }
+    } else {
+      callListener = listener;
+    }
+    for (var i = 0; i < elements.length; ++i) {
+      var item = elements[i];  
+      item.addEventListener(action, callListener, false);
+    }
+};
+
 function backHome() {
     if (window.device && device.platform && (device.platform.toLowerCase() == 'android' || device.platform.toLowerCase() == 'amazon-fireos')) {
         navigator.app.backHistory();

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/events/index.html
----------------------------------------------------------------------
diff --git a/events/index.html b/events/index.html
index d2ad8d4..3f45021 100644
--- a/events/index.html
+++ b/events/index.html
@@ -28,60 +28,10 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>      
-
-      
-<script type="text/javascript" charset="utf-8">
-
-    var deviceReady = false;
-
-    function interceptBackbutton() {
-    	eventOutput("Back button intercepted");
-    }
-    function interceptMenubutton() {
-    	eventOutput("Menu button intercepted");
-    }
-    function interceptSearchbutton() {
-    	eventOutput("Search button intercepted");
-    }
-    function interceptResume() {
-      eventOutput("Resume event intercepted");
-    }
-    function interceptPause() {
-      eventOutput("Pause event intercepted");
-    }
-    function interceptOnline() {
-      eventOutput("Online event intercepted");
-    }
-    function interceptOffline() {
-      eventOutput("Offline event intercepted");
-    }
-    
-    var eventOutput = function(s) {
-        var el = document.getElementById("results");
-        el.innerHTML = el.innerHTML + s + "<br>";
-    };
-
-    
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-                deviceReady = true;
-                console.log("Device="+device.platform+" "+device.version);
-                eventOutput("deviceready event: "+device.platform+" "+device.version);
-            }, false);
-        window.setTimeout(function() {
-        	if (!deviceReady) {
-        		alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
-        	}
-        },1000);
-    }
-
-</script>
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
 
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>Events</h1>
     <div id="info">
@@ -90,21 +40,21 @@
     </div>
     <input type="text" value="Type here to test events when fields are focused" />
     <h2>Action</h2>
-    <div class="btn large" onclick="document.addEventListener('backbutton', interceptBackbutton, false);">Intercept backbutton</div>
-    <div class="btn large" onclick="document.removeEventListener('backbutton', interceptBackbutton, false);">Stop intercept of backbutton</div>
-    <div class="btn large" onclick="document.addEventListener('menubutton', interceptMenubutton, false);">Intercept menubutton</div>
-    <div class="btn large" onclick="document.removeEventListener('menubutton', interceptMenubutton, false);">Stop intercept of menubutton</div>
-    <div class="btn large" onclick="document.addEventListener('searchbutton', interceptSearchbutton, false);">Intercept searchbutton</div>
-    <div class="btn large" onclick="document.removeEventListener('searchbutton', interceptSearchbutton, false);">Stop intercept of searchbutton</div>
-    <div class="btn large" onclick="document.addEventListener('resume', interceptResume, false);">Intercept resume</div>
-    <div class="btn large" onclick="document.removeEventListener('resume', interceptResume, false);">Stop intercept of resume</div>
-    <div class="btn large" onclick="document.addEventListener('pause', interceptPause, false);">Intercept pause</div>
-    <div class="btn large" onclick="document.removeEventListener('pause', interceptPause, false);">Stop intercept of pause</div>
-    <div class="btn large" onclick="document.addEventListener('online', interceptOnline, false);">Intercept online</div>
-    <div class="btn large" onclick="document.removeEventListener('online', interceptOnline, false);">Stop intercept of online</div>
-    <div class="btn large" onclick="document.addEventListener('offline', interceptOffline, false);">Intercept offline</div>
-    <div class="btn large" onclick="document.removeEventListener('offline', interceptOffline, false);">Stop intercept of offline</div>
-
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <div class="btn large interceptBackButton">Intercept backbutton</div>
+    <div class="btn large stopInterceptOfBackButton">Stop intercept of backbutton</div>
+    <div class="btn large interceptMenuButton">Intercept menubutton</div>
+    <div class="btn large stopInterceptOfMenuButton">Stop intercept of menubutton</div>
+    <div class="btn large interceptSearchButton">Intercept searchbutton</div>
+    <div class="btn large stopInterceptOfSearchButton">Stop intercept of searchbutton</div>
+    <div class="btn large interceptResume">Intercept resume</div>
+    <div class="btn large stopInterceptOfResume">Stop intercept of resume</div>
+    <div class="btn large interceptPause">Intercept pause</div>
+    <div class="btn large stopInterceptOfPause">Stop intercept of pause</div>
+    <div class="btn large interceptOnline">Intercept online</div>
+    <div class="btn large stopInterceptOfOnline">Stop intercept of online</div>
+    <div class="btn large interceptOffline">Intercept offline</div>
+    <div class="btn large stopInterceptOfOffline">Stop intercept of offline</div>
+
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/events/index.js
----------------------------------------------------------------------
diff --git a/events/index.js b/events/index.js
new file mode 100644
index 0000000..e1bb922
--- /dev/null
+++ b/events/index.js
@@ -0,0 +1,94 @@
+var deviceReady = false;
+
+function interceptBackbutton() {
+  eventOutput("Back button intercepted");
+}
+function interceptMenubutton() {
+  eventOutput("Menu button intercepted");
+}
+function interceptSearchbutton() {
+  eventOutput("Search button intercepted");
+}
+function interceptResume() {
+  eventOutput("Resume event intercepted");
+}
+function interceptPause() {
+  eventOutput("Pause event intercepted");
+}
+function interceptOnline() {
+  eventOutput("Online event intercepted");
+}
+function interceptOffline() {
+  eventOutput("Offline event intercepted");
+}
+
+var eventOutput = function(s) {
+    var el = document.getElementById("results");
+    el.innerHTML = el.innerHTML + s + "<br>";
+};
+
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+            deviceReady = true;
+            console.log("Device="+device.platform+" "+device.version);
+            eventOutput("deviceready event: "+device.platform+" "+device.version);
+        }, false);
+    window.setTimeout(function() {
+      if (!deviceReady) {
+        alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
+      }
+    },1000);
+}
+
+
+window.onload = function() {
+  addListenerToClass('interceptBackButton', function() {
+    document.addEventListener('backbutton', interceptBackbutton, false);
+  });
+  addListenerToClass('stopInterceptOfBackButton', function() {
+    document.removeEventListener('backbutton', interceptBackbutton, false);
+  });
+  addListenerToClass('interceptMenuButton', function() {
+    document.addEventListener('menubutton', interceptMenubutton, false);
+  });
+  addListenerToClass('stopInterceptOfMenuButton', function() {
+    document.removeEventListener('menubutton', interceptMenubutton, false);
+  });
+  addListenerToClass('interceptSearchButton', function() {
+    document.addEventListener('searchbutton', interceptSearchbutton, false);
+  });
+  addListenerToClass('stopInterceptOfSearchButton', function() {
+    document.removeEventListener('searchbutton', interceptSearchbutton, false);
+  });
+  addListenerToClass('interceptResume', function() {
+    document.addEventListener('resume', interceptResume, false);
+  });
+  addListenerToClass('stopInterceptOfResume', function() {
+    document.removeEventListener('resume', interceptResume, false);
+  });
+  addListenerToClass('interceptPause', function() {
+    document.addEventListener('pause', interceptPause, false);
+  });
+  addListenerToClass('stopInterceptOfPause', function() {
+    document.removeEventListener('pause', interceptPause, false);
+  });
+  addListenerToClass('interceptOnline', function() {
+    document.addEventListener('online', interceptOnline, false);
+  });
+  addListenerToClass('stopInterceptOfOnline', function() {
+    document.removeEventListener('online', interceptOnline, false);
+  });
+  addListenerToClass('interceptOffline', function() {
+    document.addEventListener('offline', interceptOffline, false);
+  });
+  addListenerToClass('stopInterceptOfOffline', function() {
+    document.removeEventListener('offline', interceptOffline, false);
+  });
+
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/file/index.html
----------------------------------------------------------------------
diff --git a/file/index.html b/file/index.html
index 033b97d..8f00e86 100644
--- a/file/index.html
+++ b/file/index.html
@@ -28,162 +28,10 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>
-
-
-<script type="text/javascript" charset="utf-8">
-
-    var deviceReady = false;
-
-    var imageURL = "http://apache.org/images/feather-small.gif";
-    var videoURL = "http://techslides.com/demos/sample-videos/small.mp4";
-
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-                deviceReady = true;
-                console.log("Device="+device.platform+" "+device.version);
-                bindEvents();
-                document.body.classList.add(device.platform.toLowerCase() + "-platform");
-            }, false);
-        window.setTimeout(function() {
-            if (!deviceReady) {
-                alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
-            }
-        },1000);
-    }
-
-    function bindEvents() {
-        document.getElementById('downloadImgCDV').addEventListener('click', downloadImgCDV, false);
-        document.getElementById('downloadImgNative').addEventListener('click', downloadImgNative, false);
-        document.getElementById('downloadVideoCDV').addEventListener('click', downloadVideoCDV, false);
-        document.getElementById('downloadVideoNative').addEventListener('click', downloadVideoNative, false);
-        document.getElementById('testPrivateURL').addEventListener('click', testPrivateURL, false);
-        var fsButtons = document.querySelectorAll('.resolveFs');
-        for (var i=0; i < fsButtons.length; ++i) {
-            fsButtons[i].addEventListener('click', resolveFs, false);
-        }
-    }
-
-    function clearLog() {
-        var log = document.getElementById("log");
-        log.innerHTML = "";
-    }
-
-    function logMessage(message, color) {
-        var log = document.getElementById("log");
-        var logLine = document.createElement('div');
-        if (color) {
-            logLine.style.color = color;
-        }
-        logLine.innerHTML = message;
-        log.appendChild(logLine);
-    }
-
-    function logError(serviceName) {
-        return function(err) {
-            logMessage("ERROR: " + serviceName + " " + JSON.stringify(err), "red");
-        };
-    }
-
-    function downloadImgCDV(ev) {
-        ev.preventDefault();
-        ev.stopPropagation();
-        downloadImg(imageURL, function(entry) { return entry.toURL(); }, new Image());
-    }
-
-    function downloadImgNative(ev) {
-        ev.preventDefault();
-        ev.stopPropagation();
-        downloadImg(imageURL, function(entry) { return entry.toNativeURL(); }, new Image);
-    }
-
-    function downloadVideoCDV(ev) {
-        ev.preventDefault();
-        ev.stopPropagation();
-        var videoElement = document.createElement('video');
-        videoElement.controls = "controls";
-        downloadImg(videoURL, function(entry) { return entry.toURL(); }, videoElement);
-    }
-
-    function downloadVideoNative(ev) {
-        ev.preventDefault();
-        ev.stopPropagation();
-        var videoElement = document.createElement('video');
-        videoElement.controls = "controls";
-        downloadImg(videoURL, function(entry) { return entry.toNativeURL(); }, videoElement);
-    }
-
-    function downloadImg(source, urlFn, element) {
-        var filename = source.substring(source.lastIndexOf("/")+1);
-        function download(fileSystem) {
-            var ft = new FileTransfer();
-            logMessage("Starting download");
-            ft.download(source, fileSystem.root.toURL() + filename, function(entry) {
-                logMessage("Download complete")
-                element.src = urlFn(entry)
-                logMessage("Src URL is " + element.src, "green");
-                logMessage("Inserting element");
-                document.getElementById("output").appendChild(element);
-            }, logError("ft.download"));
-        }
-        clearLog();
-        logMessage("Requesting filesystem");
-        requestFileSystem(TEMPORARY, 0, function(fileSystem) {
-            logMessage("Checking for existing file");
-            fileSystem.root.getFile(filename, {create: false}, function(entry) {
-                logMessage("Removing existing file");
-                entry.remove(function() {
-                    download(fileSystem);
-                }, logError("entry.remove"));
-            }, function() {
-                download(fileSystem);
-            });
-        }, logError("requestFileSystem"));
-    }
-
-    function testPrivateURL(ev) {
-        ev.preventDefault();
-        ev.stopPropagation();
-        requestFileSystem(TEMPORARY, 0, function(fileSystem) {
-            logMessage("Temporary root is at " + fileSystem.root.toNativeURL());
-            fileSystem.root.getFile("testfile", {create: true}, function(entry) {
-                logMessage("Temporary file is at " + entry.toNativeURL());
-                if (entry.toNativeURL().substring(0,12) == "file:///var/") {
-                    logMessage("File starts with /var/, trying /private/var");
-                    var newURL = "file://localhost/private/var/" + entry.toNativeURL().substring(12) + "?and=another_thing";
-                    //var newURL = entry.toNativeURL();
-                    logMessage(newURL, 'blue');
-                    resolveLocalFileSystemURL(newURL, function(newEntry) {
-                        logMessage("Successfully resolved.", 'green');
-                        logMessage(newEntry.toURL(), 'blue');
-                        logMessage(newEntry.toNativeURL(), 'blue');
-                    }, logError("resolveLocalFileSystemURL"));
-                }
-            }, logError("getFile"));
-        }, logError("requestFileSystem"));
-    }
-
-    function resolveFs(ev) {
-        var fsURL = "cdvfile://localhost/" + ev.target.getAttribute('data-fsname') + "/";
-        logMessage("Resolving URL: " + fsURL);
-        resolveLocalFileSystemURL(fsURL, function(entry) {
-            logMessage("Success", 'green');
-            logMessage(entry.toURL(), 'blue');
-            logMessage(entry.toInternalURL(), 'blue');
-            logMessage("Resolving URL: " + entry.toURL());
-            resolveLocalFileSystemURL(entry.toURL(), function(entry2) {
-                logMessage("Success", 'green');
-                logMessage(entry2.toURL(), 'blue');
-                logMessage(entry2.toInternalURL(), 'blue');
-            }, logError("resolveLocalFileSystemURL"));
-        }, logError("resolveLocalFileSystemURL"));
-    }
-</script>
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
 
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
 
     <h1>File and File Transfer</h1>
     <h2>File</h2>
@@ -219,6 +67,6 @@
 
     <div id="log"></div>
     <div id="output"></div>
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/0de5e956/file/index.js
----------------------------------------------------------------------
diff --git a/file/index.js b/file/index.js
new file mode 100644
index 0000000..1f570dd
--- /dev/null
+++ b/file/index.js
@@ -0,0 +1,153 @@
+var deviceReady = false;
+
+var imageURL = "http://apache.org/images/feather-small.gif";
+var videoURL = "http://techslides.com/demos/sample-videos/small.mp4";
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+            deviceReady = true;
+            console.log("Device="+device.platform+" "+device.version);
+            bindEvents();
+            document.body.classList.add(device.platform.toLowerCase() + "-platform");
+        }, false);
+    window.setTimeout(function() {
+        if (!deviceReady) {
+            alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
+        }
+    },1000);
+}
+
+function bindEvents() {
+    document.getElementById('downloadImgCDV').addEventListener('click', downloadImgCDV, false);
+    document.getElementById('downloadImgNative').addEventListener('click', downloadImgNative, false);
+    document.getElementById('downloadVideoCDV').addEventListener('click', downloadVideoCDV, false);
+    document.getElementById('downloadVideoNative').addEventListener('click', downloadVideoNative, false);
+    document.getElementById('testPrivateURL').addEventListener('click', testPrivateURL, false);
+    var fsButtons = document.querySelectorAll('.resolveFs');
+    for (var i=0; i < fsButtons.length; ++i) {
+        fsButtons[i].addEventListener('click', resolveFs, false);
+    }
+}
+
+function clearLog() {
+    var log = document.getElementById("log");
+    log.innerHTML = "";
+}
+
+function logMessage(message, color) {
+    var log = document.getElementById("log");
+    var logLine = document.createElement('div');
+    if (color) {
+        logLine.style.color = color;
+    }
+    logLine.innerHTML = message;
+    log.appendChild(logLine);
+}
+
+function logError(serviceName) {
+    return function(err) {
+        logMessage("ERROR: " + serviceName + " " + JSON.stringify(err), "red");
+    };
+}
+
+function downloadImgCDV(ev) {
+    ev.preventDefault();
+    ev.stopPropagation();
+    downloadImg(imageURL, function(entry) { return entry.toURL(); }, new Image());
+}
+
+function downloadImgNative(ev) {
+    ev.preventDefault();
+    ev.stopPropagation();
+    downloadImg(imageURL, function(entry) { return entry.toNativeURL(); }, new Image);
+}
+
+function downloadVideoCDV(ev) {
+    ev.preventDefault();
+    ev.stopPropagation();
+    var videoElement = document.createElement('video');
+    videoElement.controls = "controls";
+    downloadImg(videoURL, function(entry) { return entry.toURL(); }, videoElement);
+}
+
+function downloadVideoNative(ev) {
+    ev.preventDefault();
+    ev.stopPropagation();
+    var videoElement = document.createElement('video');
+    videoElement.controls = "controls";
+    downloadImg(videoURL, function(entry) { return entry.toNativeURL(); }, videoElement);
+}
+
+function downloadImg(source, urlFn, element) {
+    var filename = source.substring(source.lastIndexOf("/")+1);
+    function download(fileSystem) {
+        var ft = new FileTransfer();
+        logMessage("Starting download");
+        ft.download(source, fileSystem.root.toURL() + filename, function(entry) {
+            logMessage("Download complete")
+            element.src = urlFn(entry)
+            logMessage("Src URL is " + element.src, "green");
+            logMessage("Inserting element");
+            document.getElementById("output").appendChild(element);
+        }, logError("ft.download"));
+    }
+    clearLog();
+    logMessage("Requesting filesystem");
+    requestFileSystem(TEMPORARY, 0, function(fileSystem) {
+        logMessage("Checking for existing file");
+        fileSystem.root.getFile(filename, {create: false}, function(entry) {
+            logMessage("Removing existing file");
+            entry.remove(function() {
+                download(fileSystem);
+            }, logError("entry.remove"));
+        }, function() {
+            download(fileSystem);
+        });
+    }, logError("requestFileSystem"));
+}
+
+function testPrivateURL(ev) {
+    ev.preventDefault();
+    ev.stopPropagation();
+    requestFileSystem(TEMPORARY, 0, function(fileSystem) {
+        logMessage("Temporary root is at " + fileSystem.root.toNativeURL());
+        fileSystem.root.getFile("testfile", {create: true}, function(entry) {
+            logMessage("Temporary file is at " + entry.toNativeURL());
+            if (entry.toNativeURL().substring(0,12) == "file:///var/") {
+                logMessage("File starts with /var/, trying /private/var");
+                var newURL = "file://localhost/private/var/" + entry.toNativeURL().substring(12) + "?and=another_thing";
+                //var newURL = entry.toNativeURL();
+                logMessage(newURL, 'blue');
+                resolveLocalFileSystemURL(newURL, function(newEntry) {
+                    logMessage("Successfully resolved.", 'green');
+                    logMessage(newEntry.toURL(), 'blue');
+                    logMessage(newEntry.toNativeURL(), 'blue');
+                }, logError("resolveLocalFileSystemURL"));
+            }
+        }, logError("getFile"));
+    }, logError("requestFileSystem"));
+}
+
+function resolveFs(ev) {
+    var fsURL = "cdvfile://localhost/" + ev.target.getAttribute('data-fsname') + "/";
+    logMessage("Resolving URL: " + fsURL);
+    resolveLocalFileSystemURL(fsURL, function(entry) {
+        logMessage("Success", 'green');
+        logMessage(entry.toURL(), 'blue');
+        logMessage(entry.toInternalURL(), 'blue');
+        logMessage("Resolving URL: " + entry.toURL());
+        resolveLocalFileSystemURL(entry.toURL(), function(entry2) {
+            logMessage("Success", 'green');
+            logMessage(entry2.toURL(), 'blue');
+            logMessage(entry2.toInternalURL(), 'blue');
+        }, logError("resolveLocalFileSystemURL"));
+    }, logError("resolveLocalFileSystemURL"));
+}
+
+window.onload = function() {
+  addListenerToClass('backBtn', backHome);
+  init();
+}


[02/12] Manual tests fixed

Posted by za...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/inappbrowser/index.html
----------------------------------------------------------------------
diff --git a/inappbrowser/index.html b/inappbrowser/index.html
index b0c1ad0..b06ed11 100644
--- a/inappbrowser/index.html
+++ b/inappbrowser/index.html
@@ -28,177 +28,9 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>      
-
-      
-    <script type="text/javascript" charset="utf-8">
-
-    var deviceReady = false;
-    
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-                deviceReady = true;
-                console.log("Device="+device.platform+" "+device.version);
-            }, false);
-        function updateUserAgent() {
-            document.getElementById("user-agent").textContent = navigator.userAgent;
-        }
-        updateUserAgent();
-        window.setInterval(updateUserAgent, 1500);
-        window.setTimeout(function() {
-        	if (!deviceReady) {
-        		alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
-        	}
-        },1000);
-    }
-
-    function doOpen(url, target, params, numExpectedRedirects) {
-        numExpectedRedirects = numExpectedRedirects || 0;
-        var iab = window.open(url, target, params);
-        if (!iab) {
-            alert('window.open returned ' + iab);
-            return;
-        }
-        var counts;
-        var lastLoadStartURL;
-        var wasReset = false;
-        function reset()  {
-            counts = {
-                'loaderror': 0,
-                'loadstart': 0,
-                'loadstop': 0,
-                'exit': 0
-            };
-            lastLoadStartURL = '';
-        }
-        reset();
-
-        function logEvent(e) {
-            console.log('IAB event=' + JSON.stringify(e));
-            counts[e.type]++;
-            // Verify that event.url gets updated on redirects.
-            if (e.type == 'loadstart') {
-                if (e.url == lastLoadStartURL) {
-                    alert('Unexpected: loadstart fired multiple times for the same URL.');
-                }
-                lastLoadStartURL = e.url;
-            }
-            // Verify the right number of loadstart events were fired.
-            if (e.type == 'loadstop' || e.type == 'loaderror') {
-                if (e.url != lastLoadStartURL) {
-                    alert('Unexpected: ' + e.type + ' event.url != loadstart\'s event.url');
-                }
-                if (numExpectedRedirects === 0 && counts['loadstart'] !== 1) {
-                    // Do allow a loaderror without a loadstart (e.g. in the case of an invalid URL).
-                    if (!(e.type == 'loaderror' && counts['loadstart'] === 0)) {
-                        alert('Unexpected: got multiple loadstart events. (' + counts['loadstart'] + ')');
-                    }
-                } else if (numExpectedRedirects > 0 && counts['loadstart'] < (numExpectedRedirects+1)) {
-                    alert('Unexpected: should have got at least ' + (numExpectedRedirects+1) + ' loadstart events, but got ' + counts['loadstart']);
-                }
-                wasReset = true;
-                numExpectedRedirects = 0;
-                reset();
-            }
-            // Verify that loadend / loaderror was called.
-            if (e.type == 'exit') {
-                var numStopEvents = counts['loadstop'] + counts['loaderror'];
-                if (numStopEvents === 0 && !wasReset) {
-                    alert('Unexpected: browser closed without a loadstop or loaderror.')
-                } else if (numStopEvents > 1) {
-                    alert('Unexpected: got multiple loadstop/loaderror events.');
-                }
-            }
-        }
-        iab.addEventListener('loaderror', logEvent);
-        iab.addEventListener('loadstart', logEvent);
-        iab.addEventListener('loadstop', logEvent);
-        iab.addEventListener('exit', logEvent);
-
-        return iab;
-    }
-
-    function openWithStyle(url, cssUrl, useCallback) {
-        var iab = doOpen(url, '_blank', 'location=yes');
-        var callback = function(results) {
-            if (results && results.length === 0) {
-                alert('Results verified');
-            } else {
-                console.log(results);
-                alert('Got: ' + typeof(results) + '\n' + JSON.stringify(results));
-            }
-        };
-        if (cssUrl) {
-            iab.addEventListener('loadstop', function(event) {
-                iab.insertCSS({file: cssUrl}, useCallback && callback);
-            });
-        } else {
-            iab.addEventListener('loadstop', function(event) {
-                iab.insertCSS({code:'#style-update-literal { \ndisplay: block !important; \n}'},
-                              useCallback && callback);
-            });
-        }
-    }
-
-    function openWithScript(url, jsUrl, useCallback) {
-        var iab = doOpen(url, '_blank', 'location=yes');
-        if (jsUrl) {
-            iab.addEventListener('loadstop', function(event) {
-                iab.executeScript({file: jsUrl}, useCallback && function(results) {
-                    if (results && results.length === 0) {
-                        alert('Results verified');
-                    } else {
-                        console.log(results);
-                        alert('Got: ' + typeof(results) + '\n' + JSON.stringify(results));
-                    }
-                });
-            });
-        } else {
-            iab.addEventListener('loadstop', function(event) {
-                var code = '(function(){\n' +
-                  '    var header = document.getElementById("header");\n' +
-                  '    header.innerHTML = "Script literal successfully injected";\n' +
-                  '    return "abc";\n' +
-                  '})()';
-                iab.executeScript({code:code}, useCallback && function(results) {
-                    if (results && results.length === 1 && results[0] === 'abc') {
-                        alert('Results verified');
-                    } else {
-                        console.log(results);
-                        alert('Got: ' + typeof(results) + '\n' + JSON.stringify(results));
-                    }
-                });
-            });
-        }
-    }
-    var hiddenwnd=null;
-    var loadlistener = function(event) { alert('background window loaded ' ); };
-    function openHidden(url, startHidden) {
-        var shopt =(startHidden) ? 'hidden=yes' : '';
-        hiddenwnd = window.open(url,'random_string',shopt);
-        if (!hiddenwnd) {
-            alert('window.open returned ' + hiddenwnd);
-            return;
-        }
-        if(startHidden) hiddenwnd.addEventListener('loadstop', loadlistener);
-    }
-    function showHidden() {
-        if(!!hiddenwnd ) {
-            hiddenwnd.show();
-        }
-    }
-    function closeHidden() {
-       if(!!hiddenwnd ) {
-           hiddenwnd.removeEventListener('loadstop',loadlistener);
-           hiddenwnd.close();
-           hiddenwnd=null;
-       }
-    }
-    </script>
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>InAppBrowser</h1>
     <div id="info">
@@ -206,199 +38,199 @@
         Make sure http://www.apple.com is not in the white list.</br>  In iOS, starred <span style="vertical-align:super">*</span> tests will put the app in a state with no way to return.  </br>
         <h4>User-Agent: <span id="user-agent"> </span></h4>
     </div>
-    <div class="btn small" onclick="backHome();">Back</div>
+    <div class="btn small backBtn">Back</div>
 
     <h1>Local URL</h1>
-    <div class="btn large" onclick="doOpen('local.html');">target = Default</div>
+    <div class="btn large openLocal">target = Default</div>
     Expected result: opens successfully in CordovaWebView.
 
     <p/>
-    <div class="btn large" onclick="doOpen('local.html', '_self');">target=_self</div>
+    <div class="btn large openLocalSelf">target=_self</div>
     Expected result: opens successfully in CordovaWebView.
 
     <p/>
-    <div class="btn large" onclick="doOpen('local.html', '_system');">target=_system</div>
+    <div class="btn large openLocalSystem">target=_system</div>
     Expected result: fails to open.
 
     <p/>
-    <div class="btn large" onclick="doOpen('local.html', '_blank');">target=_blank</div>
+    <div class="btn large openLocalBlank">target=_blank</div>
     Expected result: opens successfully in InAppBrowser with locationBar at top.
 
     <p/>
-    <div class="btn large" onclick="doOpen('local.html', 'random_string', 'location=no,disallowoverscroll=yes');">target=Random, location=no,disallowoverscroll=yes</div>
+    <div class="btn large openLocalRandomNoLocation">target=Random, location=no,disallowoverscroll=yes</div>
     Expected result: opens successfully in InAppBrowser without locationBar.
 
     <p/>
-    <div class="btn large" onclick="doOpen('local.html', 'random_string', 'toolbarposition=bottom');">target=Random, toolbarposition=bottom</div>
+    <div class="btn large openLocalRandomToolBarBottom">target=Random, toolbarposition=bottom</div>
     Expected result: opens successfully in InAppBrowser with locationBar. On iOS the toolbar is at the bottom.
 
     <p/>
-    <div class="btn large" onclick="doOpen('local.html', 'random_string', 'toolbarposition=top');">target=Random, toolbarposition=top</div>
+    <div class="btn large openLocalRandomToolBarTop">target=Random, toolbarposition=top</div>
     Expected result: opens successfully in InAppBrowser with locationBar. On iOS the toolbar is at the top.
 
     <p/>
-    <div class="btn large" onclick="doOpen('local.html', 'random_string', 'toolbarposition=top,location=no');">target=Random, toolbarposition=top,location=no</div>
+    <div class="btn large openLocalRandomToolBarTopNoLocation">target=Random, toolbarposition=top,location=no</div>
     Expected result: opens successfully in InAppBrowser with no locationBar. On iOS the toolbar is at the top.
 
     <h1>White Listed URL</h1>
 
-    <div class="btn large" onclick="doOpen('http://www.google.com');">target=Default<span style="vertical-align:super">*</span></div>
+    <div class="btn large openWhiteListed">target=Default<span style="vertical-align:super">*</span></div>
     Expected result: open successfully in CordovaWebView to www.google.com.
 
     <p/>
-    <div class="btn large" onclick="doOpen('http://www.google.com', '_self');">target=_self<span style="vertical-align:super">*</span></div>
+    <div class="btn large openWhiteListedSelf">target=_self<span style="vertical-align:super">*</span></div>
     Expected result: open successfully in CordovaWebView to www.google.com.
 
     <p/>
-    <div class="btn large" onclick="doOpen('http://www.google.com', '_system');">target=_system</div>
+    <div class="btn large openWhiteListedSystem">target=_system</div>
     Expected result: open successfully in system browser to www.google.com.
 
     <p/>
-    <div class="btn large" onclick="doOpen('http://www.google.com', '_blank');">target=_blank</div>
+    <div class="btn large openWhiteListedBlank">target=_blank</div>
     Expected result: open successfully in InAppBrowser to www.google.com.
 
     <p/>
-    <div class="btn large" onclick="doOpen('http://www.google.com', 'random_string');">target=Random</div>
+    <div class="btn large openWhiteListedRandom">target=Random</div>
     Expected result: open successfully in InAppBrowser to www.google.com.
 
     <p/>
-    <div class="btn large" onclick="doOpen('http://www.google.com', 'random_string', 'location=no');">target=Random, no location bar<span style="vertical-align:super">*</span></div>
+    <div class="btn large openWhiteListedRandomNoLocation">target=Random, no location bar<span style="vertical-align:super">*</span></div>
     Expected result: open successfully in InAppBrowser to www.google.com with no location bar.
 
     <h1>Non White Listed URL</h1>
 
-    <div class="btn large" onclick="doOpen('http://www.apple.com');">target=Default</div>
+    <div class="btn large openNonWhiteListed">target=Default</div>
     Expected result: open successfully in InAppBrowser to apple.com (_self enforces whitelist).
 
     <p/>
-    <div class="btn large" onclick="doOpen('http://www.apple.com', '_self');">target=_self</div>
+    <div class="btn larg openNonWhiteListedSelf">target=_self</div>
     Expected result: open successfully in InAppBrowser to apple.com (_self enforces whitelist).
 
     <p/>
-    <div class="btn large" onclick="doOpen('http://www.apple.com', '_system');">target=_system</div>
+    <div class="btn large openNonWhiteListedSystem">target=_system</div>
     Expected result: open successfully in system browser to apple.com.
 
     <p/>
-    <div class="btn large" onclick="doOpen('http://www.apple.com', '_blank');">target=_blank</div>
+    <div class="btn large openNonWhiteListedBlank">target=_blank</div>
     Expected result: open successfully in InAppBrowser to apple.com.
 
     <p/>
-    <div class="btn large" onclick="doOpen('http://www.apple.com', 'random_string');">target=Random</div>
+    <div class="btn large openNonWhiteListedRandom">target=Random</div>
     Expected result: open successfully in InAppBrowser to apple.com.
 
     <p/>
-    <div class="btn large" onclick="doOpen('http://www.apple.com', 'random_string', 'location=no');">target=Random, no location bar<span style="vertical-align:super">*</span></div>
+    <div class="btn large openNonWhiteListedRandomNoLocation">target=Random, no location bar<span style="vertical-align:super">*</span></div>
     Expected result: open successfully in InAppBrowser to apple.com without locationBar.
 
     <h1>Page with redirect</h1>
 
-    <div class="btn large" onclick="doOpen('http://google.com', 'random_string', '', 1);">http://google.com</div>
+    <div class="btn large openRedirect301">http://google.com</div>
     Expected result: should 301 and open successfully in InAppBrowser to www.google.com.
 
     <p/>
-    <div class="btn large" onclick="doOpen('http://goo.gl/pUFqg', 'random_string', '', 2);">http://goo.gl/pUFqg</div>
+    <div class="btn large openRedirect302">http://goo.gl/pUFqg</div>
     Expected result: should 302 and open successfully in InAppBrowser to www.zhihu.com/answer/16714076.
 
     <h1>PDF URL</h1>
 
-    <div class="btn large" onclick="doOpen('http://www.stluciadance.com/prospectus_file/sample.pdf');">Remote URL</div>
+    <div class="btn large openPDF">Remote URL</div>
     Expected result: InAppBrowser opens. PDF should render on iOS.
 
     <p/>
-    <div class="btn large" onclick="doOpen('local.pdf', '_blank');">Local URL</div>
+    <div class="btn large openPDFBlank">Local URL</div>
     Expected result: InAppBrowser opens. PDF should render on iOS.
 
     <h1>Invalid URL</h1>
 
-    <div class="btn large" onclick="doOpen('x-ttp://www.invalid.com/', '_blank');">Invalid Scheme</div>
+    <div class="btn large openInvalidScheme">Invalid Scheme</div>
     Expected result: fail to load in InAppBrowser.
 
     <p/>
-    <div class="btn large" onclick="doOpen('http://www.inv;alid.com/', '_blank');">Invalid Host</div>
+    <div class="btn large openInvalidHost">Invalid Host</div>
     Expected result: fail to load in InAppBrowser.
 
     <p/>
-    <div class="btn large" onclick="doOpen('nonexistent.html', '_blank');">Missing Local File</div>
+    <div class="btn large openInvalidMissing">Missing Local File</div>
     Expected result: fail to load in InAppBrowser (404).
 
     <h1>CSS / JS Injection</h1>
 
-    <div class="btn large" onclick="doOpen('inject.html', '_blank');">Original Document</div>
+    <div class="btn large openOriginalDocument">Original Document</div>
     Expected result: open successfully in InAppBrowser without text "Style updated from..."
 
     <p/> 
-    <div class="btn large" onclick="openWithStyle('inject.html','inject.css');">CSS File Injection</div>
+    <div class="btn large openCSSInjection">CSS File Injection</div>
     Expected result: open successfully in InAppBrowser with "Style updated from file".
 
     <p/>
-    <div class="btn large" onclick="openWithStyle('inject.html','inject.css', true);">CSS File Injection (callback)</div>
+    <div class="btn large openCSSInjectionCallback">CSS File Injection (callback)</div>
     Expected result: open successfully in InAppBrowser with "Style updated from file", and alert dialog with text "Results verified".
 
     <p/>
-    <div class="btn large" onclick="openWithStyle('inject.html');">CSS Literal Injection</div>
+    <div class="btn large openCSSLiteralInjection">CSS Literal Injection</div>
     Expected result: open successfully in InAppBrowser with "Style updated from literal".
 
     <p/>
-    <div class="btn large" onclick="openWithStyle('inject.html', null, true);">CSS Literal Injection (callback)</div>
+    <div class="btn large openCSSLiteralInjectionCallback">CSS Literal Injection (callback)</div>
     Expected result: open successfully in InAppBrowser with "Style updated from literal", and alert dialog with text "Results verified".
 
     <p/>
-    <div class="btn large" onclick="openWithScript('inject.html', 'inject.js');">Script File Injection</div>
+    <div class="btn large openScriptInjection">Script File Injection</div>
     Expected result: open successfully in InAppBrowser with text "Script file successfully injected".
 
     <p/>
-    <div class="btn large" onclick="openWithScript('inject.html', 'inject.js', true);">Script File Injection (callback)</div>
+    <div class="btn large openScriptInjectionCallback">Script File Injection (callback)</div>
     Expected result: open successfully in InAppBrowser with text "Script file successfully injected" and alert dialog with the text "Results verified".
 
     <p/>
-    <div class="btn large" onclick="openWithScript('inject.html');">Script Literal Injection</div>
+    <div class="btn large openScriptLiteralInjection">Script Literal Injection</div>
     Expected result: open successfully in InAppBrowser with the text "Script literal successfully injected" .
 
     <p/>
-    <div class="btn large" onclick="openWithScript('inject.html', null, true);">Script Literal Injection (callback)</div>
+    <div class="btn large openScriptLiteralInjectionCallback">Script Literal Injection (callback)</div>
     Expected result: open successfully in InAppBrowser with the text "Script literal successfully injected" and alert dialog with the text "Results verified".
 
     <h1>Open Hidden </h1>
-    <div class="btn large" onclick="openHidden('http://google.com',true);">create hidden</div>
+    <div class="btn large openHidden">create hidden</div>
     Expected result: no additional browser window. Alert appears with the text "background window loaded".
 
     <p/>
-    <div class="btn large" onclick="showHidden();">show hidden</div>
+    <div class="btn large showHidden">show hidden</div>
     Expected result: after first clicking on previous test "create hidden", open successfully in InAppBrowser to google.com.
 
     <p/>
-    <div class="btn large" onclick="closeHidden();">close hidden</div>
+    <div class="btn large closeHidden">close hidden</div>
     Expected result: no output. But click on "show hidden" again and nothing should be shown.
 
     <p/>
-    <div class="btn large" onclick="openHidden('http://google.com',false);">google.com not hidden</div>
+    <div class="btn large openHiddenShow">google.com not hidden</div>
     Expected result: open successfully in InAppBrowser to www.google.com
 
     <h1>Clearing Cache</h1>
 
-    <div class="btn large" onclick="doOpen('http://www.google.com', '_blank', 'clearcache=yes');">Clear Browser Cache</div>
+    <div class="btn large openClearCache">Clear Browser Cache</div>
     Expected result: ?
 
     <p/>
-    <div class="btn large" onclick="doOpen('http://www.google.com', '_blank', 'clearsessioncache=yes');">Clear Session Cache</div>
+    <div class="btn large openClearSessionCache">Clear Session Cache</div>
     Expected result: ?
 
     <h1>Video tag</h1>
 
-    <div class="btn large" onclick="doOpen('video.html', '_blank');">remote video</div>
+    <div class="btn large openRemoteVideo">remote video</div>
     Expected result: open successfully in InAppBrowser with an embedded video that works after clicking the "play" button.
 
     <h1>Local with anchor tag</h1>
 
-    <div class="btn large" onclick="doOpen('local.html#anchor1', '_blank');">Anchor1</div>
+    <div class="btn large openAnchor1">Anchor1</div>
     Expected result: open successfully in InAppBrowser to the local page, scrolled to the top.
 
     <p/>
-    <div class="btn large" onclick="doOpen('local.html#anchor2', '_blank');">Anchor2</div>
+    <div class="btn large openAnchor2">Anchor2</div>
     Expected result: open successfully in InAppBrowser to the local page, scrolled to the beginning of the tall div with border.
     
     <p/>
-    <div class="backBtn" onclick="backHome();">Back</div>
+    <div class="backBtn">Back</div>
 
   </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/inappbrowser/index.js
----------------------------------------------------------------------
diff --git a/inappbrowser/index.js b/inappbrowser/index.js
new file mode 100644
index 0000000..a08c30d
--- /dev/null
+++ b/inappbrowser/index.js
@@ -0,0 +1,242 @@
+var deviceReady = false;
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+            deviceReady = true;
+            console.log("Device="+device.platform+" "+device.version);
+        }, false);
+    function updateUserAgent() {
+        document.getElementById("user-agent").textContent = navigator.userAgent;
+    }
+    updateUserAgent();
+    window.setInterval(updateUserAgent, 1500);
+    window.setTimeout(function() {
+      if (!deviceReady) {
+        alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
+      }
+    },1000);
+}
+
+function doOpen(url, target, params, numExpectedRedirects) {
+    numExpectedRedirects = numExpectedRedirects || 0;
+    var iab = window.open(url, target, params);
+    if (!iab) {
+        alert('window.open returned ' + iab);
+        return;
+    }
+    var counts;
+    var lastLoadStartURL;
+    var wasReset = false;
+    function reset()  {
+        counts = {
+            'loaderror': 0,
+            'loadstart': 0,
+            'loadstop': 0,
+            'exit': 0
+        };
+        lastLoadStartURL = '';
+    }
+    reset();
+
+    function logEvent(e) {
+        console.log('IAB event=' + JSON.stringify(e));
+        counts[e.type]++;
+        // Verify that event.url gets updated on redirects.
+        if (e.type == 'loadstart') {
+            if (e.url == lastLoadStartURL) {
+                alert('Unexpected: loadstart fired multiple times for the same URL.');
+            }
+            lastLoadStartURL = e.url;
+        }
+        // Verify the right number of loadstart events were fired.
+        if (e.type == 'loadstop' || e.type == 'loaderror') {
+            if (e.url != lastLoadStartURL) {
+                alert('Unexpected: ' + e.type + ' event.url != loadstart\'s event.url');
+            }
+            if (numExpectedRedirects === 0 && counts['loadstart'] !== 1) {
+                // Do allow a loaderror without a loadstart (e.g. in the case of an invalid URL).
+                if (!(e.type == 'loaderror' && counts['loadstart'] === 0)) {
+                    alert('Unexpected: got multiple loadstart events. (' + counts['loadstart'] + ')');
+                }
+            } else if (numExpectedRedirects > 0 && counts['loadstart'] < (numExpectedRedirects+1)) {
+                alert('Unexpected: should have got at least ' + (numExpectedRedirects+1) + ' loadstart events, but got ' + counts['loadstart']);
+            }
+            wasReset = true;
+            numExpectedRedirects = 0;
+            reset();
+        }
+        // Verify that loadend / loaderror was called.
+        if (e.type == 'exit') {
+            var numStopEvents = counts['loadstop'] + counts['loaderror'];
+            if (numStopEvents === 0 && !wasReset) {
+                alert('Unexpected: browser closed without a loadstop or loaderror.')
+            } else if (numStopEvents > 1) {
+                alert('Unexpected: got multiple loadstop/loaderror events.');
+            }
+        }
+    }
+    iab.addEventListener('loaderror', logEvent);
+    iab.addEventListener('loadstart', logEvent);
+    iab.addEventListener('loadstop', logEvent);
+    iab.addEventListener('exit', logEvent);
+
+    return iab;
+}
+
+function openWithStyle(url, cssUrl, useCallback) {
+    var iab = doOpen(url, '_blank', 'location=yes');
+    var callback = function(results) {
+        if (results && results.length === 0) {
+            alert('Results verified');
+        } else {
+            console.log(results);
+            alert('Got: ' + typeof(results) + '\n' + JSON.stringify(results));
+        }
+    };
+    if (cssUrl) {
+        iab.addEventListener('loadstop', function(event) {
+            iab.insertCSS({file: cssUrl}, useCallback && callback);
+        });
+    } else {
+        iab.addEventListener('loadstop', function(event) {
+            iab.insertCSS({code:'#style-update-literal { \ndisplay: block !important; \n}'},
+                          useCallback && callback);
+        });
+    }
+}
+
+function openWithScript(url, jsUrl, useCallback) {
+    var iab = doOpen(url, '_blank', 'location=yes');
+    if (jsUrl) {
+        iab.addEventListener('loadstop', function(event) {
+            iab.executeScript({file: jsUrl}, useCallback && function(results) {
+                if (results && results.length === 0) {
+                    alert('Results verified');
+                } else {
+                    console.log(results);
+                    alert('Got: ' + typeof(results) + '\n' + JSON.stringify(results));
+                }
+            });
+        });
+    } else {
+        iab.addEventListener('loadstop', function(event) {
+            var code = '(function(){\n' +
+              '    var header = document.getElementById("header");\n' +
+              '    header.innerHTML = "Script literal successfully injected";\n' +
+              '    return "abc";\n' +
+              '})()';
+            iab.executeScript({code:code}, useCallback && function(results) {
+                if (results && results.length === 1 && results[0] === 'abc') {
+                    alert('Results verified');
+                } else {
+                    console.log(results);
+                    alert('Got: ' + typeof(results) + '\n' + JSON.stringify(results));
+                }
+            });
+        });
+    }
+}
+var hiddenwnd=null;
+var loadlistener = function(event) { alert('background window loaded ' ); };
+function openHidden(url, startHidden) {
+    var shopt =(startHidden) ? 'hidden=yes' : '';
+    hiddenwnd = window.open(url,'random_string',shopt);
+    if (!hiddenwnd) {
+        alert('window.open returned ' + hiddenwnd);
+        return;
+    }
+    if(startHidden) hiddenwnd.addEventListener('loadstop', loadlistener);
+}
+function showHidden() {
+    if(!!hiddenwnd ) {
+        hiddenwnd.show();
+    }
+}
+function closeHidden() {
+   if(!!hiddenwnd ) {
+       hiddenwnd.removeEventListener('loadstop',loadlistener);
+       hiddenwnd.close();
+       hiddenwnd=null;
+   }
+}
+
+window.onload = function() {
+  addListenerToClass('openLocal', doOpen, 'local.html');
+  addListenerToClass('openLocalSelf', doOpen, ['local.html', '_self']);
+  addListenerToClass('openLocalSystem', doOpen, ['local.html', '_system']);
+  addListenerToClass('openLocalBlank', doOpen, ['local.html', '_blank']);
+  addListenerToClass('openLocalRandomNoLocation', doOpen, 
+      ['local.html', 'random_string', 'location=no,disallowoverscroll=yes']);
+  addListenerToClass('openLocalRandomToolBarBottom', doOpen,
+      ['local.html', 'random_string', 'toolbarposition=bottom']);
+  addListenerToClass('openLocalRandomToolBarTop', doOpen, 
+      ['local.html', 'random_string', 'toolbarposition=top']);
+  addListenerToClass('openLocalRandomToolBarTopNoLocation', doOpen, 
+      ['local.html', 'random_string', 'toolbarposition=top,location=no']);
+  addListenerToClass('openWhiteListed', doOpen, 'http://www.google.com');
+  addListenerToClass('openWhiteListedSelf', doOpen, 
+      ['http://www.google.com', '_self']);
+  addListenerToClass('openWhiteListedSystem', doOpen,
+      ['http://www.google.com', '_system']);
+  addListenerToClass('openWhiteListedBlank', doOpen, 
+      ['http://www.google.com', '_blank']);
+  addListenerToClass('openWhiteListedRandom', doOpen,
+      ['http://www.google.com', 'random_string']);
+  addListenerToClass('openWhiteListedRandomNoLocation', doOpen,
+      ['http://www.google.com', 'random_string', 'location=no']);
+  addListenerToClass('openNonWhiteListed', doOpen, 'http://www.apple.com');
+  addListenerToClass('openNonWhiteListedSelf', doOpen, 
+      ['http://www.apple.com', '_self']);
+  addListenerToClass('openNonWhiteListedSystem', doOpen, 
+      ['http://www.apple.com', '_system']);
+  addListenerToClass('openNonWhiteListedBlank', doOpen, 
+      ['http://www.apple.com', '_blank']);
+  addListenerToClass('openNonWhiteListedRandom', doOpen,
+      ['http://www.apple.com', 'random_string']);
+  addListenerToClass('openNonWhiteListedRandomNoLocation', doOpen, 
+      ['http://www.apple.com', 'random_string', 'location=no']);
+  addListenerToClass('openRedirect301', doOpen, 
+      ['http://google.com', 'random_string', '', 1]);
+  addListenerToClass('openRedirect302', doOpen, 
+      ['http://goo.gl/pUFqg', 'random_string', '', 2]);
+  addListenerToClass('openPDF', doOpen, 'http://www.stluciadance.com/prospectus_file/sample.pdf');
+  addListenerToClass('openPDFBlank', doOpen, ['local.pdf', '_blank']);
+  addListenerToClass('openInvalidScheme', doOpen, 
+      ['x-ttp://www.invalid.com/', '_blank']);
+  addListenerToClass('openInvalidHost', doOpen, 
+      ['http://www.inv;alid.com/', '_blank']);
+  addListenerToClass('openInvalidMissing', doOpen, ['nonexistent.html', '_blank']);
+  addListenerToClass('openOriginalDocument', doOpen, ['inject.html', '_blank']);
+  addListenerToClass('openCSSInjection', openWithStyle, 
+      ['inject.html','inject.css']);
+  addListenerToClass('openCSSInjectionCallback', openWithStyle, 
+      ['inject.html','inject.css', true]);
+  addListenerToClass('openCSSLiteralInjection', openWithStyle, 'inject.html');
+  addListenerToClass('openCSSLiteralInjectionCallback', openWithStyle, 
+    ['inject.html', null, true]);
+  addListenerToClass('openScriptInjection', openWithScript, 
+    ['inject.html', 'inject.js']);
+  addListenerToClass('openScriptInjectionCallback', openWithScript, 
+    ['inject.html', 'inject.js', true]);
+  addListenerToClass('openScriptLiteralInjection', openWithScript, 'inject.html');
+  addListenerToClass('openScriptLiteralInjectionCallback', openWithScript, 
+    ['inject.html', null, true]);
+  addListenerToClass('openHidden', openHidden, ['http://google.com', true]);
+  addListenerToClass('showHidden', showHidden);
+  addListenerToClass('closeHidden', closeHidden);
+  addListenerToClass('openHiddenShow', openHidden, ['http://google.com', false]);
+  addListenerToClass('openClearCache', doOpen, 
+    ['http://www.google.com', '_blank', 'clearcache=yes']);
+  addListenerToClass('openClearSessionCache', doOpen, 
+    ['http://www.google.com', '_blank', 'clearsessioncache=yes']);
+  addListenerToClass('openRemoteVideo', doOpen, ['video.html', '_blank']);
+  addListenerToClass('openAnchor1', doOpen, ['local.html#anchor1', '_blank']);
+  addListenerToClass('openAnchor2', doOpen, ['local.html#anchor2', '_blank']);
+
+
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/index.html
----------------------------------------------------------------------
diff --git a/index.html b/index.html
index 314d847..86b1173 100644
--- a/index.html
+++ b/index.html
@@ -31,7 +31,7 @@
 	  <script type="text/javascript" charset="utf-8" src="main.js"></script>
 
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
     <h1>Apache Cordova Tests</h1>
     <div id="info">
         <h4>cordova.version: <span id="cordova"> </span></h4>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/keyboard/index.html
----------------------------------------------------------------------
diff --git a/keyboard/index.html b/keyboard/index.html
index 23b47a3..9a66add 100644
--- a/keyboard/index.html
+++ b/keyboard/index.html
@@ -64,53 +64,11 @@
     }
 
     </style>
-    <script>
-        window.onerror = function(err,fn,ln) {alert("ERROR:" + err + ", " + fn + ":" + ln);};
-    </script>
+    <script type="text/javascript" charset="utf-8" src="./window-onerror.js"></script>      
     <script type="text/javascript" charset="utf-8" src="../cordova-incl.js"></script>      
-    
-    <script type="text/javascript" charset="utf-8">
-
-    var deviceReady = false;
-    var keyboardPlugin = null;
-    
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-                deviceReady = true;
-                keyboardPlugin = window.Keyboard; // for now, before plugin re-factor
-                                  
-                if (keyboardPlugin == null) {
-                    var msg = 'The plugin org.apache.cordova.keyboard was not found. Check that you have it installed.';
-                    alert(msg);
-                }
-
-            }, false);
-        window.setTimeout(function() {
-        	if (!deviceReady) {
-                var msg = 'Error: Apache Cordova did not initialize.  Demo will not run correctly.';
-                alert(msg);
-        	}
-        },1000);
-    }
-    
-    function setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(shrinkView, hideFormAccessoryBar, disableScrollingInShrinkView)
-    {
-        keyboardPlugin.shrinkView(shrinkView);
-        document.getElementById("shrinkView-arg").innerHTML = shrinkView;
-        
-        keyboardPlugin.hideFormAccessoryBar(hideFormAccessoryBar);
-        document.getElementById("hideFormAccessoryBar-arg").innerHTML = hideFormAccessoryBar;
-
-        keyboardPlugin.disableScrollingInShrinkView(disableScrollingInShrinkView);
-        document.getElementById("disableScrollingInShrinkView-arg").innerHTML = disableScrollingInShrinkView;
-    }
-
-    </script>
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>Keyboard (iOS)</h1>
 
@@ -121,7 +79,7 @@
 
     <h1>isVisible</h1>
     <br />
-    <div class="btn large" onclick="alert('Keyboard.isVisible: ' + Keyboard.isVisible);">Keyboard.isVisible</div>
+    <div class="btn large keyboardIsVisible">Keyboard.isVisible</div>
     
     <h1>API Tests</h1>
     <br />
@@ -143,7 +101,7 @@
         </tr>
         <tr>
             <td class="highlight-w">
-                <div class="btn small" onclick="setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(false, false, false)">1</div>
+                <div class="btn small set_1">1</div>
             </td>
             <td>&#x2717;</td>
             <td>&#x2717;</td>
@@ -151,7 +109,7 @@
         </tr>
         <tr>
             <td class="highlight-w">
-                <div class="btn small" onclick="setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(false, false, true)">2</div>
+                <div class="btn small set_2">2</div>
             </td>
             <td>&#x2717;</td>
             <td>&#x2717;</td>
@@ -159,7 +117,7 @@
         </tr>
         <tr>
             <td class="highlight-w">
-                <div class="btn small" onclick="setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(false, true, true)">3</div>
+                <div class="btn small set_3">3</div>
             </td>
             <td>&#x2717;</td>
             <td class="highlight-w">&#10004;</td>
@@ -167,7 +125,7 @@
         </tr>
         <tr>
             <td class="highlight-w">
-                <div class="btn small" onclick="setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(false, true, false)">4</div>
+                <div class="btn small set_4">4</div>
             </td>
             <td>&#x2717;</td>
             <td class="highlight-w">&#10004;</td>
@@ -175,7 +133,7 @@
         </tr>
         <tr>
             <td class="highlight-w">
-                <div class="btn small" onclick="setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(true, false, false)">5</div>
+                <div class="btn small set_5">5</div>
             </td>
             <td class="highlight-w">&#10004;</td>
             <td>&#x2717;</td>
@@ -183,7 +141,7 @@
         </tr>
         <tr>
             <td class="highlight-w">
-                <div class="btn small" onclick="setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(true, false, true)">6</div>
+                <div class="btn small set_6">6</div>
             </td>
             <td class="highlight-w">&#10004;</td>
             <td>&#x2717;</td>
@@ -191,7 +149,7 @@
         </tr>
         <tr>
             <td class="highlight-w">
-                <div class="btn small" onclick="setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(true, true, true)">7</div>
+                <div class="btn small set_7">7</div>
             </td>
             <td class="highlight-w">&#10004;</td>
             <td class="highlight-w">&#10004;</td>
@@ -199,7 +157,7 @@
         </tr>
         <tr>
             <td class="highlight-w">
-                <div class="btn small" onclick="setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(true, true, false)">8</div>
+                <div class="btn small set_8">8</div>
             </td>
             <td class="highlight-w">&#10004;</td>
             <td class="highlight-w">&#10004;</td>
@@ -211,7 +169,7 @@
         <input type="text" placeholder="touch to see keyboard" /><button class="btn-dismiss">dismiss</button>
     </div>
     <br />
-    <div class="backBtn" onclick="backHome();">Back</div>
+    <div class="backBtn">Back</div>
     
   </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/keyboard/index.js
----------------------------------------------------------------------
diff --git a/keyboard/index.js b/keyboard/index.js
new file mode 100644
index 0000000..2302f31
--- /dev/null
+++ b/keyboard/index.js
@@ -0,0 +1,69 @@
+
+var deviceReady = false;
+var keyboardPlugin = null;
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+            deviceReady = true;
+            keyboardPlugin = window.Keyboard; // for now, before plugin re-factor
+                              
+            if (keyboardPlugin == null) {
+                var msg = 'The plugin org.apache.cordova.keyboard was not found. Check that you have it installed.';
+                alert(msg);
+            }
+
+        }, false);
+    window.setTimeout(function() {
+      if (!deviceReady) {
+            var msg = 'Error: Apache Cordova did not initialize.  Demo will not run correctly.';
+            alert(msg);
+      }
+    },1000);
+}
+
+function setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(shrinkView, hideFormAccessoryBar, disableScrollingInShrinkView)
+{
+    keyboardPlugin.shrinkView(shrinkView);
+    document.getElementById("shrinkView-arg").innerHTML = shrinkView;
+    
+    keyboardPlugin.hideFormAccessoryBar(hideFormAccessoryBar);
+    document.getElementById("hideFormAccessoryBar-arg").innerHTML = hideFormAccessoryBar;
+
+    keyboardPlugin.disableScrollingInShrinkView(disableScrollingInShrinkView);
+    document.getElementById("disableScrollingInShrinkView-arg").innerHTML = disableScrollingInShrinkView;
+}
+
+window.onload = function() {
+  addListenerToClass('keyboardIsVisible', function() {
+    alert('Keyboard.isVisible: ' + Keyboard.isVisible);
+  });
+  addListenerToClass('set_1', function() {
+    setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(false, false, false)
+  });
+  addListenerToClass('set_2', function() {
+    setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(false, false, true)
+  });
+  addListenerToClass('set_3', function() {
+    setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(false, true, true)
+  });
+  addListenerToClass('set_4', function() {
+    setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(false, true, false)
+  });
+  addListenerToClass('set_5', function() {
+    setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(true, false, false)
+  });
+  addListenerToClass('set_6', function() {
+    setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(true, false, true)
+  });
+  addListenerToClass('set_7', function() {
+    setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(true, true, true)
+  });
+  addListenerToClass('set_8', function() {
+    setShrinkView_hideFormAccessoryBar_andDisableScrollingInShrinkView(true, true, false)
+  });
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/keyboard/window-onerror.js
----------------------------------------------------------------------
diff --git a/keyboard/window-onerror.js b/keyboard/window-onerror.js
new file mode 100644
index 0000000..f833882
--- /dev/null
+++ b/keyboard/window-onerror.js
@@ -0,0 +1 @@
+window.onerror = function(err,fn,ln) {alert("ERROR:" + err + ", " + fn + ":" + ln);};

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/lazyloadjs/do-not-write-cordova-script.js
----------------------------------------------------------------------
diff --git a/lazyloadjs/do-not-write-cordova-script.js b/lazyloadjs/do-not-write-cordova-script.js
new file mode 100644
index 0000000..0f20c76
--- /dev/null
+++ b/lazyloadjs/do-not-write-cordova-script.js
@@ -0,0 +1 @@
+_doNotWriteCordovaScript = true;

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/lazyloadjs/index.html
----------------------------------------------------------------------
diff --git a/lazyloadjs/index.html b/lazyloadjs/index.html
index 7a0c06f..5816349 100644
--- a/lazyloadjs/index.html
+++ b/lazyloadjs/index.html
@@ -27,27 +27,15 @@
     <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <!-- ISO-8859-1 -->
     <title>Lazy-Loading of cordova-incl.js test</title>
     <link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title" charset="utf-8"/>
-    <script>_doNotWriteCordovaScript = true</script>
+    <script type="text/javascript" charset="utf-8" src="./do-not-write-cordova-script.js"></script>      
     <script type="text/javascript" charset="utf-8" src="../cordova-incl.js"></script>
-<script type="text/javascript" charset="utf-8">
-    function init() {
-        document.addEventListener("deviceready", function() {
-            console.log("Device="+device.platform+" "+device.version);
-            document.getElementById('info').innerHTML = 'Cordova loaded just fine.';
-        }, false);
-        window.setTimeout(function() {
-            var s = document.createElement('script');
-            s.src = cordovaPath;
-            document.body.appendChild(s);
-        }, 0);
-    }
-</script>
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
     <h1>Lazy-Loading of cordova-incl.js</h1>
     <div id="info">
       onDeviceReady has not yet fired.
     </div>
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/lazyloadjs/index.js
----------------------------------------------------------------------
diff --git a/lazyloadjs/index.js b/lazyloadjs/index.js
new file mode 100644
index 0000000..6559319
--- /dev/null
+++ b/lazyloadjs/index.js
@@ -0,0 +1,16 @@
+function init() {
+    document.addEventListener("deviceready", function() {
+        console.log("Device="+device.platform+" "+device.version);
+        document.getElementById('info').innerHTML = 'Cordova loaded just fine.';
+    }, false);
+    window.setTimeout(function() {
+        var s = document.createElement('script');
+        s.src = cordovaPath;
+        document.body.appendChild(s);
+    }, 0);
+}
+
+window.onload = function() {
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/location/index.html
----------------------------------------------------------------------
diff --git a/location/index.html b/location/index.html
index 542f264..f0cc7de 100644
--- a/location/index.html
+++ b/location/index.html
@@ -28,130 +28,9 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>      
-
-      
-<script type="text/javascript" charset="utf-8">
-
-    var origGeolocation = null;
-    var newGeolocation = null;
-
-    //-------------------------------------------------------------------------
-    // Location
-    //-------------------------------------------------------------------------
-    var watchLocationId = null;
-
-    /**
-     * Start watching location
-     */
-    var watchLocation = function(usePlugin) {
-        var geo = usePlugin ? newGeolocation : origGeolocation;
-        if (!geo) {
-            alert('geolocation object is missing. usePlugin = ' + usePlugin);
-            return;
-        }
-
-        // Success callback
-        var success = function(p){
-              console.log('watch location success');
-              setLocationDetails(p);
-        };
-
-        // Fail callback
-        var fail = function(e){
-            console.log("watchLocation fail callback with error code "+e);
-            stopLocation(geo);
-        };
-
-        // Get location
-        watchLocationId = geo.watchPosition(success, fail, {enableHighAccuracy: true});
-        setLocationStatus("Running");
-    };
-
-    /**
-     * Stop watching the location
-     */
-    var stopLocation = function(usePlugin) {
-        var geo = usePlugin ? newGeolocation : origGeolocation;
-        if (!geo) {
-            alert('geolocation object is missing. usePlugin = ' + usePlugin);
-            return;
-        }
-        setLocationStatus("Stopped");
-        if (watchLocationId) {
-            geo.clearWatch(watchLocationId);
-            watchLocationId = null;
-        }
-    };
-
-    /**
-     * Get current location
-     */
-    var getLocation = function(usePlugin, opts) {
-        var geo = usePlugin ? newGeolocation : origGeolocation;
-        if (!geo) {
-            alert('geolocation object is missing. usePlugin = ' + usePlugin);
-            return;
-        }
-
-        // Stop location if running
-        stopLocation(geo);
-
-        // Success callback
-        var success = function(p){
-            console.log('get location success');
-            setLocationDetails(p);
-            setLocationStatus("Done");
-        };
-
-        // Fail callback
-        var fail = function(e){
-            console.log("getLocation fail callback with error code "+e.code);
-            setLocationStatus("Error: "+e.code);
-        };
-
-        setLocationStatus("Retrieving location...");
-
-        // Get location
-        geo.getCurrentPosition(success, fail, opts || {enableHighAccuracy: true}); //, {timeout: 10000});
-
-    };
-
-    /**
-     * Set location status
-     */
-    var setLocationStatus = function(status) {
-        document.getElementById('location_status').innerHTML = status;
-    };
-var setLocationDetails = function(p) {
-var date = (new Date(p.timestamp));
-            document.getElementById('latitude').innerHTML = p.coords.latitude;
-            document.getElementById('longitude').innerHTML = p.coords.longitude;
-            document.getElementById('altitude').innerHTML = p.coords.altitude;
-            document.getElementById('accuracy').innerHTML = p.coords.accuracy;
-            document.getElementById('heading').innerHTML = p.coords.heading;
-            document.getElementById('speed').innerHTML = p.coords.speed;
-            document.getElementById('altitude_accuracy').innerHTML = p.coords.altitudeAccuracy;
-            document.getElementById('timestamp').innerHTML =  date.toDateString() + " " + date.toTimeString();
-    }
-    
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-            newGeolocation = navigator.geolocation;
-            origGeolocation = cordova.require('cordova/modulemapper').getOriginalSymbol(window, 'navigator.geolocation');
-            if (!origGeolocation) {
-                origGeolocation = newGeolocation;
-                newGeolocation = null;
-            }
-        }, false);
-    }
-
-</script>
-
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>Location</h1>
     <div id="info">
@@ -205,15 +84,15 @@ var date = (new Date(p.timestamp));
     </div>
     <h2>Action</h2>
     <h3>Use Built-in WebView navigator.geolocation</h3>
-    <a href="javascript:" class="btn large" onclick="getLocation(false);">Get Location</a>
-    <a href="javascript:" class="btn large" onclick="watchLocation(false);">Start Watching Location</a>
-    <a href="javascript:" class="btn large" onclick="stopLocation(false);">Stop Watching Location</a>
-    <a href="javascript:" class="btn large" onclick="getLocation(false, {maximumAge:30000});">Get Location Up to 30 Seconds Old</a>
+    <a href="javascript:" class="btn large getWebViewLocation">Get Location</a>
+    <a href="javascript:" class="btn large watchWebViewLocation">Start Watching Location</a>
+    <a href="javascript:" class="btn large stopWebViewLocation">Stop Watching Location</a>
+    <a href="javascript:" class="btn large getWebViewLocation30">Get Location Up to 30 Seconds Old</a>
     <h3>Use Cordova Geolocation Plugin</h3>
-    <a href="javascript:" class="btn large" onclick="getLocation(true);">Get Location</a>
-    <a href="javascript:" class="btn large" onclick="watchLocation(true);">Start Watching Location</a>
-    <a href="javascript:" class="btn large" onclick="stopLocation(true);">Stop Watching Location</a>
-    <a href="javascript:" class="btn large" onclick="getLocation(true, {maximumAge:30000});">Get Location Up to 30 Seconds Old</a>
-    <h2>&nbsp;</h2><a href="javascript:" class="backBtn" onclick="backHome();">Back</a>    
+    <a href="javascript:" class="btn large getLocation">Get Location</a>
+    <a href="javascript:" class="btn large watchLocation">Start Watching Location</a>
+    <a href="javascript:" class="btn large stopLocation">Stop Watching Location</a>
+    <a href="javascript:" class="btn large getLocation30">Get Location Up to 30 Seconds Old</a>
+    <h2>&nbsp;</h2><a href="javascript:" class="backBtn"">Back</a>    
   </body>
 </html>      

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/location/index.js
----------------------------------------------------------------------
diff --git a/location/index.js b/location/index.js
new file mode 100644
index 0000000..242919d
--- /dev/null
+++ b/location/index.js
@@ -0,0 +1,128 @@
+var origGeolocation = null;
+var newGeolocation = null;
+
+//-------------------------------------------------------------------------
+// Location
+//-------------------------------------------------------------------------
+var watchLocationId = null;
+
+/**
+ * Start watching location
+ */
+var watchLocation = function(usePlugin) {
+    var geo = usePlugin ? newGeolocation : origGeolocation;
+    if (!geo) {
+        alert('geolocation object is missing. usePlugin = ' + usePlugin);
+        return;
+    }
+
+    // Success callback
+    var success = function(p){
+          console.log('watch location success');
+          setLocationDetails(p);
+    };
+
+    // Fail callback
+    var fail = function(e){
+        console.log("watchLocation fail callback with error code "+e);
+        stopLocation(geo);
+    };
+
+    // Get location
+    watchLocationId = geo.watchPosition(success, fail, {enableHighAccuracy: true});
+    setLocationStatus("Running");
+};
+
+/**
+ * Stop watching the location
+ */
+var stopLocation = function(usePlugin) {
+    var geo = usePlugin ? newGeolocation : origGeolocation;
+    if (!geo) {
+        alert('geolocation object is missing. usePlugin = ' + usePlugin);
+        return;
+    }
+    setLocationStatus("Stopped");
+    if (watchLocationId) {
+        geo.clearWatch(watchLocationId);
+        watchLocationId = null;
+    }
+};
+
+/**
+ * Get current location
+ */
+var getLocation = function(usePlugin, opts) {
+    var geo = usePlugin ? newGeolocation : origGeolocation;
+    if (!geo) {
+        alert('geolocation object is missing. usePlugin = ' + usePlugin);
+        return;
+    }
+
+    // Stop location if running
+    stopLocation(geo);
+
+    // Success callback
+    var success = function(p){
+        console.log('get location success');
+        setLocationDetails(p);
+        setLocationStatus("Done");
+    };
+
+    // Fail callback
+    var fail = function(e){
+        console.log("getLocation fail callback with error code "+e.code);
+        setLocationStatus("Error: "+e.code);
+    };
+
+    setLocationStatus("Retrieving location...");
+
+    // Get location
+    geo.getCurrentPosition(success, fail, opts || {enableHighAccuracy: true}); //, {timeout: 10000});
+
+};
+
+/**
+ * Set location status
+ */
+var setLocationStatus = function(status) {
+    document.getElementById('location_status').innerHTML = status;
+};
+var setLocationDetails = function(p) {
+var date = (new Date(p.timestamp));
+        document.getElementById('latitude').innerHTML = p.coords.latitude;
+        document.getElementById('longitude').innerHTML = p.coords.longitude;
+        document.getElementById('altitude').innerHTML = p.coords.altitude;
+        document.getElementById('accuracy').innerHTML = p.coords.accuracy;
+        document.getElementById('heading').innerHTML = p.coords.heading;
+        document.getElementById('speed').innerHTML = p.coords.speed;
+        document.getElementById('altitude_accuracy').innerHTML = p.coords.altitudeAccuracy;
+        document.getElementById('timestamp').innerHTML =  date.toDateString() + " " + date.toTimeString();
+}
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+        newGeolocation = navigator.geolocation;
+        origGeolocation = cordova.require('cordova/modulemapper').getOriginalSymbol(window, 'navigator.geolocation');
+        if (!origGeolocation) {
+            origGeolocation = newGeolocation;
+            newGeolocation = null;
+        }
+    }, false);
+}
+
+window.onload = function() {
+  addListenerToClass('getWebViewLocation', getLocation, [false]);
+  addListenerToClass('watchWebViewLocation', watchLocation, [false]);
+  addListenerToClass('stopWebViewLocation', stopLocation, [false]);
+  addListenerToClass('getWebViewLocation30', getLocation, [false, {maximumAge:30000}]);
+  addListenerToClass('getLocation', getLocation, [true]);
+  addListenerToClass('watchLocation', watchLocation, [true]);
+  addListenerToClass('stopLocation', stopLocation, [true]);
+  addListenerToClass('getLocation30', getLocation, [true, {maximumAge:30000}]);
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/main.js
----------------------------------------------------------------------
diff --git a/main.js b/main.js
index 9508770..42e9edd 100644
--- a/main.js
+++ b/main.js
@@ -161,3 +161,5 @@ function init() {
     document.addEventListener("deviceready", deviceInfo, true);
     document.getElementById("user-agent").textContent = navigator.userAgent;
 }
+
+window.onload = init;

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/misc/index.html
----------------------------------------------------------------------
diff --git a/misc/index.html b/misc/index.html
index 2245ed9..0ebb217 100644
--- a/misc/index.html
+++ b/misc/index.html
@@ -28,43 +28,16 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>      
-
-      
-<script type="text/javascript" charset="utf-8">
-
-    var deviceReady = false;
-
-    function roundNumber(num) {
-        var dec = 3;
-        var result = Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
-        return result;
-    }
-    
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-                deviceReady = true;
-                console.log("Device="+device.platform+" "+device.version);
-            }, false);
-        window.setTimeout(function() {
-        	if (!deviceReady) {
-        		alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
-        	}
-        },1000);
-    }
-
-</script>
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
 
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>Display Other Content</h1>
     <div id="info">
     </div>
     <h2>Action</h2>
-    <div class="btn large" onclick="document.location='tel:5551212';" >Call 411</div>
+    <div class="btn large telLocation">Call 411</div>
     <a href="mailto:bob@abc.org?subject=My Subject&body=This is the body.%0D%0ANew line." class="btn large">Send Mail</a>
     <a href="sms:5125551234?body=The SMS message." class="btn large">Send SMS</a>
     <a href="http://www.google.com" class="btn large">Load Web Site</a>
@@ -82,6 +55,6 @@
     <a href="market://search?q=google" class="btn large">Search Android market</a>
     <a href="content://media/external/images/media" class="btn large">View image app</a>
 
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>      

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/misc/index.js
----------------------------------------------------------------------
diff --git a/misc/index.js b/misc/index.js
new file mode 100644
index 0000000..e38ade7
--- /dev/null
+++ b/misc/index.js
@@ -0,0 +1,30 @@
+var deviceReady = false;
+
+function roundNumber(num) {
+    var dec = 3;
+    var result = Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
+    return result;
+}
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+            deviceReady = true;
+            console.log("Device="+device.platform+" "+device.version);
+        }, false);
+    window.setTimeout(function() {
+      if (!deviceReady) {
+        alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
+      }
+    },1000);
+}
+
+window.onload = function() {
+  addListenerToClass('telLocation', function() {
+    document.location='tel:5551212';
+  });
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/misc/page2.html
----------------------------------------------------------------------
diff --git a/misc/page2.html b/misc/page2.html
index 6b4eba1..1d370a9 100644
--- a/misc/page2.html
+++ b/misc/page2.html
@@ -29,6 +29,7 @@
     <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="../cordova-incl.js"></script>
     <script type="text/javascript" charset="utf-8" src="../main.js"></script>
+    <script type="text/javascript" charset="utf-8" src="./page2.js"></script>      
     <style>
       iframe, .iframe_container {
         height:100px;
@@ -36,7 +37,7 @@
       }
     </style>
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
     <h1>Page2 App</h1>
     <h2>This is page 2 of a Apache Cordova app</h2>
     <div id="info">
@@ -58,15 +59,6 @@
      <div class="iframe_container">
        <iframe src="" id="apacheiframe"></iframe>
      </div>
-     <div><button class="backBtn" onclick="backHome();">Back</button></div>
+     <div><button class="backBtn">Back</button></div>
   </body>
-  <script>
-    setTimeout(function() {
-        console.log('loading iframe after timeout.');
-        document.querySelector('#apacheiframe').src = 'http://apache.org';
-    }, 2000);
-    document.addEventListener("deviceready", function() {
-        document.getElementById('info').textContent += '\nDevice is ready.';
-    }, false);
-  </script>
 </html>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/misc/page2.js
----------------------------------------------------------------------
diff --git a/misc/page2.js b/misc/page2.js
new file mode 100644
index 0000000..1f489c2
--- /dev/null
+++ b/misc/page2.js
@@ -0,0 +1,12 @@
+setTimeout(function() {
+    console.log('loading iframe after timeout.');
+    document.querySelector('#apacheiframe').src = 'http://apache.org';
+}, 2000);
+document.addEventListener("deviceready", function() {
+    document.getElementById('info').textContent += '\nDevice is ready.';
+}, false);
+
+window.onload = function() {
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/misc/page3.html
----------------------------------------------------------------------
diff --git a/misc/page3.html b/misc/page3.html
index da90d39..6677677 100644
--- a/misc/page3.html
+++ b/misc/page3.html
@@ -27,35 +27,7 @@
     <meta http-equiv="Content-type" content="text/html; charset=utf-8">
     <title>Cordova Mobile Spec</title>
     <link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title" charset="utf-8">
-    <script>
-      console.log('Changing hash #1.');
-      if (location.search.indexOf('hash1') != -1) {
-        location.hash = 'a';
-      } else if (location.search.indexOf('hash2') != -1) {
-        location.replace('#replaced');
-      }
-      var hashCount = 0;
-      function changeHash() {
-        hashCount += 1;
-        if (hashCount % 1) {
-          location.hash = hashCount;
-        } else {
-          location.replace('#' + hashCount);
-        }
-      }
-      if (location.search.indexOf('changeURL') != -1) {
-        history.replaceState(null, null, 'fakepage.html');
-      }
-      function loadFrame() {
-        var ifr = document.createElement('iframe');
-        ifr.src="data:text/html;base64,PGh0bWw+";
-        document.body.appendChild(ifr);
-      }
-      function reload() {
-        // Test that iOS CDVWebViewDelegate doesn't ignore changes when URL doesn't change.
-        location.reload();
-      }
-    </script>
+    <script type="text/javascript" charset="utf-8" src="./page3A.js"></script>      
     <script type="text/javascript" charset="utf-8" src="../cordova-incl.js"></script>
     <script type="text/javascript" charset="utf-8" src="../main.js"></script>
   </head>

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/misc/page3A.js
----------------------------------------------------------------------
diff --git a/misc/page3A.js b/misc/page3A.js
new file mode 100644
index 0000000..8efad58
--- /dev/null
+++ b/misc/page3A.js
@@ -0,0 +1,27 @@
+console.log('Changing hash #1.');
+if (location.search.indexOf('hash1') != -1) {
+  location.hash = 'a';
+} else if (location.search.indexOf('hash2') != -1) {
+  location.replace('#replaced');
+}
+var hashCount = 0;
+function changeHash() {
+  hashCount += 1;
+  if (hashCount % 1) {
+    location.hash = hashCount;
+  } else {
+    location.replace('#' + hashCount);
+  }
+}
+if (location.search.indexOf('changeURL') != -1) {
+  history.replaceState(null, null, 'fakepage.html');
+}
+function loadFrame() {
+  var ifr = document.createElement('iframe');
+  ifr.src="data:text/html;base64,PGh0bWw+";
+  document.body.appendChild(ifr);
+}
+function reload() {
+  // Test that iOS CDVWebViewDelegate doesn't ignore changes when URL doesn't change.
+  location.reload();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/network/index.html
----------------------------------------------------------------------
diff --git a/network/index.html b/network/index.html
index 2902849..b750f6c 100644
--- a/network/index.html
+++ b/network/index.html
@@ -28,48 +28,11 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>
-
-      
-<script type="text/javascript" charset="utf-8">
-
-
-    function eventOutput(s) {
-        var el = document.getElementById("results");
-        el.innerHTML = el.innerHTML + s + "<br>";
-    }
-
-    function printNetwork() {
-        eventOutput("navigator.connection.type=" + navigator.connection.type);
-        eventOutput("navigator.network.connection.type=" + navigator.network.connection.type);
-    }
-
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        var deviceReady = false;
-        function onEvent(e) {
-            eventOutput('Event of type: ' + e.type);
-            printNetwork();
-        }
-        document.addEventListener('online', onEvent, false);
-        document.addEventListener('offline', onEvent, false);
-        document.addEventListener("deviceready", function() {
-            deviceReady = true;
-            eventOutput("Device="+device.platform+" "+device.version);
-            printNetwork();
-        }, false);
-        window.setTimeout(function() {
-            if (!deviceReady) {
-                alert("Error: Cordova did not initialize.  Demo will not run correctly.");
-            }
-        }, 1000);
-    }
-
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
 </script>
 
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>Network Events and State</h1>
     <div id="info">
@@ -78,8 +41,8 @@
     </div>
 
     <h2>Action</h2>
-    <div class="btn large" onclick="printNetwork();">Show Network Connection</div>
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <div class="btn large printNetwork">Show Network Connection</div>
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>
 

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/network/index.js
----------------------------------------------------------------------
diff --git a/network/index.js b/network/index.js
new file mode 100644
index 0000000..41c2c47
--- /dev/null
+++ b/network/index.js
@@ -0,0 +1,38 @@
+function eventOutput(s) {
+    var el = document.getElementById("results");
+    el.innerHTML = el.innerHTML + s + "<br>";
+}
+
+function printNetwork() {
+    eventOutput("navigator.connection.type=" + navigator.connection.type);
+    eventOutput("navigator.network.connection.type=" + navigator.network.connection.type);
+}
+
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    var deviceReady = false;
+    function onEvent(e) {
+        eventOutput('Event of type: ' + e.type);
+        printNetwork();
+    }
+    document.addEventListener('online', onEvent, false);
+    document.addEventListener('offline', onEvent, false);
+    document.addEventListener("deviceready", function() {
+        deviceReady = true;
+        eventOutput("Device="+device.platform+" "+device.version);
+        printNetwork();
+    }, false);
+    window.setTimeout(function() {
+        if (!deviceReady) {
+            alert("Error: Cordova did not initialize.  Demo will not run correctly.");
+        }
+    }, 1000);
+}
+
+window.onload = function() {
+  addListenerToClass('printNetwork', printNetwork);
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/notification/index.html
----------------------------------------------------------------------
diff --git a/notification/index.html b/notification/index.html
index 16aad7d..ab648df 100644
--- a/notification/index.html
+++ b/notification/index.html
@@ -28,112 +28,24 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>      
-
-      
-<script type="text/javascript" charset="utf-8">
-
-    var deviceReady = false;
-
-    //-------------------------------------------------------------------------
-    // Notifications
-    //-------------------------------------------------------------------------
-
-    var beep = function(){
-        navigator.notification.beep(3);
-    };
-
-    var alertDialog = function(message, title, button) {
-        console.log("alertDialog()");
-        navigator.notification.alert(message,
-            function(){
-                console.log("Alert dismissed.");
-            },
-            title, button);
-        console.log("After alert");
-    };
-
-    var confirmDialogA = function(message, title, buttons) {
-        navigator.notification.confirm(message,
-            function(r) {
-                if(r===0){
-                    console.log("Dismissed dialog without making a selection.");
-                    alert("Dismissed dialog without making a selection.");
-                }else{
-                    console.log("You selected " + r);
-                    alert("You selected " + (buttons.split(","))[r-1]);
-                }
-            },
-            title,
-            buttons);
-    };
-
-    var confirmDialogB = function(message, title, buttons) {
-        navigator.notification.confirm(message,
-            function(r) {
-                if(r===0){
-                    console.log("Dismissed dialog without making a selection.");
-                    alert("Dismissed dialog without making a selection.");
-                }else{
-                    console.log("You selected " + r);
-                    alert("You selected " + buttons[r-1]);
-                }
-            },
-            title,
-            buttons);
-    };
-
-    var promptDialog = function(message, title, buttons) {
-        navigator.notification.prompt(message,
-            function(r) {
-                if(r && r.buttonIndex===0){
-                    var msg = "Dismissed dialog";
-                    if( r.input1 ){
-                        msg+=" with input: " + r.input1
-                    }
-                    console.log(msg);
-                    alert(msg);
-                }else{
-                    console.log("You selected " + r.buttonIndex + " and entered: " + r.input1);
-                    alert("You selected " + buttons[r.buttonIndex-1] + " and entered: " + r.input1);
-                }
-            },
-            title,
-            buttons);
-    };
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-                deviceReady = true;
-                console.log("Device="+device.platform+" "+device.version);
-            }, false);
-        window.setTimeout(function() {
-            if (!deviceReady) {
-                alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
-            }
-        },1000);
-    }
-
-</script>
-
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>Notifications and Dialogs</h1>
     <div id="info">
     </div>
     
     <h2>Action</h2>
-    <div class="btn large" onclick="beep();">Beep</div>
-    <div class="btn large" onclick="alertDialog('You pressed alert.', 'Alert Dialog', 'Continue');">Alert Dialog</div>
-    <div class="btn large" onclick="confirmDialogA('You pressed confirm.', 'Confirm Dialog', 'Yes,No,Maybe');">Confirm Dialog - Deprecated</div>
-    <div class="btn large" onclick="confirmDialogB('You pressed confirm.', 'Confirm Dialog', ['Yes', 'No', 'Maybe, Not Sure']);">Confirm Dialog</div>
-    <div class="btn large" onclick="promptDialog('You pressed prompt.', 'Prompt Dialog', ['Yes', 'No', 'Maybe, Not Sure']);">Prompt Dialog</div>
+    <div class="btn large beep">Beep</div>
+    <div class="btn large alertDialog">Alert Dialog</div>
+    <div class="btn large confirmDialogA">Confirm Dialog - Deprecated</div>
+    <div class="btn large confirmDialogB">Confirm Dialog</div>
+    <div class="btn large promptDialog">Prompt Dialog</div>
     
-    <div class="btn large" onclick="alert('You pressed alert.');">Built-in Alert Dialog</div>
-    <div class="btn large" onclick="confirm('You selected confirm');">Built-in Confirm Dialog</div>
-    <div class="btn large" onclick="prompt('This is a prompt.', 'Default value');">Built-in Prompt Dialog</div>
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+    <div class="btn large builtInAlert">Built-in Alert Dialog</div>
+    <div class="btn large builtInConfirm">Built-in Confirm Dialog</div>
+    <div class="btn large builtInPrompt">Built-in Prompt Dialog</div>
+    <h2> </h2><div class="backBtn">Back</div>
   </body>
 </html>      

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/notification/index.js
----------------------------------------------------------------------
diff --git a/notification/index.js b/notification/index.js
new file mode 100644
index 0000000..12e672f
--- /dev/null
+++ b/notification/index.js
@@ -0,0 +1,100 @@
+var deviceReady = false;
+
+//-------------------------------------------------------------------------
+// Notifications
+//-------------------------------------------------------------------------
+
+var beep = function(){
+    navigator.notification.beep(3);
+};
+
+var alertDialog = function(message, title, button) {
+    console.log("alertDialog()");
+    navigator.notification.alert(message,
+        function(){
+            console.log("Alert dismissed.");
+        },
+        title, button);
+    console.log("After alert");
+};
+
+var confirmDialogA = function(message, title, buttons) {
+    navigator.notification.confirm(message,
+        function(r) {
+            if(r===0){
+                console.log("Dismissed dialog without making a selection.");
+                alert("Dismissed dialog without making a selection.");
+            }else{
+                console.log("You selected " + r);
+                alert("You selected " + (buttons.split(","))[r-1]);
+            }
+        },
+        title,
+        buttons);
+};
+
+var confirmDialogB = function(message, title, buttons) {
+    navigator.notification.confirm(message,
+        function(r) {
+            if(r===0){
+                console.log("Dismissed dialog without making a selection.");
+                alert("Dismissed dialog without making a selection.");
+            }else{
+                console.log("You selected " + r);
+                alert("You selected " + buttons[r-1]);
+            }
+        },
+        title,
+        buttons);
+};
+
+var promptDialog = function(message, title, buttons) {
+    navigator.notification.prompt(message,
+        function(r) {
+            if(r && r.buttonIndex===0){
+                var msg = "Dismissed dialog";
+                if( r.input1 ){
+                    msg+=" with input: " + r.input1
+                }
+                console.log(msg);
+                alert(msg);
+            }else{
+                console.log("You selected " + r.buttonIndex + " and entered: " + r.input1);
+                alert("You selected " + buttons[r.buttonIndex-1] + " and entered: " + r.input1);
+            }
+        },
+        title,
+        buttons);
+};
+/**
+ * Function called when page has finished loading.
+ */
+function init() {
+    document.addEventListener("deviceready", function() {
+            deviceReady = true;
+            console.log("Device="+device.platform+" "+device.version);
+        }, false);
+    window.setTimeout(function() {
+        if (!deviceReady) {
+            alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
+        }
+    },1000);
+}
+
+window.onload = function() {
+  addListenerToClass('beep', beep);
+  addListenerToClass('alertDialog', alertDialog, 
+      ['You pressed alert.', 'Alert Dialog', 'Continue']);
+  addListenerToClass('confirmDialogA', confirmDialogA, 
+      ['You pressed confirm.', 'Confirm Dialog', 'Yes,No,Maybe']);
+  addListenerToClass('confirmDialogB', confirmDialogB,
+      ['You pressed confirm.', 'Confirm Dialog', ['Yes', 'No', 'Maybe, Not Sure']]);
+  addListenerToClass('promptDialog', promptDialog,
+      ['You pressed prompt.', 'Prompt Dialog', ['Yes', 'No', 'Maybe, Not Sure']]);
+  addListenerToClass('builtInAlert', alert, 'You pressed alert.');
+  addListenerToClass('builtInConfirm', confirm, 'You selected confirm');
+  addListenerToClass('builtInPrompt', prompt, ['This is a prompt.', 'Default value']);
+
+  addListenerToClass('backBtn', backHome);
+  init();
+}

http://git-wip-us.apache.org/repos/asf/cordova-mobile-spec/blob/a7c88d8f/sql/index.html
----------------------------------------------------------------------
diff --git a/sql/index.html b/sql/index.html
index 5827521..da0d809 100644
--- a/sql/index.html
+++ b/sql/index.html
@@ -28,126 +28,9 @@
     <title>Cordova Mobile Spec</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="../cordova-incl.js"></script>      
-
-      
-<script type="text/javascript" charset="utf-8">
-
-    //-------------------------------------------------------------------------
-    // HTML5 Database
-    //-------------------------------------------------------------------------
-    var dbs = [];
-    var quotas = [2000000, 2000000];
-    var names = ['mydb', 'rand' + Math.random()];
-    function openDb(index) {
-        try {
-            databaseOutput('Openning db with name: ' + names[index]);
-            return openDatabase(names[index], "1.0", "Apache Cordova Demo", quotas[index]);
-        } catch (e) {
-            databaseOutput('Got exception: ' + e);
-        }
-    }
-
-    var callDatabase = function(index) {
-        var db = dbs[index] = openDb(index);
-        if (!db) {
-            return;
-        }
-        databaseOutput("Database opened.");
-        db.transaction(function (tx) {
-            tx.executeSql('DROP TABLE IF EXISTS DEMO');
-            tx.executeSql('CREATE TABLE IF NOT EXISTS DEMO (id unique, data)', [],
-                 function(tx,results) { console.log("Created table"); },
-                 function(tx,err) { alert("Error creating table: "+err.message); });
-            tx.executeSql('INSERT INTO DEMO (id, data) VALUES (1, "First row")', [],
-                 function(tx,results) { console.log("Insert row1 success"); },
-                 function(tx,err) { alert("Error adding 1st row: "+err.message); });
-            tx.executeSql('INSERT INTO DEMO (id, data) VALUES (2, "Second row")', [],
-                 function(tx,results) { console.log("Insert row2 success"); },
-                 function(tx,err) { alert("Error adding 2nd row: "+err.message); });
-            databaseOutput("Data written to DEMO table.");
-            console.log("Data written to DEMO table.");
-
-            tx.executeSql('SELECT * FROM DEMO', [], function (tx, results) {
-                var len = results.rows.length;
-                var text = "DEMO table: " + len + " rows found.<br>";
-                text = text + "<table border='1'><tr><td>Row</td><td>Data</td></tr>";
-                for (var i=0; i<len; i++){
-                    text = text + "<tr><td>" + i + "</td><td>" + results.rows.item(i).id + ", " + results.rows.item(i).data + "</td></tr>";
-                }
-                text = text + "</table>";
-                databaseOutput(text);
-            }, function(tx, err) {
-                alert("Error processing SELECT * SQL: "+err.message);
-            });
-            tx.executeSql('SELECT ID FROM DEMO', [], function (tx, results) {
-                var len = results.rows.length;
-                var text = "DEMO table: " + len + " rows found.<br>";
-                text = text + "<table border='1'><tr><td>Row</td><td>Data</td></tr>";
-                for (var i=0; i<len; i++){
-                    text = text + "<tr><td>" + i + "</td><td>" + results.rows.item(i).id + "</td></tr>";
-                }
-                text = text + "</table>";
-                databaseOutput(text);
-            }, function(tx, err) {
-                alert("Error processing SELECT ID SQL: "+err.message);
-            });
-            
-        },
-        function(err) {
-            console.log("Transaction failed: " + err.message);
-        });
-
-
-    };
-
-    var readDatabase = function(index) {
-        var db = dbs[index];
-    	if (!db) {
-            db = dbs[index] = openDb(index);
-            if (!db) {
-                return;
-            }
-        }
-        db.transaction(function (tx) {
-            tx.executeSql('SELECT * FROM DEMO WHERE id=2', [], function (tx, results) {
-                var len = results.rows.length;
-                var text = "DEMO table: " + len + " rows found.<br>";
-                text = text + "<table border='1'><tr><td>Row</td><td>Data</td></tr>";
-                for (var i=0; i<len; i++){
-                    text = text + "<tr><td>" + i + "</td><td>" + results.rows.item(i).id + ", " + results.rows.item(i).data + "</td></tr>";
-                }
-                text = text + "</table>";
-                databaseOutput(text);
-            }, function(tx, err) {
-                alert("Error processing SELECT * WHERE id=2 SQL: "+err.message);
-            });
-        });
-    }
-
-    function increaseQuota(index) {
-        quotas[index] *= 2;
-        databaseOutput('quota ' + index + ' is now ' + quotas[index]);
-    }
-
-    var databaseOutput = function(s) {
-        var el = document.getElementById("database_results");
-        el.innerHTML = el.innerHTML + s + "<br>";
-        el.scrollByLines(20000);
-    };
-    
-    /**
-     * Function called when page has finished loading.
-     */
-    function init() {
-        document.addEventListener("deviceready", function() {
-            console.log("Device="+device.platform+" "+device.version);
-        }, false);
-    }
-
-</script>
-
+    <script type="text/javascript" charset="utf-8" src="./index.js"></script>      
   </head>
-  <body onload="init();" id="stage" class="theme">
+  <body id="stage" class="theme">
   
     <h1>HTML5 Database</h1>   
     <div id="info">
@@ -155,13 +38,13 @@
         <span id="database_results"></span>
     </div>
     <h2>Action</h2>
-    <div class="btn large" onclick="callDatabase(0);">Create, Add, Read Database (Constant name)</div>
-    <div class="btn large" onclick="readDatabase(0);">Read Database (Constant name)</div>
-    <div class="btn large" onclick="increaseQuota(0);">Increase Quota (Constant name)</div>
-    <div class="btn large" onclick="callDatabase(1);">Create, Add, Read Database (Random Name)</div>
-    <div class="btn large" onclick="readDatabase(1);">Read Database (Random Name)</div>
-    <div class="btn large" onclick="increaseQuota(1);">Increase Quota (Random Name)</div>
-    <div class="btn large" onclick="location = location.href">Reload Page</div>
-    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>    
+    <div class="btn large callDatabase0">Create, Add, Read Database (Constant name)</div>
+    <div class="btn large readDatabase0">Read Database (Constant name)</div>
+    <div class="btn large increaseQuota0">Increase Quota (Constant name)</div>
+    <div class="btn large callDatabase1">Create, Add, Read Database (Random Name)</div>
+    <div class="btn large readDatabase1">Read Database (Random Name)</div>
+    <div class="btn large increaseQuota1">Increase Quota (Random Name)</div>
+    <div class="btn large reloadPage">Reload Page</div>
+    <h2> </h2><div class="backBtn">Back</div>    
   </body>
 </html>