diff --git a/Documentation/files/PushNotification-js.html b/Documentation/files/PushNotification-js.html new file mode 100644 index 00000000..7b22fa70 --- /dev/null +++ b/Documentation/files/PushNotification-js.html @@ -0,0 +1,151 @@ + + +PushNotification + + + + + + + + + +

PushNotification

Class to interact with Pushwoosh Push Notifications plugin

Example

var pushwoosh = cordova.require("com.pushwoosh.plugins.pushwoosh.PushNotification");
+pushwoosh.onDeviceReady({ projectid: "XXXXXXXXXXXXXXX", pw_appid : "XXXXX-XXXXX" });
Summary
PushNotificationClass to interact with Pushwoosh Push Notifications plugin
Functions
registerDeviceCall this to register for push notifications and retreive a push Token
setTagsCall this to set tags for the device
getPushTokenCall this to get push token if it is available.
getPushwooshHWIDCall this to get Pushwoosh HWID used for communications with Pushwoosh API
onDeviceReadyCall this first thing with your Pushwoosh App ID (pw_appid parameter) and Google Project ID for Android (projectid parameter)
getTagsCall this to get tags for the device
unregisterDeviceUnregisters device from push notifications
startLocationTrackingStarts geolocation based push notifications.
stopLocationTrackingStops geolocation based push notifications
createLocalNotificationAndroid only, Creates local notification, config params: {msg:”message”, seconds:30, userData:”optional”}
clearLocalNotificationAndroid only, Clears pending local notifications created by createLocalNotification
clearNotificationCenterAndroid only, Clears all notifications presented in Android Notification Center
startGeoPushesAndroid only, Deprecated, use startLocationTracking and stopLocationTracking
stopGeoPushesAndroid only, Deprecated, use startLocationTracking and stopLocationTracking
startBeaconPushesAndroid only, iOS available per request, Call this to start beacon tracking
stopBeaconPushesAndroid only, iOS available per request, Call this to stop beacon tracking
setBeaconBackgroundModeAndroid only, let the plugin know that the app went to background mode (or vise versa).
setMultiNotificationModeAndroid only, Allows multiple notifications to be displayed in the Android Notification Center
setSingleNotificationModeAndroid only, Allows only the last one notification to be displayed in the Android Notification Center
setSoundTypeAndroid only, Sets default sound to play when push notification arrive.
setVibrateTypeAndroid only, Sets default vibration mode when push notification arrive.
setLightScreenOnNotificationAndroid only, Should the screen be lit up when push notification arrive
setEnableLEDAndroid only, Set to enable led blinking when notification arrives and display is off
setEnableLEDAndroid only, Set led color.
getPushHistoryAndroid only, Gets push history, returns array of push notifications received.
clearPushHistoryAndroid only, Clears push history
getRemoteNotificationStatusiOS only, Call this to get a detailed status of push notification permissions.
setApplicationIconBadgeNumberiOS only, Call this to set the application icon badge
getApplicationIconBadgeNumberiOS only, Call this to get the application icon badge
addToApplicationIconBadgeNumberiOS only, Call this to add value to the application icon badge
cancelAllLocalNotificationsiOS only, Call this to clear all notifications from the notification center
getLaunchNotificationReturns push notification payload if the app was started in response to push notification or null otherwise
+ +

Functions

+ +

registerDevice

PushNotification.prototype.registerDevice = function(success,
fail)

Call this to register for push notifications and retreive a push Token

Example

pushNotification.registerDevice(
+    function(token)
+    {
+        alert(token);
+    },
+    function(status)
+    {
+        alert("failed to register: " +  status);
+    }
+);
+ +

setTags

PushNotification.prototype.setTags = function(config,
success,
fail)

Call this to set tags for the device

Example

sets the following tags: “deviceName” with value “hello” and “deviceId” with value 10

pushNotification.setTags({deviceName:"hello", deviceId:10},
+    function(status) {
+        console.warn('setTags success');
+    },
+    function(status) {
+        console.warn('setTags failed');
+    }
+);
+
+//setings list tags "MyTag" with values (array) "hello", "world"
+pushNotification.setTags({"MyTag":["hello", "world"]});
+ +

getPushToken

PushNotification.prototype.getPushToken = function(success)

Call this to get push token if it is available.  Note the token also comes in registerDevice function callback.

Example

pushNotification.getPushToken(
+    function(token)
+    {
+        console.warn('push token: ' + token);
+    }
+);
+ +

getPushwooshHWID

PushNotification.prototype.getPushwooshHWID = function(success)

Call this to get Pushwoosh HWID used for communications with Pushwoosh API

Example

pushNotification.getPushwooshHWID(
+    function(token) {
+        console.warn('Pushwoosh HWID: ' + token);
+    }
+);
+ +

onDeviceReady

PushNotification.prototype.onDeviceReady = function(config)

Call this first thing with your Pushwoosh App ID (pw_appid parameter) and Google Project ID for Android (projectid parameter)

Example

//initialize Pushwoosh with projectid: "GOOGLE_PROJECT_ID", appid : "PUSHWOOSH_APP_ID". This will trigger all pending push notifications on start.
+pushNotification.onDeviceReady({ projectid: "XXXXXXXXXXXXXXX", pw_appid : "XXXXX-XXXXX" });
+ +

getTags

PushNotification.prototype.getTags = function(success,
fail)

Call this to get tags for the device

Example

pushNotification.getTags(
+    function(tags)
+    {
+        console.warn('tags for the device: ' + JSON.stringify(tags));
+    },
+    function(error)
+    {
+        console.warn('get tags error: ' + JSON.stringify(error));
+    }
+);
+ +

unregisterDevice

PushNotification.prototype.unregisterDevice = function(success,
fail)

Unregisters device from push notifications

+ +

startLocationTracking

PushNotification.prototype.startLocationTracking = function(success,
fail)

Starts geolocation based push notifications.  You need to configure Geozones in Pushwoosh Control panel.

+ +

stopLocationTracking

PushNotification.prototype.stopLocationTracking = function(success,
fail)

Stops geolocation based push notifications

+ +

createLocalNotification

PushNotification.prototype.createLocalNotification = function(config,
success,
fail)

Android only, Creates local notification, config params: {msg:”message”, seconds:30, userData:”optional”}

Example

