Merge branch 'master' of https://github.com/hermwong/phonegap-webos
diff --git a/Makefile b/Makefile
index 73ce259..92162ba 100755
--- a/Makefile
+++ b/Makefile
@@ -18,6 +18,7 @@
 ECHO = echo
 ECHO_N = echo -n
 JAVA = java
+PGVERSION = 1.0.0
 
 NAME = `$(CAT) framework/appinfo.json | $(GREP) '"id"' | $(CUT) -d \" -f 4`
 VERSION = `$(CAT) framework/appinfo.json | $(GREP) '"version"' | $(CUT) -d \" -f 4`
@@ -41,14 +42,14 @@
 	palm-launch $(NAME)
 	
 copy_js:
-	cp lib/phonegap.js framework/phonegap.js
+	cp lib/phonegap.js framework/phonegap-$(PGVERSION).js
 	
 js: lib/phonegap.js
 
-lib/phonegap.js: js/phonegap.js.base js/acceleration.js js/accelerometer.js js/application.js js/audio.js js/camera.js js/contacts.js js/debugconsole.js js/device.js js/file.js js/geolocation.js js/map.js js/mojo.js js/mouse.js js/network.js js/notification.js js/orientation.js js/position.js js/service.js js/sms.js js/telephony.js js/window.js js/windowproperties.js
+lib/phonegap.js: js/phonegap-core.js js/acceleration.js js/accelerometer.js js/application.js js/audio.js js/camera.js js/contacts.js js/debugconsole.js js/device.js js/file.js js/geolocation.js js/map.js js/mojo.js js/mouse.js js/network.js js/notification.js js/orientation.js js/position.js js/service.js js/sms.js js/telephony.js js/window.js js/windowproperties.js lib/thumbs.0.5.2.js
 	$(MKPATH) lib
 	$(RM_F) $@
-	$(CAT) js/phonegap.js.base >> $@
+	$(CAT) js/phonegap-core.js >> $@
 	$(CAT) js/acceleration.js >> $@
 	$(CAT) js/accelerometer.js >> $@
 	$(CAT) js/application.js >> $@
@@ -71,3 +72,4 @@
 	$(CAT) js/telephony.js >> $@
 	$(CAT) js/window.js >> $@
 	$(CAT) js/windowproperties.js >> $@
+	$(CAT) lib/thumbs.0.5.2.js >> $@
diff --git a/README.md b/README.md
index 2c62fa6..9e1910d 100755
--- a/README.md
+++ b/README.md
@@ -40,7 +40,7 @@
 -----------------------------------------------------
  - In order to use the vibration API on palm, your application needs to have a "com.palm.*" namespace, as vibration on webOS is a private API. The caveat of doing this is that you are essentially indicating that your app should pretend to be a "Palm app" (rather than a Nitobi app, for example) ... and as a result your app will be denied from the Palm app catalog.
  - Currently the map.show function can only accept one position, as Palm uses google maps as its native maps application, and it only can take one marker as a parameter.
- - Touch event not supported, natively. Must use the click event, or maybe we can emulate the touch event by capturing the click event.
+ - Touch event not supported, natively. PhoneGap now includes event handlers for mouse & touch events - please see the example app bundled with PhoneGap-webOS
  - If using Lawnchair, the only supported adaptor is webkitsqlite.
  - html select boxes are implemented by phonegap, not supported natively (believe it or not). only the most basic functionality is implemented, so be aware using this control could cause problems.
  - To enable verbose logging, add the file framework_config.json to your framework/www/ folder, containing the following json content: { "logLevel": 99 }
diff --git a/framework/dashboard.html b/framework/dashboard.html
index b09f6cf..5ae26d0 100644
--- a/framework/dashboard.html
+++ b/framework/dashboard.html
@@ -7,11 +7,8 @@
 <head>
 	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 	<title>Dashboard</title>
-	
-	<link rel="stylesheet" type="text/css" href="menu.css">
-	
 </head>
 <body>
-Win
+Hello World
 </body>
 </html>
diff --git a/framework/index.html b/framework/index.html
index 693206f..d5c45c3 100644
--- a/framework/index.html
+++ b/framework/index.html
@@ -16,35 +16,29 @@
 	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 	<title>PhoneGap WebOS</title>
 	
-	<link rel="stylesheet" href="jqtouch/jqtouch.css" />
-	<link rel="stylesheet" href="jqtouch/themes/default/theme.css" />
-	<link rel="stylesheet" href="css/main.css" />
-	
-	
-	<script type="text/javascript" src="phonegap.js"></script>   
+	<script type="text/javascript" src="phonegap-1.0.0.js"></script>   
 	<script type="text/javascript">
 		// create global var for sqlite database instance
 		var db;
 	</script>
-	
-	
+		
 	<link rel="stylesheet" type="text/css" href="menu.css">
 	
 </head>
 <body>
 
-<a onclick="dashboard();">Dashboard</a>
-
 <div id="menu">
 	<a onclick="page('screen');">Adjust Screen Settings</a>
+	<a onclick="page('notifications');">Notification Examples</a>
 	<a onclick="info();">Show Device Info</a>
-	<a onclick="net();">Show Network Info</a>	
-	<a onclick="navigator.notification.showBanner('Banner test','banner');menu(false);">Show Banner Message</a>
+	<a onclick="net();">Show Network Info</a>		
 	<a onclick="window.debug.log('trace this');">Console Logging</a>
 	<a onclick="launchmap()">Launch Map App</a>
-	<a onclick="navigator.window.newCard('about:blank', '<html><body>Hello again!</body></html>');menu(false);">Launch New Card</a>
+	<a onclick="navigator.window.newCard('dashboard.html'); menu(false);">Launch New Card</a>
 	<a onclick="getPicture();">Launch Camera</a>
-	<a onclick="storage();">Storage Tests</a>
+	<a onclick="storage();">Storage Tests</a> 
+	<a onclick="callPhoneGapExec();menu(false);">PhoneGap Exec</a>
+	<a onclick="page('touchDemo');">Touch Events Examples</a>
 	<a onclick="menu(false);">Done</a>
 </div>
 
@@ -52,31 +46,53 @@
 	<p><input type="checkbox" onchange="navigator.window.setFullScreen(this.checked);">navigator.window.setFullScreen();</p>
 	<p><input type="checkbox" onchange="navigator.window.blockScreenTimeout(this.checked);">navigator.window.blockScreenTimeout();</p>
 	<p><input type="checkbox" onchange="navigator.accelerometer.setFastAccelerometer(this.checked);">navigator.accelerometer.fastAccelerometer();</p>
+	
 	<p>navigator.orientation.setWindowOrientation();</p>
 	<input type="radio" onchange="navigator.orientation.setOrientation(this.value);" value="up" name="orientation" checked>up
 	<input type="radio" onchange="navigator.orientation.setOrientation(this.value);" value="down" name="orientation">down
 	<input type="radio" onchange="navigator.orientation.setOrientation(this.value);" value="left" name="orientation">left
 	<input type="radio" onchange="navigator.orientation.setOrientation(this.value);" value="right" name="orientation">right
 	<input type="radio" onchange="navigator.orientation.setOrientation(this.value);" value="free" name="orientation">free
-
-	
+		
 	<p>navigator.orientation.getCurrentOrientation()</p>
-	<input type="button" onclick="displayCurrentOrientation();" value="Get Current Orientation">  
-	
-	<p>navigator.notification.alert();</p>
-	<input type="button" onclick="navigator.notification.alert('alert');" value="Show Alert">    
-	
+	<button onclick="displayCurrentOrientation();">Get Current Orientation</button>  	
 </div>
 
-<div id="info"></div>
+<div id="notifications" style="display: none;">
+	<p>navigator.notification.newDashboard();</p>
+	<button onclick="navigator.notification.newDashboard('dashboard.html');">Dashboard</button>
+	
+	<p>navigator.notification.alert();</p>
+	<button onclick="navigator.notification.alert('alert');">Show Alert</button>
+	
+	<p>navigator.notification.showBanner();</p>
+	<button onclick="navigator.notification.showBanner('Banner test','banner');">Show Banner Message</button>	
+</div>
 
-<div id="net"></div>
+<div id="blank" width="100%" height="100%" style="background: #FFFFFF;"></div>
 
-<div id="camera"></div> 
+<div id="info" style="display: none;"></div>
+
+<div id="net" style="display: none;"></div>
+
+<div id="camera" style="display: none;"></div>
+
+<div id="touchDemo" style="display: none;">
+	<p>Touch Events Demo</p>
+	<button id="btnTouchStart">Touch Start</button>
+	<button id="btnTouchEnd">Touch End</button>
+	<p>Run your finger/mouse along button to trigger touchmove</p>
+	<button id="btnTouchMove" width="250">Touch Move</button>	
+	<p>Mouse Events Demo</p>
+	<button id="btnMouseDown">Mouse Down</button>
+	<button id="btnMouseUp">Mouse Up</button>
+	<p>Run your finger/mouse along button to trigger mousemove</p>
+	<button id="btnMouseMove" width="250">Mouse Move</button>
+</div> 
 
 <div id="storage" style="display: none">
 	<p>storage tests</p>
-	<input type="button" onclick="createDB();" value="Test SQLite DB"> 
+	<button onclick="createDB();">Test SQLite DB</button> 
 	<div id="storageResults"></div>
 </div>
 
@@ -85,6 +101,33 @@
     // PhoneGap is ready, do all your stuf here
 }, false);
 