pushNotification.createLocalNotification({msg:"Your pumpkins are ready!", seconds:30, userData:"optional"}
+ +

clearLocalNotification

PushNotification.prototype.clearLocalNotification = function()

Android only, Clears pending local notifications created by createLocalNotification

+ +

clearNotificationCenter

PushNotification.prototype.clearNotificationCenter = function()

Android only, Clears all notifications presented in Android Notification Center

+ +

startGeoPushes

PushNotification.prototype.startGeoPushes = function(success,
fail)

Android only, Deprecated, use startLocationTracking and stopLocationTracking

+ +

stopGeoPushes

PushNotification.prototype.stopGeoPushes = function(success,
fail)

Android only, Deprecated, use startLocationTracking and stopLocationTracking

+ +

startBeaconPushes

PushNotification.prototype.startBeaconPushes = function(success,
fail)

Android only, iOS available per request, Call this to start beacon tracking

+ +

stopBeaconPushes

PushNotification.prototype.stopBeaconPushes = function(success,
fail)

Android only, iOS available per request, Call this to stop beacon tracking

+ +

setBeaconBackgroundMode

PushNotification.prototype.setBeaconBackgroundMode = function(on,
success,
fail)

Android only, let the plugin know that the app went to background mode (or vise versa).  Call this when going background when using beacons

+ +

setMultiNotificationMode

PushNotification.prototype.setMultiNotificationMode = function(success,
fail)

Android only, Allows multiple notifications to be displayed in the Android Notification Center

+ +

setSingleNotificationMode

PushNotification.prototype.setSingleNotificationMode = function(success,
fail)

Android only, Allows only the last one notification to be displayed in the Android Notification Center

+ +

setSoundType

PushNotification.prototype.setSoundType = function(type,
success,
fail)

Android only, Sets default sound to play when push notification arrive.  Values: 0 - default, 1 - no sound, 2 - always

+ +

setVibrateType

PushNotification.prototype.setVibrateType = function(type,
success,
fail)

Android only, Sets default vibration mode when push notification arrive.  Values: 0 - default, 1 - no vibration, 2 - always

+ +

setLightScreenOnNotification

PushNotification.prototype.setLightScreenOnNotification = function(on,
success,
fail)

Android only, Should the screen be lit up when push notification arrive

+ +

setEnableLED

PushNotification.prototype.setEnableLED = function(on,
success,
fail)

Android only, Set to enable led blinking when notification arrives and display is off

+ +

setEnableLED

Android only, Set led color.  Use with setEnableLED

+ +

getPushHistory

PushNotification.prototype.getPushHistory = function(success)

Android only, Gets push history, returns array of push notifications received.

Example

pushNotification.getPushHistory(function(pushHistory) {
+    if(pushHistory.length == 0)
+        alert("no push history");
+    else
+        alert(JSON.stringify(pushHistory));
+});
+
+pushNotification.clearPushHistory();
+ +

clearPushHistory

PushNotification.prototype.clearPushHistory = function()

Android only, Clears push history

+ +

getRemoteNotificationStatus

PushNotification.prototype.getRemoteNotificationStatus = function(callback)

iOS only, Call this to get a detailed status of push notification permissions.

Returns array with the following items

”enabled”if push notificaions enabled.
”pushBadge”badges permission granted.
”pushAlert”alert permission granted.
”pushSound”sound permission granted.
+ +

setApplicationIconBadgeNumber

PushNotification.prototype.setApplicationIconBadgeNumber = function(badgeNumber)

iOS only, Call this to set the application icon badge

+ +

getApplicationIconBadgeNumber

PushNotification.prototype.getApplicationIconBadgeNumber = function(callback)

iOS only, Call this to get the application icon badge

Example

pushwoosh.getApplicationIconBadgeNumber(function(badge){ alert(badge);} );
+ +

addToApplicationIconBadgeNumber

PushNotification.prototype.addToApplicationIconBadgeNumber = function(
   badgeNumber
)

iOS only, Call this to add value to the application icon badge

Example

pushwoosh.addToApplicationIconBadgeNumber(5);
+pushwoosh.addToApplicationIconBadgeNumber(-5);
+ +

cancelAllLocalNotifications

PushNotification.prototype.cancelAllLocalNotifications = function(callback)

iOS only, Call this to clear all notifications from the notification center

+ +

getLaunchNotification

PushNotification.prototype.getLaunchNotification = function(callback)

Returns push notification payload if the app was started in response to push notification or null otherwise

+ +
+ + + + + + + + + + +
PushNotification.prototype.registerDevice = function(success,
fail)
Call this to register for push notifications and retreive a push Token
PushNotification.prototype.setTags = function(config,
success,
fail)
Call this to set tags for the device
PushNotification.prototype.getPushToken = function(success)
Call this to get push token if it is available.
PushNotification.prototype.getPushwooshHWID = function(success)
Call this to get Pushwoosh HWID used for communications with Pushwoosh API
PushNotification.prototype.onDeviceReady = function(config)
Call this first thing with your Pushwoosh App ID (pw_appid parameter) and Google Project ID for Android (projectid parameter)
PushNotification.prototype.getTags = function(success,
fail)
Call this to get tags for the device
PushNotification.prototype.unregisterDevice = function(success,
fail)
Unregisters device from push notifications
PushNotification.prototype.startLocationTracking = function(success,
fail)
Starts geolocation based push notifications.
PushNotification.prototype.stopLocationTracking = function(success,
fail)
Stops geolocation based push notifications
PushNotification.prototype.createLocalNotification = function(config,
success,
fail)
Android only, Creates local notification, config params: {msg:”message”, seconds:30, userData:”optional”}
PushNotification.prototype.clearLocalNotification = function()
Android only, Clears pending local notifications created by createLocalNotification
PushNotification.prototype.clearNotificationCenter = function()
Android only, Clears all notifications presented in Android Notification Center
PushNotification.prototype.startGeoPushes = function(success,
fail)
Android only, Deprecated, use startLocationTracking and stopLocationTracking
PushNotification.prototype.stopGeoPushes = function(success,
fail)
Android only, Deprecated, use startLocationTracking and stopLocationTracking
PushNotification.prototype.startBeaconPushes = function(success,
fail)
Android only, iOS available per request, Call this to start beacon tracking
PushNotification.prototype.stopBeaconPushes = function(success,
fail)
Android only, iOS available per request, Call this to stop beacon tracking
PushNotification.prototype.setBeaconBackgroundMode = function(on,
success,
fail)
Android only, let the plugin know that the app went to background mode (or vise versa).
PushNotification.prototype.setMultiNotificationMode = function(success,
fail)
Android only, Allows multiple notifications to be displayed in the Android Notification Center
PushNotification.prototype.setSingleNotificationMode = function(success,
fail)
Android only, Allows only the last one notification to be displayed in the Android Notification Center
PushNotification.prototype.setSoundType = function(type,
success,
fail)
Android only, Sets default sound to play when push notification arrive.
PushNotification.prototype.setVibrateType = function(type,
success,
fail)
Android only, Sets default vibration mode when push notification arrive.
PushNotification.prototype.setLightScreenOnNotification = function(on,
success,
fail)
Android only, Should the screen be lit up when push notification arrive
PushNotification.prototype.setEnableLED = function(on,
success,
fail)
Android only, Set to enable led blinking when notification arrives and display is off
PushNotification.prototype.getPushHistory = function(success)
Android only, Gets push history, returns array of push notifications received.
PushNotification.prototype.clearPushHistory = function()
Android only, Clears push history
PushNotification.prototype.getRemoteNotificationStatus = function(callback)
iOS only, Call this to get a detailed status of push notification permissions.
PushNotification.prototype.setApplicationIconBadgeNumber = function(badgeNumber)
iOS only, Call this to set the application icon badge
PushNotification.prototype.getApplicationIconBadgeNumber = function(callback)
iOS only, Call this to get the application icon badge
PushNotification.prototype.addToApplicationIconBadgeNumber = function(
   badgeNumber
)
iOS only, Call this to add value to the application icon badge
PushNotification.prototype.cancelAllLocalNotifications = function(callback)
iOS only, Call this to clear all notifications from the notification center
PushNotification.prototype.getLaunchNotification = function(callback)
Returns push notification payload if the app was started in response to push notification or null otherwise
+ + + + +
Close
+ + + \ No newline at end of file diff --git a/Documentation/index.html b/Documentation/index.html new file mode 100644 index 00000000..fa908f05 --- /dev/null +++ b/Documentation/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Documentation/index/Classes.html b/Documentation/index/Classes.html new file mode 100644 index 00000000..a273851b --- /dev/null +++ b/Documentation/index/Classes.html @@ -0,0 +1,33 @@ + + +Class Index + + + + + + + + + +
Class Index
$#! · 0-9 · A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
P
 PushNotification
+ +
Class to interact with Pushwoosh Push Notifications plugin
+ +
+ + + + + + + + +
Close
+ + + \ No newline at end of file diff --git a/Documentation/index/Functions.html b/Documentation/index/Functions.html new file mode 100644 index 00000000..5a837193 --- /dev/null +++ b/Documentation/index/Functions.html @@ -0,0 +1,57 @@ + + +Function Index + + + + + + + + + +
Function Index
$#! · 0-9 · A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
A
 addToApplicationIconBadgeNumber, PushNotification
C
 cancelAllLocalNotifications, PushNotification
 clearLocalNotification, PushNotification
 clearNotificationCenter, PushNotification
 clearPushHistory, PushNotification
 createLocalNotification, PushNotification
G
 getApplicationIconBadgeNumber, PushNotification
 getLaunchNotification, PushNotification
 getPushHistory, PushNotification
 getPushToken, PushNotification
 getPushwooshHWID, PushNotification
 getRemoteNotificationStatus, PushNotification
 getTags, PushNotification
O
 onDeviceReady, PushNotification
R
 registerDevice, PushNotification
S
 setApplicationIconBadgeNumber, PushNotification
 setBeaconBackgroundMode, PushNotification
 setEnableLED, PushNotification
 setLightScreenOnNotification, PushNotification
 setMultiNotificationMode, PushNotification
 setSingleNotificationMode, PushNotification
 setSoundType, PushNotification
 setTags, PushNotification
 setVibrateType, PushNotification
 startBeaconPushes, PushNotification
 startGeoPushes, PushNotification
 startLocationTracking, PushNotification
 stopBeaconPushes, PushNotification
 stopGeoPushes, PushNotification
 stopLocationTracking, PushNotification
U
 unregisterDevice, PushNotification
+ +
PushNotification.prototype.addToApplicationIconBadgeNumber = function(
   badgeNumber
)
iOS only, Call this to add value to the application icon badge
+ + + +
PushNotification.prototype.cancelAllLocalNotifications = function(callback)
iOS only, Call this to clear all notifications from the notification center
PushNotification.prototype.clearLocalNotification = function()
Android only, Clears pending local notifications created by createLocalNotification
PushNotification.prototype.clearNotificationCenter = function()
Android only, Clears all notifications presented in Android Notification Center
PushNotification.prototype.clearPushHistory = function()
Android only, Clears push history
PushNotification.prototype.createLocalNotification = function(config,
success,
fail)
Android only, Creates local notification, config params: {msg:”message”, seconds:30, userData:”optional”}
+ + + +
PushNotification.prototype.getApplicationIconBadgeNumber = function(callback)
iOS only, Call this to get the application icon badge
PushNotification.prototype.getLaunchNotification = function(callback)
Returns push notification payload if the app was started in response to push notification or null otherwise
PushNotification.prototype.getPushHistory = function(success)
Android only, Gets push history, returns array of push notifications received.
PushNotification.prototype.getPushToken = function(success)
Call this to get push token if it is available.
PushNotification.prototype.getPushwooshHWID = function(success)
Call this to get Pushwoosh HWID used for communications with Pushwoosh API
PushNotification.prototype.getRemoteNotificationStatus = function(callback)
iOS only, Call this to get a detailed status of push notification permissions.
PushNotification.prototype.getTags = function(success,
fail)
Call this to get tags for the device
+ + + +
PushNotification.prototype.onDeviceReady = function(config)
Call this first thing with your Pushwoosh App ID (pw_appid parameter) and Google Project ID for Android (projectid parameter)
+ + + +
PushNotification.prototype.registerDevice = function(success,
fail)
Call this to register for push notifications and retreive a push Token
+ + + +
PushNotification.prototype.setApplicationIconBadgeNumber = function(badgeNumber)
iOS only, Call this to set the application icon badge
PushNotification.prototype.setBeaconBackgroundMode = function(on,
success,
fail)
Android only, let the plugin know that the app went to background mode (or vise versa).
PushNotification.prototype.setEnableLED = function(on,
success,
fail)
Android only, Set to enable led blinking when notification arrives and display is off
PushNotification.prototype.setLightScreenOnNotification = function(on,
success,
fail)
Android only, Should the screen be lit up when push notification arrive
PushNotification.prototype.setMultiNotificationMode = function(success,
fail)
Android only, Allows multiple notifications to be displayed in the Android Notification Center
PushNotification.prototype.setSingleNotificationMode = function(success,
fail)
Android only, Allows only the last one notification to be displayed in the Android Notification Center
PushNotification.prototype.setSoundType = function(type,
success,
fail)
Android only, Sets default sound to play when push notification arrive.
PushNotification.prototype.setTags = function(config,
success,
fail)
Call this to set tags for the device
PushNotification.prototype.setVibrateType = function(type,
success,
fail)
Android only, Sets default vibration mode when push notification arrive.
PushNotification.prototype.startBeaconPushes = function(success,
fail)
Android only, iOS available per request, Call this to start beacon tracking
PushNotification.prototype.startGeoPushes = function(success,
fail)
Android only, Deprecated, use startLocationTracking and stopLocationTracking
PushNotification.prototype.startLocationTracking = function(success,
fail)
Starts geolocation based push notifications.
PushNotification.prototype.stopBeaconPushes = function(success,
fail)
Android only, iOS available per request, Call this to stop beacon tracking
PushNotification.prototype.stopGeoPushes = function(success,
fail)
Android only, Deprecated, use startLocationTracking and stopLocationTracking
PushNotification.prototype.stopLocationTracking = function(success,
fail)
Stops geolocation based push notifications
+ + + +
PushNotification.prototype.unregisterDevice = function(success,
fail)
Unregisters device from push notifications
+ +
+ + + + + + + + +
Close
+ + + \ No newline at end of file diff --git a/Documentation/index/General.html b/Documentation/index/General.html new file mode 100644 index 00000000..4eb4c36a --- /dev/null +++ b/Documentation/index/General.html @@ -0,0 +1,65 @@ + + +Index + + + + + + + + + +
Index
$#! · 0-9 · A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
A
 addToApplicationIconBadgeNumber, PushNotification
C
 cancelAllLocalNotifications, PushNotification
 clearLocalNotification, PushNotification
 clearNotificationCenter, PushNotification
 clearPushHistory, PushNotification
 createLocalNotification, PushNotification
F
 Functions, PushNotification
G
 getApplicationIconBadgeNumber, PushNotification
 getLaunchNotification, PushNotification
 getPushHistory, PushNotification
 getPushToken, PushNotification
 getPushwooshHWID, PushNotification
 getRemoteNotificationStatus, PushNotification
 getTags, PushNotification
O
 onDeviceReady, PushNotification
P
 PushNotification
R
 registerDevice, PushNotification
S
 setApplicationIconBadgeNumber, PushNotification
 setBeaconBackgroundMode, PushNotification
 setEnableLED, PushNotification
 setLightScreenOnNotification, PushNotification
 setMultiNotificationMode, PushNotification
 setSingleNotificationMode, PushNotification
 setSoundType, PushNotification
 setTags, PushNotification
 setVibrateType, PushNotification
 startBeaconPushes, PushNotification
 startGeoPushes, PushNotification
 startLocationTracking, PushNotification
 stopBeaconPushes, PushNotification
 stopGeoPushes, PushNotification
 stopLocationTracking, PushNotification
U
 unregisterDevice, PushNotification
+ +
PushNotification.prototype.addToApplicationIconBadgeNumber = function(
   badgeNumber
)
iOS only, Call this to add value to the application icon badge
+ + + +
PushNotification.prototype.cancelAllLocalNotifications = function(callback)
iOS only, Call this to clear all notifications from the notification center
PushNotification.prototype.clearLocalNotification = function()
Android only, Clears pending local notifications created by createLocalNotification
PushNotification.prototype.clearNotificationCenter = function()
Android only, Clears all notifications presented in Android Notification Center
PushNotification.prototype.clearPushHistory = function()
Android only, Clears push history
PushNotification.prototype.createLocalNotification = function(config,
success,
fail)
Android only, Creates local notification, config params: {msg:”message”, seconds:30, userData:”optional”}
+ + + + + + + +
PushNotification.prototype.getApplicationIconBadgeNumber = function(callback)
iOS only, Call this to get the application icon badge
PushNotification.prototype.getLaunchNotification = function(callback)
Returns push notification payload if the app was started in response to push notification or null otherwise
PushNotification.prototype.getPushHistory = function(success)
Android only, Gets push history, returns array of push notifications received.
PushNotification.prototype.getPushToken = function(success)
Call this to get push token if it is available.
PushNotification.prototype.getPushwooshHWID = function(success)
Call this to get Pushwoosh HWID used for communications with Pushwoosh API
PushNotification.prototype.getRemoteNotificationStatus = function(callback)
iOS only, Call this to get a detailed status of push notification permissions.
PushNotification.prototype.getTags = function(success,
fail)
Call this to get tags for the device
+ + + +
PushNotification.prototype.onDeviceReady = function(config)
Call this first thing with your Pushwoosh App ID (pw_appid parameter) and Google Project ID for Android (projectid parameter)
+ + + +
Class to interact with Pushwoosh Push Notifications plugin
+ + + +
PushNotification.prototype.registerDevice = function(success,
fail)
Call this to register for push notifications and retreive a push Token
+ + + +
PushNotification.prototype.setApplicationIconBadgeNumber = function(badgeNumber)
iOS only, Call this to set the application icon badge
PushNotification.prototype.setBeaconBackgroundMode = function(on,
success,
fail)
Android only, let the plugin know that the app went to background mode (or vise versa).
PushNotification.prototype.setEnableLED = function(on,
success,
fail)
Android only, Set to enable led blinking when notification arrives and display is off
PushNotification.prototype.setLightScreenOnNotification = function(on,
success,
fail)
Android only, Should the screen be lit up when push notification arrive
PushNotification.prototype.setMultiNotificationMode = function(success,
fail)
Android only, Allows multiple notifications to be displayed in the Android Notification Center
PushNotification.prototype.setSingleNotificationMode = function(success,
fail)
Android only, Allows only the last one notification to be displayed in the Android Notification Center
PushNotification.prototype.setSoundType = function(type,
success,
fail)
Android only, Sets default sound to play when push notification arrive.
PushNotification.prototype.setTags = function(config,
success,
fail)
Call this to set tags for the device
PushNotification.prototype.setVibrateType = function(type,
success,
fail)
Android only, Sets default vibration mode when push notification arrive.
PushNotification.prototype.startBeaconPushes = function(success,
fail)
Android only, iOS available per request, Call this to start beacon tracking
PushNotification.prototype.startGeoPushes = function(success,
fail)
Android only, Deprecated, use startLocationTracking and stopLocationTracking
PushNotification.prototype.startLocationTracking = function(success,
fail)
Starts geolocation based push notifications.
PushNotification.prototype.stopBeaconPushes = function(success,
fail)
Android only, iOS available per request, Call this to stop beacon tracking
PushNotification.prototype.stopGeoPushes = function(success,
fail)
Android only, Deprecated, use startLocationTracking and stopLocationTracking
PushNotification.prototype.stopLocationTracking = function(success,
fail)
Stops geolocation based push notifications
+ + + +
PushNotification.prototype.unregisterDevice = function(success,
fail)
Unregisters device from push notifications
+ +
+ + + + + + + + +
Close
+ + + \ No newline at end of file diff --git a/Documentation/javascript/main.js b/Documentation/javascript/main.js new file mode 100644 index 00000000..3f42acde --- /dev/null +++ b/Documentation/javascript/main.js @@ -0,0 +1,841 @@ +// This file is part of Natural Docs, which is Copyright © 2003-2010 Greg Valure +// Natural Docs is licensed under version 3 of the GNU Affero General Public License (AGPL) +// Refer to License.txt for the complete details + +// This file may be distributed with documentation files generated by Natural Docs. +// Such documentation is not covered by Natural Docs' copyright and licensing, +// and may have its own copyright and distribution terms as decided by its author. + + +// +// Browser Styles +// ____________________________________________________________________________ + +var agt=navigator.userAgent.toLowerCase(); +var browserType; +var browserVer; + +if (agt.indexOf("opera") != -1) + { + browserType = "Opera"; + + if (agt.indexOf("opera 7") != -1 || agt.indexOf("opera/7") != -1) + { browserVer = "Opera7"; } + else if (agt.indexOf("opera 8") != -1 || agt.indexOf("opera/8") != -1) + { browserVer = "Opera8"; } + else if (agt.indexOf("opera 9") != -1 || agt.indexOf("opera/9") != -1) + { browserVer = "Opera9"; } + } + +else if (agt.indexOf("applewebkit") != -1) + { + browserType = "Safari"; + + if (agt.indexOf("version/3") != -1) + { browserVer = "Safari3"; } + else if (agt.indexOf("safari/4") != -1) + { browserVer = "Safari2"; } + } + +else if (agt.indexOf("khtml") != -1) + { + browserType = "Konqueror"; + } + +else if (agt.indexOf("msie") != -1) + { + browserType = "IE"; + + if (agt.indexOf("msie 6") != -1) + { browserVer = "IE6"; } + else if (agt.indexOf("msie 7") != -1) + { browserVer = "IE7"; } + } + +else if (agt.indexOf("gecko") != -1) + { + browserType = "Firefox"; + + if (agt.indexOf("rv:1.7") != -1) + { browserVer = "Firefox1"; } + else if (agt.indexOf("rv:1.8)") != -1 || agt.indexOf("rv:1.8.0") != -1) + { browserVer = "Firefox15"; } + else if (agt.indexOf("rv:1.8.1") != -1) + { browserVer = "Firefox2"; } + } + + +// +// Support Functions +// ____________________________________________________________________________ + + +function GetXPosition(item) + { + var position = 0; + + if (item.offsetWidth != null) + { + while (item != document.body && item != null) + { + position += item.offsetLeft; + item = item.offsetParent; + }; + }; + + return position; + }; + + +function GetYPosition(item) + { + var position = 0; + + if (item.offsetWidth != null) + { + while (item != document.body && item != null) + { + position += item.offsetTop; + item = item.offsetParent; + }; + }; + + return position; + }; + + +function MoveToPosition(item, x, y) + { + // Opera 5 chokes on the px extension, so it can use the Microsoft one instead. + + if (item.style.left != null) + { + item.style.left = x + "px"; + item.style.top = y + "px"; + } + else if (item.style.pixelLeft != null) + { + item.style.pixelLeft = x; + item.style.pixelTop = y; + }; + }; + + +// +// Menu +// ____________________________________________________________________________ + + +function ToggleMenu(id) + { + if (!window.document.getElementById) + { return; }; + + var display = window.document.getElementById(id).style.display; + + if (display == "none") + { display = "block"; } + else + { display = "none"; } + + window.document.getElementById(id).style.display = display; + } + +function HideAllBut(ids, max) + { + if (document.getElementById) + { + ids.sort( function(a,b) { return a - b; } ); + var number = 1; + + while (number < max) + { + if (ids.length > 0 && number == ids[0]) + { ids.shift(); } + else + { + document.getElementById("MGroupContent" + number).style.display = "none"; + }; + + number++; + }; + }; + } + + +// +// Tooltips +// ____________________________________________________________________________ + + +var tooltipTimer = 0; + +function ShowTip(event, tooltipID, linkID) + { + if (tooltipTimer) + { clearTimeout(tooltipTimer); }; + + var docX = event.clientX + window.pageXOffset; + var docY = event.clientY + window.pageYOffset; + + var showCommand = "ReallyShowTip('" + tooltipID + "', '" + linkID + "', " + docX + ", " + docY + ")"; + + tooltipTimer = setTimeout(showCommand, 1000); + } + +function ReallyShowTip(tooltipID, linkID, docX, docY) + { + tooltipTimer = 0; + + var tooltip; + var link; + + if (document.getElementById) + { + tooltip = document.getElementById(tooltipID); + link = document.getElementById(linkID); + } +/* else if (document.all) + { + tooltip = eval("document.all['" + tooltipID + "']"); + link = eval("document.all['" + linkID + "']"); + } +*/ + if (tooltip) + { + var left = GetXPosition(link); + var top = GetYPosition(link); + top += link.offsetHeight; + + + // The fallback method is to use the mouse X and Y relative to the document. We use a separate if and test if its a number + // in case some browser snuck through the above if statement but didn't support everything. + + if (!isFinite(top) || top == 0) + { + left = docX; + top = docY; + } + + // Some spacing to get it out from under the cursor. + + top += 10; + + // Make sure the tooltip doesnt get smushed by being too close to the edge, or in some browsers, go off the edge of the + // page. We do it here because Konqueror does get offsetWidth right even if it doesnt get the positioning right. + + if (tooltip.offsetWidth != null) + { + var width = tooltip.offsetWidth; + var docWidth = document.body.clientWidth; + + if (left + width > docWidth) + { left = docWidth - width - 1; } + + // If there's a horizontal scroll bar we could go past zero because it's using the page width, not the window width. + if (left < 0) + { left = 0; }; + } + + MoveToPosition(tooltip, left, top); + tooltip.style.visibility = "visible"; + } + } + +function HideTip(tooltipID) + { + if (tooltipTimer) + { + clearTimeout(tooltipTimer); + tooltipTimer = 0; + } + + var tooltip; + + if (document.getElementById) + { tooltip = document.getElementById(tooltipID); } + else if (document.all) + { tooltip = eval("document.all['" + tooltipID + "']"); } + + if (tooltip) + { tooltip.style.visibility = "hidden"; } + } + + +// +// Blockquote fix for IE +// ____________________________________________________________________________ + + +function NDOnLoad() + { + if (browserVer == "IE6") + { + var scrollboxes = document.getElementsByTagName('blockquote'); + + if (scrollboxes.item(0)) + { + NDDoResize(); + window.onresize=NDOnResize; + }; + }; + }; + + +var resizeTimer = 0; + +function NDOnResize() + { + if (resizeTimer != 0) + { clearTimeout(resizeTimer); }; + + resizeTimer = setTimeout(NDDoResize, 250); + }; + + +function NDDoResize() + { + var scrollboxes = document.getElementsByTagName('blockquote'); + + var i; + var item; + + i = 0; + while (item = scrollboxes.item(i)) + { + item.style.width = 100; + i++; + }; + + i = 0; + while (item = scrollboxes.item(i)) + { + item.style.width = item.parentNode.offsetWidth; + i++; + }; + + clearTimeout(resizeTimer); + resizeTimer = 0; + } + + + +/* ________________________________________________________________________________________________________ + + Class: SearchPanel + ________________________________________________________________________________________________________ + + A class handling everything associated with the search panel. + + Parameters: + + name - The name of the global variable that will be storing this instance. Is needed to be able to set timeouts. + mode - The mode the search is going to work in. Pass CommandLineOption()>, so the + value will be something like "HTML" or "FramedHTML". + + ________________________________________________________________________________________________________ +*/ + + +function SearchPanel(name, mode, resultsPath) + { + if (!name || !mode || !resultsPath) + { alert("Incorrect parameters to SearchPanel."); }; + + + // Group: Variables + // ________________________________________________________________________ + + /* + var: name + The name of the global variable that will be storing this instance of the class. + */ + this.name = name; + + /* + var: mode + The mode the search is going to work in, such as "HTML" or "FramedHTML". + */ + this.mode = mode; + + /* + var: resultsPath + The relative path from the current HTML page to the results page directory. + */ + this.resultsPath = resultsPath; + + /* + var: keyTimeout + The timeout used between a keystroke and when a search is performed. + */ + this.keyTimeout = 0; + + /* + var: keyTimeoutLength + The length of in thousandths of a second. + */ + this.keyTimeoutLength = 500; + + /* + var: lastSearchValue + The last search string executed, or an empty string if none. + */ + this.lastSearchValue = ""; + + /* + var: lastResultsPage + The last results page. The value is only relevant if is set. + */ + this.lastResultsPage = ""; + + /* + var: deactivateTimeout + + The timeout used between when a control is deactivated and when the entire panel is deactivated. Is necessary + because a control may be deactivated in favor of another control in the same panel, in which case it should stay + active. + */ + this.deactivateTimout = 0; + + /* + var: deactivateTimeoutLength + The length of in thousandths of a second. + */ + this.deactivateTimeoutLength = 200; + + + + + // Group: DOM Elements + // ________________________________________________________________________ + + + // Function: DOMSearchField + this.DOMSearchField = function() + { return document.getElementById("MSearchField"); }; + + // Function: DOMSearchType + this.DOMSearchType = function() + { return document.getElementById("MSearchType"); }; + + // Function: DOMPopupSearchResults + this.DOMPopupSearchResults = function() + { return document.getElementById("MSearchResults"); }; + + // Function: DOMPopupSearchResultsWindow + this.DOMPopupSearchResultsWindow = function() + { return document.getElementById("MSearchResultsWindow"); }; + + // Function: DOMSearchPanel + this.DOMSearchPanel = function() + { return document.getElementById("MSearchPanel"); }; + + + + + // Group: Event Handlers + // ________________________________________________________________________ + + + /* + Function: OnSearchFieldFocus + Called when focus is added or removed from the search field. + */ + this.OnSearchFieldFocus = function(isActive) + { + this.Activate(isActive); + }; + + + /* + Function: OnSearchFieldChange + Called when the content of the search field is changed. + */ + this.OnSearchFieldChange = function() + { + if (this.keyTimeout) + { + clearTimeout(this.keyTimeout); + this.keyTimeout = 0; + }; + + var searchValue = this.DOMSearchField().value.replace(/ +/g, ""); + + if (searchValue != this.lastSearchValue) + { + if (searchValue != "") + { + this.keyTimeout = setTimeout(this.name + ".Search()", this.keyTimeoutLength); + } + else + { + if (this.mode == "HTML") + { this.DOMPopupSearchResultsWindow().style.display = "none"; }; + this.lastSearchValue = ""; + }; + }; + }; + + + /* + Function: OnSearchTypeFocus + Called when focus is added or removed from the search type. + */ + this.OnSearchTypeFocus = function(isActive) + { + this.Activate(isActive); + }; + + + /* + Function: OnSearchTypeChange + Called when the search type is changed. + */ + this.OnSearchTypeChange = function() + { + var searchValue = this.DOMSearchField().value.replace(/ +/g, ""); + + if (searchValue != "") + { + this.Search(); + }; + }; + + + + // Group: Action Functions + // ________________________________________________________________________ + + + /* + Function: CloseResultsWindow + Closes the results window. + */ + this.CloseResultsWindow = function() + { + this.DOMPopupSearchResultsWindow().style.display = "none"; + this.Activate(false, true); + }; + + + /* + Function: Search + Performs a search. + */ + this.Search = function() + { + this.keyTimeout = 0; + + var searchValue = this.DOMSearchField().value.replace(/^ +/, ""); + var searchTopic = this.DOMSearchType().value; + + var pageExtension = searchValue.substr(0,1); + + if (pageExtension.match(/^[a-z]/i)) + { pageExtension = pageExtension.toUpperCase(); } + else if (pageExtension.match(/^[0-9]/)) + { pageExtension = 'Numbers'; } + else + { pageExtension = "Symbols"; }; + + var resultsPage; + var resultsPageWithSearch; + var hasResultsPage; + + // indexSectionsWithContent is defined in searchdata.js + if (indexSectionsWithContent[searchTopic][pageExtension] == true) + { + resultsPage = this.resultsPath + '/' + searchTopic + pageExtension + '.html'; + resultsPageWithSearch = resultsPage+'?'+escape(searchValue); + hasResultsPage = true; + } + else + { + resultsPage = this.resultsPath + '/NoResults.html'; + resultsPageWithSearch = resultsPage; + hasResultsPage = false; + }; + + var resultsFrame; + if (this.mode == "HTML") + { resultsFrame = window.frames.MSearchResults; } + else if (this.mode == "FramedHTML") + { resultsFrame = window.top.frames['Content']; }; + + + if (resultsPage != this.lastResultsPage || + + // Bug in IE. If everything becomes hidden in a run, none of them will be able to be reshown in the next for some + // reason. It counts the right number of results, and you can even read the display as "block" after setting it, but it + // just doesn't work in IE 6 or IE 7. So if we're on the right page but the previous search had no results, reload the + // page anyway to get around the bug. + (browserType == "IE" && hasResultsPage && + (!resultsFrame.searchResults || resultsFrame.searchResults.lastMatchCount == 0)) ) + + { + resultsFrame.location.href = resultsPageWithSearch; + } + + // So if the results page is right and there's no IE bug, reperform the search on the existing page. We have to check if there + // are results because NoResults.html doesn't have any JavaScript, and it would be useless to do anything on that page even + // if it did. + else if (hasResultsPage) + { + // We need to check if this exists in case the frame is present but didn't finish loading. + if (resultsFrame.searchResults) + { resultsFrame.searchResults.Search(searchValue); } + + // Otherwise just reload instead of waiting. + else + { resultsFrame.location.href = resultsPageWithSearch; }; + }; + + + var domPopupSearchResultsWindow = this.DOMPopupSearchResultsWindow(); + + if (this.mode == "HTML" && domPopupSearchResultsWindow.style.display != "block") + { + var domSearchType = this.DOMSearchType(); + + var left = GetXPosition(domSearchType); + var top = GetYPosition(domSearchType) + domSearchType.offsetHeight; + + MoveToPosition(domPopupSearchResultsWindow, left, top); + domPopupSearchResultsWindow.style.display = 'block'; + }; + + + this.lastSearchValue = searchValue; + this.lastResultsPage = resultsPage; + }; + + + + // Group: Activation Functions + // Functions that handle whether the entire panel is active or not. + // ________________________________________________________________________ + + + /* + Function: Activate + + Activates or deactivates the search panel, resetting things to their default values if necessary. You can call this on every + control's OnBlur() and it will handle not deactivating the entire panel when focus is just switching between them transparently. + + Parameters: + + isActive - Whether you're activating or deactivating the panel. + ignoreDeactivateDelay - Set if you're positive the action will deactivate the panel and thus want to skip the delay. + */ + this.Activate = function(isActive, ignoreDeactivateDelay) + { + // We want to ignore isActive being false while the results window is open. + if (isActive || (this.mode == "HTML" && this.DOMPopupSearchResultsWindow().style.display == "block")) + { + if (this.inactivateTimeout) + { + clearTimeout(this.inactivateTimeout); + this.inactivateTimeout = 0; + }; + + this.DOMSearchPanel().className = 'MSearchPanelActive'; + + var searchField = this.DOMSearchField(); + + if (searchField.value == 'Search') + { searchField.value = ""; } + } + else if (!ignoreDeactivateDelay) + { + this.inactivateTimeout = setTimeout(this.name + ".InactivateAfterTimeout()", this.inactivateTimeoutLength); + } + else + { + this.InactivateAfterTimeout(); + }; + }; + + + /* + Function: InactivateAfterTimeout + + Called by , which is set by . Inactivation occurs on a timeout because a control may + receive OnBlur() when focus is really transferring to another control in the search panel. In this case we don't want to + actually deactivate the panel because not only would that cause a visible flicker but it could also reset the search value. + So by doing it on a timeout instead, there's a short period where the second control's OnFocus() can cancel the deactivation. + */ + this.InactivateAfterTimeout = function() + { + this.inactivateTimeout = 0; + + this.DOMSearchPanel().className = 'MSearchPanelInactive'; + this.DOMSearchField().value = "Search"; + + this.lastSearchValue = ""; + this.lastResultsPage = ""; + }; + }; + + + + +/* ________________________________________________________________________________________________________ + + Class: SearchResults + _________________________________________________________________________________________________________ + + The class that handles everything on the search results page. + _________________________________________________________________________________________________________ +*/ + + +function SearchResults(name, mode) + { + /* + var: mode + The mode the search is going to work in, such as "HTML" or "FramedHTML". + */ + this.mode = mode; + + /* + var: lastMatchCount + The number of matches from the last run of . + */ + this.lastMatchCount = 0; + + + /* + Function: Toggle + Toggles the visibility of the passed element ID. + */ + this.Toggle = function(id) + { + if (this.mode == "FramedHTML") + { return; }; + + var parentElement = document.getElementById(id); + + var element = parentElement.firstChild; + + while (element && element != parentElement) + { + if (element.nodeName == 'DIV' && element.className == 'ISubIndex') + { + if (element.style.display == 'block') + { element.style.display = "none"; } + else + { element.style.display = 'block'; } + }; + + if (element.nodeName == 'DIV' && element.hasChildNodes()) + { element = element.firstChild; } + else if (element.nextSibling) + { element = element.nextSibling; } + else + { + do + { + element = element.parentNode; + } + while (element && element != parentElement && !element.nextSibling); + + if (element && element != parentElement) + { element = element.nextSibling; }; + }; + }; + }; + + + /* + Function: Search + + Searches for the passed string. If there is no parameter, it takes it from the URL query. + + Always returns true, since other documents may try to call it and that may or may not be possible. + */ + this.Search = function(search) + { + if (!search) + { + search = window.location.search; + search = search.substring(1); // Remove the leading ? + search = unescape(search); + }; + + search = search.replace(/^ +/, ""); + search = search.replace(/ +$/, ""); + search = search.toLowerCase(); + + if (search.match(/[^a-z0-9]/)) // Just a little speedup so it doesn't have to go through the below unnecessarily. + { + search = search.replace(/\_/g, "_und"); + search = search.replace(/\ +/gi, "_spc"); + search = search.replace(/\~/g, "_til"); + search = search.replace(/\!/g, "_exc"); + search = search.replace(/\@/g, "_att"); + search = search.replace(/\#/g, "_num"); + search = search.replace(/\$/g, "_dol"); + search = search.replace(/\%/g, "_pct"); + search = search.replace(/\^/g, "_car"); + search = search.replace(/\&/g, "_amp"); + search = search.replace(/\*/g, "_ast"); + search = search.replace(/\(/g, "_lpa"); + search = search.replace(/\)/g, "_rpa"); + search = search.replace(/\-/g, "_min"); + search = search.replace(/\+/g, "_plu"); + search = search.replace(/\=/g, "_equ"); + search = search.replace(/\{/g, "_lbc"); + search = search.replace(/\}/g, "_rbc"); + search = search.replace(/\[/g, "_lbk"); + search = search.replace(/\]/g, "_rbk"); + search = search.replace(/\:/g, "_col"); + search = search.replace(/\;/g, "_sco"); + search = search.replace(/\"/g, "_quo"); + search = search.replace(/\'/g, "_apo"); + search = search.replace(/\/g, "_ran"); + search = search.replace(/\,/g, "_com"); + search = search.replace(/\./g, "_per"); + search = search.replace(/\?/g, "_que"); + search = search.replace(/\//g, "_sla"); + search = search.replace(/[^a-z0-9\_]i/gi, "_zzz"); + }; + + var resultRows = document.getElementsByTagName("div"); + var matches = 0; + + var i = 0; + while (i < resultRows.length) + { + var row = resultRows.item(i); + + if (row.className == "SRResult") + { + var rowMatchName = row.id.toLowerCase(); + rowMatchName = rowMatchName.replace(/^sr\d*_/, ''); + + if (search.length <= rowMatchName.length && rowMatchName.substr(0, search.length) == search) + { + row.style.display = "block"; + matches++; + } + else + { row.style.display = "none"; }; + }; + + i++; + }; + + document.getElementById("Searching").style.display="none"; + + if (matches == 0) + { document.getElementById("NoMatches").style.display="block"; } + else + { document.getElementById("NoMatches").style.display="none"; } + + this.lastMatchCount = matches; + + return true; + }; + }; + diff --git a/Documentation/javascript/prettify.js b/Documentation/javascript/prettify.js new file mode 100644 index 00000000..fda4bf1e --- /dev/null +++ b/Documentation/javascript/prettify.js @@ -0,0 +1,1526 @@ + +// This code comes from the December 2009 release of Google Prettify, which is Copyright © 2006 Google Inc. +// Minor modifications are marked with "ND Change" comments. +// As part of Natural Docs, this code is licensed under version 3 of the GNU Affero General Public License (AGPL.) +// However, it may also be obtained separately under version 2.0 of the Apache License. +// Refer to License.txt for the complete details + + +// Main code +// ____________________________________________________________________________ + +// Copyright (C) 2006 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/** + * @fileoverview + * some functions for browser-side pretty printing of code contained in html. + *

+ * + * For a fairly comprehensive set of languages see the + * README + * file that came with this source. At a minimum, the lexer should work on a + * number of languages including C and friends, Java, Python, Bash, SQL, HTML, + * XML, CSS, Javascript, and Makefiles. It works passably on Ruby, PHP and Awk + * and a subset of Perl, but, because of commenting conventions, doesn't work on + * Smalltalk, Lisp-like, or CAML-like languages without an explicit lang class. + *

+ * Usage:

    + *
  1. include this source file in an html page via + * {@code } + *
  2. define style rules. See the example page for examples. + *
  3. mark the {@code
    } and {@code } tags in your source with
    + *    {@code class=prettyprint.}
    + *    You can also use the (html deprecated) {@code } tag, but the pretty
    + *    printer needs to do more substantial DOM manipulations to support that, so
    + *    some css styles may not be preserved.
    + * </ol>
    + * That's it.  I wanted to keep the API as simple as possible, so there's no
    + * need to specify which language the code is in, but if you wish, you can add
    + * another class to the {@code <pre>} or {@code <code>} element to specify the
    + * language, as in {@code <pre class="prettyprint lang-java">}.  Any class that
    + * starts with "lang-" followed by a file extension, specifies the file type.
    + * See the "lang-*.js" files in this directory for code that implements
    + * per-language file handlers.
    + * <p>
    + * Change log:<br>
    + * cbeust, 2006/08/22
    + * <blockquote>
    + *   Java annotations (start with "@") are now captured as literals ("lit")
    + * </blockquote>
    + * @requires console
    + * @overrides window
    + */
    +
    +// JSLint declarations
    +/*global console, document, navigator, setTimeout, window */
    +
    +/**
    + * Split {@code prettyPrint} into multiple timeouts so as not to interfere with
    + * UI events.
    + * If set to {@code false}, {@code prettyPrint()} is synchronous.
    + */
    +window['PR_SHOULD_USE_CONTINUATION'] = true;
    +
    +/** the number of characters between tab columns */
    +window['PR_TAB_WIDTH'] = 8;
    +
    +/** Walks the DOM returning a properly escaped version of innerHTML.
    +  * @param {Node} node
    +  * @param {Array.<string>} out output buffer that receives chunks of HTML.
    +  */
    +window['PR_normalizedHtml']
    +
    +/** Contains functions for creating and registering new language handlers.
    +  * @type {Object}
    +  */
    +  = window['PR']
    +
    +/** Pretty print a chunk of code.
    +  *
    +  * @param {string} sourceCodeHtml code as html
    +  * @return {string} code as html, but prettier
    +  */
    +  = window['prettyPrintOne']
    +/** Find all the {@code <pre>} and {@code <code>} tags in the DOM with
    +  * {@code class=prettyprint} and prettify them.
    +  * @param {Function?} opt_whenDone if specified, called when the last entry
    +  *     has been finished.
    +  */
    +  = window['prettyPrint'] = void 0;
    +
    +/** browser detection. @extern @returns false if not IE, otherwise the major version. */
    +window['_pr_isIE6'] = function () {
    +  var ieVersion = navigator && navigator.userAgent &&
    +      navigator.userAgent.match(/\bMSIE ([678])\./);
    +  ieVersion = ieVersion ? +ieVersion[1] : false;
    +  window['_pr_isIE6'] = function () { return ieVersion; };
    +  return ieVersion;
    +};
    +
    +
    +(function () {
    +  // Keyword lists for various languages.
    +  var FLOW_CONTROL_KEYWORDS =
    +      "break continue do else for if return while ";
    +  var C_KEYWORDS = FLOW_CONTROL_KEYWORDS + "auto case char const default " +
    +      "double enum extern float goto int long register short signed sizeof " +
    +      "static struct switch typedef union unsigned void volatile ";
    +  var COMMON_KEYWORDS = C_KEYWORDS + "catch class delete false import " +
    +      "new operator private protected public this throw true try typeof ";
    +  var CPP_KEYWORDS = COMMON_KEYWORDS + "alignof align_union asm axiom bool " +
    +      "concept concept_map const_cast constexpr decltype " +
    +      "dynamic_cast explicit export friend inline late_check " +
    +      "mutable namespace nullptr reinterpret_cast static_assert static_cast " +
    +      "template typeid typename using virtual wchar_t where ";
    +  var JAVA_KEYWORDS = COMMON_KEYWORDS +
    +      "abstract boolean byte extends final finally implements import " +
    +      "instanceof null native package strictfp super synchronized throws " +
    +      "transient ";
    +  var CSHARP_KEYWORDS = JAVA_KEYWORDS +
    +      "as base by checked decimal delegate descending event " +
    +      "fixed foreach from group implicit in interface internal into is lock " +
    +      "object out override orderby params partial readonly ref sbyte sealed " +
    +      "stackalloc string select uint ulong unchecked unsafe ushort var ";
    +  var JSCRIPT_KEYWORDS = COMMON_KEYWORDS +
    +      "debugger eval export function get null set undefined var with " +
    +      "Infinity NaN ";
    +  var PERL_KEYWORDS = "caller delete die do dump elsif eval exit foreach for " +
    +      "goto if import last local my next no our print package redo require " +
    +      "sub undef unless until use wantarray while BEGIN END ";
    +  var PYTHON_KEYWORDS = FLOW_CONTROL_KEYWORDS + "and as assert class def del " +
    +      "elif except exec finally from global import in is lambda " +
    +      "nonlocal not or pass print raise try with yield " +
    +      "False True None ";
    +  var RUBY_KEYWORDS = FLOW_CONTROL_KEYWORDS + "alias and begin case class def" +
    +      " defined elsif end ensure false in module next nil not or redo rescue " +
    +      "retry self super then true undef unless until when yield BEGIN END ";
    +  var SH_KEYWORDS = FLOW_CONTROL_KEYWORDS + "case done elif esac eval fi " +
    +      "function in local set then until ";
    +  var ALL_KEYWORDS = (
    +      CPP_KEYWORDS + CSHARP_KEYWORDS + JSCRIPT_KEYWORDS + PERL_KEYWORDS +
    +      PYTHON_KEYWORDS + RUBY_KEYWORDS + SH_KEYWORDS);
    +
    +  // token style names.  correspond to css classes
    +  /** token style for a string literal */
    +  var PR_STRING = 'str';
    +  /** token style for a keyword */
    +  var PR_KEYWORD = 'kwd';
    +  /** token style for a comment */
    +  var PR_COMMENT = 'com';
    +  /** token style for a type */
    +  var PR_TYPE = 'typ';
    +  /** token style for a literal value.  e.g. 1, null, true. */
    +  var PR_LITERAL = 'lit';
    +  /** token style for a punctuation string. */
    +  var PR_PUNCTUATION = 'pun';
    +  /** token style for a punctuation string. */
    +  var PR_PLAIN = 'pln';
    +
    +  /** token style for an sgml tag. */
    +  var PR_TAG = 'tag';
    +  /** token style for a markup declaration such as a DOCTYPE. */
    +  var PR_DECLARATION = 'dec';
    +  /** token style for embedded source. */
    +  var PR_SOURCE = 'src';
    +  /** token style for an sgml attribute name. */
    +  var PR_ATTRIB_NAME = 'atn';
    +  /** token style for an sgml attribute value. */
    +  var PR_ATTRIB_VALUE = 'atv';
    +
    +  /**
    +   * A class that indicates a section of markup that is not code, e.g. to allow
    +   * embedding of line numbers within code listings.
    +   */
    +  var PR_NOCODE = 'nocode';
    +
    +  /** A set of tokens that can precede a regular expression literal in
    +    * javascript.
    +    * http://www.mozilla.org/js/language/js20/rationale/syntax.html has the full
    +    * list, but I've removed ones that might be problematic when seen in
    +    * languages that don't support regular expression literals.
    +    *
    +    * <p>Specifically, I've removed any keywords that can't precede a regexp
    +    * literal in a syntactically legal javascript program, and I've removed the
    +    * "in" keyword since it's not a keyword in many languages, and might be used
    +    * as a count of inches.
    +    *
    +    * <p>The link a above does not accurately describe EcmaScript rules since
    +    * it fails to distinguish between (a=++/b/i) and (a++/b/i) but it works
    +    * very well in practice.
    +    *
    +    * @private
    +    */
    +  var REGEXP_PRECEDER_PATTERN = function () {
    +      var preceders = [
    +          "!", "!=", "!==", "#", "%", "%=", "&", "&&", "&&=",
    +          "&=", "(", "*", "*=", /* "+", */ "+=", ",", /* "-", */ "-=",
    +          "->", /*".", "..", "...", handled below */ "/", "/=", ":", "::", ";",
    +          "<", "<<", "<<=", "<=", "=", "==", "===", ">",
    +          ">=", ">>", ">>=", ">>>", ">>>=", "?", "@", "[",
    +          "^", "^=", "^^", "^^=", "{", "|", "|=", "||",
    +          "||=", "~" /* handles =~ and !~ */,
    +          "break", "case", "continue", "delete",
    +          "do", "else", "finally", "instanceof",
    +          "return", "throw", "try", "typeof"
    +          ];
    +      var pattern = '(?:^^|[+-]';
    +      for (var i = 0; i < preceders.length; ++i) {
    +        pattern += '|' + preceders[i].replace(/([^=<>:&a-z])/g, '\\$1');
    +      }
    +      pattern += ')\\s*';  // matches at end, and matches empty string
    +      return pattern;
    +      // CAVEAT: this does not properly handle the case where a regular
    +      // expression immediately follows another since a regular expression may
    +      // have flags for case-sensitivity and the like.  Having regexp tokens
    +      // adjacent is not valid in any language I'm aware of, so I'm punting.
    +      // TODO: maybe style special characters inside a regexp as punctuation.
    +    }();
    +
    +  // Define regexps here so that the interpreter doesn't have to create an
    +  // object each time the function containing them is called.
    +  // The language spec requires a new object created even if you don't access
    +  // the $1 members.
    +  var pr_amp = /&/g;
    +  var pr_lt = /</g;
    +  var pr_gt = />/g;
    +  var pr_quot = /\"/g;
    +  /** like textToHtml but escapes double quotes to be attribute safe. */
    +  function attribToHtml(str) {
    +    return str.replace(pr_amp, '&amp;')
    +        .replace(pr_lt, '&lt;')
    +        .replace(pr_gt, '&gt;')
    +        .replace(pr_quot, '&quot;');
    +  }
    +
    +  /** escapest html special characters to html. */
    +  function textToHtml(str) {
    +    return str.replace(pr_amp, '&amp;')
    +        .replace(pr_lt, '&lt;')
    +        .replace(pr_gt, '&gt;');
    +  }
    +
    +
    +  var pr_ltEnt = /&lt;/g;
    +  var pr_gtEnt = /&gt;/g;
    +  var pr_aposEnt = /&apos;/g;
    +  var pr_quotEnt = /&quot;/g;
    +  var pr_ampEnt = /&amp;/g;
    +  var pr_nbspEnt = /&nbsp;/g;
    +  /** unescapes html to plain text. */
    +  function htmlToText(html) {
    +    var pos = html.indexOf('&');
    +    if (pos < 0) { return html; }
    +    // Handle numeric entities specially.  We can't use functional substitution
    +    // since that doesn't work in older versions of Safari.
    +    // These should be rare since most browsers convert them to normal chars.
    +    for (--pos; (pos = html.indexOf('&#', pos + 1)) >= 0;) {
    +      var end = html.indexOf(';', pos);
    +      if (end >= 0) {
    +        var num = html.substring(pos + 3, end);
    +        var radix = 10;
    +        if (num && num.charAt(0) === 'x') {
    +          num = num.substring(1);
    +          radix = 16;
    +        }
    +        var codePoint = parseInt(num, radix);
    +        if (!isNaN(codePoint)) {
    +          html = (html.substring(0, pos) + String.fromCharCode(codePoint) +
    +                  html.substring(end + 1));
    +        }
    +      }
    +    }
    +
    +    return html.replace(pr_ltEnt, '<')
    +        .replace(pr_gtEnt, '>')
    +        .replace(pr_aposEnt, "'")
    +        .replace(pr_quotEnt, '"')
    +        .replace(pr_nbspEnt, ' ')
    +        .replace(pr_ampEnt, '&');
    +  }
    +
    +  /** is the given node's innerHTML normally unescaped? */
    +  function isRawContent(node) {
    +    return 'XMP' === node.tagName;
    +  }
    +
    +  var newlineRe = /[\r\n]/g;
    +  /**
    +   * Are newlines and adjacent spaces significant in the given node's innerHTML?
    +   */
    +  function isPreformatted(node, content) {
    +    // PRE means preformatted, and is a very common case, so don't create
    +    // unnecessary computed style objects.
    +    if ('PRE' === node.tagName) { return true; }
    +    if (!newlineRe.test(content)) { return true; }  // Don't care
    +    var whitespace = '';
    +    // For disconnected nodes, IE has no currentStyle.
    +    if (node.currentStyle) {
    +      whitespace = node.currentStyle.whiteSpace;
    +    } else if (window.getComputedStyle) {
    +      // Firefox makes a best guess if node is disconnected whereas Safari
    +      // returns the empty string.
    +      whitespace = window.getComputedStyle(node, null).whiteSpace;
    +    }
    +    return !whitespace || whitespace === 'pre';
    +  }
    +
    +  function normalizedHtml(node, out) {
    +    switch (node.nodeType) {
    +      case 1:  // an element
    +        var name = node.tagName.toLowerCase();
    +        out.push('<', name);
    +        for (var i = 0; i < node.attributes.length; ++i) {
    +          var attr = node.attributes[i];
    +          if (!attr.specified) { continue; }
    +          out.push(' ');
    +          normalizedHtml(attr, out);
    +        }
    +        out.push('>');
    +        for (var child = node.firstChild; child; child = child.nextSibling) {
    +          normalizedHtml(child, out);
    +        }
    +        if (node.firstChild || !/^(?:br|link|img)$/.test(name)) {
    +          out.push('<\/', name, '>');
    +        }
    +        break;
    +      case 2: // an attribute
    +        out.push(node.name.toLowerCase(), '="', attribToHtml(node.value), '"');
    +        break;
    +      case 3: case 4: // text
    +        out.push(textToHtml(node.nodeValue));
    +        break;
    +    }
    +  }
    +
    +  /**
    +   * Given a group of {@link RegExp}s, returns a {@code RegExp} that globally
    +   * matches the union o the sets o strings matched d by the input RegExp.
    +   * Since it matches globally, if the input strings have a start-of-input
    +   * anchor (/^.../), it is ignored for the purposes of unioning.
    +   * @param {Array.<RegExp>} regexs non multiline, non-global regexs.
    +   * @return {RegExp} a global regex.
    +   */
    +  function combinePrefixPatterns(regexs) {
    +    var capturedGroupIndex = 0;
    +
    +    var needToFoldCase = false;
    +    var ignoreCase = false;
    +    for (var i = 0, n = regexs.length; i < n; ++i) {
    +      var regex = regexs[i];
    +      if (regex.ignoreCase) {
    +        ignoreCase = true;
    +      } else if (/[a-z]/i.test(regex.source.replace(
    +                     /\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi, ''))) {
    +        needToFoldCase = true;
    +        ignoreCase = false;
    +        break;
    +      }
    +    }
    +
    +    function decodeEscape(charsetPart) {
    +      if (charsetPart.charAt(0) !== '\\') { return charsetPart.charCodeAt(0); }
    +      switch (charsetPart.charAt(1)) {
    +        case 'b': return 8;
    +        case 't': return 9;
    +        case 'n': return 0xa;
    +        case 'v': return 0xb;
    +        case 'f': return 0xc;
    +        case 'r': return 0xd;
    +        case 'u': case 'x':
    +          return parseInt(charsetPart.substring(2), 16)
    +              || charsetPart.charCodeAt(1);
    +        case '0': case '1': case '2': case '3': case '4':
    +        case '5': case '6': case '7':
    +          return parseInt(charsetPart.substring(1), 8);
    +        default: return charsetPart.charCodeAt(1);
    +      }
    +    }
    +
    +    function encodeEscape(charCode) {
    +      if (charCode < 0x20) {
    +        return (charCode < 0x10 ? '\\x0' : '\\x') + charCode.toString(16);
    +      }
    +      var ch = String.fromCharCode(charCode);
    +      if (ch === '\\' || ch === '-' || ch === '[' || ch === ']') {
    +        ch = '\\' + ch;
    +      }
    +      return ch;
    +    }
    +
    +    function caseFoldCharset(charSet) {
    +      var charsetParts = charSet.substring(1, charSet.length - 1).match(
    +          new RegExp(
    +              '\\\\u[0-9A-Fa-f]{4}'
    +              + '|\\\\x[0-9A-Fa-f]{2}'
    +              + '|\\\\[0-3][0-7]{0,2}'
    +              + '|\\\\[0-7]{1,2}'
    +              + '|\\\\[\\s\\S]'
    +              + '|-'
    +              + '|[^-\\\\]',
    +              'g'));
    +      var groups = [];
    +      var ranges = [];
    +      var inverse = charsetParts[0] === '^';
    +      for (var i = inverse ? 1 : 0, n = charsetParts.length; i < n; ++i) {
    +        var p = charsetParts[i];
    +        switch (p) {
    +          case '\\B': case '\\b':
    +          case '\\D': case '\\d':
    +          case '\\S': case '\\s':
    +          case '\\W': case '\\w':
    +            groups.push(p);
    +            continue;
    +        }
    +        var start = decodeEscape(p);
    +        var end;
    +        if (i + 2 < n && '-' === charsetParts[i + 1]) {
    +          end = decodeEscape(charsetParts[i + 2]);
    +          i += 2;
    +        } else {
    +          end = start;
    +        }
    +        ranges.push([start, end]);
    +        // If the range might intersect letters, then expand it.
    +        if (!(end < 65 || start > 122)) {
    +          if (!(end < 65 || start > 90)) {
    +            ranges.push([Math.max(65, start) | 32, Math.min(end, 90) | 32]);
    +          }
    +          if (!(end < 97 || start > 122)) {
    +            ranges.push([Math.max(97, start) & ~32, Math.min(end, 122) & ~32]);
    +          }
    +        }
    +      }
    +
    +      // [[1, 10], [3, 4], [8, 12], [14, 14], [16, 16], [17, 17]]
    +      // -> [[1, 12], [14, 14], [16, 17]]
    +      ranges.sort(function (a, b) { return (a[0] - b[0]) || (b[1]  - a[1]); });
    +      var consolidatedRanges = [];
    +      var lastRange = [NaN, NaN];
    +      for (var i = 0; i < ranges.length; ++i) {
    +        var range = ranges[i];
    +        if (range[0] <= lastRange[1] + 1) {
    +          lastRange[1] = Math.max(lastRange[1], range[1]);
    +        } else {
    +          consolidatedRanges.push(lastRange = range);
    +        }
    +      }
    +
    +      var out = ['['];
    +      if (inverse) { out.push('^'); }
    +      out.push.apply(out, groups);
    +      for (var i = 0; i < consolidatedRanges.length; ++i) {
    +        var range = consolidatedRanges[i];
    +        out.push(encodeEscape(range[0]));
    +        if (range[1] > range[0]) {
    +          if (range[1] + 1 > range[0]) { out.push('-'); }
    +          out.push(encodeEscape(range[1]));
    +        }
    +      }
    +      out.push(']');
    +      return out.join('');
    +    }
    +
    +    function allowAnywhereFoldCaseAndRenumberGroups(regex) {
    +      // Split into character sets, escape sequences, punctuation strings
    +      // like ('(', '(?:', ')', '^'), and runs of characters that do not
    +      // include any of the above.
    +      var parts = regex.source.match(
    +          new RegExp(
    +              '(?:'
    +              + '\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]'  // a character set
    +              + '|\\\\u[A-Fa-f0-9]{4}'  // a unicode escape
    +              + '|\\\\x[A-Fa-f0-9]{2}'  // a hex escape
    +              + '|\\\\[0-9]+'  // a back-reference or octal escape
    +              + '|\\\\[^ux0-9]'  // other escape sequence
    +              + '|\\(\\?[:!=]'  // start of a non-capturing group
    +              + '|[\\(\\)\\^]'  // start/emd of a group, or line start
    +              + '|[^\\x5B\\x5C\\(\\)\\^]+'  // run of other characters
    +              + ')',
    +              'g'));
    +      var n = parts.length;
    +
    +      // Maps captured group numbers to the number they will occupy in
    +      // the output or to -1 if that has not been determined, or to
    +      // undefined if they need not be capturing in the output.
    +      var capturedGroups = [];
    +
    +      // Walk over and identify back references to build the capturedGroups
    +      // mapping.
    +      for (var i = 0, groupIndex = 0; i < n; ++i) {
    +        var p = parts[i];
    +        if (p === '(') {
    +          // groups are 1-indexed, so max group index is count of '('
    +          ++groupIndex;
    +        } else if ('\\' === p.charAt(0)) {
    +          var decimalValue = +p.substring(1);
    +          if (decimalValue && decimalValue <= groupIndex) {
    +            capturedGroups[decimalValue] = -1;
    +          }
    +        }
    +      }
    +
    +      // Renumber groups and reduce capturing groups to non-capturing groups
    +      // where possible.
    +      for (var i = 1; i < capturedGroups.length; ++i) {
    +        if (-1 === capturedGroups[i]) {
    +          capturedGroups[i] = ++capturedGroupIndex;
    +        }
    +      }
    +      for (var i = 0, groupIndex = 0; i < n; ++i) {
    +        var p = parts[i];
    +        if (p === '(') {
    +          ++groupIndex;
    +          if (capturedGroups[groupIndex] === undefined) {
    +            parts[i] = '(?:';
    +          }
    +        } else if ('\\' === p.charAt(0)) {
    +          var decimalValue = +p.substring(1);
    +          if (decimalValue && decimalValue <= groupIndex) {
    +            parts[i] = '\\' + capturedGroups[groupIndex];
    +          }
    +        }
    +      }
    +
    +      // Remove any prefix anchors so that the output will match anywhere.
    +      // ^^ really does mean an anchored match though.
    +      for (var i = 0, groupIndex = 0; i < n; ++i) {
    +        if ('^' === parts[i] && '^' !== parts[i + 1]) { parts[i] = ''; }
    +      }
    +
    +      // Expand letters to groupts to handle mixing of case-sensitive and
    +      // case-insensitive patterns if necessary.
    +      if (regex.ignoreCase && needToFoldCase) {
    +        for (var i = 0; i < n; ++i) {
    +          var p = parts[i];
    +          var ch0 = p.charAt(0);
    +          if (p.length >= 2 && ch0 === '[') {
    +            parts[i] = caseFoldCharset(p);
    +          } else if (ch0 !== '\\') {
    +            // TODO: handle letters in numeric escapes.
    +            parts[i] = p.replace(
    +                /[a-zA-Z]/g,
    +                function (ch) {
    +                  var cc = ch.charCodeAt(0);
    +                  return '[' + String.fromCharCode(cc & ~32, cc | 32) + ']';
    +                });
    +          }
    +        }
    +      }
    +
    +      return parts.join('');
    +    }
    +
    +    var rewritten = [];
    +    for (var i = 0, n = regexs.length; i < n; ++i) {
    +      var regex = regexs[i];
    +      if (regex.global || regex.multiline) { throw new Error('' + regex); }
    +      rewritten.push(
    +          '(?:' + allowAnywhereFoldCaseAndRenumberGroups(regex) + ')');
    +    }
    +
    +    return new RegExp(rewritten.join('|'), ignoreCase ? 'gi' : 'g');
    +  }
    +
    +  var PR_innerHtmlWorks = null;
    +  function getInnerHtml(node) {
    +    // inner html is hopelessly broken in Safari 2.0.4 when the content is
    +    // an html description of well formed XML and the containing tag is a PRE
    +    // tag, so we detect that case and emulate innerHTML.
    +    if (null === PR_innerHtmlWorks) {
    +      var testNode = document.createElement('PRE');
    +      testNode.appendChild(
    +          document.createTextNode('<!DOCTYPE foo PUBLIC "foo bar">\n<foo />'));
    +      PR_innerHtmlWorks = !/</.test(testNode.innerHTML);
    +    }
    +
    +    if (PR_innerHtmlWorks) {
    +      var content = node.innerHTML;
    +      // XMP tags contain unescaped entities so require special handling.
    +      if (isRawContent(node)) {
    +        content = textToHtml(content);
    +      } else if (!isPreformatted(node, content)) {
    +        content = content.replace(/(<br\s*\/?>)[\r\n]+/g, '$1')
    +            .replace(/(?:[\r\n]+[ \t]*)+/g, ' ');
    +      }
    +      return content;
    +    }
    +
    +    var out = [];
    +    for (var child = node.firstChild; child; child = child.nextSibling) {
    +      normalizedHtml(child, out);
    +    }
    +    return out.join('');
    +  }
    +
    +  /** returns a function that expand tabs to spaces.  This function can be fed
    +    * successive chunks of text, and will maintain its own internal state to
    +    * keep track of how tabs are expanded.
    +    * @return {function (string) : string} a function that takes
    +    *   plain text and return the text with tabs expanded.
    +    * @private
    +    */
    +  function makeTabExpander(tabWidth) {
    +    var SPACES = '                ';
    +    var charInLine = 0;
    +
    +    return function (plainText) {
    +      // walk over each character looking for tabs and newlines.
    +      // On tabs, expand them.  On newlines, reset charInLine.
    +      // Otherwise increment charInLine
    +      var out = null;
    +      var pos = 0;
    +      for (var i = 0, n = plainText.length; i < n; ++i) {
    +        var ch = plainText.charAt(i);
    +
    +        switch (ch) {
    +          case '\t':
    +            if (!out) { out = []; }
    +            out.push(plainText.substring(pos, i));
    +            // calculate how much space we need in front of this part
    +            // nSpaces is the amount of padding -- the number of spaces needed
    +            // to move us to the next column, where columns occur at factors of
    +            // tabWidth.
    +            var nSpaces = tabWidth - (charInLine % tabWidth);
    +            charInLine += nSpaces;
    +            for (; nSpaces >= 0; nSpaces -= SPACES.length) {
    +              out.push(SPACES.substring(0, nSpaces));
    +            }
    +            pos = i + 1;
    +            break;
    +          case '\n':
    +            charInLine = 0;
    +            break;
    +          default:
    +            ++charInLine;
    +        }
    +      }
    +      if (!out) { return plainText; }
    +      out.push(plainText.substring(pos));
    +      return out.join('');
    +    };
    +  }
    +
    +  var pr_chunkPattern = new RegExp(
    +      '[^<]+'  // A run of characters other than '<'
    +      + '|<\!--[\\s\\S]*?--\>'  // an HTML comment
    +      + '|<!\\[CDATA\\[[\\s\\S]*?\\]\\]>'  // a CDATA section
    +      // a probable tag that should not be highlighted
    +      + '|<\/?[a-zA-Z](?:[^>\"\']|\'[^\']*\'|\"[^\"]*\")*>'
    +      + '|<',  // A '<' that does not begin a larger chunk
    +      'g');
    +  var pr_commentPrefix = /^<\!--/;
    +  var pr_cdataPrefix = /^<!\[CDATA\[/;
    +  var pr_brPrefix = /^<br\b/i;
    +  var pr_tagNameRe = /^<(\/?)([a-zA-Z][a-zA-Z0-9]*)/;
    +
    +  /** split markup into chunks of html tags (style null) and
    +    * plain text (style {@link #PR_PLAIN}), converting tags which are
    +    * significant for tokenization (<br>) into their textual equivalent.
    +    *
    +    * @param {string} s html where whitespace is considered significant.
    +    * @return {Object} source code and extracted tags.
    +    * @private
    +    */
    +  function extractTags(s) {
    +    // since the pattern has the 'g' modifier and defines no capturing groups,
    +    // this will return a list of all chunks which we then classify and wrap as
    +    // PR_Tokens
    +    var matches = s.match(pr_chunkPattern);
    +    var sourceBuf = [];
    +    var sourceBufLen = 0;
    +    var extractedTags = [];
    +    if (matches) {
    +      for (var i = 0, n = matches.length; i < n; ++i) {
    +        var match = matches[i];
    +        if (match.length > 1 && match.charAt(0) === '<') {
    +          if (pr_commentPrefix.test(match)) { continue; }
    +          if (pr_cdataPrefix.test(match)) {
    +            // strip CDATA prefix and suffix.  Don't unescape since it's CDATA
    +            sourceBuf.push(match.substring(9, match.length - 3));
    +            sourceBufLen += match.length - 12;
    +          } else if (pr_brPrefix.test(match)) {
    +            // <br> tags are lexically significant so convert them to text.
    +            // This is undone later.
    +            sourceBuf.push('\n');
    +            ++sourceBufLen;
    +          } else {
    +            if (match.indexOf(PR_NOCODE) >= 0 && isNoCodeTag(match)) {
    +              // A <span class="nocode"> will start a section that should be
    +              // ignored.  Continue walking the list until we see a matching end
    +              // tag.
    +              var name = match.match(pr_tagNameRe)[2];
    +              var depth = 1;
    +              var j;
    +              end_tag_loop:
    +              for (j = i + 1; j < n; ++j) {
    +                var name2 = matches[j].match(pr_tagNameRe);
    +                if (name2 && name2[2] === name) {
    +                  if (name2[1] === '/') {
    +                    if (--depth === 0) { break end_tag_loop; }
    +                  } else {
    +                    ++depth;
    +                  }
    +                }
    +              }
    +              if (j < n) {
    +                extractedTags.push(
    +                    sourceBufLen, matches.slice(i, j + 1).join(''));
    +                i = j;
    +              } else {  // Ignore unclosed sections.
    +                extractedTags.push(sourceBufLen, match);
    +              }
    +            } else {
    +              extractedTags.push(sourceBufLen, match);
    +            }
    +          }
    +        } else {
    +          var literalText = htmlToText(match);
    +          sourceBuf.push(literalText);
    +          sourceBufLen += literalText.length;
    +        }
    +      }
    +    }
    +    return { source: sourceBuf.join(''), tags: extractedTags };
    +  }
    +
    +  /** True if the given tag contains a class attribute with the nocode class. */
    +  function isNoCodeTag(tag) {
    +    return !!tag
    +        // First canonicalize the representation of attributes
    +        .replace(/\s(\w+)\s*=\s*(?:\"([^\"]*)\"|'([^\']*)'|(\S+))/g,
    +                 ' $1="$2$3$4"')
    +        // Then look for the attribute we want.
    +        .match(/[cC][lL][aA][sS][sS]=\"[^\"]*\bnocode\b/);
    +  }
    +
    +  /**
    +   * Apply the given language handler to sourceCode and add the resulting
    +   * decorations to out.
    +   * @param {number} basePos the index of sourceCode within the chunk of source
    +   *    whose decorations are already present on out.
    +   */
    +  function appendDecorations(basePos, sourceCode, langHandler, out) {
    +    if (!sourceCode) { return; }
    +    var job = {
    +      source: sourceCode,
    +      basePos: basePos
    +    };
    +    langHandler(job);
    +    out.push.apply(out, job.decorations);
    +  }
    +
    +  /** Given triples of [style, pattern, context] returns a lexing function,
    +    * The lexing function interprets the patterns to find token boundaries and
    +    * returns a decoration list of the form
    +    * [index_0, style_0, index_1, style_1, ..., index_n, style_n]
    +    * where index_n is an index into the sourceCode, and style_n is a style
    +    * constant like PR_PLAIN.  index_n-1 <= index_n, and style_n-1 applies to
    +    * all characters in sourceCode[index_n-1:index_n].
    +    *
    +    * The stylePatterns is a list whose elements have the form
    +    * [style : string, pattern : RegExp, DEPRECATED, shortcut : string].
    +    *
    +    * Style is a style constant like PR_PLAIN, or can be a string of the
    +    * form 'lang-FOO', where FOO is a language extension describing the
    +    * language of the portion of the token in $1 after pattern executes.
    +    * E.g., if style is 'lang-lisp', and group 1 contains the text
    +    * '(hello (world))', then that portion of the token will be passed to the
    +    * registered lisp handler for formatting.
    +    * The text before and after group 1 will be restyled using this decorator
    +    * so decorators should take care that this doesn't result in infinite
    +    * recursion.  For example, the HTML lexer rule for SCRIPT elements looks
    +    * something like ['lang-js', /<[s]cript>(.+?)<\/script>/].  This may match
    +    * '<script>foo()<\/script>', which would cause the current decorator to
    +    * be called with '<script>' which would not match the same rule since
    +    * group 1 must not be empty, so it would be instead styled as PR_TAG by
    +    * the generic tag rule.  The handler registered for the 'js' extension would
    +    * then be called with 'foo()', and finally, the current decorator would
    +    * be called with '<\/script>' which would not match the original rule and
    +    * so the generic tag rule would identify it as a tag.
    +    *
    +    * Pattern must only match prefixes, and if it matches a prefix, then that
    +    * match is considered a token with the same style.
    +    *
    +    * Context is applied to the last non-whitespace, non-comment token
    +    * recognized.
    +    *
    +    * Shortcut is an optional string of characters, any of which, if the first
    +    * character, gurantee that this pattern and only this pattern matches.
    +    *
    +    * @param {Array} shortcutStylePatterns patterns that always start with
    +    *   a known character.  Must have a shortcut string.
    +    * @param {Array} fallthroughStylePatterns patterns that will be tried in
    +    *   order if the shortcut ones fail.  May have shortcuts.
    +    *
    +    * @return {function (Object)} a
    +    *   function that takes source code and returns a list of decorations.
    +    */
    +  function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) {
    +    var shortcuts = {};
    +    var tokenizer;
    +    (function () {
    +      var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns);
    +      var allRegexs = [];
    +      var regexKeys = {};
    +      for (var i = 0, n = allPatterns.length; i < n; ++i) {
    +        var patternParts = allPatterns[i];
    +        var shortcutChars = patternParts[3];
    +        if (shortcutChars) {
    +          for (var c = shortcutChars.length; --c >= 0;) {
    +            shortcuts[shortcutChars.charAt(c)] = patternParts;
    +          }
    +        }
    +        var regex = patternParts[1];
    +        var k = '' + regex;
    +        if (!regexKeys.hasOwnProperty(k)) {
    +          allRegexs.push(regex);
    +          regexKeys[k] = null;
    +        }
    +      }
    +      allRegexs.push(/[\0-\uffff]/);
    +      tokenizer = combinePrefixPatterns(allRegexs);
    +    })();
    +
    +    var nPatterns = fallthroughStylePatterns.length;
    +    var notWs = /\S/;
    +
    +    /**
    +     * Lexes job.source and produces an output array job.decorations of style
    +     * classes preceded by the position at which they start in job.source in
    +     * order.
    +     *
    +     * @param {Object} job an object like {@code
    +     *    source: {string} sourceText plain text,
    +     *    basePos: {int} position of job.source in the larger chunk of
    +     *        sourceCode.
    +     * }
    +     */
    +    var decorate = function (job) {
    +      var sourceCode = job.source, basePos = job.basePos;
    +      /** Even entries are positions in source in ascending order.  Odd enties
    +        * are style markers (e.g., PR_COMMENT) that run from that position until
    +        * the end.
    +        * @type {Array.<number|string>}
    +        */
    +      var decorations = [basePos, PR_PLAIN];
    +      var pos = 0;  // index into sourceCode
    +      var tokens = sourceCode.match(tokenizer) || [];
    +      var styleCache = {};
    +
    +      for (var ti = 0, nTokens = tokens.length; ti < nTokens; ++ti) {
    +        var token = tokens[ti];
    +        var style = styleCache[token];
    +        var match = void 0;
    +
    +        var isEmbedded;
    +        if (typeof style === 'string') {
    +          isEmbedded = false;
    +        } else {
    +          var patternParts = shortcuts[token.charAt(0)];
    +          if (patternParts) {
    +            match = token.match(patternParts[1]);
    +            style = patternParts[0];
    +          } else {
    +            for (var i = 0; i < nPatterns; ++i) {
    +              patternParts = fallthroughStylePatterns[i];
    +              match = token.match(patternParts[1]);
    +              if (match) {
    +                style = patternParts[0];
    +                break;
    +              }
    +            }
    +
    +            if (!match) {  // make sure that we make progress
    +              style = PR_PLAIN;
    +            }
    +          }
    +
    +          isEmbedded = style.length >= 5 && 'lang-' === style.substring(0, 5);
    +          if (isEmbedded && !(match && typeof match[1] === 'string')) {
    +            isEmbedded = false;
    +            style = PR_SOURCE;
    +          }
    +
    +          if (!isEmbedded) { styleCache[token] = style; }
    +        }
    +
    +        var tokenStart = pos;
    +        pos += token.length;
    +
    +        if (!isEmbedded) {
    +          decorations.push(basePos + tokenStart, style);
    +        } else {  // Treat group 1 as an embedded block of source code.
    +          var embeddedSource = match[1];
    +          var embeddedSourceStart = token.indexOf(embeddedSource);
    +          var embeddedSourceEnd = embeddedSourceStart + embeddedSource.length;
    +          if (match[2]) {
    +            // If embeddedSource can be blank, then it would match at the
    +            // beginning which would cause us to infinitely recurse on the
    +            // entire token, so we catch the right context in match[2].
    +            embeddedSourceEnd = token.length - match[2].length;
    +            embeddedSourceStart = embeddedSourceEnd - embeddedSource.length;
    +          }
    +          var lang = style.substring(5);
    +          // Decorate the left of the embedded source
    +          appendDecorations(
    +              basePos + tokenStart,
    +              token.substring(0, embeddedSourceStart),
    +              decorate, decorations);
    +          // Decorate the embedded source
    +          appendDecorations(
    +              basePos + tokenStart + embeddedSourceStart,
    +              embeddedSource,
    +              langHandlerForExtension(lang, embeddedSource),
    +              decorations);
    +          // Decorate the right of the embedded section
    +          appendDecorations(
    +              basePos + tokenStart + embeddedSourceEnd,
    +              token.substring(embeddedSourceEnd),
    +              decorate, decorations);
    +        }
    +      }
    +      job.decorations = decorations;
    +    };
    +    return decorate;
    +  }
    +
    +  /** returns a function that produces a list of decorations from source text.
    +    *
    +    * This code treats ", ', and ` as string delimiters, and \ as a string
    +    * escape.  It does not recognize perl's qq() style strings.
    +    * It has no special handling for double delimiter escapes as in basic, or
    +    * the tripled delimiters used in python, but should work on those regardless
    +    * although in those cases a single string literal may be broken up into
    +    * multiple adjacent string literals.
    +    *
    +    * It recognizes C, C++, and shell style comments.
    +    *
    +    * @param {Object} options a set of optional parameters.
    +    * @return {function (Object)} a function that examines the source code
    +    *     in the input job and builds the decoration list.
    +    */
    +  function sourceDecorator(options) {
    +    var shortcutStylePatterns = [], fallthroughStylePatterns = [];
    +    if (options['tripleQuotedStrings']) {
    +      // '''multi-line-string''', 'single-line-string', and double-quoted
    +      shortcutStylePatterns.push(
    +          [PR_STRING,  /^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,
    +           null, '\'"']);
    +    } else if (options['multiLineStrings']) {
    +      // 'multi-line-string', "multi-line-string"
    +      shortcutStylePatterns.push(
    +          [PR_STRING,  /^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,
    +           null, '\'"`']);
    +    } else {
    +      // 'single-line-string', "single-line-string"
    +      shortcutStylePatterns.push(
    +          [PR_STRING,
    +           /^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,
    +           null, '"\'']);
    +    }
    +    if (options['verbatimStrings']) {
    +      // verbatim-string-literal production from the C# grammar.  See issue 93.
    +      fallthroughStylePatterns.push(
    +          [PR_STRING, /^@\"(?:[^\"]|\"\")*(?:\"|$)/, null]);
    +    }
    +    if (options['hashComments']) {
    +      if (options['cStyleComments']) {
    +        // Stop C preprocessor declarations at an unclosed open comment
    +        shortcutStylePatterns.push(
    +            [PR_COMMENT, /^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,
    +             null, '#']);
    +        fallthroughStylePatterns.push(
    +            [PR_STRING,
    +             /^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,
    +             null]);
    +      } else {
    +        shortcutStylePatterns.push([PR_COMMENT, /^#[^\r\n]*/, null, '#']);
    +      }
    +    }
    +    if (options['cStyleComments']) {
    +      fallthroughStylePatterns.push([PR_COMMENT, /^\/\/[^\r\n]*/, null]);
    +      fallthroughStylePatterns.push(
    +          [PR_COMMENT, /^\/\*[\s\S]*?(?:\*\/|$)/, null]);
    +    }
    +    if (options['regexLiterals']) {
    +      var REGEX_LITERAL = (
    +          // A regular expression literal starts with a slash that is
    +          // not followed by * or / so that it is not confused with
    +          // comments.
    +          '/(?=[^/*])'
    +          // and then contains any number of raw characters,
    +          + '(?:[^/\\x5B\\x5C]'
    +          // escape sequences (\x5C),
    +          +    '|\\x5C[\\s\\S]'
    +          // or non-nesting character sets (\x5B\x5D);
    +          +    '|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+'
    +          // finally closed by a /.
    +          + '/');
    +      fallthroughStylePatterns.push(
    +          ['lang-regex',
    +           new RegExp('^' + REGEXP_PRECEDER_PATTERN + '(' + REGEX_LITERAL + ')')
    +           ]);
    +    }
    +
    +    var keywords = options['keywords'].replace(/^\s+|\s+$/g, '');
    +    if (keywords.length) {
    +      fallthroughStylePatterns.push(
    +          [PR_KEYWORD,
    +           new RegExp('^(?:' + keywords.replace(/\s+/g, '|') + ')\\b'), null]);
    +    }
    +
    +    shortcutStylePatterns.push([PR_PLAIN,       /^\s+/, null, ' \r\n\t\xA0']);
    +    fallthroughStylePatterns.push(
    +        // TODO(mikesamuel): recognize non-latin letters and numerals in idents
    +        [PR_LITERAL,     /^@[a-z_$][a-z_$@0-9]*/i, null],
    +        [PR_TYPE,        /^@?[A-Z]+[a-z][A-Za-z_$@0-9]*/, null],
    +        [PR_PLAIN,       /^[a-z_$][a-z_$@0-9]*/i, null],
    +        [PR_LITERAL,
    +         new RegExp(
    +             '^(?:'
    +             // A hex number
    +             + '0x[a-f0-9]+'
    +             // or an octal or decimal number,
    +             + '|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)'
    +             // possibly in scientific notation
    +             + '(?:e[+\\-]?\\d+)?'
    +             + ')'
    +             // with an optional modifier like UL for unsigned long
    +             + '[a-z]*', 'i'),
    +         null, '0123456789'],
    +        [PR_PUNCTUATION, /^.[^\s\w\.$@\'\"\`\/\#]*/, null]);
    +
    +    return createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns);
    +  }
    +
    +  var decorateSource = sourceDecorator({
    +        'keywords': ALL_KEYWORDS,
    +        'hashComments': true,
    +        'cStyleComments': true,
    +        'multiLineStrings': true,
    +        'regexLiterals': true
    +      });
    +
    +  /** Breaks {@code job.source} around style boundaries in
    +    * {@code job.decorations} while re-interleaving {@code job.extractedTags},
    +    * and leaves the result in {@code job.prettyPrintedHtml}.
    +    * @param {Object} job like {
    +    *    source: {string} source as plain text,
    +    *    extractedTags: {Array.<number|string>} extractedTags chunks of raw
    +    *                   html preceded by their position in {@code job.source}
    +    *                   in order
    +    *    decorations: {Array.<number|string} an array of style classes preceded
    +    *                 by the position at which they start in job.source in order
    +    * }
    +    * @private
    +    */
    +  function recombineTagsAndDecorations(job) {
    +    var sourceText = job.source;
    +    var extractedTags = job.extractedTags;
    +    var decorations = job.decorations;
    +
    +    var html = [];
    +    // index past the last char in sourceText written to html
    +    var outputIdx = 0;
    +
    +    var openDecoration = null;
    +    var currentDecoration = null;
    +    var tagPos = 0;  // index into extractedTags
    +    var decPos = 0;  // index into decorations
    +    var tabExpander = makeTabExpander(window['PR_TAB_WIDTH']);
    +
    +    var adjacentSpaceRe = /([\r\n ]) /g;
    +    var startOrSpaceRe = /(^| ) /gm;
    +    var newlineRe = /\r\n?|\n/g;
    +    var trailingSpaceRe = /[ \r\n]$/;
    +    var lastWasSpace = true;  // the last text chunk emitted ended with a space.
    +
    +    // A helper function that is responsible for opening sections of decoration
    +    // and outputing properly escaped chunks of source
    +    function emitTextUpTo(sourceIdx) {
    +      if (sourceIdx > outputIdx) {
    +        if (openDecoration && openDecoration !== currentDecoration) {
    +          // Close the current decoration
    +          html.push('</span>');
    +          openDecoration = null;
    +        }
    +        if (!openDecoration && currentDecoration) {
    +          openDecoration = currentDecoration;
    +          html.push('<span class="', openDecoration, '">');
    +        }
    +        // This interacts badly with some wikis which introduces paragraph tags
    +        // into pre blocks for some strange reason.
    +        // It's necessary for IE though which seems to lose the preformattedness
    +        // of <pre> tags when their innerHTML is assigned.
    +        // http://stud3.tuwien.ac.at/~e0226430/innerHtmlQuirk.html
    +        // and it serves to undo the conversion of <br>s to newlines done in
    +        // chunkify.
    +        var htmlChunk = textToHtml(
    +            tabExpander(sourceText.substring(outputIdx, sourceIdx)))
    +            .replace(lastWasSpace
    +                     ? startOrSpaceRe
    +                     : adjacentSpaceRe, '$1&nbsp;');
    +        // Keep track of whether we need to escape space at the beginning of the
    +        // next chunk.
    +        lastWasSpace = trailingSpaceRe.test(htmlChunk);
    +        // IE collapses multiple adjacient <br>s into 1 line break.
    +        // Prefix every <br> with '&nbsp;' can prevent such IE's behavior.
    +        var lineBreakHtml = window['_pr_isIE6']() ? '&nbsp;<br />' : '<br />';
    +        html.push(htmlChunk.replace(newlineRe, lineBreakHtml));
    +        outputIdx = sourceIdx;
    +      }
    +    }
    +
    +    while (true) {
    +      // Determine if we're going to consume a tag this time around.  Otherwise
    +      // we consume a decoration or exit.
    +      var outputTag;
    +      if (tagPos < extractedTags.length) {
    +        if (decPos < decorations.length) {
    +          // Pick one giving preference to extractedTags since we shouldn't open
    +          // a new style that we're going to have to immediately close in order
    +          // to output a tag.
    +          outputTag = extractedTags[tagPos] <= decorations[decPos];
    +        } else {
    +          outputTag = true;
    +        }
    +      } else {
    +        outputTag = false;
    +      }
    +      // Consume either a decoration or a tag or exit.
    +      if (outputTag) {
    +        emitTextUpTo(extractedTags[tagPos]);
    +        if (openDecoration) {
    +          // Close the current decoration
    +          html.push('</span>');
    +          openDecoration = null;
    +        }
    +        html.push(extractedTags[tagPos + 1]);
    +        tagPos += 2;
    +      } else if (decPos < decorations.length) {
    +        emitTextUpTo(decorations[decPos]);
    +        currentDecoration = decorations[decPos + 1];
    +        decPos += 2;
    +      } else {
    +        break;
    +      }
    +    }
    +    emitTextUpTo(sourceText.length);
    +    if (openDecoration) {
    +      html.push('</span>');
    +    }
    +    job.prettyPrintedHtml = html.join('');
    +  }
    +
    +  /** Maps language-specific file extensions to handlers. */
    +  var langHandlerRegistry = {};
    +  /** Register a language handler for the given file extensions.
    +    * @param {function (Object)} handler a function from source code to a list
    +    *      of decorations.  Takes a single argument job which describes the
    +    *      state of the computation.   The single parameter has the form
    +    *      {@code {
    +    *        source: {string} as plain text.
    +    *        decorations: {Array.<number|string>} an array of style classes
    +    *                     preceded by the position at which they start in
    +    *                     job.source in order.
    +    *                     The language handler should assigned this field.
    +    *        basePos: {int} the position of source in the larger source chunk.
    +    *                 All positions in the output decorations array are relative
    +    *                 to the larger source chunk.
    +    *      } }
    +    * @param {Array.<string>} fileExtensions
    +    */
    +  function registerLangHandler(handler, fileExtensions) {
    +    for (var i = fileExtensions.length; --i >= 0;) {
    +      var ext = fileExtensions[i];
    +      if (!langHandlerRegistry.hasOwnProperty(ext)) {
    +        langHandlerRegistry[ext] = handler;
    +      } else if ('console' in window) {
    +        console.warn('cannot override language handler %s', ext);
    +      }
    +    }
    +  }
    +  function langHandlerForExtension(extension, source) {
    +    if (!(extension && langHandlerRegistry.hasOwnProperty(extension))) {
    +      // Treat it as markup if the first non whitespace character is a < and
    +      // the last non-whitespace character is a >.
    +      extension = /^\s*</.test(source)
    +          ? 'default-markup'
    +          : 'default-code';
    +    }
    +    return langHandlerRegistry[extension];
    +  }
    +  registerLangHandler(decorateSource, ['default-code']);
    +  registerLangHandler(
    +      createSimpleLexer(
    +          [],
    +          [
    +           [PR_PLAIN,       /^[^<?]+/],
    +           [PR_DECLARATION, /^<!\w[^>]*(?:>|$)/],
    +           [PR_COMMENT,     /^<\!--[\s\S]*?(?:-\->|$)/],
    +           // Unescaped content in an unknown language
    +           ['lang-',        /^<\?([\s\S]+?)(?:\?>|$)/],
    +           ['lang-',        /^<%([\s\S]+?)(?:%>|$)/],
    +           [PR_PUNCTUATION, /^(?:<[%?]|[%?]>)/],
    +           ['lang-',        /^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],
    +           // Unescaped content in javascript.  (Or possibly vbscript).
    +           ['lang-js',      /^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],
    +           // Contains unescaped stylesheet content
    +           ['lang-css',     /^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],
    +           ['lang-in.tag',  /^(<\/?[a-z][^<>]*>)/i]
    +          ]),
    +      ['default-markup', 'htm', 'html', 'mxml', 'xhtml', 'xml', 'xsl']);
    +  registerLangHandler(
    +      createSimpleLexer(
    +          [
    +           [PR_PLAIN,        /^[\s]+/, null, ' \t\r\n'],
    +           [PR_ATTRIB_VALUE, /^(?:\"[^\"]*\"?|\'[^\']*\'?)/, null, '\"\'']
    +           ],
    +          [
    +           [PR_TAG,          /^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],
    +           [PR_ATTRIB_NAME,  /^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],
    +           ['lang-uq.val',   /^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],
    +           [PR_PUNCTUATION,  /^[=<>\/]+/],
    +           ['lang-js',       /^on\w+\s*=\s*\"([^\"]+)\"/i],
    +           ['lang-js',       /^on\w+\s*=\s*\'([^\']+)\'/i],
    +           ['lang-js',       /^on\w+\s*=\s*([^\"\'>\s]+)/i],
    +           ['lang-css',      /^style\s*=\s*\"([^\"]+)\"/i],
    +           ['lang-css',      /^style\s*=\s*\'([^\']+)\'/i],
    +           ['lang-css',      /^style\s*=\s*([^\"\'>\s]+)/i]
    +           ]),
    +      ['in.tag']);
    +  registerLangHandler(
    +      createSimpleLexer([], [[PR_ATTRIB_VALUE, /^[\s\S]+/]]), ['uq.val']);
    +  registerLangHandler(sourceDecorator({
    +          'keywords': CPP_KEYWORDS,
    +          'hashComments': true,
    +          'cStyleComments': true
    +        }), ['c', 'cc', 'cpp', 'cxx', 'cyc', 'm']);
    +  registerLangHandler(sourceDecorator({
    +          'keywords': 'null true false'
    +        }), ['json']);
    +  registerLangHandler(sourceDecorator({
    +          'keywords': CSHARP_KEYWORDS,
    +          'hashComments': true,
    +          'cStyleComments': true,
    +          'verbatimStrings': true
    +        }), ['cs']);
    +  registerLangHandler(sourceDecorator({
    +          'keywords': JAVA_KEYWORDS,
    +          'cStyleComments': true
    +        }), ['java']);
    +  registerLangHandler(sourceDecorator({
    +          'keywords': SH_KEYWORDS,
    +          'hashComments': true,
    +          'multiLineStrings': true
    +        }), ['bsh', 'csh', 'sh']);
    +  registerLangHandler(sourceDecorator({
    +          'keywords': PYTHON_KEYWORDS,
    +          'hashComments': true,
    +          'multiLineStrings': true,
    +          'tripleQuotedStrings': true
    +        }), ['cv', 'py']);
    +  registerLangHandler(sourceDecorator({
    +          'keywords': PERL_KEYWORDS,
    +          'hashComments': true,
    +          'multiLineStrings': true,
    +          'regexLiterals': true
    +        }), ['perl', 'pl', 'pm']);
    +  registerLangHandler(sourceDecorator({
    +          'keywords': RUBY_KEYWORDS,
    +          'hashComments': true,
    +          'multiLineStrings': true,
    +          'regexLiterals': true
    +        }), ['rb']);
    +  registerLangHandler(sourceDecorator({
    +          'keywords': JSCRIPT_KEYWORDS,
    +          'cStyleComments': true,
    +          'regexLiterals': true
    +        }), ['js']);
    +  registerLangHandler(
    +      createSimpleLexer([], [[PR_STRING, /^[\s\S]+/]]), ['regex']);
    +
    +  function applyDecorator(job) {
    +    var sourceCodeHtml = job.sourceCodeHtml;
    +    var opt_langExtension = job.langExtension;
    +
    +    // Prepopulate output in case processing fails with an exception.
    +    job.prettyPrintedHtml = sourceCodeHtml;
    +
    +    try {
    +      // Extract tags, and convert the source code to plain text.
    +      var sourceAndExtractedTags = extractTags(sourceCodeHtml);
    +      /** Plain text. @type {string} */
    +      var source = sourceAndExtractedTags.source;
    +      job.source = source;
    +      job.basePos = 0;
    +
    +      /** Even entries are positions in source in ascending order.  Odd entries
    +        * are tags that were extracted at that position.
    +        * @type {Array.<number|string>}
    +        */
    +      job.extractedTags = sourceAndExtractedTags.tags;
    +
    +      // Apply the appropriate language handler
    +      langHandlerForExtension(opt_langExtension, source)(job);
    +      // Integrate the decorations and tags back into the source code to produce
    +      // a decorated html string which is left in job.prettyPrintedHtml.
    +      recombineTagsAndDecorations(job);
    +    } catch (e) {
    +      if ('console' in window) {
    +        console.log(e);
    +        console.trace();
    +      }
    +    }
    +  }
    +
    +  function prettyPrintOne(sourceCodeHtml, opt_langExtension) {
    +    var job = {
    +      sourceCodeHtml: sourceCodeHtml,
    +      langExtension: opt_langExtension
    +    };
    +    applyDecorator(job);
    +    return job.prettyPrintedHtml;
    +  }
    +
    +  function prettyPrint(opt_whenDone) {
    +    var isIE678 = window['_pr_isIE6']();
    +    var ieNewline = isIE678 === 6 ? '\r\n' : '\r';
    +    // See bug 71 and http://stackoverflow.com/questions/136443/why-doesnt-ie7-
    +
    +    // fetch a list of nodes to rewrite
    +    var codeSegments = [
    +        document.getElementsByTagName('pre'),
    +        document.getElementsByTagName('code'),
    +        document.getElementsByTagName('td'),  /* ND Change: Add tables to support prototypes. */
    +        document.getElementsByTagName('xmp') ];
    +    var elements = [];
    +    for (var i = 0; i < codeSegments.length; ++i) {
    +      for (var j = 0, n = codeSegments[i].length; j < n; ++j) {
    +        elements.push(codeSegments[i][j]);
    +      }
    +    }
    +    codeSegments = null;
    +
    +    var clock = Date;
    +    if (!clock['now']) {
    +      clock = { 'now': function () { return (new Date).getTime(); } };
    +    }
    +
    +    // The loop is broken into a series of continuations to make sure that we
    +    // don't make the browser unresponsive when rewriting a large page.
    +    var k = 0;
    +    var prettyPrintingJob;
    +
    +    function doWork() {
    +      var endTime = (window['PR_SHOULD_USE_CONTINUATION'] ?
    +                     clock.now() + 250 /* ms */ :
    +                     Infinity);
    +      for (; k < elements.length && clock.now() < endTime; k++) {
    +        var cs = elements[k];
    +        if (cs.className && cs.className.indexOf('prettyprint') >= 0) {
    +          // If the classes includes a language extensions, use it.
    +          // Language extensions can be specified like
    +          //     <pre class="prettyprint lang-cpp">
    +          // the language extension "cpp" is used to find a language handler as
    +          // passed to PR_registerLangHandler.
    +          var langExtension = cs.className.match(/\blang-(\w+)\b/);
    +          if (langExtension) { langExtension = langExtension[1]; }
    +
    +          // make sure this is not nested in an already prettified element
    +          var nested = false;
    +          for (var p = cs.parentNode; p; p = p.parentNode) {
    +            if ((p.tagName === 'pre' || p.tagName === 'code' ||
    +                 p.tagName === 'xmp' || p.tagName === 'td') &&  /* ND Change: Add tables to support prototypes */
    +                p.className && p.className.indexOf('prettyprint') >= 0) {
    +              nested = true;
    +              break;
    +            }
    +          }
    +          if (!nested) {
    +            // fetch the content as a snippet of properly escaped HTML.
    +            // Firefox adds newlines at the end.
    +            var content = getInnerHtml(cs);
    +            content = content.replace(/(?:\r\n?|\n)$/, '');
    +
    +	  		/* ND Change: we need to preserve &nbsp;s so change them to a special character instead of a space. */
    +			content = content.replace(/&nbsp;/g, '\x11');
    +
    +            // do the pretty printing
    +            prettyPrintingJob = {
    +              sourceCodeHtml: content,
    +              langExtension: langExtension,
    +              sourceNode: cs
    +            };
    +            applyDecorator(prettyPrintingJob);
    +            replaceWithPrettyPrintedHtml();
    +          }
    +        }
    +      }
    +      if (k < elements.length) {
    +        // finish up in a continuation
    +        setTimeout(doWork, 250);
    +      } else if (opt_whenDone) {
    +        opt_whenDone();
    +      }
    +    }
    +
    +    function replaceWithPrettyPrintedHtml() {
    +      var newContent = prettyPrintingJob.prettyPrintedHtml;
    +      if (!newContent) { return; }
    +
    +      /* ND Change: Restore the preserved &nbsp;s.  */
    +	  newContent = newContent.replace(/\x11/g, '&nbsp;');
    +
    +      var cs = prettyPrintingJob.sourceNode;
    +
    +      // push the prettified html back into the tag.
    +      if (!isRawContent(cs)) {
    +        // just replace the old html with the new
    +        cs.innerHTML = newContent;
    +      } else {
    +        // we need to change the tag to a <pre> since <xmp>s do not allow
    +        // embedded tags such as the span tags used to attach styles to
    +        // sections of source code.
    +        var pre = document.createElement('PRE');
    +        for (var i = 0; i < cs.attributes.length; ++i) {
    +          var a = cs.attributes[i];
    +          if (a.specified) {
    +            var aname = a.name.toLowerCase();
    +            if (aname === 'class') {
    +              pre.className = a.value;  // For IE 6
    +            } else {
    +              pre.setAttribute(a.name, a.value);
    +            }
    +          }
    +        }
    +        pre.innerHTML = newContent;
    +
    +        // remove the old
    +        cs.parentNode.replaceChild(pre, cs);
    +        cs = pre;
    +      }
    +
    +      // Replace <br>s with line-feeds so that copying and pasting works
    +      // on IE 6.
    +      // Doing this on other browsers breaks lots of stuff since \r\n is
    +      // treated as two newlines on Firefox, and doing this also slows
    +      // down rendering.
    +      if (isIE678 && cs.tagName === 'PRE') {
    +        var lineBreaks = cs.getElementsByTagName('br');
    +        for (var j = lineBreaks.length; --j >= 0;) {
    +          var lineBreak = lineBreaks[j];
    +          lineBreak.parentNode.replaceChild(
    +              document.createTextNode(ieNewline), lineBreak);
    +        }
    +      }
    +    }
    +
    +    doWork();
    +  }
    +
    +  window['PR_normalizedHtml'] = normalizedHtml;
    +  window['prettyPrintOne'] = prettyPrintOne;
    +  window['prettyPrint'] = prettyPrint;
    +  window['PR'] = {
    +        'combinePrefixPatterns': combinePrefixPatterns,
    +        'createSimpleLexer': createSimpleLexer,
    +        'registerLangHandler': registerLangHandler,
    +        'sourceDecorator': sourceDecorator,
    +        'PR_ATTRIB_NAME': PR_ATTRIB_NAME,
    +        'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE,
    +        'PR_COMMENT': PR_COMMENT,
    +        'PR_DECLARATION': PR_DECLARATION,
    +        'PR_KEYWORD': PR_KEYWORD,
    +        'PR_LITERAL': PR_LITERAL,
    +        'PR_NOCODE': PR_NOCODE,
    +        'PR_PLAIN': PR_PLAIN,
    +        'PR_PUNCTUATION': PR_PUNCTUATION,
    +        'PR_SOURCE': PR_SOURCE,
    +        'PR_STRING': PR_STRING,
    +        'PR_TAG': PR_TAG,
    +        'PR_TYPE': PR_TYPE
    +      };
    +})();
    +
    +
    +// ____________________________________________________________________________
    +
    +
    +
    +// Lua extension
    +
    +PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[\t\n\r \xA0]+/,null,'	\n\r \xa0'],[PR.PR_STRING,/^(?:\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)|\'(?:[^\'\\]|\\[\s\S])*(?:\'|$))/,null,'\"\'']],[[PR.PR_COMMENT,/^--(?:\[(=*)\[[\s\S]*?(?:\]\1\]|$)|[^\r\n]*)/],[PR.PR_STRING,/^\[(=*)\[[\s\S]*?(?:\]\1\]|$)/],[PR.PR_KEYWORD,/^(?:and|break|do|else|elseif|end|false|for|function|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/,null],[PR.PR_LITERAL,/^[+-]?(?:0x[\da-f]+|(?:(?:\.\d+|\d+(?:\.\d*)?)(?:e[+\-]?\d+)?))/i],[PR.PR_PLAIN,/^[a-z_]\w*/i],[PR.PR_PUNCTUATION,/^[^\w\t\n\r \xA0][^\w\t\n\r \xA0\"\'\-\+=]*/]]),['lua'])
    +
    +
    +// Haskell extension
    +
    +PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[\t\n\x0B\x0C\r ]+/,null,'	\n\r '],[PR.PR_STRING,/^\"(?:[^\"\\\n\x0C\r]|\\[\s\S])*(?:\"|$)/,null,'\"'],[PR.PR_STRING,/^\'(?:[^\'\\\n\x0C\r]|\\[^&])\'?/,null,'\''],[PR.PR_LITERAL,/^(?:0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+\-]?\d+)?)/i,null,'0123456789']],[[PR.PR_COMMENT,/^(?:(?:--+(?:[^\r\n\x0C]*)?)|(?:\{-(?:[^-]|-+[^-\}])*-\}))/],[PR.PR_KEYWORD,/^(?:case|class|data|default|deriving|do|else|if|import|in|infix|infixl|infixr|instance|let|module|newtype|of|then|type|where|_)(?=[^a-zA-Z0-9\']|$)/,null],[PR.PR_PLAIN,/^(?:[A-Z][\w\']*\.)*[a-zA-Z][\w\']*/],[PR.PR_PUNCTUATION,/^[^\t\n\x0B\x0C\r a-zA-Z0-9\'\"]+/]]),['hs'])
    +
    +
    +// ML extension
    +
    +PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[\t\n\r \xA0]+/,null,'	\n\r \xa0'],[PR.PR_COMMENT,/^#(?:if[\t\n\r \xA0]+(?:[a-z_$][\w\']*|``[^\r\n\t`]*(?:``|$))|else|endif|light)/i,null,'#'],[PR.PR_STRING,/^(?:\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)|\'(?:[^\'\\]|\\[\s\S])*(?:\'|$))/,null,'\"\'']],[[PR.PR_COMMENT,/^(?:\/\/[^\r\n]*|\(\*[\s\S]*?\*\))/],[PR.PR_KEYWORD,/^(?:abstract|and|as|assert|begin|class|default|delegate|do|done|downcast|downto|elif|else|end|exception|extern|false|finally|for|fun|function|if|in|inherit|inline|interface|internal|lazy|let|match|member|module|mutable|namespace|new|null|of|open|or|override|private|public|rec|return|static|struct|then|to|true|try|type|upcast|use|val|void|when|while|with|yield|asr|land|lor|lsl|lsr|lxor|mod|sig|atomic|break|checked|component|const|constraint|constructor|continue|eager|event|external|fixed|functor|global|include|method|mixin|object|parallel|process|protected|pure|sealed|trait|virtual|volatile)\b/],[PR.PR_LITERAL,/^[+\-]?(?:0x[\da-f]+|(?:(?:\.\d+|\d+(?:\.\d*)?)(?:e[+\-]?\d+)?))/i],[PR.PR_PLAIN,/^(?:[a-z_]\w*[!?#]?|``[^\r\n\t`]*(?:``|$))/i],[PR.PR_PUNCTUATION,/^[^\t\n\r \xA0\"\'\w]+/]]),['fs','ml'])
    +
    +
    +// SQL extension
    +
    +PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[\t\n\r \xA0]+/,null,'	\n\r \xa0'],[PR.PR_STRING,/^(?:"(?:[^\"\\]|\\.)*"|'(?:[^\'\\]|\\.)*')/,null,'\"\'']],[[PR.PR_COMMENT,/^(?:--[^\r\n]*|\/\*[\s\S]*?(?:\*\/|$))/],[PR.PR_KEYWORD,/^(?:ADD|ALL|ALTER|AND|ANY|AS|ASC|AUTHORIZATION|BACKUP|BEGIN|BETWEEN|BREAK|BROWSE|BULK|BY|CASCADE|CASE|CHECK|CHECKPOINT|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMN|COMMIT|COMPUTE|CONSTRAINT|CONTAINS|CONTAINSTABLE|CONTINUE|CONVERT|CREATE|CROSS|CURRENT|CURRENT_DATE|CURRENT_TIME|CURRENT_TIMESTAMP|CURRENT_USER|CURSOR|DATABASE|DBCC|DEALLOCATE|DECLARE|DEFAULT|DELETE|DENY|DESC|DISK|DISTINCT|DISTRIBUTED|DOUBLE|DROP|DUMMY|DUMP|ELSE|END|ERRLVL|ESCAPE|EXCEPT|EXEC|EXECUTE|EXISTS|EXIT|FETCH|FILE|FILLFACTOR|FOR|FOREIGN|FREETEXT|FREETEXTTABLE|FROM|FULL|FUNCTION|GOTO|GRANT|GROUP|HAVING|HOLDLOCK|IDENTITY|IDENTITYCOL|IDENTITY_INSERT|IF|IN|INDEX|INNER|INSERT|INTERSECT|INTO|IS|JOIN|KEY|KILL|LEFT|LIKE|LINENO|LOAD|NATIONAL|NOCHECK|NONCLUSTERED|NOT|NULL|NULLIF|OF|OFF|OFFSETS|ON|OPEN|OPENDATASOURCE|OPENQUERY|OPENROWSET|OPENXML|OPTION|OR|ORDER|OUTER|OVER|PERCENT|PLAN|PRECISION|PRIMARY|PRINT|PROC|PROCEDURE|PUBLIC|RAISERROR|READ|READTEXT|RECONFIGURE|REFERENCES|REPLICATION|RESTORE|RESTRICT|RETURN|REVOKE|RIGHT|ROLLBACK|ROWCOUNT|ROWGUIDCOL|RULE|SAVE|SCHEMA|SELECT|SESSION_USER|SET|SETUSER|SHUTDOWN|SOME|STATISTICS|SYSTEM_USER|TABLE|TEXTSIZE|THEN|TO|TOP|TRAN|TRANSACTION|TRIGGER|TRUNCATE|TSEQUAL|UNION|UNIQUE|UPDATE|UPDATETEXT|USE|USER|VALUES|VARYING|VIEW|WAITFOR|WHEN|WHERE|WHILE|WITH|WRITETEXT)(?=[^\w-]|$)/i,null],[PR.PR_LITERAL,/^[+-]?(?:0x[\da-f]+|(?:(?:\.\d+|\d+(?:\.\d*)?)(?:e[+\-]?\d+)?))/i],[PR.PR_PLAIN,/^[a-z_][\w-]*/i],[PR.PR_PUNCTUATION,/^[^\w\t\n\r \xA0\"\'][^\w\t\n\r \xA0+\-\"\']*/]]),['sql'])
    +
    +
    +// VB extension
    +
    +PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[\t\n\r \xA0\u2028\u2029]+/,null,'	\n\r \xa0\u2028\u2029'],[PR.PR_STRING,/^(?:[\"\u201C\u201D](?:[^\"\u201C\u201D]|[\"\u201C\u201D]{2})(?:[\"\u201C\u201D]c|$)|[\"\u201C\u201D](?:[^\"\u201C\u201D]|[\"\u201C\u201D]{2})*(?:[\"\u201C\u201D]|$))/i,null,'\"\u201c\u201d'],[PR.PR_COMMENT,/^[\'\u2018\u2019][^\r\n\u2028\u2029]*/,null,'\'\u2018\u2019']],[[PR.PR_KEYWORD,/^(?:AddHandler|AddressOf|Alias|And|AndAlso|Ansi|As|Assembly|Auto|Boolean|ByRef|Byte|ByVal|Call|Case|Catch|CBool|CByte|CChar|CDate|CDbl|CDec|Char|CInt|Class|CLng|CObj|Const|CShort|CSng|CStr|CType|Date|Decimal|Declare|Default|Delegate|Dim|DirectCast|Do|Double|Each|Else|ElseIf|End|EndIf|Enum|Erase|Error|Event|Exit|Finally|For|Friend|Function|Get|GetType|GoSub|GoTo|Handles|If|Implements|Imports|In|Inherits|Integer|Interface|Is|Let|Lib|Like|Long|Loop|Me|Mod|Module|MustInherit|MustOverride|MyBase|MyClass|Namespace|New|Next|Not|NotInheritable|NotOverridable|Object|On|Option|Optional|Or|OrElse|Overloads|Overridable|Overrides|ParamArray|Preserve|Private|Property|Protected|Public|RaiseEvent|ReadOnly|ReDim|RemoveHandler|Resume|Return|Select|Set|Shadows|Shared|Short|Single|Static|Step|Stop|String|Structure|Sub|SyncLock|Then|Throw|To|Try|TypeOf|Unicode|Until|Variant|Wend|When|While|With|WithEvents|WriteOnly|Xor|EndIf|GoSub|Let|Variant|Wend)\b/i,null],[PR.PR_COMMENT,/^REM[^\r\n\u2028\u2029]*/i],[PR.PR_LITERAL,/^(?:True\b|False\b|Nothing\b|\d+(?:E[+\-]?\d+[FRD]?|[FRDSIL])?|(?:&H[0-9A-F]+|&O[0-7]+)[SIL]?|\d*\.\d+(?:E[+\-]?\d+)?[FRD]?|#\s+(?:\d+[\-\/]\d+[\-\/]\d+(?:\s+\d+:\d+(?::\d+)?(\s*(?:AM|PM))?)?|\d+:\d+(?::\d+)?(\s*(?:AM|PM))?)\s+#)/i],[PR.PR_PLAIN,/^(?:(?:[a-z]|_\w)\w*|\[(?:[a-z]|_\w)\w*\])/i],[PR.PR_PUNCTUATION,/^[^\w\t\n\r \"\'\[\]\xA0\u2018\u2019\u201C\u201D\u2028\u2029]+/],[PR.PR_PUNCTUATION,/^(?:\[|\])/]]),['vb','vbs'])
    diff --git a/Documentation/javascript/searchdata.js b/Documentation/javascript/searchdata.js
    new file mode 100644
    index 00000000..4bba0f6a
    --- /dev/null
    +++ b/Documentation/javascript/searchdata.js
    @@ -0,0 +1,92 @@
    +var indexSectionsWithContent = {
    +   "General": {
    +      "Symbols": false,
    +      "Numbers": false,
    +      "A": true,
    +      "B": false,
    +      "C": true,
    +      "D": false,
    +      "E": false,
    +      "F": true,
    +      "G": true,
    +      "H": false,
    +      "I": false,
    +      "J": false,
    +      "K": false,
    +      "L": false,
    +      "M": false,
    +      "N": false,
    +      "O": true,
    +      "P": true,
    +      "Q": false,
    +      "R": true,
    +      "S": true,
    +      "T": false,
    +      "U": true,
    +      "V": false,
    +      "W": false,
    +      "X": false,
    +      "Y": false,
    +      "Z": false
    +      },
    +   "Classes": {
    +      "Symbols": false,
    +      "Numbers": false,
    +      "A": false,
    +      "B": false,
    +      "C": false,
    +      "D": false,
    +      "E": false,
    +      "F": false,
    +      "G": false,
    +      "H": false,
    +      "I": false,
    +      "J": false,
    +      "K": false,
    +      "L": false,
    +      "M": false,
    +      "N": false,
    +      "O": false,
    +      "P": true,
    +      "Q": false,
    +      "R": false,
    +      "S": false,
    +      "T": false,
    +      "U": false,
    +      "V": false,
    +      "W": false,
    +      "X": false,
    +      "Y": false,
    +      "Z": false
    +      },
    +   "Functions": {
    +      "Symbols": false,
    +      "Numbers": false,
    +      "A": true,
    +      "B": false,
    +      "C": true,
    +      "D": false,
    +      "E": false,
    +      "F": false,
    +      "G": true,
    +      "H": false,
    +      "I": false,
    +      "J": false,
    +      "K": false,
    +      "L": false,
    +      "M": false,
    +      "N": false,
    +      "O": true,
    +      "P": false,
    +      "Q": false,
    +      "R": true,
    +      "S": true,
    +      "T": false,
    +      "U": true,
    +      "V": false,
    +      "W": false,
    +      "X": false,
    +      "Y": false,
    +      "Z": false
    +      }
    +   }
    \ No newline at end of file
    diff --git a/Documentation/search/ClassesP.html b/Documentation/search/ClassesP.html
    new file mode 100644
    index 00000000..357318fc
    --- /dev/null
    +++ b/Documentation/search/ClassesP.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_PushNotification><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification" target=_parent class=ISymbol>PushNotification</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/Documentation/search/FunctionsA.html b/Documentation/search/FunctionsA.html
    new file mode 100644
    index 00000000..64fd027a
    --- /dev/null
    +++ b/Documentation/search/FunctionsA.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_addToApplicationIconBadgeNumber><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.addToApplicationIconBadgeNumber" target=_parent class=ISymbol>addToApplicationIconBadgeNumber</a>, <span class=IParent>PushNotification</span></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/Documentation/search/FunctionsC.html b/Documentation/search/FunctionsC.html
    new file mode 100644
    index 00000000..ad8ceb68
    --- /dev/null
    +++ b/Documentation/search/FunctionsC.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_cancelAllLocalNotifications><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.cancelAllLocalNotifications" target=_parent class=ISymbol>cancelAllLocalNotifications</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_clearLocalNotification><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.clearLocalNotification" target=_parent class=ISymbol>clearLocalNotification</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_clearNotificationCenter><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.clearNotificationCenter" target=_parent class=ISymbol>clearNotificationCenter</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_clearPushHistory><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.clearPushHistory" target=_parent class=ISymbol>clearPushHistory</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_createLocalNotification><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.createLocalNotification" target=_parent class=ISymbol>createLocalNotification</a>, <span class=IParent>PushNotification</span></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/Documentation/search/FunctionsG.html b/Documentation/search/FunctionsG.html
    new file mode 100644
    index 00000000..2890d537
    --- /dev/null
    +++ b/Documentation/search/FunctionsG.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_getApplicationIconBadgeNumber><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.getApplicationIconBadgeNumber" target=_parent class=ISymbol>getApplicationIconBadgeNumber</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_getLaunchNotification><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.getLaunchNotification" target=_parent class=ISymbol>getLaunchNotification</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_getPushHistory><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.getPushHistory" target=_parent class=ISymbol>getPushHistory</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_getPushToken><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.getPushToken" target=_parent class=ISymbol>getPushToken</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_getPushwooshHWID><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.getPushwooshHWID" target=_parent class=ISymbol>getPushwooshHWID</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_getRemoteNotificationStatus><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.getRemoteNotificationStatus" target=_parent class=ISymbol>getRemoteNotificationStatus</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_getTags><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.getTags" target=_parent class=ISymbol>getTags</a>, <span class=IParent>PushNotification</span></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/Documentation/search/FunctionsO.html b/Documentation/search/FunctionsO.html
    new file mode 100644
    index 00000000..c58ca8a4
    --- /dev/null
    +++ b/Documentation/search/FunctionsO.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_onDeviceReady><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.onDeviceReady" target=_parent class=ISymbol>onDeviceReady</a>, <span class=IParent>PushNotification</span></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/Documentation/search/FunctionsR.html b/Documentation/search/FunctionsR.html
    new file mode 100644
    index 00000000..ac601feb
    --- /dev/null
    +++ b/Documentation/search/FunctionsR.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_registerDevice><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.registerDevice" target=_parent class=ISymbol>registerDevice</a>, <span class=IParent>PushNotification</span></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/Documentation/search/FunctionsS.html b/Documentation/search/FunctionsS.html
    new file mode 100644
    index 00000000..5d8d7a7a
    --- /dev/null
    +++ b/Documentation/search/FunctionsS.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_setApplicationIconBadgeNumber><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.setApplicationIconBadgeNumber" target=_parent class=ISymbol>setApplicationIconBadgeNumber</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_setBeaconBackgroundMode><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.setBeaconBackgroundMode" target=_parent class=ISymbol>setBeaconBackgroundMode</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_setEnableLED><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.setEnableLED" target=_parent class=ISymbol>setEnableLED</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_setLightScreenOnNotification><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.setLightScreenOnNotification" target=_parent class=ISymbol>setLightScreenOnNotification</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_setMultiNotificationMode><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.setMultiNotificationMode" target=_parent class=ISymbol>setMultiNotificationMode</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_setSingleNotificationMode><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.setSingleNotificationMode" target=_parent class=ISymbol>setSingleNotificationMode</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_setSoundType><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.setSoundType" target=_parent class=ISymbol>setSoundType</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_setTags><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.setTags" target=_parent class=ISymbol>setTags</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_setVibrateType><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.setVibrateType" target=_parent class=ISymbol>setVibrateType</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_startBeaconPushes><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.startBeaconPushes" target=_parent class=ISymbol>startBeaconPushes</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_startGeoPushes><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.startGeoPushes" target=_parent class=ISymbol>startGeoPushes</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_startLocationTracking><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.startLocationTracking" target=_parent class=ISymbol>startLocationTracking</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_stopBeaconPushes><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.stopBeaconPushes" target=_parent class=ISymbol>stopBeaconPushes</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_stopGeoPushes><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.stopGeoPushes" target=_parent class=ISymbol>stopGeoPushes</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_stopLocationTracking><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.stopLocationTracking" target=_parent class=ISymbol>stopLocationTracking</a>, <span class=IParent>PushNotification</span></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/Documentation/search/FunctionsU.html b/Documentation/search/FunctionsU.html
    new file mode 100644
    index 00000000..92d594af
    --- /dev/null
    +++ b/Documentation/search/FunctionsU.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_unregisterDevice><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.unregisterDevice" target=_parent class=ISymbol>unregisterDevice</a>, <span class=IParent>PushNotification</span></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/Documentation/search/GeneralA.html b/Documentation/search/GeneralA.html
    new file mode 100644
    index 00000000..64fd027a
    --- /dev/null
    +++ b/Documentation/search/GeneralA.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_addToApplicationIconBadgeNumber><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.addToApplicationIconBadgeNumber" target=_parent class=ISymbol>addToApplicationIconBadgeNumber</a>, <span class=IParent>PushNotification</span></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/Documentation/search/GeneralC.html b/Documentation/search/GeneralC.html
    new file mode 100644
    index 00000000..ad8ceb68
    --- /dev/null
    +++ b/Documentation/search/GeneralC.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_cancelAllLocalNotifications><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.cancelAllLocalNotifications" target=_parent class=ISymbol>cancelAllLocalNotifications</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_clearLocalNotification><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.clearLocalNotification" target=_parent class=ISymbol>clearLocalNotification</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_clearNotificationCenter><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.clearNotificationCenter" target=_parent class=ISymbol>clearNotificationCenter</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_clearPushHistory><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.clearPushHistory" target=_parent class=ISymbol>clearPushHistory</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_createLocalNotification><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.createLocalNotification" target=_parent class=ISymbol>createLocalNotification</a>, <span class=IParent>PushNotification</span></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/Documentation/search/GeneralF.html b/Documentation/search/GeneralF.html
    new file mode 100644
    index 00000000..b1ff5d02
    --- /dev/null
    +++ b/Documentation/search/GeneralF.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_Functions><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.Functions" target=_parent class=ISymbol>Functions</a>, <span class=IParent>PushNotification</span></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/Documentation/search/GeneralG.html b/Documentation/search/GeneralG.html
    new file mode 100644
    index 00000000..2890d537
    --- /dev/null
    +++ b/Documentation/search/GeneralG.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_getApplicationIconBadgeNumber><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.getApplicationIconBadgeNumber" target=_parent class=ISymbol>getApplicationIconBadgeNumber</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_getLaunchNotification><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.getLaunchNotification" target=_parent class=ISymbol>getLaunchNotification</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_getPushHistory><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.getPushHistory" target=_parent class=ISymbol>getPushHistory</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_getPushToken><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.getPushToken" target=_parent class=ISymbol>getPushToken</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_getPushwooshHWID><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.getPushwooshHWID" target=_parent class=ISymbol>getPushwooshHWID</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_getRemoteNotificationStatus><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.getRemoteNotificationStatus" target=_parent class=ISymbol>getRemoteNotificationStatus</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_getTags><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.getTags" target=_parent class=ISymbol>getTags</a>, <span class=IParent>PushNotification</span></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/Documentation/search/GeneralO.html b/Documentation/search/GeneralO.html
    new file mode 100644
    index 00000000..c58ca8a4
    --- /dev/null
    +++ b/Documentation/search/GeneralO.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_onDeviceReady><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.onDeviceReady" target=_parent class=ISymbol>onDeviceReady</a>, <span class=IParent>PushNotification</span></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/Documentation/search/GeneralP.html b/Documentation/search/GeneralP.html
    new file mode 100644
    index 00000000..357318fc
    --- /dev/null
    +++ b/Documentation/search/GeneralP.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_PushNotification><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification" target=_parent class=ISymbol>PushNotification</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/Documentation/search/GeneralR.html b/Documentation/search/GeneralR.html
    new file mode 100644
    index 00000000..ac601feb
    --- /dev/null
    +++ b/Documentation/search/GeneralR.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_registerDevice><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.registerDevice" target=_parent class=ISymbol>registerDevice</a>, <span class=IParent>PushNotification</span></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/Documentation/search/GeneralS.html b/Documentation/search/GeneralS.html
    new file mode 100644
    index 00000000..5d8d7a7a
    --- /dev/null
    +++ b/Documentation/search/GeneralS.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_setApplicationIconBadgeNumber><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.setApplicationIconBadgeNumber" target=_parent class=ISymbol>setApplicationIconBadgeNumber</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_setBeaconBackgroundMode><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.setBeaconBackgroundMode" target=_parent class=ISymbol>setBeaconBackgroundMode</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_setEnableLED><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.setEnableLED" target=_parent class=ISymbol>setEnableLED</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_setLightScreenOnNotification><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.setLightScreenOnNotification" target=_parent class=ISymbol>setLightScreenOnNotification</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_setMultiNotificationMode><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.setMultiNotificationMode" target=_parent class=ISymbol>setMultiNotificationMode</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_setSingleNotificationMode><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.setSingleNotificationMode" target=_parent class=ISymbol>setSingleNotificationMode</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_setSoundType><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.setSoundType" target=_parent class=ISymbol>setSoundType</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_setTags><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.setTags" target=_parent class=ISymbol>setTags</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_setVibrateType><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.setVibrateType" target=_parent class=ISymbol>setVibrateType</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_startBeaconPushes><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.startBeaconPushes" target=_parent class=ISymbol>startBeaconPushes</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_startGeoPushes><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.startGeoPushes" target=_parent class=ISymbol>startGeoPushes</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_startLocationTracking><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.startLocationTracking" target=_parent class=ISymbol>startLocationTracking</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_stopBeaconPushes><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.stopBeaconPushes" target=_parent class=ISymbol>stopBeaconPushes</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_stopGeoPushes><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.stopGeoPushes" target=_parent class=ISymbol>stopGeoPushes</a>, <span class=IParent>PushNotification</span></div></div><div class=SRResult id=SR_stopLocationTracking><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.stopLocationTracking" target=_parent class=ISymbol>stopLocationTracking</a>, <span class=IParent>PushNotification</span></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/Documentation/search/GeneralU.html b/Documentation/search/GeneralU.html
    new file mode 100644
    index 00000000..92d594af
    --- /dev/null
    +++ b/Documentation/search/GeneralU.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_unregisterDevice><div class=IEntry><a href="../files/PushNotification-js.html#PushNotification.unregisterDevice" target=_parent class=ISymbol>unregisterDevice</a>, <span class=IParent>PushNotification</span></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/Documentation/search/NoResults.html b/Documentation/search/NoResults.html
    new file mode 100644
    index 00000000..8c724966
    --- /dev/null
    +++ b/Documentation/search/NoResults.html
    @@ -0,0 +1,15 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=NoMatches>No Matches</div></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/Documentation/styles/main.css b/Documentation/styles/main.css
    new file mode 100644
    index 00000000..511703fc
    --- /dev/null
    +++ b/Documentation/styles/main.css
    @@ -0,0 +1,828 @@
    +/*
    +   IMPORTANT: If you're editing this file in the output directory of one of
    +   your projects, your changes will be overwritten the next time you run
    +   Natural Docs.  Instead, copy this file to your project directory, make your
    +   changes, and you can use it with -s.  Even better would be to make a CSS
    +   file in your project directory with only your changes, which you can then
    +   use with -s [original style] [your changes].
    +
    +   On the other hand, if you're editing this file in the Natural Docs styles
    +   directory, the changes will automatically be applied to all your projects
    +   that use this style the next time Natural Docs is run on them.
    +
    +   This file is part of Natural Docs, which is Copyright © 2003-2010 Greg Valure.
    +   Natural Docs is licensed under version 3 of the GNU Affero General Public
    +   License (AGPL).  Refer to License.txt for the complete details.
    +
    +   This file may be distributed with documentation files generated by Natural Docs.
    +   Such documentation is not covered by Natural Docs' copyright and licensing,
    +   and may have its own copyright and distribution terms as decided by its author.
    +*/
    +
    +body {
    +    font: 10pt Verdana, Arial, sans-serif;
    +    color: #000000;
    +    margin: 0; padding: 0;
    +    }
    +
    +.ContentPage,
    +.IndexPage,
    +.FramedMenuPage {
    +    background-color: #E8E8E8;
    +    }
    +.FramedContentPage,
    +.FramedIndexPage,
    +.FramedSearchResultsPage,
    +.PopupSearchResultsPage {
    +    background-color: #FFFFFF;
    +    }
    +
    +
    +a:link,
    +a:visited { color: #900000; text-decoration: none }
    +a:hover { color: #900000; text-decoration: underline }
    +a:active { color: #FF0000; text-decoration: underline }
    +
    +td {
    +    vertical-align: top }
    +
    +img { border: 0;  }
    +
    +
    +/*
    +    Comment out this line to use web-style paragraphs (blank line between
    +    paragraphs, no indent) instead of print-style paragraphs (no blank line,
    +    indented.)
    +*/
    +p {
    +    text-indent: 5ex; margin: 0 }
    +
    +
    +/*  Opera doesn't break with just wbr, but will if you add this.  */
    +.Opera wbr:after {
    +	content: "\00200B";
    +	}
    +
    +
    +/*  Blockquotes are used as containers for things that may need to scroll.  */
    +blockquote {
    +    padding: 0;
    +    margin: 0;
    +    overflow: auto;
    +    }
    +
    +
    +.Firefox1 blockquote {
    +    padding-bottom: .5em;
    +    }
    +
    +/*  Turn off scrolling when printing.  */
    +@media print {
    +    blockquote {
    +        overflow: visible;
    +        }
    +    .IE blockquote {
    +        width: auto;
    +        }
    +    }
    +
    +
    +
    +#Menu {
    +    font-size: 9pt;
    +    padding: 10px 0 0 0;
    +    }
    +.ContentPage #Menu,
    +.IndexPage #Menu {
    +    position: absolute;
    +    top: 0;
    +    left: 0;
    +    width: 31ex;
    +    overflow: hidden;
    +    }
    +.ContentPage .Firefox #Menu,
    +.IndexPage .Firefox #Menu {
    +    width: 27ex;
    +    }
    +
    +
    +    .MTitle {
    +        font-size: 16pt; font-weight: bold; font-variant: small-caps;
    +        text-align: center;
    +        padding: 5px 10px 15px 10px;
    +        border-bottom: 1px dotted #000000;
    +        margin-bottom: 15px }
    +
    +    .MSubTitle {
    +        font-size: 9pt; font-weight: normal; font-variant: normal;
    +        margin-top: 1ex; margin-bottom: 5px }
    +
    +
    +    .MEntry a:link,
    +    .MEntry a:hover,
    +    .MEntry a:visited { color: #606060; margin-right: 0 }
    +    .MEntry a:active { color: #A00000; margin-right: 0 }
    +
    +
    +    .MGroup {
    +        font-variant: small-caps; font-weight: bold;
    +        margin: 1em 0 1em 10px;
    +        }
    +
    +    .MGroupContent {
    +        font-variant: normal; font-weight: normal }
    +
    +    .MGroup a:link,
    +    .MGroup a:hover,
    +    .MGroup a:visited { color: #545454; margin-right: 10px }
    +    .MGroup a:active { color: #A00000; margin-right: 10px }
    +
    +
    +    .MFile,
    +    .MText,
    +    .MLink,
    +    .MIndex {
    +        padding: 1px 17px 2px 10px;
    +        margin: .25em 0 .25em 0;
    +        }
    +
    +    .MText {
    +        font-size: 8pt; font-style: italic }
    +
    +    .MLink {
    +        font-style: italic }
    +
    +    #MSelected {
    +        color: #000000; background-color: #FFFFFF;
    +        /*  Replace padding with border.  */
    +        padding: 0 10px 0 10px;
    +        border-width: 1px 2px 2px 0; border-style: solid; border-color: #000000;
    +        margin-right: 5px;
    +        }
    +
    +    /*  Close off the left side when its in a group.  */
    +    .MGroup #MSelected {
    +        padding-left: 9px; border-left-width: 1px }
    +
    +    /*  A treat for Mozilla users.  Blatantly non-standard.  Will be replaced with CSS 3 attributes when finalized/supported.  */
    +    .Firefox #MSelected {
    +        -moz-border-radius-topright: 10px;
    +        -moz-border-radius-bottomright: 10px }
    +    .Firefox .MGroup #MSelected {
    +        -moz-border-radius-topleft: 10px;
    +        -moz-border-radius-bottomleft: 10px }
    +
    +
    +    #MSearchPanel {
    +        padding: 0px 6px;
    +        margin: .25em 0;
    +        }
    +
    +
    +    #MSearchField {
    +        font: italic 9pt Verdana, sans-serif;
    +        color: #606060;
    +        background-color: #E8E8E8;
    +        border: none;
    +        padding: 2px 4px;
    +        width: 100%;
    +        }
    +    /* Only Opera gets it right. */
    +    .Firefox #MSearchField,
    +    .IE #MSearchField,
    +    .Safari #MSearchField {
    +        width: 94%;
    +        }
    +    .Opera9 #MSearchField,
    +    .Konqueror #MSearchField {
    +        width: 97%;
    +        }
    +    .FramedMenuPage .Firefox #MSearchField,
    +    .FramedMenuPage .Safari #MSearchField,
    +    .FramedMenuPage .Konqueror #MSearchField {
    +        width: 98%;
    +        }
    +
    +    /* Firefox doesn't do this right in frames without #MSearchPanel added on.
    +        It's presence doesn't hurt anything other browsers. */
    +    #MSearchPanel.MSearchPanelInactive:hover #MSearchField {
    +        background-color: #FFFFFF;
    +        border: 1px solid #C0C0C0;
    +        padding: 1px 3px;
    +        }
    +    .MSearchPanelActive #MSearchField {
    +        background-color: #FFFFFF;
    +        border: 1px solid #C0C0C0;
    +        font-style: normal;
    +        padding: 1px 3px;
    +        }
    +
    +    #MSearchType {
    +        visibility: hidden;
    +        font: 8pt Verdana, sans-serif;
    +        width: 98%;
    +        padding: 0;
    +        border: 1px solid #C0C0C0;
    +        }
    +    .MSearchPanelActive #MSearchType,
    +    /*  As mentioned above, Firefox doesn't do this right in frames without #MSearchPanel added on. */
    +    #MSearchPanel.MSearchPanelInactive:hover #MSearchType,
    +    #MSearchType:focus {
    +        visibility: visible;
    +        color: #606060;
    +        }
    +    #MSearchType option#MSearchEverything {
    +        font-weight: bold;
    +        }
    +
    +    .Opera8 .MSearchPanelInactive:hover,
    +    .Opera8 .MSearchPanelActive {
    +        margin-left: -1px;
    +        }
    +
    +
    +    iframe#MSearchResults {
    +        width: 60ex;
    +        height: 15em;
    +        }
    +    #MSearchResultsWindow {
    +        display: none;
    +        position: absolute;
    +        left: 0; top: 0;
    +        border: 1px solid #000000;
    +        background-color: #E8E8E8;
    +        }
    +    #MSearchResultsWindowClose {
    +        font-weight: bold;
    +        font-size: 8pt;
    +        display: block;
    +        padding: 2px 5px;
    +        }
    +    #MSearchResultsWindowClose:link,
    +    #MSearchResultsWindowClose:visited {
    +        color: #000000;
    +        text-decoration: none;
    +        }
    +    #MSearchResultsWindowClose:active,
    +    #MSearchResultsWindowClose:hover {
    +        color: #800000;
    +        text-decoration: none;
    +        background-color: #F4F4F4;
    +        }
    +
    +
    +
    +
    +#Content {
    +    padding-bottom: 15px;
    +    }
    +
    +.ContentPage #Content {
    +    border-width: 0 0 1px 1px;
    +    border-style: solid;
    +    border-color: #000000;
    +    background-color: #FFFFFF;
    +    font-size: 9pt;  /* To make 31ex match the menu's 31ex. */
    +    margin-left: 31ex;
    +    }
    +.ContentPage .Firefox #Content {
    +    margin-left: 27ex;
    +    }
    +
    +
    +
    +    .CTopic {
    +        font-size: 10pt;
    +        margin-bottom: 3em;
    +        }
    +
    +
    +    .CTitle {
    +        font-size: 12pt; font-weight: bold;
    +        border-width: 0 0 1px 0; border-style: solid; border-color: #A0A0A0;
    +        margin: 0 15px .5em 15px }
    +
    +    .CGroup .CTitle {
    +        font-size: 16pt; font-variant: small-caps;
    +        padding-left: 15px; padding-right: 15px;
    +        border-width: 0 0 2px 0; border-color: #000000;
    +        margin-left: 0; margin-right: 0 }
    +
    +    .CClass .CTitle,
    +    .CInterface .CTitle,
    +    .CDatabase .CTitle,
    +    .CDatabaseTable .CTitle,
    +    .CSection .CTitle {
    +        font-size: 18pt;
    +        color: #FFFFFF; background-color: #A0A0A0;
    +        padding: 10px 15px 10px 15px;
    +        border-width: 2px 0; border-color: #000000;
    +        margin-left: 0; margin-right: 0 }
    +
    +    #MainTopic .CTitle {
    +        font-size: 20pt;
    +        color: #FFFFFF; background-color: #7070C0;
    +        padding: 10px 15px 10px 15px;
    +        border-width: 0 0 3px 0; border-color: #000000;
    +        margin-left: 0; margin-right: 0 }
    +
    +    .CBody {
    +        margin-left: 15px; margin-right: 15px }
    +
    +
    +    .CToolTip {
    +        position: absolute; visibility: hidden;
    +        left: 0; top: 0;
    +        background-color: #FFFFE0;
    +        padding: 5px;
    +        border-width: 1px 2px 2px 1px; border-style: solid; border-color: #000000;
    +        font-size: 8pt;
    +        }
    +
    +    .Opera .CToolTip {
    +        max-width: 98%;
    +        }
    +
    +    /*  Scrollbars would be useless.  */
    +    .CToolTip blockquote {
    +        overflow: hidden;
    +        }
    +    .IE6 .CToolTip blockquote {
    +        overflow: visible;
    +        }
    +
    +    .CHeading {
    +        font-weight: bold; font-size: 10pt;
    +        margin: 1.5em 0 .5em 0;
    +        }
    +
    +    .CBody pre {
    +        font: 10pt "Courier New", Courier, monospace;
    +	    background-color: #FCFCFC;
    +	    margin: 1em 35px;
    +	    padding: 10px 15px 10px 10px;
    +	    border-color: #E0E0E0 #E0E0E0 #E0E0E0 #E4E4E4;
    +	    border-width: 1px 1px 1px 6px;
    +	    border-style: dashed dashed dashed solid;
    +        }
    +
    +    .CBody ul {
    +        /*  I don't know why CBody's margin doesn't apply, but it's consistent across browsers so whatever.
    +             Reapply it here as padding.  */
    +        padding-left: 15px; padding-right: 15px;
    +        margin: .5em 5ex .5em 5ex;
    +        }
    +
    +    .CDescriptionList {
    +        margin: .5em 5ex 0 5ex }
    +
    +        .CDLEntry {
    +            font: 10pt "Courier New", Courier, monospace; color: #808080;
    +            padding-bottom: .25em;
    +            white-space: nowrap }
    +
    +        .CDLDescription {
    +            font-size: 10pt;  /*  For browsers that don't inherit correctly, like Opera 5.  */
    +            padding-bottom: .5em; padding-left: 5ex }
    +
    +
    +    .CTopic img {
    +        text-align: center;
    +        display: block;
    +        margin: 1em auto;
    +        }
    +    .CImageCaption {
    +        font-variant: small-caps;
    +        font-size: 8pt;
    +        color: #808080;
    +        text-align: center;
    +        position: relative;
    +        top: 1em;
    +        }
    +
    +    .CImageLink {
    +        color: #808080;
    +        font-style: italic;
    +        }
    +    a.CImageLink:link,
    +    a.CImageLink:visited,
    +    a.CImageLink:hover { color: #808080 }
    +
    +
    +
    +
    +
    +.Prototype {
    +    font: 10pt "Courier New", Courier, monospace;
    +    padding: 5px 3ex;
    +    border-width: 1px; border-style: solid;
    +    margin: 0 5ex 1.5em 5ex;
    +    }
    +
    +    .Prototype td {
    +        font-size: 10pt;
    +        }
    +
    +    .PDefaultValue,
    +    .PDefaultValuePrefix,
    +    .PTypePrefix {
    +        color: #8F8F8F;
    +        }
    +    .PTypePrefix {
    +        text-align: right;
    +        }
    +    .PAfterParameters {
    +        vertical-align: bottom;
    +        }
    +
    +    .IE .Prototype table {
    +        padding: 0;
    +        }
    +
    +    .CFunction .Prototype {
    +        background-color: #F4F4F4; border-color: #D0D0D0 }
    +    .CProperty .Prototype {
    +        background-color: #F4F4FF; border-color: #C0C0E8 }
    +    .CVariable .Prototype {
    +        background-color: #FFFFF0; border-color: #E0E0A0 }
    +
    +    .CClass .Prototype {
    +        border-width: 1px 2px 2px 1px; border-style: solid; border-color: #A0A0A0;
    +        background-color: #F4F4F4;
    +        }
    +    .CInterface .Prototype {
    +        border-width: 1px 2px 2px 1px; border-style: solid; border-color: #A0A0D0;
    +        background-color: #F4F4FF;
    +        }
    +
    +    .CDatabaseIndex .Prototype,
    +    .CConstant .Prototype {
    +        background-color: #D0D0D0; border-color: #000000 }
    +    .CType .Prototype,
    +    .CEnumeration .Prototype {
    +        background-color: #FAF0F0; border-color: #E0B0B0;
    +        }
    +    .CDatabaseTrigger .Prototype,
    +    .CEvent .Prototype,
    +    .CDelegate .Prototype {
    +        background-color: #F0FCF0; border-color: #B8E4B8 }
    +
    +    .CToolTip .Prototype {
    +        margin: 0 0 .5em 0;
    +        white-space: nowrap;
    +        }
    +
    +
    +
    +
    +
    +.Summary {
    +    margin: 1.5em 5ex 0 5ex }
    +
    +    .STitle {
    +        font-size: 12pt; font-weight: bold;
    +        margin-bottom: .5em }
    +
    +
    +    .SBorder {
    +        background-color: #FFFFF0;
    +        padding: 15px;
    +        border: 1px solid #C0C060 }
    +
    +    /* In a frame IE 6 will make them too long unless you set the width to 100%.  Without frames it will be correct without a width
    +        or slightly too long (but not enough to scroll) with a width.  This arbitrary weirdness simply astounds me.  IE 7 has the same
    +        problem with frames, haven't tested it without.  */
    +    .FramedContentPage .IE .SBorder {
    +        width: 100% }
    +
    +    /*  A treat for Mozilla users.  Blatantly non-standard.  Will be replaced with CSS 3 attributes when finalized/supported.  */
    +    .Firefox .SBorder {
    +        -moz-border-radius: 20px }
    +
    +
    +    .STable {
    +        font-size: 9pt; width: 100% }
    +
    +    .SEntry {
    +        width: 30% }
    +    .SDescription {
    +        width: 70% }
    +
    +
    +    .SMarked {
    +        background-color: #F8F8D8 }
    +
    +    .SDescription { padding-left: 2ex }
    +    .SIndent1 .SEntry { padding-left: 1.5ex }   .SIndent1 .SDescription { padding-left: 3.5ex }
    +    .SIndent2 .SEntry { padding-left: 3.0ex }   .SIndent2 .SDescription { padding-left: 5.0ex }
    +    .SIndent3 .SEntry { padding-left: 4.5ex }   .SIndent3 .SDescription { padding-left: 6.5ex }
    +    .SIndent4 .SEntry { padding-left: 6.0ex }   .SIndent4 .SDescription { padding-left: 8.0ex }
    +    .SIndent5 .SEntry { padding-left: 7.5ex }   .SIndent5 .SDescription { padding-left: 9.5ex }
    +
    +    .SDescription a { color: #800000}
    +    .SDescription a:active { color: #A00000 }
    +
    +    .SGroup td {
    +        padding-top: .5em; padding-bottom: .25em }
    +
    +    .SGroup .SEntry {
    +        font-weight: bold; font-variant: small-caps }
    +
    +    .SGroup .SEntry a { color: #800000 }
    +    .SGroup .SEntry a:active { color: #F00000 }
    +
    +
    +    .SMain td,
    +    .SClass td,
    +    .SDatabase td,
    +    .SDatabaseTable td,
    +    .SSection td {
    +        font-size: 10pt;
    +        padding-bottom: .25em }
    +
    +    .SClass td,
    +    .SDatabase td,
    +    .SDatabaseTable td,
    +    .SSection td {
    +        padding-top: 1em }
    +
    +    .SMain .SEntry,
    +    .SClass .SEntry,
    +    .SDatabase .SEntry,
    +    .SDatabaseTable .SEntry,
    +    .SSection .SEntry {
    +        font-weight: bold;
    +        }
    +
    +    .SMain .SEntry a,
    +    .SClass .SEntry a,
    +    .SDatabase .SEntry a,
    +    .SDatabaseTable .SEntry a,
    +    .SSection .SEntry a { color: #000000 }
    +
    +    .SMain .SEntry a:active,
    +    .SClass .SEntry a:active,
    +    .SDatabase .SEntry a:active,
    +    .SDatabaseTable .SEntry a:active,
    +    .SSection .SEntry a:active { color: #A00000 }
    +
    +
    +
    +
    +
    +.ClassHierarchy {
    +    margin: 0 15px 1em 15px }
    +
    +    .CHEntry {
    +        border-width: 1px 2px 2px 1px; border-style: solid; border-color: #A0A0A0;
    +        margin-bottom: 3px;
    +        padding: 2px 2ex;
    +        font-size: 10pt;
    +        background-color: #F4F4F4; color: #606060;
    +        }
    +
    +    .Firefox .CHEntry {
    +        -moz-border-radius: 4px;
    +        }
    +
    +    .CHCurrent .CHEntry {
    +        font-weight: bold;
    +        border-color: #000000;
    +        color: #000000;
    +        }
    +
    +    .CHChildNote .CHEntry {
    +        font-style: italic;
    +        font-size: 8pt;
    +        }
    +
    +    .CHIndent {
    +        margin-left: 3ex;
    +        }
    +
    +    .CHEntry a:link,
    +    .CHEntry a:visited,
    +    .CHEntry a:hover {
    +        color: #606060;
    +        }
    +    .CHEntry a:active {
    +        color: #800000;
    +        }
    +
    +
    +
    +
    +
    +#Index {
    +    background-color: #FFFFFF;
    +    }
    +
    +/*  As opposed to .PopupSearchResultsPage #Index  */
    +.IndexPage #Index,
    +.FramedIndexPage #Index,
    +.FramedSearchResultsPage #Index {
    +    padding: 15px;
    +    }
    +
    +.IndexPage #Index {
    +    border-width: 0 0 1px 1px;
    +    border-style: solid;
    +    border-color: #000000;
    +    font-size: 9pt;  /* To make 27ex match the menu's 27ex. */
    +    margin-left: 27ex;
    +    }
    +
    +
    +    .IPageTitle {
    +        font-size: 20pt; font-weight: bold;
    +        color: #FFFFFF; background-color: #7070C0;
    +        padding: 10px 15px 10px 15px;
    +        border-width: 0 0 3px 0; border-color: #000000; border-style: solid;
    +        margin: -15px -15px 0 -15px }
    +
    +    .FramedSearchResultsPage .IPageTitle {
    +        margin-bottom: 15px;
    +        }
    +
    +    .INavigationBar {
    +        font-size: 10pt;
    +        text-align: center;
    +        background-color: #FFFFF0;
    +        padding: 5px;
    +        border-bottom: solid 1px black;
    +        margin: 0 -15px 15px -15px;
    +        }
    +
    +    .INavigationBar a {
    +        font-weight: bold }
    +
    +    .IHeading {
    +        font-size: 16pt; font-weight: bold;
    +        padding: 2.5em 0 .5em 0;
    +        text-align: center;
    +        width: 3.5ex;
    +        }
    +    #IFirstHeading {
    +        padding-top: 0;
    +        }
    +
    +    .IEntry {
    +        font-size: 10pt;
    +        padding-left: 1ex;
    +        }
    +    .PopupSearchResultsPage .IEntry {
    +        font-size: 8pt;
    +        padding: 1px 5px;
    +        }
    +    .PopupSearchResultsPage .Opera9 .IEntry,
    +    .FramedSearchResultsPage .Opera9 .IEntry {
    +        text-align: left;
    +        }
    +    .FramedSearchResultsPage .IEntry {
    +        padding: 0;
    +        }
    +
    +    .ISubIndex {
    +        padding-left: 3ex; padding-bottom: .5em }
    +    .PopupSearchResultsPage .ISubIndex {
    +        display: none;
    +        }
    +
    +    /*  While it may cause some entries to look like links when they aren't, I found it's much easier to read the
    +         index if everything's the same color.  */
    +    .ISymbol {
    +        font-weight: bold; color: #900000  }
    +
    +    .IndexPage .ISymbolPrefix,
    +    .FramedIndexPage .ISymbolPrefix {
    +        font-size: 10pt;
    +        text-align: right;
    +        color: #C47C7C;
    +        background-color: #F8F8F8;
    +        border-right: 3px solid #E0E0E0;
    +        border-left: 1px solid #E0E0E0;
    +        padding: 0 1px 0 2px;
    +        }
    +    .PopupSearchResultsPage .ISymbolPrefix,
    +    .FramedSearchResultsPage .ISymbolPrefix {
    +        color: #900000;
    +        }
    +    .PopupSearchResultsPage .ISymbolPrefix {
    +        font-size: 8pt;
    +        }
    +
    +    .IndexPage #IFirstSymbolPrefix,
    +    .FramedIndexPage #IFirstSymbolPrefix {
    +        border-top: 1px solid #E0E0E0;
    +        }
    +    .IndexPage #ILastSymbolPrefix,
    +    .FramedIndexPage #ILastSymbolPrefix {
    +        border-bottom: 1px solid #E0E0E0;
    +        }
    +    .IndexPage #IOnlySymbolPrefix,
    +    .FramedIndexPage #IOnlySymbolPrefix {
    +        border-top: 1px solid #E0E0E0;
    +        border-bottom: 1px solid #E0E0E0;
    +        }
    +
    +    a.IParent,
    +    a.IFile {
    +        display: block;
    +        }
    +
    +    .PopupSearchResultsPage .SRStatus {
    +        padding: 2px 5px;
    +        font-size: 8pt;
    +        font-style: italic;
    +        }
    +    .FramedSearchResultsPage .SRStatus {
    +        font-size: 10pt;
    +        font-style: italic;
    +        }
    +
    +    .SRResult {
    +        display: none;
    +        }
    +
    +
    +
    +#Footer {
    +    font-size: 8pt;
    +    color: #989898;
    +    text-align: right;
    +    }
    +
    +#Footer p {
    +    text-indent: 0;
    +    margin-bottom: .5em;
    +    }
    +
    +.ContentPage #Footer,
    +.IndexPage #Footer {
    +    text-align: right;
    +    margin: 2px;
    +    }
    +
    +.FramedMenuPage #Footer {
    +    text-align: center;
    +    margin: 5em 10px 10px 10px;
    +    padding-top: 1em;
    +    border-top: 1px solid #C8C8C8;
    +    }
    +
    +    #Footer a:link,
    +    #Footer a:hover,
    +    #Footer a:visited { color: #989898 }
    +    #Footer a:active { color: #A00000 }
    +
    +
    +
    +.prettyprint .kwd { color: #800000; }  /* keywords */
    +
    +    .prettyprint.PDefaultValue .kwd,
    +    .prettyprint.PDefaultValuePrefix .kwd,
    +    .prettyprint.PTypePrefix .kwd {
    +        color: #C88F8F;
    +        }
    +
    +.prettyprint .com { color: #008000; }  /* comments */
    +
    +    .prettyprint.PDefaultValue .com,
    +    .prettyprint.PDefaultValuePrefix .com,
    +    .prettyprint.PTypePrefix .com {
    +        color: #8FC88F;
    +        }
    +
    +.prettyprint .str { color: #0000B0; }  /* strings */
    +.prettyprint .lit { color: #0000B0; }  /* literals */
    +
    +    .prettyprint.PDefaultValue .str,
    +    .prettyprint.PDefaultValuePrefix .str,
    +    .prettyprint.PTypePrefix .str,
    +    .prettyprint.PDefaultValue .lit,
    +    .prettyprint.PDefaultValuePrefix .lit,
    +    .prettyprint.PTypePrefix .lit {
    +        color: #8F8FC0;
    +        }
    +
    +.prettyprint .typ { color: #000000; }  /* types */
    +.prettyprint .pun { color: #000000; }  /* punctuation */
    +.prettyprint .pln { color: #000000; }  /* punctuation */
    +
    +    .prettyprint.PDefaultValue .typ,
    +    .prettyprint.PDefaultValuePrefix .typ,
    +    .prettyprint.PTypePrefix .typ,
    +    .prettyprint.PDefaultValue .pun,
    +    .prettyprint.PDefaultValuePrefix .pun,
    +    .prettyprint.PTypePrefix .pun,
    +    .prettyprint.PDefaultValue .pln,
    +    .prettyprint.PDefaultValuePrefix .pln,
    +    .prettyprint.PTypePrefix .pln {
    +        color: #8F8F8F;
    +        }
    +
    +.prettyprint .tag { color: #008; }
    +.prettyprint .atn { color: #606; }
    +.prettyprint .atv { color: #080; }
    +.prettyprint .dec { color: #606; }
    +
    diff --git a/README.md b/README.md
    index c82e17f2..8c004770 100644
    --- a/README.md
    +++ b/README.md
    @@ -16,6 +16,9 @@ http://www.pushwoosh.com/programming-push-notification/android/android-additiona
     ####WP8:
     http://www.pushwoosh.com/programming-push-notification/windows-phone/wp-additional-platforms/windows-phone-cordova-sdk-integration-guide/
     
    +###Plugin documentation:  
    +https://rawgit.com/Pushwoosh/pushwoosh-phonegap-3.0-plugin/master/Documentation/files/PushNotification-js.html
    +
     ## Acknowledgments
     Plugman support by Platogo
     
    diff --git a/VERSION.md b/VERSION.md
    new file mode 100644
    index 00000000..31f49113
    --- /dev/null
    +++ b/VERSION.md
    @@ -0,0 +1,76 @@
    +Current version: 3.6.16
    +=========================
    +Add armv7s arch for iOS
    +Current version: 3.6.15
    +=========================
    +Fixed https://github.com/Pushwoosh/pushwoosh-ios-sdk/issues/25
    +Current version: 3.6.14
    +=========================
    +Fixed double alerts on iOS9
    +Current version: 3.6.13
    +=========================
    +Fixed https://github.com/Pushwoosh/pushwoosh-phonegap-3.0-plugin/issues/133
    +Current version: 3.6.12
    +=========================
    +Fixed https://github.com/Pushwoosh/pushwoosh-phonegap-3.0-plugin/issues/132
    +Current version: 3.6.11
    +=========================
    +Application icon badge number for Android
    +Current version: 3.6.10
    +=========================
    +Actual fixes for 3.6.8 and 3.6.9
    +Current version: 3.6.9
    +=========================
    +fixed https://github.com/Pushwoosh/pushwoosh-phonegap-3.0-plugin/issues/129
    +Current version: 3.6.8
    +=========================
    +Fixed XCode 7 warnings
    +iOS log level management
    +Current version: 3.6.7
    +=========================
    +Remote notification tag identifier for Android
    +Current version: 3.6.6
    +=========================
    +iOS 9 support
    +Current version: 3.6.5
    +=========================
    +Fixed plugin incompatibility
    +Current version: 3.6.4
    +=========================
    +Pushwoosh library update
    +Current version: 3.6.3
    +=========================
    +Using Google Play Services and Android Support v4 libraries
    +Current version: 3.6.2
    +=========================
    +plugin.xml update
    +Current version: 3.6.1
    +=========================
    +Pushwoosh SDK update
    +Current version: 3.6.0
    +=========================
    +Android push priority, visibility and badges support
    +Current version: 3.5.9
    +=========================
    +Updated to latest SDK
    +Current version: 3.5.8
    +=========================
    +fix: https://github.com/Pushwoosh/pushwoosh-phonegap-3.0-plugin/issues/110
    +Current version: 3.5.7
    +=========================
    +PW_NO_BROADCAST_PUSH Android Manifest flag
    +Code style fixes
    +Current version: 3.5.6
    +=========================
    +Publishing to NPM activated.
    +Current version: 3.5.5
    +=========================
    +publishing to npm
    +Current version: 3.5.4
    +=========================
    +getLaunchNotification method implemented (iOS, Android)
    +Current version: 3.5.3
    +=========================
    +Updated iOS/Android SDK
    +Current version: 3.5.2
    +=========================
    diff --git a/package.json b/package.json
    new file mode 100644
    index 00000000..0d02dc06
    --- /dev/null
    +++ b/package.json
    @@ -0,0 +1,29 @@
    +{
    +  "name": "pushwoosh-cordova-plugin",
    +  "version": "3.6.16",
    +  "description": "\n    This plugin allows you to send and receive push notifications. Powered by Pushwoosh (www.pushwoosh.com).\n    ",
    +  "cordova": {
    +    "id": "com.pushwoosh.plugins.pushwoosh",
    +    "platforms": [
    +      "android",
    +      "ios",
    +      "wp8"
    +    ]
    +  },
    +  "repository": {
    +    "type": "git",
    +    "url": "git+https://github.com/Pushwoosh/pushwoosh-phonegap-3.0-plugin.git"
    +  },
    +  "keywords": [
    +    "ecosystem:cordova",
    +    "cordova-android",
    +    "cordova-ios",
    +    "cordova-wp8"
    +  ],
    +  "author": "Pushwoosh",
    +  "license": "MIT",
    +  "bugs": {
    +    "url": "https://github.com/Pushwoosh/pushwoosh-phonegap-3.0-plugin/issues"
    +  },
    +  "homepage": "https://github.com/Pushwoosh/pushwoosh-phonegap-3.0-plugin#readme"
    +}
    diff --git a/plugin.xml b/plugin.xml
    index 32abd0f1..f94e2d26 100644
    --- a/plugin.xml
    +++ b/plugin.xml
    @@ -1,166 +1,181 @@
     <?xml version="1.0" encoding="UTF-8"?>
     <plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android"
    -    id="com.pushwoosh.plugins.pushwoosh"
    -    version="3.4.13">
    -
    -    <name>Pushwoosh</name>
    -
    -    <description>
    -    This plugin allows you to send and receive push notifications. Powered by Pushwoosh (www.pushwoosh.com).
    -    </description>
    -
    -    <!-- <engines>
    -        <engine name="cordova" version=">=3.1.0" />
    -    </engines> -->
    -
    -    <license>MIT</license>
    -
    -    <js-module src="www/PushNotification.js" name="PushNotification">
    -          <clobbers target="plugins.pushNotification" />
    -      </js-module>
    -
    -      <!-- android -->
    -    <platform name="android">
    -
    -      <config-file>
    -        <access origin="*.pushwoosh.com" />
    -      </config-file>
    -
    -      <config-file target="AndroidManifest.xml" parent="/manifest">
    -        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    -
    -        <uses-permission android:name="android.permission.VIBRATE" />
    -
    -        <!-- GCM connects to Google Services. -->
    -        <uses-permission android:name="android.permission.INTERNET"/>
    -
    -        <!-- Keeps the processor from sleeping when a message is received. -->
    -        <uses-permission android:name="android.permission.WAKE_LOCK"/>
    -
    -        <!-- So the sounds from assets folder could work for notification sounds. -->
    -        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    -
    -        <!--
    -         Creates a custom permission so only this app can receive its messages.
    -
    -         NOTE: the permission *must* be called PACKAGE.permission.C2D_MESSAGE,
    -         where PACKAGE is the application's package name.
    -         -->
    -        <permission
    -        android:name="$PACKAGE_NAME.permission.C2D_MESSAGE"
    -        android:protectionLevel="signature"/>
    -        <uses-permission
    -        android:name="$PACKAGE_NAME.permission.C2D_MESSAGE"/>
    -
    -        <!-- This app has permission to register and receive data message. -->
    -        <uses-permission
    -        android:name="com.google.android.c2dm.permission.RECEIVE"/>
    -      </config-file>
    -
    -      <config-file target="AndroidManifest.xml" parent="/manifest/application/activity">
    -        <intent-filter>
    -          <action android:name="$PACKAGE_NAME.MESSAGE"/>
    -          <category android:name="android.intent.category.DEFAULT"/>
    -        </intent-filter>
    -      </config-file>
    -
    -      <config-file target="AndroidManifest.xml" parent="/manifest/application">
    -        <activity android:name="com.arellomobile.android.push.PushWebview"/>
    -
    -        <activity android:name="com.arellomobile.android.push.MessageActivity"/>
    -
    -        <activity android:name="com.arellomobile.android.push.PushHandlerActivity"/>
    -
    -        <activity android:label="@string/app_name" android:name="com.facebook.LoginActivity"/>
    -
    -        <!--
    -         BroadcastReceiver that will receive intents from GCM
    -         services and handle them to the custom IntentService.
    -
    -         The com.google.android.c2dm.permission.SEND permission is necessary
    -         so only GCM services can send data messages for the app.
    -         -->
    -        <receiver
    -          android:name="com.google.android.gcm.GCMBroadcastReceiver"
    -          android:permission="com.google.android.c2dm.permission.SEND">
    -          <intent-filter>
    -            <!-- Receives the actual messages. -->
    -            <action android:name="com.google.android.c2dm.intent.RECEIVE"/>
    -            <!-- Receives the registration id. -->
    -            <action android:name="com.google.android.c2dm.intent.REGISTRATION"/>
    -            <category android:name="$PACKAGE_NAME"/>
    -          </intent-filter>
    -        </receiver>
    -
    -        <!--
    -         Application-specific subclass of PushGCMIntentService that will
    -         handle received messages.
    -         -->
    -        <service android:name="com.arellomobile.android.push.PushGCMIntentService"/>
    -
    -            <!--
    -              Service for sending location updates
    -            -->
    -            <service android:name="com.arellomobile.android.push.GeoLocationService"/>
    -
    -            <receiver android:name="com.arellomobile.android.push.AlarmReceiver"></receiver>
    -
    -      </config-file>
    -
    -      <config-file target="res/xml/config.xml" parent="/*">
    -        <feature name="PushNotification">
    -          <param name="android-package" value="com.pushwoosh.plugin.pushnotifications.PushNotifications" onload="true" />
    -        </feature>
    -      </config-file>
    -
    -      <source-file src="src/android/src/com/pushwoosh/plugin/pushnotifications/PushNotifications.java"
    -              target-dir="src/com/pushwoosh/plugin/pushnotifications" />
    -
    -      <source-file src="src/android/lib/Pushwoosh.jar" target-dir="libs" />
    -    </platform>
    -
    -    <!-- ios -->
    -    <platform name="ios">
    -      <framework src="Security.framework" />
    -      <framework src="Storekit.framework" />
    -      <framework src="CoreLocation.framework" />
    -      <framework src="src/ios/Pushwoosh.framework" custom="true" />
    -      <config-file target="config.xml" parent="/*">
    -        <feature name="PushNotification">
    -          <param name="ios-package" value="PushNotification"/>
    -        </feature>
    -      </config-file>
    -
    -      <config-file>
    -        <access origin="*.pushwoosh.com" />
    -      </config-file>
    -
    -      <header-file src="src/ios/PushNotification.h" target-dir="ios"/>
    -      <source-file src="src/ios/PushNotification.m" target-dir="ios"/>
    -    </platform>
    -
    -  <!-- wp8 -->
    -  <platform name="wp8">
    -
    -    <config-file target="config.xml" parent="/*">
    -      <feature name="PushNotification">
    -        <param name="wp-package" value="PushNotification"/>
    -      </feature>
    -    </config-file>
    -
    -    <config-file>
    -      <access origin="*.pushwoosh.com" />
    -    </config-file>
    -
    -    <config-file target="Properties/WMAppManifest.xml" parent="/Deployment/App/Capabilities">
    -      <Capability Name="ID_CAP_PUSH_NOTIFICATION"/>
    -      <Capability Name="ID_CAP_IDENTITY_DEVICE"/>
    -      <Capability Name="ID_CAP_LOCATION"/>
    -    </config-file>
    -
    -    <source-file src="src/wp8/PushNotification.cs" />
    -
    -    <framework src="src/wp8/PushSDK/Newtonsoft.Json.dll" custom="true" />
    -    <framework src="src/wp8/PushSDK/PushSDK.dll" custom="true" />
    -  </platform>
    +		id="com.pushwoosh.plugins.pushwoosh"
    +    version="3.6.16">
    +
    +		<name>Pushwoosh</name>
    +
    +		<description>
    +		This plugin allows you to send and receive push notifications. Powered by Pushwoosh (www.pushwoosh.com).
    +		</description>
    +
    +		<!-- <engines>
    +				<engine name="cordova" version=">=3.1.0" />
    +		</engines> -->
    +
    +		<license>MIT</license>
    +
    +		<js-module src="www/PushNotification.js" name="PushNotification">
    +					<clobbers target="plugins.pushNotification" />
    +			</js-module>
    +
    +			<!-- android -->
    +		<platform name="android">
    +			<config-file>
    +				<access origin="*.pushwoosh.com" />
    +			</config-file>
    +
    +			<config-file target="AndroidManifest.xml" parent="/manifest">
    +				<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    +
    +				<uses-permission android:name="android.permission.VIBRATE" />
    +
    +				<!-- GCM connects to Google Services. -->
    +				<uses-permission android:name="android.permission.INTERNET"/>
    +
    +				<!-- Keeps the processor from sleeping when a message is received. -->
    +				<uses-permission android:name="android.permission.WAKE_LOCK"/>
    +
    +				<!-- So the sounds from assets folder could work for notification sounds. -->
    +				<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    +
    +				<!--
    +				 Creates a custom permission so only this app can receive its messages.
    +
    +				 NOTE: the permission *must* be called PACKAGE.permission.C2D_MESSAGE,
    +				 where PACKAGE is the application's package name.
    +				 -->
    +				<permission
    +				android:name="$PACKAGE_NAME.permission.C2D_MESSAGE"
    +				android:protectionLevel="signature"/>
    +				<uses-permission
    +				android:name="$PACKAGE_NAME.permission.C2D_MESSAGE"/>
    +
    +				<!-- This app has permission to register and receive data message. -->
    +				<uses-permission
    +				android:name="com.google.android.c2dm.permission.RECEIVE"/>
    +
    +				<!-- <badges> -->
    +					 <!--for Samsung-->
    +				    <uses-permission android:name="com.sec.android.provider.badge.permission.READ"/>
    +				    <uses-permission android:name="com.sec.android.provider.badge.permission.WRITE"/>
    +
    +				    <!--for htc-->
    +				    <uses-permission android:name="com.htc.launcher.permission.READ_SETTINGS"/>
    +				    <uses-permission android:name="com.htc.launcher.permission.UPDATE_SHORTCUT"/>
    +
    +				    <!--for sony-->
    +				    <uses-permission android:name="com.sonyericsson.home.permission.BROADCAST_BADGE"/>
    +
    +				    <!--for apex-->
    +				    <uses-permission android:name="com.anddoes.launcher.permission.UPDATE_COUNT"/>
    +
    +				    <!--for solid-->
    +				    <uses-permission android:name="com.majeur.launcher.permission.UPDATE_BADGE"/>
    +			    <!-- </badges> -->
    +			</config-file>
    +
    +			<config-file target="AndroidManifest.xml" parent="/manifest/application">
    +
    +				<!-- Push notification services -->
    +				<activity android:name="com.pushwoosh.MessageActivity" />
    +				<activity android:name="com.pushwoosh.PushHandlerActivity" />
    +
    +				<receiver android:name="com.google.android.gms.gcm.GcmReceiver" android:exported="true" android:permission="com.google.android.c2dm.permission.SEND">
    +					<intent-filter>
    +						<action android:name="com.google.android.c2dm.intent.RECEIVE" />
    +						<category android:name="PACKAGE_NAME" />
    +					</intent-filter>
    +				</receiver>
    +				<service android:name="com.pushwoosh.GCMListenerService" android:exported="false">
    +					<intent-filter>
    +						<action android:name="com.google.android.c2dm.intent.RECEIVE" />
    +					</intent-filter>
    +				</service>
    +				<service android:name="com.pushwoosh.GCMInstanceIDListenerService" android:exported="false">
    +					<intent-filter>
    +						<action android:name="com.google.android.gms.iid.InstanceID" />
    +					</intent-filter>
    +				</service>
    +				<service android:name="com.pushwoosh.GCMRegistrationService" android:exported="false"></service>
    +
    +				<!-- Local notification services -->
    +				<receiver android:name="com.pushwoosh.local.BootReceiver" android:permission="android.permission.RECEIVE_BOOT_COMPLETED" android:enabled="true">
    +					<intent-filter>
    +							<action android:name="android.intent.action.BOOT_COMPLETED" />
    +							<category android:name="android.intent.category.DEFAULT" />
    +					</intent-filter>
    +				</receiver>
    +
    +				<receiver android:name="com.pushwoosh.local.AlarmReceiver" />
    +
    +				<!-- Rich page activity -->
    +				<activity android:name="com.pushwoosh.richpages.RichPageActivity"/>
    +
    +				<!-- Service for sending location updates -->
    +				<service android:name="com.pushwoosh.location.GeoLocationService" />
    +
    +			</config-file>
    +
    +			<config-file target="res/xml/config.xml" parent="/*">
    +				<feature name="PushNotification">
    +					<param name="android-package" value="com.pushwoosh.plugin.pushnotifications.PushNotifications" onload="true" />
    +				</feature>
    +			</config-file>
    +
    +			<source-file src="src/android/src/com/pushwoosh/plugin/pushnotifications/PushNotifications.java"
    +							target-dir="src/com/pushwoosh/plugin/pushnotifications" />
    +
    +			<source-file src="src/android/lib/Pushwoosh.jar" target-dir="libs" />
    +			<framework src="com.google.android.gms:play-services-gcm:+" />
    +			<framework src="com.android.support:support-v4:+" />
    +		</platform>
    +
    +		<!-- ios -->
    +		<platform name="ios">
    +			<framework src="Security.framework" />
    +			<framework src="Storekit.framework" />
    +			<framework src="CoreLocation.framework" />
    +			<framework src="libstdc++.dylib"/>
    +			<framework src="libz.dylib"/>
    +			<config-file target="config.xml" parent="/*">
    +				<feature name="PushNotification">
    +					<param name="ios-package" value="PushNotification"/>
    +				</feature>
    +			</config-file>
    +
    +			<config-file>
    +				<access origin="*.pushwoosh.com" />
    +			</config-file>
    +
    +			<header-file src="src/ios/PushNotification.h" target-dir="ios"/>
    +			<source-file src="src/ios/PushNotification.m" target-dir="ios"/>
    +			<header-file src="src/ios/Pushwoosh.framework/Versions/A/Headers/PushNotificationManager.h" target-dir="ios"/>
    +			<source-file src="src/ios/Pushwoosh.framework/Versions/A/Pushwoosh" framework="true"/>
    +		</platform>
    +
    +	<!-- wp8 -->
    +	<platform name="wp8">
    +
    +		<config-file target="config.xml" parent="/*">
    +			<feature name="PushNotification">
    +				<param name="wp-package" value="PushNotification"/>
    +			</feature>
    +		</config-file>
    +
    +		<config-file>
    +			<access origin="*.pushwoosh.com" />
    +		</config-file>
    +
    +		<config-file target="Properties/WMAppManifest.xml" parent="/Deployment/App/Capabilities">
    +			<Capability Name="ID_CAP_PUSH_NOTIFICATION"/>
    +			<Capability Name="ID_CAP_IDENTITY_DEVICE"/>
    +			<Capability Name="ID_CAP_LOCATION"/>
    +		</config-file>
    +
    +		<source-file src="src/wp8/PushNotification.cs" />
    +
    +		<framework src="src/wp8/PushSDK/Newtonsoft.Json.dll" custom="true" />
    +		<framework src="src/wp8/PushSDK/PushSDK.dll" custom="true" />
    +	</platform>
     </plugin>
    diff --git a/src/android/lib/Pushwoosh.jar b/src/android/lib/Pushwoosh.jar
    index 53c9ffcc..a43238ce 100644
    Binary files a/src/android/lib/Pushwoosh.jar and b/src/android/lib/Pushwoosh.jar differ
    diff --git a/src/android/src/com/pushwoosh/plugin/pushnotifications/PushNotifications.java b/src/android/src/com/pushwoosh/plugin/pushnotifications/PushNotifications.java
    index 9a2bb15f..c8ecd93d 100644
    --- a/src/android/src/com/pushwoosh/plugin/pushnotifications/PushNotifications.java
    +++ b/src/android/src/com/pushwoosh/plugin/pushnotifications/PushNotifications.java
    @@ -1,5 +1,5 @@
     //
    -//  PushNotifications.java
    +// PushNotifications.java
     //
     // Pushwoosh, 01/07/12.
     //
    @@ -22,18 +22,17 @@
     import android.location.Location;
     import android.os.Bundle;
     import android.util.Log;
    -
    -import com.arellomobile.android.push.BasePushMessageReceiver;
    -import com.arellomobile.android.push.PushManager;
    -import com.arellomobile.android.push.PushPersistance;
    -import com.arellomobile.android.push.PushManager.GetTagsListener;
    -import com.arellomobile.android.push.SendPushTagsCallBack;
    -import com.arellomobile.android.push.preference.SoundType;
    -import com.arellomobile.android.push.preference.VibrateType;
    -import com.arellomobile.android.push.utils.PreferenceUtils;
    -import com.arellomobile.android.push.utils.RegisterBroadcastReceiver;
    -import com.arellomobile.android.push.utils.rich.RichPushUtils;
    -import com.google.android.gcm.GCMRegistrar;
    +import android.content.pm.ApplicationInfo;
    +import android.content.pm.PackageManager;
    +
    +import com.pushwoosh.PushManager;
    +import com.pushwoosh.notification.SoundType;
    +import com.pushwoosh.notification.VibrateType;
    +import com.pushwoosh.PushManager.GetTagsListener;
    +import com.pushwoosh.BasePushMessageReceiver;
    +import com.pushwoosh.BaseRegistrationReceiver;
    +import com.pushwoosh.SendPushTagsCallBack;
    +import com.pushwoosh.internal.utils.GeneralUtils;
     
     import org.apache.cordova.CallbackContext;
     import org.apache.cordova.CordovaPlugin;
    @@ -53,20 +52,23 @@ public class PushNotifications extends CordovaPlugin
     	public static final String START_BEACON_PUSHES = "startBeaconPushes";
     	public static final String STOP_BEACON_PUSHES = "stopBeaconPushes";
     	public static final String SET_BEACON_BACKGROUND_MODE = "setBeaconBackgroundMode";
    -	public static final String SEND_LOCATION = "sendLocation";
     	public static final String CREATE_LOCAL_NOTIFICATION = "createLocalNotification";
     	public static final String CLEAR_LOCAL_NOTIFICATION = "clearLocalNotification";
     	public static final String GET_TAGS = "getTags";
     	public static final String ON_DEVICE_READY = "onDeviceReady";
     	public static final String GET_PUSH_TOKEN = "getPushToken";
     	public static final String GET_HWID = "getPushwooshHWID";
    +	public static final String GET_LAUNCH_NOTIFICATION = "getLaunchNotification";
     
     	boolean receiversRegistered = false;
    -	boolean deviceReady = false;
    +	boolean broadcastPush = true;
    +	JSONObject startPushData = null;
     
     	HashMap<String, CallbackContext> callbackIds = new HashMap<String, CallbackContext>();
     	PushManager mPushManager = null;
     
    +	private String TAG = "PWCordovaPlugin";
    +
     	/**
     	 * Called when the activity receives a new intent.
     	 */
    @@ -74,10 +76,11 @@ public void onNewIntent(Intent intent)
     	{
     		super.onNewIntent(intent);
     
    +		startPushData = getPushFromIntent(intent);
     		checkMessage(intent);
     	}
     
    -	BroadcastReceiver mBroadcastReceiver = new RegisterBroadcastReceiver()
    +	BroadcastReceiver mBroadcastReceiver = new BaseRegistrationReceiver()
     	{
     		@Override
     		public void onRegisterActionReceive(Context context, Intent intent)
    @@ -95,7 +98,8 @@ public void registerReceivers()
     		IntentFilter intentFilter = new IntentFilter(cordova.getActivity().getPackageName() + ".action.PUSH_MESSAGE_RECEIVE");
     
     		//comment this code out if you would like to receive the notifications in the notifications center when the app is in foreground
    -		cordova.getActivity().registerReceiver(mReceiver, intentFilter);
    +		if (broadcastPush)
    +			cordova.getActivity().registerReceiver(mReceiver, intentFilter);
     
     		//registration receiver
     		cordova.getActivity().registerReceiver(mBroadcastReceiver, new IntentFilter(cordova.getActivity().getPackageName() + "." + PushManager.REGISTER_BROAD_CAST_ACTION));
    @@ -161,11 +165,32 @@ private void initialize(JSONArray data, CallbackContext callbackContext)
     		catch (JSONException e)
     		{
     			e.printStackTrace();
    +			Log.e(TAG, "No parameters has been passed to onDeviceReady function. Did you follow the guide correctly?");
     			return;
     		}
     
     		try
     		{
    +			String packageName = cordova.getActivity().getApplicationContext().getPackageName();
    +			ApplicationInfo ai = cordova.getActivity().getPackageManager().getApplicationInfo(packageName, PackageManager.GET_META_DATA);
    +			
    +			if (ai.metaData != null && ai.metaData.containsKey("PW_NO_BROADCAST_PUSH"))
    +				broadcastPush = !(ai.metaData.getBoolean("PW_NO_BROADCAST_PUSH"));
    +
    +			Log.d(TAG, "broadcastPush = " + broadcastPush);
    +		}
    +		catch (Exception e)
    +		{
    +			e.printStackTrace();
    +		}
    +
    +		try
    +		{
    +			//make sure the receivers are on
    +			registerReceivers();
    +
    +			startPushData = getPushFromIntent(cordova.getActivity().getIntent());
    +
     			String appid = null;
     			if (params.has("appid"))
     				appid = params.getString("appid");
    @@ -179,6 +204,7 @@ private void initialize(JSONArray data, CallbackContext callbackContext)
     		catch (Exception e)
     		{
     			e.printStackTrace();
    +			Log.e("Pushwoosh", "Missing pw_appid parameter. Did you follow the guide correctly?");
     			return;
     		}
     	}
    @@ -194,6 +220,7 @@ private boolean internalRegister(JSONArray data, CallbackContext callbackContext
     		{
     			callbackIds.remove("registerDevice");
     			e.printStackTrace();
    +			Log.e("Pushwoosh", "registering for push notifications failed");
     
     			callbackContext.error(e.getMessage());
     			return true;
    @@ -203,6 +230,30 @@ private boolean internalRegister(JSONArray data, CallbackContext callbackContext
     		return true;
     	}
     
    +	private JSONObject getPushFromIntent(Intent intent)
    +	{
    +		if (null == intent)
    +			return null;
    +
    +		if (intent.hasExtra(PushManager.PUSH_RECEIVE_EVENT))
    +		{
    +			String pushString = intent.getExtras().getString(PushManager.PUSH_RECEIVE_EVENT);
    +			JSONObject pushObject = null;
    +			try
    +			{
    +				pushObject = new JSONObject(pushString);
    +			}
    +			catch (JSONException e)
    +			{
    +				e.printStackTrace();
    +			}
    +
    +			return pushObject;
    +		}
    +
    +		return null;
    +	}
    +
     	private void checkMessage(Intent intent)
     	{
     		if (null != intent)
    @@ -244,7 +295,7 @@ private boolean internalUnregister(JSONArray data, CallbackContext callbackConte
     
     		try
     		{
    -			GCMRegistrar.unregister(cordova.getActivity());
    +			mPushManager.unregisterForPushNotifications();
     		}
     		catch (Exception e)
     		{
    @@ -256,46 +307,6 @@ private boolean internalUnregister(JSONArray data, CallbackContext callbackConte
     		return true;
     	}
     
    -	private boolean internalSendLocation(JSONArray data, CallbackContext callbackContext)
    -	{
    -		if (mPushManager == null)
    -		{
    -			return false;
    -		}
    -
    -		JSONObject params = null;
    -		try
    -		{
    -			params = data.getJSONObject(0);
    -		}
    -		catch (JSONException e)
    -		{
    -			e.printStackTrace();
    -			return false;
    -		}
    -
    -		double lat = 0;
    -		double lon = 0;
    -
    -		try
    -		{
    -			lat = params.getDouble("lat");
    -			lon = params.getDouble("lon");
    -		}
    -		catch (JSONException e)
    -		{
    -			e.printStackTrace();
    -			return false;
    -		}
    -
    -		Location location = new Location("");
    -		location.setLatitude(lat);
    -		location.setLongitude(lon);
    -		PushManager.sendLocation(cordova.getActivity(), location);
    -
    -		return true;
    -	}
    -
     	private boolean internalSendTags(JSONArray data, final CallbackContext callbackContext)
     	{
     		JSONObject params;
    @@ -305,11 +316,13 @@ private boolean internalSendTags(JSONArray data, final CallbackContext callbackC
     		}
     		catch (JSONException e)
     		{
    +			Log.e("Pushwoosh", "No tags information passed (missing parameters)");
     			e.printStackTrace();
     			return false;
     		}
     
    -		@SuppressWarnings("unchecked") Iterator<String> nameItr = params.keys();
    +		@SuppressWarnings("unchecked")
    +		Iterator<String> nameItr = params.keys();
     		Map<String, Object> paramsMap = new HashMap<String, Object>();
     		while (nameItr.hasNext())
     		{
    @@ -320,6 +333,7 @@ private boolean internalSendTags(JSONArray data, final CallbackContext callbackC
     			}
     			catch (JSONException e)
     			{
    +				Log.e("Pushwoosh", "Tag parameter is invalid");
     				e.printStackTrace();
     				return false;
     			}
    @@ -352,9 +366,11 @@ public void onSentTagsError(Exception e)
     			}
     
     			@Override
    -			public void taskStarted() {}
    +			public void taskStarted()
    +			{
    +			}
     		}
    -		
    +
     		PushManager.sendTags(cordova.getActivity(), paramsMap, new SendTagsListenerImpl());
     		return true;
     	}
    @@ -362,10 +378,7 @@ public void taskStarted() {}
     	@Override
     	public boolean execute(String action, JSONArray data, CallbackContext callbackId)
     	{
    -		Log.d("PushNotifications", "Plugin Called");
    -
    -		//make sure the receivers are on
    -		registerReceivers();
    +		Log.d(TAG, "Plugin Method Called: " + action);
     
     		if (GET_PUSH_TOKEN.equals(action))
     		{
    @@ -383,7 +396,6 @@ public boolean execute(String action, JSONArray data, CallbackContext callbackId
     		{
     			initialize(data, callbackId);
     			checkMessage(cordova.getActivity().getIntent());
    -			deviceReady = true;
     			return true;
     		}
     
    @@ -402,11 +414,6 @@ public boolean execute(String action, JSONArray data, CallbackContext callbackId
     			return internalSendTags(data, callbackId);
     		}
     
    -		if (SEND_LOCATION.equals(action))
    -		{
    -			return internalSendLocation(data, callbackId);
    -		}
    -
     		if (START_GEO_PUSHES.equals(action) || START_LOCATION_TRACKING.equals(action))
     		{
     			if (mPushManager == null)
    @@ -459,6 +466,7 @@ public boolean execute(String action, JSONArray data, CallbackContext callbackId
     			}
     			catch (Exception e)
     			{
    +				Log.e(TAG, "No parameters passed (missing parameters)");
     				e.printStackTrace();
     				return false;
     			}
    @@ -475,6 +483,7 @@ public boolean execute(String action, JSONArray data, CallbackContext callbackId
     			}
     			catch (JSONException e)
     			{
    +				Log.e(TAG, "No parameters passed (missing parameters)");
     				e.printStackTrace();
     				return false;
     			}
    @@ -497,6 +506,7 @@ public boolean execute(String action, JSONArray data, CallbackContext callbackId
     			}
     			catch (JSONException e)
     			{
    +				Log.e(TAG, "Not correct parameters passed (missing parameters)");
     				e.printStackTrace();
     				return false;
     			}
    @@ -510,6 +520,20 @@ public boolean execute(String action, JSONArray data, CallbackContext callbackId
     			return true;
     		}
     
    +		if (GET_LAUNCH_NOTIFICATION.equals(action))
    +		{
    +			// unfortunately null object can only be returned as String
    +			if (startPushData != null)
    +			{
    +				callbackId.success(startPushData);
    +			}
    +			else
    +			{
    +				callbackId.success((String) null);
    +			}
    +			return true;
    +		}
    +
     		if ("setMultiNotificationMode".equals(action))
     		{
     			PushManager.setMultiNotificationMode(cordova.getActivity());
    @@ -534,6 +558,7 @@ public boolean execute(String action, JSONArray data, CallbackContext callbackId
     			}
     			catch (Exception e)
     			{
    +				Log.e(TAG, "No sound parameters passed (missing parameters)");
     				e.printStackTrace();
     				return false;
     			}
    @@ -553,6 +578,7 @@ public boolean execute(String action, JSONArray data, CallbackContext callbackId
     			}
     			catch (Exception e)
     			{
    +				Log.e(TAG, "No vibration parameters passed (missing parameters)");
     				e.printStackTrace();
     				return false;
     			}
    @@ -570,6 +596,7 @@ public boolean execute(String action, JSONArray data, CallbackContext callbackId
     			catch (Exception e)
     			{
     				e.printStackTrace();
    +				Log.e(TAG, "No parameters passed (missing parameters)");
     				return false;
     			}
     
    @@ -585,13 +612,14 @@ public boolean execute(String action, JSONArray data, CallbackContext callbackId
     			}
     			catch (Exception e)
     			{
    +				Log.e(TAG, "No parameters passed (missing parameters)");
     				e.printStackTrace();
     				return false;
     			}
     
     			return true;
     		}
    -		
    +
     		if ("setColorLED".equals(action))
     		{
     			try
    @@ -600,47 +628,12 @@ public boolean execute(String action, JSONArray data, CallbackContext callbackId
     				if (colorString == null)
     					return false;
     
    -				int colorLed = RichPushUtils.parseColor(colorString);
    +				int colorLed = GeneralUtils.parseColor(colorString);
     				PushManager.setColorLED(cordova.getActivity(), colorLed);
     			}
     			catch (Exception e)
     			{
    -				e.printStackTrace();
    -				return false;
    -			}
    -
    -			return true;
    -		}
    -
    -
    -		if ("sendGoalAchieved".equals(action))
    -		{
    -			JSONObject params = null;
    -			try
    -			{
    -				params = data.getJSONObject(0);
    -			}
    -			catch (JSONException e)
    -			{
    -				e.printStackTrace();
    -				return false;
    -			}
    -
    -			try
    -			{
    -				//config params: {goal:"goalName", count:30}
    -				String goal = params.getString("goal");
    -				if (goal == null)
    -					return false;
    -
    -				Integer count = null;
    -				if (params.has("count"))
    -					count = params.getInt("count");
    -
    -				PushManager.sendGoalAchieved(cordova.getActivity(), goal, count);
    -			}
    -			catch (Exception e)
    -			{
    +				Log.e(TAG, "No parameters passed (missing parameters)");
     				e.printStackTrace();
     				return false;
     			}
    @@ -680,27 +673,71 @@ public void onError(Exception e)
     			PushManager.getTagsAsync(cordova.getActivity(), new GetTagsListenerImpl());
     			return true;
     		}
    -		
    -		if(action.equals("getPushHistory"))
    +
    +		if (action.equals("getPushHistory"))
     		{
    -			ArrayList<String> pushHistory = PushPersistance.getPushHistory(cordova.getActivity());
    +			ArrayList<String> pushHistory = mPushManager.getPushHistory();
     			callbackId.success(new JSONArray(pushHistory));
     			return true;
     		}
     
    -		if(action.equals("clearPushHistory"))
    +		if (action.equals("clearPushHistory"))
     		{
    -			PushPersistance.clearPushHistory(cordova.getActivity());
    +			mPushManager.clearPushHistory();
     			return true;
     		}
     
    -		if(action.equals("clearNotificationCenter"))
    +		if (action.equals("clearNotificationCenter"))
     		{
     			PushManager.clearNotificationCenter(cordova.getActivity());
     			return true;
     		}
     
    -		Log.d("DirectoryListPlugin", "Invalid action : " + action + " passed");
    +		if (action.equals("setApplicationIconBadgeNumber"))
    +		{
    +			try
    +			{
    +				Integer badgeNumber = data.getJSONObject(0).getInt("badge");
    +				if (badgeNumber == null)
    +					return false;
    +
    +				mPushManager.setBadgeNumber(badgeNumber);
    +			}
    +			catch (JSONException e)
    +			{
    +				e.printStackTrace();
    +				Log.e(TAG, "No parameters passed (missing parameters)");
    +				return false;
    +			}
    +			return true;
    +		}
    +
    +		if (action.equals("getApplicationIconBadgeNumber"))
    +		{
    +			Integer badgeNumber = new Integer(mPushManager.getBadgeNumber());
    +			callbackId.success(badgeNumber);
    +			return true;
    +		}
    +
    +		if (action.equals("addToApplicationIconBadgeNumber"))
    +		{
    +			try
    +			{
    +				Integer badgeNumber = data.getJSONObject(0).getInt("badge");
    +				if (badgeNumber == null)
    +					return false;
    +				mPushManager.addBadgeNumber(badgeNumber);
    +			}
    +			catch (JSONException e)
    +			{
    +				e.printStackTrace();
    +				Log.e(TAG, "No parameters passed (missing parameters)");
    +				return false;
    +			}
    +			return true;
    +		}
    +
    +		Log.d(TAG, "Invalid action : " + action + " passed");
     		return false;
     	}
     
    @@ -746,20 +783,18 @@ private void doOnUnregisteredError(String errorId)
     
     	private void doOnMessageReceive(String message)
     	{
    -		Log.e("doOnMessageReceive", "message is: " + message);
    -		final String jsStatement = String.format("window.plugins.pushNotification.notificationCallback(%s);", message);
    +		Log.e(TAG, "message is: " + message);
    +		final String jsStatement = String.format("cordova.require(\"com.pushwoosh.plugins.pushwoosh.PushNotification\").notificationCallback(%s);", message);
     		//webView.sendJavascript(jsStatement);
     
    -		cordova.getActivity().runOnUiThread(
    -				new Runnable()
    -				{
    -					@Override
    -					public void run()
    -					{
    -						webView.loadUrl("javascript:" + jsStatement);
    -					}
    -				}
    -		);
    +		cordova.getActivity().runOnUiThread(new Runnable()
    +		{
    +			@Override
    +			public void run()
    +			{
    +				webView.loadUrl("javascript:" + jsStatement);
    +			}
    +		});
     	}
     
     	private BroadcastReceiver mReceiver = new BasePushMessageReceiver()
    diff --git a/src/ios/PushNotification.h b/src/ios/PushNotification.h
    index 5852ec97..d2d8ba02 100755
    --- a/src/ios/PushNotification.h
    +++ b/src/ios/PushNotification.h
    @@ -10,41 +10,41 @@
     // MIT Licensed
     
     #import <Foundation/Foundation.h>
    +#import <Cordova/CDV.h>
     #import <Cordova/CDVPlugin.h>
     #import <Pushwoosh/PushNotificationManager.h>
     
     @interface PushNotification : CDVPlugin <PushNotificationDelegate> {
    -
    -	NSMutableDictionary* callbackIds;
    +	NSMutableDictionary *callbackIds;
     	PushNotificationManager *pushManager;
    -	NSString *startPushData;
    +	NSDictionary *startPushData;
     	BOOL deviceReady;
     }
     
    -@property (nonatomic, retain) NSMutableDictionary* callbackIds;
    +@property (nonatomic, retain) NSMutableDictionary *callbackIds;
     @property (nonatomic, retain) PushNotificationManager *pushManager;
    -@property (nonatomic, copy) NSString *startPushData;
    -
    -- (void)registerDevice:(CDVInvokedUrlCommand*)command;
    -- (void)unregisterDevice:(CDVInvokedUrlCommand*)command;
    -- (void)setTags:(CDVInvokedUrlCommand*)command;
    -- (void)sendLocation:(CDVInvokedUrlCommand*)command;
    -- (void)startLocationTracking:(CDVInvokedUrlCommand*)command;
    -- (void)stopLocationTracking:(CDVInvokedUrlCommand*)command;
    -
    -- (void)onDeviceReady:(CDVInvokedUrlCommand*)command;
    -- (void)onDidRegisterForRemoteNotificationsWithDeviceToken:(NSString*)deviceToken;
    -- (void)onDidFailToRegisterForRemoteNotificationsWithError:(NSError*)error;
    -+ (NSMutableDictionary*)getRemoteNotificationStatus;
    -- (void)getRemoteNotificationStatus:(CDVInvokedUrlCommand*)command;
    -- (void)setApplicationIconBadgeNumber:(CDVInvokedUrlCommand*)command;
    -- (void)cancelAllLocalNotifications:(CDVInvokedUrlCommand*)command;
    +@property (nonatomic, copy) NSDictionary *startPushData;
    +
    +- (void)registerDevice:(CDVInvokedUrlCommand *)command;
    +- (void)unregisterDevice:(CDVInvokedUrlCommand *)command;
    +- (void)setTags:(CDVInvokedUrlCommand *)command;
    +- (void)sendLocation:(CDVInvokedUrlCommand *)command;
    +- (void)startLocationTracking:(CDVInvokedUrlCommand *)command;
    +- (void)stopLocationTracking:(CDVInvokedUrlCommand *)command;
    +
    +- (void)onDeviceReady:(CDVInvokedUrlCommand *)command;
    +- (void)onDidRegisterForRemoteNotificationsWithDeviceToken:(NSString *)deviceToken;
    +- (void)onDidFailToRegisterForRemoteNotificationsWithError:(NSError *)error;
    ++ (NSMutableDictionary *)getRemoteNotificationStatus;
    +- (void)getRemoteNotificationStatus:(CDVInvokedUrlCommand *)command;
    +- (void)setApplicationIconBadgeNumber:(CDVInvokedUrlCommand *)command;
    +- (void)cancelAllLocalNotifications:(CDVInvokedUrlCommand *)command;
     
     @end
     
     #ifdef DEBUG
    -#   define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
    +#define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
     #else
    -#   define DLog(...)
    +#define DLog(...)
     #endif
     #define ALog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
    diff --git a/src/ios/PushNotification.m b/src/ios/PushNotification.m
    index a955dbbd..499f9c25 100755
    --- a/src/ios/PushNotification.m
    +++ b/src/ios/PushNotification.m
    @@ -21,15 +21,15 @@ @implementation PushNotification
     @synthesize callbackIds = _callbackIds;
     @synthesize pushManager, startPushData;
     
    -- (NSMutableDictionary*)callbackIds {
    -	if(_callbackIds == nil) {
    +- (NSMutableDictionary *)callbackIds {
    +	if (_callbackIds == nil) {
     		_callbackIds = [[NSMutableDictionary alloc] init];
     	}
     	return _callbackIds;
     }
     
    -- (PushNotificationManager*)pushManager {
    -	if(pushManager == nil) {
    +- (PushNotificationManager *)pushManager {
    +	if (pushManager == nil) {
     		pushManager = [PushNotificationManager pushManager];
     		pushManager.delegate = self;
     		pushManager.showPushnotificationAlert = FALSE;
    @@ -37,44 +37,41 @@ - (PushNotificationManager*)pushManager {
     	return pushManager;
     }
     
    -- (void)getPushToken:(CDVInvokedUrlCommand*)command {
    -	NSString * token = [[PushNotificationManager pushManager] getPushToken];
    -	CDVPluginResult * pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:token];
    +- (void)getPushToken:(CDVInvokedUrlCommand *)command {
    +	NSString *token = [[PushNotificationManager pushManager] getPushToken];
    +	CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:token];
     	[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
     }
     
    -- (void)getPushwooshHWID:(CDVInvokedUrlCommand*)command {
    -	NSString * token = [[PushNotificationManager pushManager] getHWID];
    -	CDVPluginResult * pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:token];
    +- (void)getPushwooshHWID:(CDVInvokedUrlCommand *)command {
    +	NSString *token = [[PushNotificationManager pushManager] getHWID];
    +	CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:token];
     	[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
     }
     
    -- (void)onDeviceReady:(CDVInvokedUrlCommand*)command {
    -	deviceReady = YES;
    -
    +- (void)onDeviceReady:(CDVInvokedUrlCommand *)command {
     	NSDictionary *options = nil;
    -	if(command.arguments.count != 0)
    +	if (command.arguments.count != 0)
     		options = [command.arguments objectAtIndex:0];
     
     	NSString *appid = [options objectForKey:@"pw_appid"];
     	NSString *appname = [options objectForKey:@"appname"];
    -	
    -	if(!appid) {
    +
    +	if (!appid) {
     		//no Pushwoosh App Id provided in JS call, let's try Info.plist (SDK default)
    -		if(self.pushManager == nil)
    -		{
    +		if (self.pushManager == nil) {
     			NSLog(@"PushNotification.registerDevice: Missing Pushwoosh App ID");
     			return;
     		}
     	}
    -	
    -	if(appid) {
    +
    +	if (appid) {
     		[[NSUserDefaults standardUserDefaults] setObject:appid forKey:@"Pushwoosh_APPID"];
     		//we need to re-set APPID if it has been changed (on start we have initialized Push Manager with app id from NSUserDefaults)
     		self.pushManager.appCode = appid;
     	}
    -	
    -	if(appname) {
    +
    +	if (appname) {
     		[[NSUserDefaults standardUserDefaults] setObject:appname forKey:@"Pushwoosh_APPNAME"];
     		//and name if it has been provided
     		self.pushManager.appName = appname;
    @@ -82,262 +79,280 @@ - (void)onDeviceReady:(CDVInvokedUrlCommand*)command {
     
     	AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
     	PushNotification *pushHandler = [delegate.viewController getCommandInstance:@"PushNotification"];
    -	if(pushHandler.startPushData) {
    -		NSString *jsStatement = [NSString stringWithFormat:@"window.plugins.pushNotification.notificationCallback(%@);", pushHandler.startPushData];
    -		[self.commandDelegate evalJs:WRITEJS(jsStatement)];
    -		
    -		pushHandler.startPushData = nil;
    +	if (pushHandler.startPushData && !deviceReady) {
    +		[self dispatchPush:pushHandler.startPushData];
     	}
     
    +	deviceReady = YES;
    +
     	[[NSUserDefaults standardUserDefaults] synchronize];
     }
     
    -- (void)registerDevice:(CDVInvokedUrlCommand*)command {
    +- (void)dispatchPush:(NSDictionary *)pushData {
    +	NSData *json = [NSJSONSerialization dataWithJSONObject:pushData options:NSJSONWritingPrettyPrinted error:nil];
    +	NSString *jsonString = [[NSString alloc] initWithData:json encoding:NSUTF8StringEncoding];
    +
    +	NSString *jsStatement = [NSString
    +		stringWithFormat:
    +			@"cordova.require(\"com.pushwoosh.plugins.pushwoosh.PushNotification\").notificationCallback(%@);",
    +			jsonString];
    +	[self.commandDelegate evalJs:WRITEJS(jsStatement)];
    +}
    +
    +- (void)registerDevice:(CDVInvokedUrlCommand *)command {
     	[self.callbackIds setValue:command.callbackId forKey:@"registerDevice"];
     
     	//Cordova BUG: https://issues.apache.org/jira/browse/CB-8063
    -//	CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_NO_RESULT messageAsDictionary:nil];
    -//	[pluginResult setKeepCallbackAsBool:YES];
    -//	[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
    -	
    -	[[PushNotificationManager pushManager] registerForPushNotifications];
    +	//	CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_NO_RESULT messageAsDictionary:nil];
    +	//	[pluginResult setKeepCallbackAsBool:YES];
    +	//	[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
     
    +	[[PushNotificationManager pushManager] registerForPushNotifications];
     }
     
    -- (void)unregisterDevice:(CDVInvokedUrlCommand*)command {
    +- (void)unregisterDevice:(CDVInvokedUrlCommand *)command {
     	[[PushNotificationManager pushManager] unregisterForPushNotifications];
    -	
    -	CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:nil];
    +
    +	CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:nil];
     	[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
     }
     
    -- (void)startBeaconPushes:(CDVInvokedUrlCommand*)command {
    +- (void)startBeaconPushes:(CDVInvokedUrlCommand *)command {
     	[[PushNotificationManager pushManager] startBeaconTracking];
    -	
    -	CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:nil];
    +
    +	CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:nil];
     	[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
     }
     
    -- (void)stopBeaconPushes:(CDVInvokedUrlCommand*)command {
    +- (void)stopBeaconPushes:(CDVInvokedUrlCommand *)command {
     	[[PushNotificationManager pushManager] stopBeaconTracking];
    -	
    -	CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:nil];
    +
    +	CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:nil];
     	[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
     }
     
    -- (void)setTags:(CDVInvokedUrlCommand*)command {
    +- (void)setTags:(CDVInvokedUrlCommand *)command {
     	[[PushNotificationManager pushManager] setTags:[command.arguments objectAtIndex:0]];
    -	
    -	CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:nil];
    +
    +	CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:nil];
     	[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
     }
     
    -- (void)getTags:(CDVInvokedUrlCommand*)command {
    +- (void)getTags:(CDVInvokedUrlCommand *)command {
     	// The first argument in the arguments parameter is the callbackID.
     	[self.callbackIds setValue:command.callbackId forKey:@"getTags"];
     
     	//Cordova BUG: https://issues.apache.org/jira/browse/CB-8063
    -//	CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_NO_RESULT messageAsDictionary:nil];
    -//	[pluginResult setKeepCallbackAsBool:YES];
    -//	[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
    -	
    -	[[PushNotificationManager pushManager] loadTags:
    -		^(NSDictionary *tags) {
    -			CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:tags];
    -			[self.commandDelegate sendPluginResult:pluginResult callbackId:[self.callbackIds valueForKey:@"getTags"]];
    -		}
    -		error:^(NSError *error) {
    -			NSMutableDictionary *results = [NSMutableDictionary dictionary];
    -			[results setValue:[NSString stringWithFormat:@"%@", error] forKey:@"error"];
    -
    -			CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:results];
    -			[self.commandDelegate sendPluginResult:pluginResult callbackId:[self.callbackIds valueForKey:@"getTags"]];
    -		 }
    -	 ];
    +	//	CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_NO_RESULT messageAsDictionary:nil];
    +	//	[pluginResult setKeepCallbackAsBool:YES];
    +	//	[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
    +
    +	[[PushNotificationManager pushManager] loadTags:^(NSDictionary *tags) {
    +		CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:tags];
    +		[self.commandDelegate sendPluginResult:pluginResult callbackId:[self.callbackIds valueForKey:@"getTags"]];
    +	} error:^(NSError *error) {
    +		NSMutableDictionary *results = [NSMutableDictionary dictionary];
    +		[results setValue:[NSString stringWithFormat:@"%@", error] forKey:@"error"];
    +
    +		CDVPluginResult *pluginResult =
    +			[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:results];
    +		[self.commandDelegate sendPluginResult:pluginResult callbackId:[self.callbackIds valueForKey:@"getTags"]];
    +	}];
     }
     
    -- (void)sendLocation:(CDVInvokedUrlCommand*)command {
    -	
    -	NSNumber * lat = [[command.arguments objectAtIndex:0] objectForKey:@"lat"];
    -	NSNumber * lon = [[command.arguments objectAtIndex:0] objectForKey:@"lon"];
    -	CLLocation * location = [[CLLocation alloc] initWithLatitude:[lat doubleValue] longitude:[lon doubleValue]];
    +- (void)sendLocation:(CDVInvokedUrlCommand *)command {
    +	NSNumber *lat = [[command.arguments objectAtIndex:0] objectForKey:@"lat"];
    +	NSNumber *lon = [[command.arguments objectAtIndex:0] objectForKey:@"lon"];
    +	CLLocation *location = [[CLLocation alloc] initWithLatitude:[lat doubleValue] longitude:[lon doubleValue]];
     	[[PushNotificationManager pushManager] sendLocation:location];
    -	
    -	CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:nil];
    +
    +	CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:nil];
     	[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
     }
     
    -- (void)startLocationTracking:(CDVInvokedUrlCommand*)command {
    -	
    +- (void)startLocationTracking:(CDVInvokedUrlCommand *)command {
     	[[PushNotificationManager pushManager] startLocationTracking];
    -	
    -	CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:nil];
    +
    +	CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:nil];
     	[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
     }
     
    -- (void)stopLocationTracking:(CDVInvokedUrlCommand*)command {
    +- (void)stopLocationTracking:(CDVInvokedUrlCommand *)command {
     	[[PushNotificationManager pushManager] stopLocationTracking];
    -	
    -	CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:nil];
    +
    +	CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:nil];
     	[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
     }
     
     - (void)onDidRegisterForRemoteNotificationsWithDeviceToken:(NSString *)token {
    +	NSMutableDictionary *results = [PushNotification getRemoteNotificationStatus];
    +	[results setValue:token forKey:@"deviceToken"];
     
    -    NSMutableDictionary *results = [PushNotification getRemoteNotificationStatus];
    -    [results setValue:token forKey:@"deviceToken"];
    -
    -	CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:results];
    +	CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:results];
     	[self.commandDelegate sendPluginResult:pluginResult callbackId:[self.callbackIds valueForKey:@"registerDevice"]];
     }
     
    -- (void)onDidFailToRegisterForRemoteNotificationsWithError:(NSError*)error {
    -
    +- (void)onDidFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
     	NSMutableDictionary *results = [NSMutableDictionary dictionary];
     	[results setValue:[NSString stringWithFormat:@"%@", error] forKey:@"error"];
     
    -	CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:results];
    +	CDVPluginResult *pluginResult =
    +		[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:results];
     	[self.commandDelegate sendPluginResult:pluginResult callbackId:[self.callbackIds valueForKey:@"registerDevice"]];
     }
     
    -
    -- (void) onPushAccepted:(PushNotificationManager *)manager withNotification:(NSDictionary *)pushNotification onStart:(BOOL)onStart{
    +- (void)onPushAccepted:(PushNotificationManager *)manager
    +	  withNotification:(NSDictionary *)pushNotification
    +			   onStart:(BOOL)onStart {
     	//reset badge counter
     	[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
    -	
    +
     	NSMutableDictionary *pn = [NSMutableDictionary dictionaryWithDictionary:pushNotification];
     
     	//pase JSON string in custom data to JSON Object
    -	NSString* u = [pushNotification objectForKey:@"u"];
    -    
    +	NSString *u = [pushNotification objectForKey:@"u"];
    +
     	if (u) {
    -        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:[u dataUsingEncoding:NSUTF8StringEncoding]
    -                                                             options:NSJSONReadingMutableContainers
    -                                                               error:nil];
    -		
    +		NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:[u dataUsingEncoding:NSUTF8StringEncoding]
    +															 options:NSJSONReadingMutableContainers
    +															   error:nil];
    +
     		if (dict) {
     			[pn setObject:dict forKey:@"u"];
    -			
    +
     			//Android passes parameter as userdata too, align with Android
     			[pn setObject:dict forKey:@"userdata"];
     		}
     	}
    -	
    +
     	[pn setValue:[NSNumber numberWithBool:onStart] forKey:@"onStart"];
    -	
    -    NSData *json = [NSJSONSerialization dataWithJSONObject:pn options:NSJSONWritingPrettyPrinted error:nil];
    -	NSString *jsonString = [[NSString alloc] initWithData:json encoding:NSUTF8StringEncoding];
    -    
    -	if(!deviceReady){
    -		//the webview is not loaded yet, keep it for the callback
    +
    +	if (!onStart && !deviceReady) {
    +		NSLog(@"PUSHWOOSH WARNING: push notification onStart is false, but onDeviceReady has not been called. Did you "
    +			  @"forget to call onDeviceReady?");
    +	}
    +
    +	if (onStart) {
    +		//keep the start push
     		AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
     		PushNotification *pushHandler = [delegate.viewController getCommandInstance:@"PushNotification"];
    -
    -		pushHandler.startPushData = jsonString;
    +		pushHandler.startPushData = pn;
     	}
    -	else {
    +
    +	if (deviceReady) {
     		//send it to the webview
    -		NSString *jsStatement = [NSString stringWithFormat:@"window.plugins.pushNotification.notificationCallback(%@);", jsonString];
    -		[self.commandDelegate evalJs:WRITEJS(jsStatement)];
    +		[self dispatchPush:pn];
     	}
     }
     
     + (NSMutableDictionary *)getRemoteNotificationStatus {
    -    NSMutableDictionary *results = [NSMutableDictionary dictionary];
    -	
    +	NSMutableDictionary *results = [NSMutableDictionary dictionary];
    +
     	NSInteger type = 0;
    -    // Set the defaults to disabled unless we find otherwise...
    -    NSString *pushBadge = @"0";
    -    NSString *pushAlert = @"0";
    -    NSString *pushSound = @"0";
    -    NSString *pushEnabled = @"0";
    -    
    -    // Check what Notifications the user has turned on.  We registered for all three, but they may have manually disabled some or all of them.
    -	
    +	// Set the defaults to disabled unless we find otherwise...
    +	NSString *pushBadge = @"0";
    +	NSString *pushAlert = @"0";
    +	NSString *pushSound = @"0";
    +	NSString *pushEnabled = @"0";
    +
    +// Check what Notifications the user has turned on.  We registered for all three, but they may have manually disabled some or all of them.
    +
     #ifdef __IPHONE_8_0
    -	if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
    -	{
    -		if([[UIApplication sharedApplication] isRegisteredForRemoteNotifications])
    +	if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {
    +		if ([[UIApplication sharedApplication] isRegisteredForRemoteNotifications])
     			pushEnabled = @"1";
     
    -		UIUserNotificationSettings * settings = [[UIApplication sharedApplication] currentUserNotificationSettings];
    +		UIUserNotificationSettings *settings = [[UIApplication sharedApplication] currentUserNotificationSettings];
     		type = settings.types;
    -		if(type & UIUserNotificationTypeBadge){
    +		if (type & UIUserNotificationTypeBadge) {
     			pushBadge = @"1";
     		}
    -		if(type & UIUserNotificationTypeAlert) {
    +		if (type & UIUserNotificationTypeAlert) {
     			pushAlert = @"1";
     		}
    -		if(type & UIUserNotificationTypeSound) {
    +		if (type & UIUserNotificationTypeSound) {
     			pushSound = @"1";
     		}
    -	}
    -	else
    +	} else
     #endif
     	{
     		type = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
    -		if(type & UIRemoteNotificationTypeBadge){
    +		if (type & UIRemoteNotificationTypeBadge) {
     			pushBadge = @"1";
     		}
    -		if(type & UIRemoteNotificationTypeAlert) {
    +		if (type & UIRemoteNotificationTypeAlert) {
     			pushAlert = @"1";
     		}
    -		if(type & UIRemoteNotificationTypeSound) {
    +		if (type & UIRemoteNotificationTypeSound) {
     			pushSound = @"1";
     		}
     
    -		if(type != UIRemoteNotificationTypeNone)
    +		if (type != UIRemoteNotificationTypeNone)
     			pushEnabled = @"1";
     	}
    -	
    -    // Affect results
    -    [results setValue:[NSString stringWithFormat:@"%d", (int)type] forKey:@"type"];
    -    [results setValue:pushEnabled forKey:@"enabled"];
    -    [results setValue:pushBadge forKey:@"pushBadge"];
    -    [results setValue:pushAlert forKey:@"pushAlert"];
    -    [results setValue:pushSound forKey:@"pushSound"];
    -    
    -    return results;
    -}
     
    -- (void)getRemoteNotificationStatus:(CDVInvokedUrlCommand*)command {
    +	// Affect results
    +	[results setValue:[NSString stringWithFormat:@"%d", (int)type] forKey:@"type"];
    +	[results setValue:pushEnabled forKey:@"enabled"];
    +	[results setValue:pushBadge forKey:@"pushBadge"];
    +	[results setValue:pushAlert forKey:@"pushAlert"];
    +	[results setValue:pushSound forKey:@"pushSound"];
    +
    +	return results;
    +}
     
    +- (void)getRemoteNotificationStatus:(CDVInvokedUrlCommand *)command {
     	NSMutableDictionary *results = [PushNotification getRemoteNotificationStatus];
     
    -	CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:results];
    +	CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:results];
     	[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
     }
     
    -- (void)setApplicationIconBadgeNumber:(CDVInvokedUrlCommand*)command {
    +- (void)setApplicationIconBadgeNumber:(CDVInvokedUrlCommand *)command {
    +	int badge = [[[command.arguments objectAtIndex:0] objectForKey:@"badge"] intValue];
    +	[[UIApplication sharedApplication] setApplicationIconBadgeNumber:badge];
     
    -    int badge = [[[command.arguments objectAtIndex:0] objectForKey:@"badge"] intValue] ?: 0;
    -    [[UIApplication sharedApplication] setApplicationIconBadgeNumber:badge];
    +	CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
    +	[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
    +}
     
    -    NSMutableDictionary *results = [NSMutableDictionary dictionary];
    -	[results setValue:[NSNumber numberWithInt:badge] forKey:@"badge"];
    -    [results setValue:[NSNumber numberWithInt:1] forKey:@"success"];
    +- (void)getApplicationIconBadgeNumber:(CDVInvokedUrlCommand *)command {
    +	NSInteger badge = [UIApplication sharedApplication].applicationIconBadgeNumber;
     
    -	CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:results];
    +	CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:badge];
     	[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
     }
     
    -- (void)cancelAllLocalNotifications:(CDVInvokedUrlCommand*)command {
    +- (void)addToApplicationIconBadgeNumber:(CDVInvokedUrlCommand *)command {
    +	int badge = [[[command.arguments objectAtIndex:0] objectForKey:@"badge"] intValue];
    +	[UIApplication sharedApplication].applicationIconBadgeNumber += badge;
     
    +	CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
    +	[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
    +}
    +
    +- (void)cancelAllLocalNotifications:(CDVInvokedUrlCommand *)command {
     	[[UIApplication sharedApplication] cancelAllLocalNotifications];
    -	
    -	CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
    +
    +	CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
    +	[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
    +}
    +
    +- (void)getLaunchNotification:(CDVInvokedUrlCommand *)command {
    +	CDVPluginResult *pluginResult =
    +		[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:self.startPushData];
     	[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
     }
     
    -- (void) dealloc {
    +- (void)dealloc {
     	self.pushManager = nil;
     	self.startPushData = nil;
     }
     
     @end
     
    -@implementation UIApplication(InternalPushRuntime)
    -- (BOOL) pushwooshUseRuntimeMagic {
    +@implementation UIApplication (InternalPushRuntime)
    +- (BOOL)pushwooshUseRuntimeMagic {
     	return YES;
     }
     
    diff --git a/src/ios/Pushwoosh.framework/Headers/PushNotificationManager.h b/src/ios/Pushwoosh.framework/Headers/PushNotificationManager.h
    index 073108fa..a6667a9c 100644
    --- a/src/ios/Pushwoosh.framework/Headers/PushNotificationManager.h
    +++ b/src/ios/Pushwoosh.framework/Headers/PushNotificationManager.h
    @@ -18,8 +18,8 @@ typedef NS_ENUM(NSInteger, PWSupportedOrientations) {
     	PWOrientationLandscapeRight = 1 << 3,
     };
     
    -typedef void(^pushwooshGetTagsHandler)(NSDictionary *tags);
    -typedef void(^pushwooshErrorHandler)(NSError *error);
    +typedef void(^PushwooshGetTagsHandler)(NSDictionary *tags);
    +typedef void(^PushwooshErrorHandler)(NSError *error);
     
     /**
      `PushNotificationDelegate` protocol defines the methods that can be implemented in the delegate of the `PushNotificationManager` class' singleton object.
    @@ -102,6 +102,11 @@ typedef void(^pushwooshErrorHandler)(NSError *error);
      */
     - (void) onRichPageButtonTapped:(NSString *)customData;
     
    +/**
    + User has tapped on the back button on Rich Push Page.
    + */
    +- (void) onRichPageBackTapped;
    +
     /**
      Tells the delegate that the push manager has received tags from the server.
      
    @@ -122,8 +127,22 @@ typedef void(^pushwooshErrorHandler)(NSError *error);
      @param error An NSError object that encapsulates information why receiving tags did not succeed.
      */
     - (void) onTagsFailedToReceive:(NSError *)error;
    -@end
     
    +/**
    + Tells the delegate that In-App with specified code has been closed
    + 
    + @param code In-App code
    + */
    +- (void) onInAppClosed:(NSString*)code;
    +
    +/**
    + Tells the delegate that In-App with specified code has been displayed
    + 
    + @param code In-App code
    + */
    +- (void) onInAppDisplayed:(NSString*)code;
    +
    +@end
     
     /**
       `PWTags` class encapsulates the methods for creating tags parameters for sending them to the server.
    @@ -159,9 +178,6 @@ typedef void(^pushwooshErrorHandler)(NSError *error);
     	NSString *appCode;
     	NSString *appName;
     
    -	UIWindow *richPushWindow;
    -	NSInteger internalIndex;
    -	NSMutableDictionary *pushNotifications;
     	NSObject<PushNotificationDelegate> *__unsafe_unretained delegate;
     }
     
    @@ -199,15 +215,16 @@ typedef void(^pushwooshErrorHandler)(NSError *error);
      */
     @property (nonatomic, assign) NSObject<PushNotificationDelegate> *delegate;
     
    -@property (nonatomic, retain) UIWindow *richPushWindow;
    -@property (nonatomic, retain) NSDictionary *pushNotifications;
    -@property (nonatomic, assign) PWSupportedOrientations supportedOrientations;
    -
     /**
      Show push notifications alert when push notification is received while the app is running, default is `YES`
      */
     @property (nonatomic, assign) BOOL showPushnotificationAlert;
     
    +/**
    + Returns push notification payload if the app was started in response to push notification or null otherwise
    + */
    +@property (nonatomic, copy, readonly) NSDictionary *launchNotification;
    +
     /**
      Initializes PushNotificationManager. Usually called by Pushwoosh Runtime internally.
      @param appcCode Pushwoosh App ID.
    @@ -233,11 +250,8 @@ typedef void(^pushwooshErrorHandler)(NSError *error);
      */
     - (void) unregisterForPushNotifications;
     
    -+ (BOOL) getAPSProductionStatus:(BOOL)canShowAlert;
    -
     - (id) initWithApplicationCode:(NSString *)appCode appName:(NSString *)appName;
     - (id) initWithApplicationCode:(NSString *)appCode navController:(UIViewController *) navController appName:(NSString *)appName __attribute__((deprecated));
    -- (void) showWebView;
     
     /**
      Start location tracking.
    @@ -277,6 +291,11 @@ typedef void(^pushwooshErrorHandler)(NSError *error);
      */
     - (void) setTags: (NSDictionary *) tags;
     
    +/**
    + Send tags to server with completion block. If setTags succeeds competion is called with nil argument. If setTags fails completion is called with error.
    + */
    +- (void) setTags: (NSDictionary *) tags withCompletion: (void(^)(NSError* error)) completion;
    +
     /**
      Get tags from the server. Calls delegate method `onTagsReceived:` or `onTagsFailedToReceive:` depending on the results.
      */
    @@ -295,7 +314,7 @@ typedef void(^pushwooshErrorHandler)(NSError *error);
      
      @param errorHandler The block is executed on the unsuccessful completion of the request. This block has no return value and takes one argument: the error that occurred during the request.
      */
    -- (void) loadTags: (pushwooshGetTagsHandler) successHandler error:(pushwooshErrorHandler) errorHandler;
    +- (void) loadTags: (PushwooshGetTagsHandler) successHandler error:(PushwooshErrorHandler) errorHandler;
     
     /**
      Informs the Pushwoosh about the app being launched. Usually called internally by SDK Runtime.
    @@ -318,28 +337,27 @@ typedef void(^pushwooshErrorHandler)(NSError *error);
     - (void) sendLocation: (CLLocation *) location;
     
     /**
    - Records stats for a goal in the application, like in-app purchase, user reaching a specific point at the game etc. This function could be used to see the performance of marketing push notification.
    + Sends in-app purchases to Pushwoosh. Use in paymentQueue:updatedTransactions: payment queue method (see example).
      
      Example:
      
    -	[[PushNotificationManager pushManager] recordGoal:@"purchase1"];
    +	 - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
    +		[[PushNotificationManager pushManager] sendSKPaymentTransactions:transactions];
    +	 }
      
    - @param goal Goal string.
    + @param transactions Array of SKPaymentTransaction items as received in the payment queue.
      */
    -- (void) recordGoal: (NSString *) goal;
    +- (void) sendSKPaymentTransactions:(NSArray *)transactions;
     
     /**
    - Records stats for a goal in the application, like in-app purchase, user reaching a specific point at the game.
    - Additional count parameter is responsible for storing the additional information about the goal achieved like price of the purchase e.t.c.
    + Tracks individual in-app purchase. See recommended `sendSKPaymentTransactions:` method.
      
    - Example:
    - 
    -	[[PushNotificationsManager pushManager] recordGoal:@"purchase" withCount:[NSNumber numberWithInt:"10"];
    -  
    - @param goal Goal string.
    - @param count Count parameter. Must be integer value.
    + @param productIdentifier purchased product ID
    + @param price price for the product
    + @param currencyCode currency of the price (ex: @"USD")
    + @param date time of the purchase (ex: [NSDate now])
      */
    -- (void) recordGoal: (NSString *) goal withCount: (NSNumber *) count;
    +- (void) sendPurchase: (NSString *) productIdentifier withPrice:(NSDecimalNumber *)price currencyCode:(NSString *)currencyCode andDate:(NSDate *)date;
     
     /**
      Gets current push token.
    @@ -448,13 +466,38 @@ typedef void(^pushwooshErrorHandler)(NSError *error);
     + (void) clearNotificationCenter;
     
     /**
    - Internal function
    + Set User indentifier. This could be Facebook ID, username or email, or any other user ID.
    + This allows data and events to be matched across multiple user devices.
      */
    -- (NSDictionary *) getPage:(NSString *)pageId;
    +- (void) setUserId: (NSString*) userId;
     
     /**
    - Internal function
    + Move all events from oldUserId to newUserId if doMerge is true. If doMerge is false all events for oldUserId are removed.
    + 
    + @param oldUserId source user
    + @param newUserId destination user
    + @param doMerge if false all events for oldUserId are removed, if true all events for oldUserId are moved to newUserId
    + @param completeion callback
      */
    -- (void) onRichPageButtonTapped:(NSString *)customData;
    +- (void) mergeUserId: (NSString*) oldUserId to: (NSString*) newUserId doMerge: (BOOL) doMerge completion: (void(^)(NSError* error)) completion;
    +
    +/**
    + Post events for In-App Messages. This can trigger In-App message display as specified in Pushwoosh Control Panel.
    + 
    + Example:
    + 
    +	 [[PushNotificationManager pushManager] setUserId:@"96da2f590cd7246bbde0051047b0d6f7"];
    +	 [[PushNotificationManager pushManager] postEvent:@"buttonPressed" withAttributes:@{ @"buttonNumber" : @"4", @"buttonLabel" : @"Banner" } completion:nil];
    +
    + @param event name of the event
    + @param attributes NSDictionary of event attributes
    + @param completion function to call after posting event
    + */
    +- (void) postEvent: (NSString*) event withAttributes: (NSDictionary*) attributes completion: (void(^)(NSError* error)) completion;
    +
    +/**
    + See `postEvent:withAttributes:completion:`
    + */
    +- (void) postEvent: (NSString*) event withAttributes: (NSDictionary*) attributes;
     
     @end
    diff --git a/src/ios/Pushwoosh.framework/Pushwoosh b/src/ios/Pushwoosh.framework/Pushwoosh
    index 951f1fb4..d436eedc 100644
    Binary files a/src/ios/Pushwoosh.framework/Pushwoosh and b/src/ios/Pushwoosh.framework/Pushwoosh differ
    diff --git a/src/ios/Pushwoosh.framework/Resources b/src/ios/Pushwoosh.framework/Resources
    deleted file mode 120000
    index 953ee36f..00000000
    --- a/src/ios/Pushwoosh.framework/Resources
    +++ /dev/null
    @@ -1 +0,0 @@
    -Versions/Current/Resources
    \ No newline at end of file
    diff --git a/src/wp8/PushNotification.cs b/src/wp8/PushNotification.cs
    index 55523e36..94736cb4 100644
    --- a/src/wp8/PushNotification.cs
    +++ b/src/wp8/PushNotification.cs
    @@ -24,6 +24,26 @@ public class PushNotification : BaseCommand
     
             private string registerCallbackId = null;
     
    +        // returns null value if it fails.
    +        private string getCallbackId(string options)
    +        {
    +            string[] optStings = null;
    +            try
    +            {
    +                optStings = JSON.JsonHelper.Deserialize<string[]>(options);
    +            }
    +            catch (Exception)
    +            {
    +                DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION), CurrentCommandCallbackId);
    +            }
    +
    +            if (optStings == null)
    +                return CurrentCommandCallbackId;
    +
    +            //callback id is the last item
    +            return optStings[optStings.Length - 1];
    +        }
    +
             //Phonegap runs all plugins methods on a separate threads, make sure onDeviceReady goes first
             void waitDeviceReady()
             {
    @@ -60,13 +80,13 @@ private void OnPushTokenFailed(object sender, string error)
     
             public void registerDevice(string options)
             {
    -            string callbackId = this.CurrentCommandCallbackId;
    +            string callbackId = getCallbackId(options);
                 waitDeviceReady();
     
                 service.SubscribeToPushService(authenticatedServiceName);
                 if (string.IsNullOrEmpty(service.PushToken))
                 {
    -                registerCallbackId = this.CurrentCommandCallbackId;
    +                registerCallbackId = callbackId;
     
                     PluginResult plugResult = new PluginResult(PluginResult.Status.NO_RESULT);
                     plugResult.KeepCallback = true;
    @@ -80,7 +100,8 @@ public void registerDevice(string options)
     
             public void unregisterDevice(string options)
             {
    -            string callbackId = this.CurrentCommandCallbackId;
    +            string callbackId = getCallbackId(options);
    +
                 PluginResult plugResult = new PluginResult(PluginResult.Status.NO_RESULT);
                 plugResult.KeepCallback = true;
                 DispatchCommandResult(plugResult);
    @@ -101,7 +122,8 @@ public void unregisterDevice(string options)
     
             public void getTags(string options)
             {
    -            string callbackId = this.CurrentCommandCallbackId;
    +            string callbackId = getCallbackId(options);
    +
                 PluginResult plugResult = new PluginResult(PluginResult.Status.NO_RESULT);
                 plugResult.KeepCallback = true;
                 DispatchCommandResult(plugResult);
    @@ -137,7 +159,8 @@ public void getPushToken(string options)
     
             public void setTags(string options)
             {
    -            string callbackId = this.CurrentCommandCallbackId;
    +            string callbackId = getCallbackId(options);
    +
                 PluginResult plugResult = new PluginResult(PluginResult.Status.NO_RESULT);
                 plugResult.KeepCallback = true;
                 DispatchCommandResult(plugResult);
    @@ -198,7 +221,7 @@ void ExecutePushNotificationCallback(object sender, ToastPush push)
                             try
                             {
                                 string pushPayload = JsonConvert.SerializeObject(push);
    -                            cView.Browser.InvokeScript("execScript", "window.plugins.pushNotification.notificationCallback(" + pushPayload + ")");
    +                            cView.Browser.InvokeScript("execScript", "cordova.require(\"com.pushwoosh.plugins.pushwoosh.PushNotification\").notificationCallback(" + pushPayload + ")");
                             }
                             catch (Exception ex)
                             {
    diff --git a/src/wp8/PushSDK/PushSDK.dll b/src/wp8/PushSDK/PushSDK.dll
    index 555fae96..314fc708 100755
    Binary files a/src/wp8/PushSDK/PushSDK.dll and b/src/wp8/PushSDK/PushSDK.dll differ
    diff --git a/www/PushNotification.js b/www/PushNotification.js
    index 6b1258ee..477e3c5f 100755
    --- a/www/PushNotification.js
    +++ b/www/PushNotification.js
    @@ -1,170 +1,337 @@
     //
     //  PushNotification.js
     //
    -// Based on the Push Notifications Cordova Plugin by Olivier Louvignes on 06/05/12.
    -// Modified by Max Konev on 18/05/12.
    +// Based on the Push Notifications Cordova Plugin by Olivier Louvignes.
    +// Modified by Pushwoosh team.
     //
    -// Pushwoosh Push Notifications Plugin for Cordova iOS
    +// Pushwoosh Push Notifications Plugin for Cordova
     // www.pushwoosh.com
     //
     // MIT Licensed
     
     var exec = require('cordova/exec');
     
    +//Class: PushNotification
    +//Class to interact with Pushwoosh Push Notifications plugin
    +//
    +//Example:
    +//(start code)
    +//	    	    var pushwoosh = cordova.require("com.pushwoosh.plugins.pushwoosh.PushNotification");
    +//				pushwoosh.onDeviceReady({ projectid: "XXXXXXXXXXXXXXX", pw_appid : "XXXXX-XXXXX" });
    +//(end)
     function PushNotification() {}
     
    -// Call this to register for push notifications and retreive a push Token
    +//Function: registerDevice
    +//Call this to register for push notifications and retreive a push Token
    +//
    +//Example:
    +//(start code)
    +//	pushNotification.registerDevice(
    +//		function(token)
    +//		{
    +//			alert(token);
    +//		},
    +//		function(status)
    +//		{
    +//			alert("failed to register: " +  status);
    +//		}
    +//	);
    +//(end)
     PushNotification.prototype.registerDevice = function(success, fail) {
     	exec(success, fail, "PushNotification", "registerDevice", []);
     };
     
    -// Call this to set tags for the device
    +//Function: setTags
    +//Call this to set tags for the device
    +//
    +//Example:
    +//sets the following tags: "deviceName" with value "hello" and "deviceId" with value 10
    +//(start code)
    +//	pushNotification.setTags({deviceName:"hello", deviceId:10},
    +//		function(status) {
    +//			console.warn('setTags success');
    +//		},
    +//		function(status) {
    +//			console.warn('setTags failed');
    +//		}
    +//	);
    +//
    +//	//setings list tags "MyTag" with values (array) "hello", "world"
    +//	pushNotification.setTags({"MyTag":["hello", "world"]});
    +//(end)
     PushNotification.prototype.setTags = function(config, success, fail) {
     	exec(success, fail, "PushNotification", "setTags", config ? [config] : []);
     };
     
    -// Call this to get push token if it is available
    +//Function: getPushToken
    +//Call this to get push token if it is available. Note the token also comes in registerDevice function callback.
    +//
    +//Example:
    +//(start code)
    +//	pushNotification.getPushToken(
    +//		function(token)
    +//		{
    +//			console.warn('push token: ' + token);
    +//		}
    +//	);
    +//(end)
     PushNotification.prototype.getPushToken = function(success) {
     	exec(success, null, "PushNotification", "getPushToken", []);
     };
     
    -// Call this to get Pushwoosh HWID used for communications with Pushwoosh API
    +//Function: getPushwooshHWID
    +//Call this to get Pushwoosh HWID used for communications with Pushwoosh API
    +//
    +//Example:
    +//(start code)
    +//	pushNotification.getPushwooshHWID(
    +//		function(token) {
    +//			console.warn('Pushwoosh HWID: ' + token);
    +//		}
    +//	);
    +//(end)
     PushNotification.prototype.getPushwooshHWID = function(success) {
     	exec(success, null, "PushNotification", "getPushwooshHWID", []);
     };
     
    -// Call this first thing with your Pushwoosh App ID (see example)
    +//Function: onDeviceReady
    +//Call this first thing with your Pushwoosh App ID (pw_appid parameter) and Google Project ID for Android (projectid parameter)
    +//
    +//Example:
    +//(start code)
    +//	//initialize Pushwoosh with projectid: "GOOGLE_PROJECT_ID", appid : "PUSHWOOSH_APP_ID". This will trigger all pending push notifications on start.
    +//	pushNotification.onDeviceReady({ projectid: "XXXXXXXXXXXXXXX", pw_appid : "XXXXX-XXXXX" });
    +//(end)
     PushNotification.prototype.onDeviceReady = function(config) {
     	exec(null, null, "PushNotification", "onDeviceReady", config ? [config] : []);
     };
     
    -// Call this to send geo location for the device
    -PushNotification.prototype.sendLocation = function(config, success, fail) {
    -	exec(success, fail, "PushNotification", "sendLocation", config ? [config] : []);
    -};
    -
    -// Call this to get tags for the device
    +//Function: getTags
    +//Call this to get tags for the device
    +//
    +//Example:
    +//(start code)
    +//	pushNotification.getTags(
    +//		function(tags)
    +//		{
    +//			console.warn('tags for the device: ' + JSON.stringify(tags));
    +//		},
    +//		function(error)
    +//		{
    +//			console.warn('get tags error: ' + JSON.stringify(error));
    +//		}
    +//	);
    +//(end)
     PushNotification.prototype.getTags = function(success, fail) {
     	exec(success, fail, "PushNotification", "getTags", []);
     };
     
    +//Function: unregisterDevice
    +//Unregisters device from push notifications
     PushNotification.prototype.unregisterDevice = function(success, fail) {
     	exec(success, fail, "PushNotification", "unregisterDevice", []);
     };
     
    -// Enable Geozones for your Pushwoosh app to be able to use these
    +//Function: startLocationTracking
    +//Starts geolocation based push notifications. You need to configure Geozones in Pushwoosh Control panel.
     PushNotification.prototype.startLocationTracking = function(success, fail) {
    -  exec(success, fail, "PushNotification", "startLocationTracking", []);
    +	exec(success, fail, "PushNotification", "startLocationTracking", []);
     };
     
    +//Function: stopLocationTracking
    +//Stops geolocation based push notifications
     PushNotification.prototype.stopLocationTracking = function(success, fail) {
    -  exec(success, fail, "PushNotification", "stopLocationTracking", []);
    +	exec(success, fail, "PushNotification", "stopLocationTracking", []);
     };
     
    -//Android Only----
    +//Function: createLocalNotification
    +//Android only, Creates local notification,
     //config params: {msg:"message", seconds:30, userData:"optional"}
    +//
    +//Example:
    +//(start code)
    +//pushNotification.createLocalNotification({msg:"Your pumpkins are ready!", seconds:30, userData:"optional"}
    +//(end)
     PushNotification.prototype.createLocalNotification = function(config, success, fail) {
     	exec(success, fail, "PushNotification", "createLocalNotification", config ? [config] : []);
     };
     
    +//Function: clearLocalNotification
    +//Android only, Clears pending local notifications created by <createLocalNotification>
     PushNotification.prototype.clearLocalNotification = function() {
     	exec(null, null, "PushNotification", "clearLocalNotification", []);
     };
     
    +//Function: clearNotificationCenter
    +//Android only, Clears all notifications presented in Android Notification Center
     PushNotification.prototype.clearNotificationCenter = function() {
     	exec(null, null, "PushNotification", "clearNotificationCenter", []);
     };
     
    -//advanced background task to track device position and not drain the battery
    -//deprecated, use startLocationTracking and stopLocationTracking
    +//Function: startGeoPushes
    +//Android only, Deprecated, use <startLocationTracking> and <stopLocationTracking>
     PushNotification.prototype.startGeoPushes = function(success, fail) {
     	exec(success, fail, "PushNotification", "startGeoPushes", []);
     };
     
    +//Function: stopGeoPushes
    +//Android only, Deprecated, use <startLocationTracking> and <stopLocationTracking>
     PushNotification.prototype.stopGeoPushes = function(success, fail) {
     	exec(success, fail, "PushNotification", "stopGeoPushes", []);
     };
     
    -//advanced background task to track device position and not drain the battery
    +//Function: startBeaconPushes
    +//Android only, iOS available per request, Call this to start beacon tracking
     PushNotification.prototype.startBeaconPushes = function(success, fail) {
     	exec(success, fail, "PushNotification", "startBeaconPushes", []);
     };
     
    +//Function: stopBeaconPushes
    +//Android only, iOS available per request, Call this to stop beacon tracking
     PushNotification.prototype.stopBeaconPushes = function(success, fail) {
     	exec(success, fail, "PushNotification", "stopBeaconPushes", []);
     };
     
    -//Android only, let the plugin know that the app went to background mode (or vise versa)
    +//Function: setBeaconBackgroundMode
    +//Android only, let the plugin know that the app went to background mode (or vise versa).
    +//Call this when going background when using beacons
     PushNotification.prototype.setBeaconBackgroundMode = function(on, success, fail) {
     	exec(success, fail, "PushNotification", "setBeaconBackgroundMode", [on]);
     };
     
    -//sets multi notification mode on
    +//Function: setMultiNotificationMode
    +//Android only, Allows multiple notifications to be displayed in the Android Notification Center
     PushNotification.prototype.setMultiNotificationMode = function(success, fail) {
     	exec(success, fail, "PushNotification", "setMultiNotificationMode", []);
     };
     
    -//sets single notification mode
    +//Function: setSingleNotificationMode
    +//Android only, Allows only the last one notification to be displayed in the Android Notification Center
     PushNotification.prototype.setSingleNotificationMode = function(success, fail) {
     	exec(success, fail, "PushNotification", "setSingleNotificationMode", []);
     };
     
    -//type: 0 default, 1 no sound, 2 always
    +//Function: setSoundType
    +//Android only, Sets default sound to play when push notification arrive.
    +//Values: 0 - default, 1 - no sound, 2 - always
     PushNotification.prototype.setSoundType = function(type, success, fail) {
     	exec(success, fail, "PushNotification", "setSoundType", [type]);
     };
     
    -//type: 0 default, 1 no vibration, 2 always
    +//Function: setVibrateType
    +//Android only, Sets default vibration mode when push notification arrive.
    +//Values: 0 - default, 1 - no vibration, 2 - always
     PushNotification.prototype.setVibrateType = function(type, success, fail) {
     	exec(success, fail, "PushNotification", "setVibrateType", [type]);
     };
     
    +//Function: setLightScreenOnNotification
    +//Android only, Should the screen be lit up when push notification arrive
     PushNotification.prototype.setLightScreenOnNotification = function(on, success, fail) {
     	exec(success, fail, "PushNotification", "setLightScreenOnNotification", [on]);
     };
     
    -//set to enable led blinking when notification arrives and display is off
    +//Function: setEnableLED
    +//Android only, Set to enable led blinking when notification arrives and display is off
     PushNotification.prototype.setEnableLED = function(on, success, fail) {
     	exec(success, fail, "PushNotification", "setEnableLED", [on]);
     };
    -//set led color
    +
    +//Function: setEnableLED
    +//Android only, Set led color. Use with <setEnableLED>
     PushNotification.prototype.setColorLED = function(color, success, fail) {
     	exec(success, fail, "PushNotification", "setColorLED", [color]);
     };
    -//{goal:'name', count:3} (count is optional)
    -PushNotification.prototype.sendGoalAchieved = function(config, success, fail) {
    -	exec(success, fail, "PushNotification", "sendGoalAchieved", config ? [config] : []);
    -};
     
    -//Android Only. Gets push history, returns array
    +//Function: getPushHistory
    +//Android only, Gets push history, returns array of push notifications received.
    +//
    +//Example:
    +//(start code)
    +//	pushNotification.getPushHistory(function(pushHistory) {
    +//		if(pushHistory.length == 0)
    +//			alert("no push history");
    +//		else
    +//			alert(JSON.stringify(pushHistory));
    +//	});
    +//
    +//	pushNotification.clearPushHistory();
    +//(end)
     PushNotification.prototype.getPushHistory = function(success) {
     	exec(success, null, "PushNotification", "getPushHistory", []);
     };
     
    -//Android Only. Clears push history
    +//Function: clearPushHistory
    +//Android only, Clears push history
     PushNotification.prototype.clearPushHistory = function() {
     	exec(null, null, "PushNotification", "clearPushHistory", []);
     };
     
    -//Android End----
    -
    -//iOS only----
    -// Call this to get a detailed status of remoteNotifications
    +//Function: getRemoteNotificationStatus
    +//iOS only,
    +//Call this to get a detailed status of push notification permissions.
    +//
    +//Returns array with the following items:
    +//
    +//"enabled" - if push notificaions enabled.
    +//"pushBadge" -  badges permission granted.
    +//"pushAlert" -  alert permission granted.
    +//"pushSound" -  sound permission granted.
     PushNotification.prototype.getRemoteNotificationStatus = function(callback) {
     	exec(callback, callback, "PushNotification", "getRemoteNotificationStatus", []);
     };
     
    -// Call this to set the application icon badge
    -PushNotification.prototype.setApplicationIconBadgeNumber = function(badgeNumber, callback) {
    -	exec(callback, callback, "PushNotification", "setApplicationIconBadgeNumber", [{badge: badgeNumber}]);
    +//Function: setApplicationIconBadgeNumber
    +//iOS only,
    +//Call this to set the application icon badge
    +PushNotification.prototype.setApplicationIconBadgeNumber = function(badgeNumber) {
    +	exec(null, null, "PushNotification", "setApplicationIconBadgeNumber", [{
    +		badge: badgeNumber
    +	}]);
     };
     
    -// Call this to clear all notifications from the notification center
    +//Function: getApplicationIconBadgeNumber
    +//iOS only,
    +//Call this to get the application icon badge
    +//
    +//Example:
    +//(start code)
    +//	pushwoosh.getApplicationIconBadgeNumber(function(badge){ alert(badge);} );
    +//(end)
    +PushNotification.prototype.getApplicationIconBadgeNumber = function(callback) {
    +	exec(callback, callback, "PushNotification", "getApplicationIconBadgeNumber", []);
    +};
    +
    +//Function: addToApplicationIconBadgeNumber
    +//iOS only,
    +//Call this to add value to the application icon badge
    +//
    +//Example:
    +//(start code)
    +//	pushwoosh.addToApplicationIconBadgeNumber(5);
    +//	pushwoosh.addToApplicationIconBadgeNumber(-5);
    +//(end)
    +PushNotification.prototype.addToApplicationIconBadgeNumber = function(badgeNumber) {
    +	exec(null, null, "PushNotification", "addToApplicationIconBadgeNumber", [{
    +		badge: badgeNumber
    +	}]);
    +};
    +
    +//Function: cancelAllLocalNotifications
    +//iOS only,
    +//Call this to clear all notifications from the notification center
     PushNotification.prototype.cancelAllLocalNotifications = function(callback) {
     	exec(callback, callback, "PushNotification", "cancelAllLocalNotifications", []);
     };
     //iOS End----
     
    +//Function: getLaunchNotification
    +//Returns push notification payload if the app was started in response to push notification
    +//or null otherwise
    +PushNotification.prototype.getLaunchNotification = function(callback) {
    +	exec(callback, callback, "PushNotification", "getLaunchNotification", []);
    +};
    +
     // Event spawned when a notification is received while the application is active
     PushNotification.prototype.notificationCallback = function(notification) {
     	var ev = document.createEvent('HTMLEvents');