+// setup event listeners for touch events 
+document.querySelector('#btnTouchStart').addEventListener('touchstart', onTouchEvent, false);
+document.querySelector('#btnTouchEnd').addEventListener('touchend', onTouchEvent, false);
+document.querySelector('#btnTouchMove').addEventListener('touchmove', onTouchEvent, false);
+// setup event listeners for mouse events
+document.querySelector('#btnMouseDown').addEventListener('mousedown', onTouchEvent, false);
+document.querySelector('#btnMouseUp').addEventListener('mouseup', onTouchEvent, false);
+document.querySelector('#btnMouseMove').addEventListener('mousemove', onTouchEvent, false);
+
+function onTouchEvent(event) {
+	navigator.notification.alert(event.type);
+}
+
+function callPhoneGapExec() {
+	//win, fail, clazz, action, args
+	PhoneGap.exec(success, fail, 'navigator.notification', 'alert', 'testing exec'); 
+	
+	function success(msg) {
+		console.log(msg + ' exec succeeded');
+	}
+	
+	function fail(msg) {
+		//navigator.notification.alert('exec failed');
+		console.log(msg + ' exec failed');
+	}
+}
+
 function createDB() {  
 	document.getElementById('storageResults').innerHTML = '';
 	db = window.openDatabase("test", "1.0", "Test DB", false);
@@ -122,10 +165,6 @@
 	}
 }
 
-function dashboard() {
-    navigator.notification.newDashboard("dashboard.html");
-}
-
 function info() {
 	var deviceinfo = JSON.stringify(navigator.device.getDeviceInfo()).replace(/,/g, ', ');
 	page('info');
diff --git a/framework/phonegap.js b/framework/phonegap-1.0.0.js
similarity index 76%
rename from framework/phonegap.js
rename to framework/phonegap-1.0.0.js
index 790c72d..1571443 100644
--- a/framework/phonegap.js
+++ b/framework/phonegap-1.0.0.js
@@ -4,8 +4,351 @@
 function PhoneGap() {
 	ready = true;
 	available = true;
-	sceneController = null;
-};
+	sceneController = null;	
+}; 
+
+PhoneGap.exec = function(win, fail, clazz, action, args) {
+
+ setTimeout(function() { 
+	 PhoneGap.plugins[clazz].execute(action, args, win, fail); 
+   }, 0);
+
+}
+
+PhoneGap.checkArgs = function(args, func) {
+    if (typeof args == 'object')
+        func.apply(null, args);
+    else
+        func(args);
+}
+
+PhoneGap.callback = function(success, win, fail) {
+	if (success)
+		win();
+	else
+		fail();    
+}
+
+// translates the action into an API call
+accelerometerAPI = {
+    execute: function(action, args, win, fail) {
+        var actionFound = false;
+		switch(action) {
+			case 'setFastAccelerometer':				
+				PhoneGap.checkArgs(args, navigator.accelerometer.setFastAccelerometer);    
+				actionFound = true; 
+				break;
+			case 'getCurrentAcceleration':
+				PhoneGap.checkArgs(args, navigator.accelerometer.getCurrentAcceleration);
+				actionFound = true;
+				break;	
+			case 'watchAcceleration':
+			    PhoneGap.checkArgs(args, navigator.accelerometer.watchAcceleration);
+			    actionFound = true;
+			    break;
+			case 'clearWatch':
+			    PhoneGap.checkArgs(args, navigator.accelerometer.clearWatch);
+			    actionFound = true;
+			    break;
+			case 'start':
+			    PhoneGap.checkArgs(args, navigator.accelerometer.start);
+			    actionFound = true;
+			    break;      		
+		}
+
+        PhoneGap.callback(actionFound, win, fail);
+    }
+}
+
+applicationAPI = {
+    execute: function(action, args, win, fail) {
+        var actionFound = false;
+		switch(action) {
+			case 'activate':				
+				PhoneGap.checkArgs(args, navigator.application.activate);    
+				actionFound = true; 
+				break;
+			case 'deactivate':
+				PhoneGap.checkArgs(args, navigator.application.deactivate);
+				actionFound = true;
+				break;	
+			case 'getIdentifier':
+			    PhoneGap.checkArgs(args, navigator.application.getIdentifier);
+			    actionFound = true;
+			    break;      		
+		}
+
+		PhoneGap.callback(actionFound, win, fail);       
+    }
+}
+
+cameraAPI = {
+    execute: function(action, args, win, fail) {
+        var actionFound = false;
+		switch(action) {
+			case 'getPicture':
+				console.log("in here");
+				PhoneGap.checkArgs(args, navigator.camera.getPicture);    
+				actionFound = true; 
+				break;      		
+		}
+
+		PhoneGap.callback(actionFound, win, fail);        
+    }
+}
+
+debugAPI = {
+    execute: function(action, args, win, fail) {
+        var actionFound = false;
+		switch(action) {
+			case 'log':				
+				PhoneGap.checkArgs(args, window.debug.log);    
+				actionFound = true; 
+				break;
+		    case 'warn':
+			    PhoneGap.checkArgs(args, window.debug.warn);    
+			    actionFound = true; 
+			    break;		    
+		    case 'error':
+			    PhoneGap.checkArgs(args, window.debug.error);    
+			    actionFound = true; 
+			    break;		          		
+		}
+
+		PhoneGap.callback(actionFound, win, fail);        
+    }
+}
+
+deviceAPI = {
+    execute: function(action, args, win, fail) {
+        var actionFound = false;
+		switch(action) {
+			case 'getDeviceInfo':				
+				PhoneGap.checkArgs(args, navigator.device.getDeviceInfo);    
+				actionFound = true; 
+				break;		          		
+		}
+
+		PhoneGap.callback(actionFound, win, fail);        
+    }
+}
+
+geolocationAPI = {
+    execute: function(action, args, win, fail) {
+        var actionFound = false;
+		switch(action) {
+			case 'getCurrentPosition':				
+				PhoneGap.checkArgs(args, navigator.geolocation.getCurrentPosition);    
+				actionFound = true; 
+				break; 
+			case 'watchPosition':				
+				PhoneGap.checkArgs(args, navigator.geolocation.watchPosition);    
+				actionFound = true; 
+				break;
+			case 'clearWatch':
+			    PhoneGap.checkArgs(args, navigator.geolocation.clearWatch);    
+			    actionFound = true; 
+			    break;
+			case 'start':
+			    PhoneGap.checkArgs(args, navigator.geolocation.start);    
+			    actionFound = true; 
+			    break;
+			case 'stop':
+			    PhoneGap.checkArgs(args, navigator.geolocation.stop);    
+			    actionFound = true; 
+			    break;								   	          		
+		}
+
+		PhoneGap.callback(actionFound, win, fail);        
+    }
+}
+
+mapAPI = {
+    execute: function(action, args, win, fail) {
+        var actionFound = false;
+		switch(action) {
+			case 'show':				
+				PhoneGap.checkArgs(args, navigator.map.show);    
+				actionFound = true; 
+				break;		          		
+		}
+
+		PhoneGap.callback(actionFound, win, fail);        
+    }
+}
+
+mouseAPI = {
+    execute: function(action, args, win, fail) {
+        var actionFound = false;
+		switch(action) {
+			case 'simulateMouseClick':				
+				PhoneGap.checkArgs(args, navigator.mouse.simulateMouseClick);    
+				actionFound = true; 
+				break;		          		
+		}
+
+		PhoneGap.callback(actionFound, win, fail);        
+    }
+} 
+
+networkAPI = {
+    execute: function(action, args, win, fail) {
+        var actionFound = false;
+		switch(action) {
+			case 'isReachable':				
+				PhoneGap.checkArgs(args, navigator.network.isReachable);    
+				actionFound = true; 
+				break;		          		
+		}
+
+		PhoneGap.callback(actionFound, win, fail);        
+    }
+}
+
+notificationAPI = {
+    execute: function(action, args, win, fail) {
+		var actionFound = false;
+		switch(action) {
+			case 'alert':				
+				PhoneGap.checkArgs(args, navigator.notification.alert);    
+				actionFound = true; 
+				break;
+			case 'showBanner':
+				PhoneGap.checkArgs(args, navigator.notification.showBanner);
+				actionFound = true;
+				break;	
+			case 'newDashboard':
+			    PhoneGap.checkArgs(args, navigator.notification.newDashboard);
+			    actionFound = true;
+			    break;
+			case 'removeBannerMessage':
+			    PhoneGap.checkArgs(args, navigator.notification.removeBannerMessage);
+			    actionFound = true;
+			    break;
+			case 'clearBannerMessage':
+			    PhoneGap.checkArgs(args, navigator.notification.clearBannerMessage);
+			    actionFound = true;
+			    break;
+			case 'vibrate':            
+			    PhoneGap.checkArgs(args, navigator.notification.vibrate);
+			    actionFound = true;
+			    break;
+			case 'beep':               
+			    PhoneGap.checkArgs(args, navigator.notification.beep);
+			    actionFound = true;
+			    break;       		
+		}
+
+		PhoneGap.callback(actionFound, win, fail);
+   }
+}
+
+orientationAPI = {
+    execute: function(action, args, win, fail) {
+        var actionFound = false;
+		switch(action) {
+			case 'setOrientation':				
+				PhoneGap.checkArgs(args, navigator.orientation.setOrientation);    
+				actionFound = true; 
+				break;
+			case 'getOrientation':
+			    PhoneGap.checkArgs(args, navigator.orientation.getOrientation);    
+			    actionFound = true; 
+			    break;			    
+			case 'start':
+			    PhoneGap.checkArgs(args, navigator.orientation.start);    
+				actionFound = true; 
+				break;
+			case 'watchOrientation':
+			    PhoneGap.checkArgs(args, navigator.orientation.watchOrientation);    
+				actionFound = true; 
+				break;
+			case 'clearWatch':
+                PhoneGap.checkArgs(args, navigator.orientation.clearWatch);    
+			    actionFound = true; 
+			    break;
+		}
+
+		PhoneGap.callback(actionFound, win, fail);        
+    }
+}
+
+smsAPI = {
+    execute: function(action, args, win, fail) {
+        var actionFound = false;
+		switch(action) {
+			case 'send':				
+				PhoneGap.checkArgs(args, navigator.sms.send);    
+				actionFound = true; 
+				break;		          		
+		}
+
+		PhoneGap.callback(actionFound, win, fail);        
+    }
+}
+
+telephonyAPI = {
+    execute: function(action, args, win, fail) {
+        var actionFound = false;
+		switch(action) {
+			case 'send':				
+				PhoneGap.checkArgs(args, navigator.telephony.send);    
+				actionFound = true; 
+				break;		          		
+		}
+
+		PhoneGap.callback(actionFound, win, fail);        
+    }
+}
+
+windowAPI = {
+    execute: function(action, args, win, fail) {
+   		var actionFound = false;
+   		switch(action) {
+   			case 'newCard':
+   			    PhoneGap.checkArgs(args, navigator.window.newCard);  				    
+   				actionFound = true; 
+   				break;
+   			case 'setFullScreen':
+   			  	PhoneGap.checkArgs(args, navigator.window.setFullScreen);
+   				actionFound = true; 
+   				break;
+   			case 'setWindowProperties':
+   			    PhoneGap.checkArgs(args, navigator.window.setWindowProperties);
+		        actionFound = true;
+		        break;   			
+   			case 'blockScreenTimeout':
+   			    PhoneGap.checkArgs(args, navigator.window.blockScreenTimeout);
+   			    actionFound = true;
+		        break;
+   			case 'setSubtleLightbar':
+   			    PhoneGap.checkArgs(args, navigator.window.setSubtleLightbar);
+   			    actionFound = true;
+   			    break;
+   				   			  	
+   		}
+
+   		PhoneGap.callback(actionFound, win, fail);
+      }    
+}
+
+// this mapping acts as a shim to the webOS APIs
+PhoneGap.plugins = {};
+PhoneGap.plugins['navigator.accelerometer'] = accelerometerAPI;
+PhoneGap.plugins['navigator.application'] = applicationAPI;
+PhoneGap.plugins['navigator.camera'] = cameraAPI;
+PhoneGap.plugins['window.debug'] = debugAPI;
+PhoneGap.plugins['navigator.device'] = deviceAPI;
+PhoneGap.plugins['navigator.geolocation'] = geolocationAPI;
+PhoneGap.plugins['navigator.map'] = mapAPI;
+PhoneGap.plugins['navigator.mouse'] = mouseAPI;
+PhoneGap.plugins['navigator.network'] = networkAPI; 
+PhoneGap.plugins['navigator.notification'] = notificationAPI;
+PhoneGap.plugins['navigator.orientation'] = orientationAPI; 
+PhoneGap.plugins['navigator.sms'] = smsAPI;
+PhoneGap.plugins['navigator.telephony'] = telephonyAPI;  
+PhoneGap.plugins['navigator.window'] = windowAPI;
+
 
 document.addEventListener('DOMContentLoaded', function () {
     window.phonegap = new PhoneGap();
@@ -424,6 +767,7 @@
     this.version  = null;
     this.name     = null;
     this.uuid     = null;
+    this.deviceInfo = null;
 };
 
 /*
@@ -432,7 +776,7 @@
  *		var deviceinfo = JSON.stringify(navigator.device.getDeviceInfo()).replace(/,/g, ', ');
  */
 Device.prototype.getDeviceInfo = function() {
-	return JSON.parse(PalmSystem.deviceInfo);
+	return this.deviceInfo;//JSON.parse(PalmSystem.deviceInfo);
 };
 
 /*
@@ -462,6 +806,15 @@
     }, 10);
 	
 	this.setUUID();
+	this.setDeviceInfo();
+};
+
+Device.prototype.setDeviceInfo = function() {
+    var parsedData = JSON.parse(PalmSystem.deviceInfo);
+    
+    this.deviceInfo = parsedData;
+    this.version = parsedData.platformVersion;
+    this.name = parsedData.modelName;
 };
 
 Device.prototype.setUUID = function() {
@@ -1393,4 +1746,83 @@
     fastAccelerometer = false;
 };
 
-if (typeof navigator.windowProperties == 'undefined') navigator.windowProperties = new WindowProperties();
\ No newline at end of file
+if (typeof navigator.windowProperties == 'undefined') navigator.windowProperties = new WindowProperties();(function(window) {
+
+    /**
+     * Do not use thumbs.js on touch-enabled devices
+     * 
+     * Thanks to Jesse MacFadyen (purplecabbage):
+     * https://gist.github.com/850593#gistcomment-22484
+     */
+    try {
+        document.createEvent('TouchEvent');
+        return;
+    }
+    catch(e) {
+    }
+
+    /**
+     * Map touch events to mouse events
+     */
+    var eventMap = {
+        'mousedown': 'touchstart',
+        'mouseup':   'touchend',
+        'mousemove': 'touchmove'
+    };
+
+    /**
+     * Fire touch events
+     *
+     * Monitor mouse events and fire a touch event on the
+     * object broadcasting the mouse event. This approach
+     * likely has poorer performance than hijacking addEventListener
+     * but it is a little more browser friendly.
+     */
+    window.addEventListener('load', function() {
+        for (var key in eventMap) {
+            document.body.addEventListener(key, function(e) {
+                // Supports:
+                //   - addEventListener
+                //   - setAttribute
+                var event = createTouchEvent(eventMap[e.type], e);
+                e.target.dispatchEvent(event);
+
+                // Supports:
+                //   - element.ontouchstart
+                var fn = e.target['on' + eventMap[e.type]];
+                if (typeof fn === 'function') fn(e);
+            }, false);
+        }
+    }, false);
+
+    /**
+     * Utility function to create a touch event.
+     *
+     * @param  name  {String} of the event
+     * @return event {Object}
+     */
+    var createTouchEvent = function(name, e) {
+        var event = document.createEvent('MouseEvents');
+
+        event.initMouseEvent(
+            name,
+            e.bubbles,
+            e.cancelable,
+            e.view,
+            e.detail,
+            e.screenX,
+            e.screenY,
+            e.clientX,
+            e.clientY,
+            e.ctrlKey,
+            e.altKey,
+            e.shiftKey,
+            e.metaKey,
+            e.button,
+            e.relatedTarget
+        );
+
+        return event;
+    };
+
+})(window);
diff --git a/js/phonegap-core.js b/js/phonegap-core.js
new file mode 100644
index 0000000..6d122d0
--- /dev/null
+++ b/js/phonegap-core.js
@@ -0,0 +1,356 @@
+if (typeof(DeviceInfo) != 'object')
+    DeviceInfo = {};
+
+function PhoneGap() {
+	ready = true;
+	available = true;
+	sceneController = null;	
+}; 
+
+PhoneGap.exec = function(win, fail, clazz, action, args) {
+
+ setTimeout(function() { 
+	 PhoneGap.plugins[clazz].execute(action, args, win, fail); 
+   }, 0);
+
+}
+
+PhoneGap.checkArgs = function(args, func) {
+    if (typeof args == 'object')
+        func.apply(null, args);
+    else
+        func(args);
+}
+
+PhoneGap.callback = function(success, win, fail) {
+	if (success)
+		win();
+	else
+		fail();    
+}
+
+// translates the action into an API call
+accelerometerAPI = {
+    execute: function(action, args, win, fail) {
+        var actionFound = false;
+		switch(action) {
+			case 'setFastAccelerometer':				
+				PhoneGap.checkArgs(args, navigator.accelerometer.setFastAccelerometer);    
+				actionFound = true; 
+				break;
+			case 'getCurrentAcceleration':
+				PhoneGap.checkArgs(args, navigator.accelerometer.getCurrentAcceleration);
+				actionFound = true;
+				break;	
+			case 'watchAcceleration':
+			    PhoneGap.checkArgs(args, navigator.accelerometer.watchAcceleration);
+			    actionFound = true;
+			    break;
+			case 'clearWatch':
+			    PhoneGap.checkArgs(args, navigator.accelerometer.clearWatch);
+			    actionFound = true;
+			    break;
+			case 'start':
+			    PhoneGap.checkArgs(args, navigator.accelerometer.start);
+			    actionFound = true;
+			    break;      		
+		}
+
+        PhoneGap.callback(actionFound, win, fail);
+    }
+}
+
+applicationAPI = {
+    execute: function(action, args, win, fail) {
+        var actionFound = false;
+		switch(action) {
+			case 'activate':				
+				PhoneGap.checkArgs(args, navigator.application.activate);    
+				actionFound = true; 
+				break;
+			case 'deactivate':
+				PhoneGap.checkArgs(args, navigator.application.deactivate);
+				actionFound = true;
+				break;	
+			case 'getIdentifier':
+			    PhoneGap.checkArgs(args, navigator.application.getIdentifier);
+			    actionFound = true;
+			    break;      		
+		}
+
+		PhoneGap.callback(actionFound, win, fail);       
+    }
+}
+
+cameraAPI = {
+    execute: function(action, args, win, fail) {
+        var actionFound = false;
+		switch(action) {
+			case 'getPicture':
+				console.log("in here");
+				PhoneGap.checkArgs(args, navigator.camera.getPicture);    
+				actionFound = true; 
+				break;      		
+		}
+
+		PhoneGap.callback(actionFound, win, fail);        
+    }
+}
+
+debugAPI = {
+    execute: function(action, args, win, fail) {
+        var actionFound = false;
+		switch(action) {
+			case 'log':				
+				PhoneGap.checkArgs(args, window.debug.log);    
+				actionFound = true; 
+				break;
+		    case 'warn':
+			    PhoneGap.checkArgs(args, window.debug.warn);    
+			    actionFound = true; 
+			    break;		    
+		    case 'error':
+			    PhoneGap.checkArgs(args, window.debug.error);    
+			    actionFound = true; 
+			    break;		          		
+		}
+
+		PhoneGap.callback(actionFound, win, fail);        
+    }
+}
+
+deviceAPI = {
+    execute: function(action, args, win, fail) {
+        var actionFound = false;
+		switch(action) {
+			case 'getDeviceInfo':				
+				PhoneGap.checkArgs(args, navigator.device.getDeviceInfo);    
+				actionFound = true; 
+				break;		          		
+		}
+
+		PhoneGap.callback(actionFound, win, fail);        
+    }
+}
+
+geolocationAPI = {
+    execute: function(action, args, win, fail) {
+        var actionFound = false;
+		switch(action) {
+			case 'getCurrentPosition':				
+				PhoneGap.checkArgs(args, navigator.geolocation.getCurrentPosition);    
+				actionFound = true; 
+				break; 
+			case 'watchPosition':				
+				PhoneGap.checkArgs(args, navigator.geolocation.watchPosition);    
+				actionFound = true; 
+				break;
+			case 'clearWatch':
+			    PhoneGap.checkArgs(args, navigator.geolocation.clearWatch);    
+			    actionFound = true; 
+			    break;
+			case 'start':
+			    PhoneGap.checkArgs(args, navigator.geolocation.start);    
+			    actionFound = true; 
+			    break;
+			case 'stop':
+			    PhoneGap.checkArgs(args, navigator.geolocation.stop);    
+			    actionFound = true; 
+			    break;								   	          		
+		}
+
+		PhoneGap.callback(actionFound, win, fail);        
+    }
+}
+
+mapAPI = {
+    execute: function(action, args, win, fail) {
+        var actionFound = false;
+		switch(action) {
+			case 'show':				
+				PhoneGap.checkArgs(args, navigator.map.show);    
+				actionFound = true; 
+				break;		          		
+		}
+
+		PhoneGap.callback(actionFound, win, fail);        
+    }
+}
+
+mouseAPI = {
+    execute: function(action, args, win, fail) {
+        var actionFound = false;
+		switch(action) {
+			case 'simulateMouseClick':				
+				PhoneGap.checkArgs(args, navigator.mouse.simulateMouseClick);    
+				actionFound = true; 
+				break;		          		
+		}
+
+		PhoneGap.callback(actionFound, win, fail);        
+    }
+} 
+
+networkAPI = {
+    execute: function(action, args, win, fail) {
+        var actionFound = false;
+		switch(action) {
+			case 'isReachable':				
+				PhoneGap.checkArgs(args, navigator.network.isReachable);    
+				actionFound = true; 
+				break;		          		
+		}
+
+		PhoneGap.callback(actionFound, win, fail);        
+    }
+}
+
+notificationAPI = {
+    execute: function(action, args, win, fail) {
+		var actionFound = false;
+		switch(action) {
+			case 'alert':				
+				PhoneGap.checkArgs(args, navigator.notification.alert);    
+				actionFound = true; 
+				break;
+			case 'showBanner':
+				PhoneGap.checkArgs(args, navigator.notification.showBanner);
+				actionFound = true;
+				break;	
+			case 'newDashboard':
+			    PhoneGap.checkArgs(args, navigator.notification.newDashboard);
+			    actionFound = true;
+			    break;
+			case 'removeBannerMessage':
+			    PhoneGap.checkArgs(args, navigator.notification.removeBannerMessage);
+			    actionFound = true;
+			    break;
+			case 'clearBannerMessage':
+			    PhoneGap.checkArgs(args, navigator.notification.clearBannerMessage);
+			    actionFound = true;
+			    break;
+			case 'vibrate':            
+			    PhoneGap.checkArgs(args, navigator.notification.vibrate);
+			    actionFound = true;
+			    break;
+			case 'beep':               
+			    PhoneGap.checkArgs(args, navigator.notification.beep);
+			    actionFound = true;
+			    break;       		
+		}
+
+		PhoneGap.callback(actionFound, win, fail);
+   }
+}
+
+orientationAPI = {
+    execute: function(action, args, win, fail) {
+        var actionFound = false;
+		switch(action) {
+			case 'setOrientation':				
+				PhoneGap.checkArgs(args, navigator.orientation.setOrientation);    
+				actionFound = true; 
+				break;
+			case 'getOrientation':
+			    PhoneGap.checkArgs(args, navigator.orientation.getOrientation);    
+			    actionFound = true; 
+			    break;			    
+			case 'start':
+			    PhoneGap.checkArgs(args, navigator.orientation.start);    
+				actionFound = true; 
+				break;
+			case 'watchOrientation':
+			    PhoneGap.checkArgs(args, navigator.orientation.watchOrientation);    
+				actionFound = true; 
+				break;
+			case 'clearWatch':
+                PhoneGap.checkArgs(args, navigator.orientation.clearWatch);    
+			    actionFound = true; 
+			    break;
+		}
+
+		PhoneGap.callback(actionFound, win, fail);        
+    }
+}
+
+smsAPI = {
+    execute: function(action, args, win, fail) {
+        var actionFound = false;
+		switch(action) {
+			case 'send':				
+				PhoneGap.checkArgs(args, navigator.sms.send);    
+				actionFound = true; 
+				break;		          		
+		}
+
+		PhoneGap.callback(actionFound, win, fail);        
+    }
+}
+
+telephonyAPI = {
+    execute: function(action, args, win, fail) {
+        var actionFound = false;
+		switch(action) {
+			case 'send':				
+				PhoneGap.checkArgs(args, navigator.telephony.send);    
+				actionFound = true; 
+				break;		          		
+		}
+
+		PhoneGap.callback(actionFound, win, fail);        
+    }
+}
+
+windowAPI = {
+    execute: function(action, args, win, fail) {
+   		var actionFound = false;
+   		switch(action) {
+   			case 'newCard':
+   			    PhoneGap.checkArgs(args, navigator.window.newCard);  				    
+   				actionFound = true; 
+   				break;
+   			case 'setFullScreen':
+   			  	PhoneGap.checkArgs(args, navigator.window.setFullScreen);
+   				actionFound = true; 
+   				break;
+   			case 'setWindowProperties':
+   			    PhoneGap.checkArgs(args, navigator.window.setWindowProperties);
+		        actionFound = true;
+		        break;   			
+   			case 'blockScreenTimeout':
+   			    PhoneGap.checkArgs(args, navigator.window.blockScreenTimeout);
+   			    actionFound = true;
+		        break;
+   			case 'setSubtleLightbar':
+   			    PhoneGap.checkArgs(args, navigator.window.setSubtleLightbar);
+   			    actionFound = true;
+   			    break;
+   				   			  	
+   		}
+
+   		PhoneGap.callback(actionFound, win, fail);
+      }    
+}
+
+// this mapping acts as a shim to the webOS APIs
+PhoneGap.plugins = {};
+PhoneGap.plugins['navigator.accelerometer'] = accelerometerAPI;
+PhoneGap.plugins['navigator.application'] = applicationAPI;
+PhoneGap.plugins['navigator.camera'] = cameraAPI;
+PhoneGap.plugins['window.debug'] = debugAPI;
+PhoneGap.plugins['navigator.device'] = deviceAPI;
+PhoneGap.plugins['navigator.geolocation'] = geolocationAPI;
+PhoneGap.plugins['navigator.map'] = mapAPI;
+PhoneGap.plugins['navigator.mouse'] = mouseAPI;
+PhoneGap.plugins['navigator.network'] = networkAPI; 
+PhoneGap.plugins['navigator.notification'] = notificationAPI;
+PhoneGap.plugins['navigator.orientation'] = orientationAPI; 
+PhoneGap.plugins['navigator.sms'] = smsAPI;
+PhoneGap.plugins['navigator.telephony'] = telephonyAPI;  
+PhoneGap.plugins['navigator.window'] = windowAPI;
+
+
+document.addEventListener('DOMContentLoaded', function () {
+    window.phonegap = new PhoneGap();
+    navigator.device.deviceReady();
+});
diff --git a/js/phonegap.js.base b/js/phonegap.js.base
deleted file mode 100644
index 0c79a0e..0000000
--- a/js/phonegap.js.base
+++ /dev/null
@@ -1,13 +0,0 @@
-if (typeof(DeviceInfo) != 'object')
-    DeviceInfo = {};
-
-function PhoneGap() {
-	ready = true;
-	available = true;
-	sceneController = null;
-};
-
-document.addEventListener('DOMContentLoaded', function () {
-    window.phonegap = new PhoneGap();
-    navigator.device.deviceReady();
-});